Contents:
Snood is a very fun puzzle game based on the popular arcade game "Bust-a-Move". The game is easy to learn but very tough to master and has kept me busy for hours since I first cracked it. If you like puzzle games, you'll probably enjoy this game.
Anyway - we have four goals in this project. Goal number one is to make it registered and although this is a trivial program to crack, I'll cover the procedure for the newbies who might be reading this essay. This will be discussed in - you guessed it - "Part 1 - A Simple Crack". In "Part 2 - Snoods HATE Bugs!" we will be doing a simple bug fix of a page fault that occurs on occasion after you finish games - it can be very irritating. In "Part 3 - Cheaters Always Prosper" we will discuss allowing the use of the "mulligan" and "aimer" features without putting a piece of "cheese" near your score (which doesn't allow you to submit your scores to the "World High Score" list). In "Part 4 - Closing" we will recap what we have learned and say a few closing words.
Tools Needed:
You can actually use any diassembler, hex editor, and debugger of your
choice, but these are my first choices for tools.
Load up the game and you will get a nag with a few options. Click "Enter Code" and
then enter whatever you want. You will get "Sorry, that code is not valid..." (unless
you somehow managed to enter a valid serial randomly, in which case you should quit
reversing and start up a "psychic friends" hotline :). Find that message in IDA and
you will find the following code referencing it:
Part 1 - A Simple Crack
0040159C call CheckRegistration 004015A1 add esp, 0Ch 004015A4 cmp al, bl 004015A6 mov byte_42D581, al 004015AB jnz short loc_4015DA 004015AD lea edx, [esp+120h+var_100] 004015B1 push edx 004015B2 push offset unk_44CB47 004015B7 call sub_40E510 004015BC push offset unk_44CB47 004015C1 call CheckRegistration 004015C6 push offset aSorryThatCodeI ; "Sorry, that code is not valid as entere"... 004015CB mov byte_42D581, al 004015D0 call sub_4034D0 004015D5 add esp, 10h 004015D8 jmp short loc_4015EC 004015DA ; --------------------------------------------------------------------------- 004015DA 004015DA loc_4015DA: ; CODE XREF: sub_4013E0+1CBj 004015DA push offset aThanksForRegis ; "Thanks for registering! Your code entr"... 004015DF call sub_4034D0 004015E4 add esp, 4 004015E7 call sub_40E500 |
We know that the function called at 40159C and 4015C1 is "CheckRegistration" because the return value is checked to set the flag for "JNZ GOOD_GUY" at 4015AB. What does the return need to NOT be? There are two ways to find out. One is to set a breakpoint on 4015A4 and see what "BL" is at the time of the compare. The other way is to trace back quite a long ways to find out what was put into EBX/BL before this piece of code. I did it the hard way the first time by tracing back in the disassembler, so lets explain both methods.
Load up SNOOD.EXE in the SoftICE loader and place a breakpoint on 4015A4. It will look like this in SoftICE:
:bpx 4015a4
When the nag shows up, follow the same method as before - press the "Enter Code" button and enter anything. SoftICE should break and you will find that EBX contains 0:
:? ebx 00000000 0000000000 ""
You can also find this out through the register window at the top, but I thought I'd include this for something visual. We now know that the CheckRegistration function must not contain a value of 0, or FALSE (my guess is that the programmer used a boolean function). Now you can clear all breakpoints:
:bc *
Look up from the address 4015a4 until you find something that would modify EBX such as "MOV EBX..." or "SUB EBX..." or "XOR EBX..." etc. Anything that would modify EBX in any way. I can tell you now that I even traced through the calls to see if EBX was ever modified. You will see this at the third line from the top of the procedure:
004013E7 xor ebx, ebx |
This clears ebx (EBX is now 0). Just as we saw in the SoftICE method.
Patching:
To patch this quickly and easily, load SNOOD.EXE into HIEW and press enter twice to go to "Decode" mode. Press F5 and enter .403CF0 (the address of CheckRegistration [if you prefix the goto address with a . in HIEW it will go to the virtual address. Pretty useful, I think :]). Press F3 to edit and F2 to assemble instructions and enter the following:
MOV EAX,1 RETN
Press F9 to update the file.
If you are using another hex editor, insert the bytes "B8 01 00 00 00 C3" at 3CF0. Run Snood once
again and you will be registered.
Now that you are a registered user, you can use a couple new features. One of these is the aimer
feature, this tells you where exactly the snood will land when you shoot it. To enable it, one
must press the "X" key during a game. The downfall is that it puts a piece of cheese next to your
score and it will not let you submit to the high score table. Anyway, there is a bug when you
try to use the aimer. Start a game and press X to enable the aimer. Lose the game (or play it :)
by shooting the same place until the snoods hit the bottom of the screen. You will get a page
fault:
Well, look at the address 4088CD in your disassembler:
Part 2 - Snoods HATE Bugs!
SNOOD caused an invalid page fault in module SNOOD.EXE at 0167:004088cd.
004088C0 sub_4088C0 proc near ; CODE XREF: sub_40D510+15p 004088C0 004088C0 arg_0 = dword ptr 8 004088C0 004088C0 push ebx 004088C1 mov ebx, [esp+arg_0] 004088C5 test ebx, ebx 004088C7 jnz short loc_4088CD 004088C9 xor eax, eax 004088CB pop ebx 004088CC retn 004088CD ; --------------------------------------------------------------------------- 004088CD 004088CD loc_4088CD: ; CODE XREF: sub_4088C0+7j 004088CD mov eax, [ebx+8] |
EBX will be some number like 101 (it is always 101 for me). Well, that is trying to
access some memory that it can't, so why not just patch that procedure to return. Open
the program up in HIEW and go to 4088C0. Enter C3 (the opcode for retn) and update.
It will now work just fine. I haven't noticed any problems from this little fix so
I'm assuming it always returns 0 for a successful call anyway. It appears so from
a bit of backtracking.
Here comes the most interesting part (IMO) of this essay. Allowing use of mulligans and the
aimer without the "cheesy" score. Load Snood and enable the aimer by pressing X during
a game (in a level greater than child mode). Score at least a few points and then either
lose or continue the level. At the end you will get a message saying "You used the aimer...".
Go to the location that referenes that screen:
Part 3 - Cheaters Always Prosper
0040DFC8 cmp cl, 1 0040DFCB jz short loc_40DFEA 0040DFCD cmp aimer_used, 1 0040DFD4 jnz short loc_40DFEA 0040DFD6 push offset aYouUsedTheAime ; "You used the aimer, so you'll have a ch"... 0040DFDB call sub_4034D0 0040DFE0 add esp, 4 0040DFE3 mov [esp+30h+var_29], 1 0040DFE8 jmp short loc_40E046 0040DFEA ; --------------------------------------------------------------------------- 0040DFEA 0040DFEA loc_40DFEA: ; CODE XREF: sub_40DFA0+2Bj 0040DFEA ; sub_40DFA0+34j 0040DFEA mov al, byte ptr mulligan_count 0040DFEF test al, al 0040DFF1 jle short loc_40E007 0040DFF3 push offset aYouTookAMullig ; "You took a mulligan, so you'll have a c"... 0040DFF8 call sub_4034D0 0040DFFD add esp, 4 0040E000 mov [esp+30h+var_29], 1 0040E005 jmp short loc_40E046 0040E007 ; --------------------------------------------------------------------------- 0040E007 0040E007 loc_40E007: ; CODE XREF: sub_40DFA0+51j 0040E007 cmp byte_444AA0, 1 0040E00E jnz short loc_40E024 0040E010 push offset aYourSavedPuzzl ; "Your saved puzzle file indicated that y"... 0040E015 call sub_4034D0 0040E01A add esp, 4 0040E01D mov [esp+30h+var_29], 1 0040E022 jmp short loc_40E046 0040E024 ; --------------------------------------------------------------------------- 0040E024 0040E024 loc_40E024: ; CODE XREF: sub_40DFA0+6Ej 0040E024 mov al, byte_42F520 0040E029 test al, al 0040E02B jz short loc_40E046 0040E02D push offset aThereSeemsToBe ; "There seems to be some problem with how"... 0040E032 call sub_4034D0 0040E037 add esp, 4 0040E03A mov [esp+30h+var_29], 1 0040E03F mov byte_42F595, 1 0040E046 loc_40E046: ; CODE XREF: sub_40DFA0+48j 0040E046 ; sub_40DFA0+65j ... 0040E046 call sub_414B20 |
It appears that when anything is wrong, it sets var_29 to 1. In order to bypass all of the notices and get on with the scoring, we can change 40DFC8 to the following:
mov [esp+30+var_29], 0 jmp 40E046
First off, the opcodes for "mov [esp+30+var_29], 1" is:
.0040DFE3: C644240701 mov b,[esp][00007],001 ;"" |
So we should change it to C644240700. If you are using HIEW, you can just input this opcode directly and let HIEW calculate the jump on the next line. If you are using another hex editor without the assemble feature, the full code to enter at DFC8 is C644240701E974000000. This little patch gets rid of the cheese.
Continue on and then when you get back to the main screen click Game->Get Score Verification Code. It will say "You used a cheat (Mulligan or Aimer)...". Find this string and the following code will reference it:
004169BE loc_4169BE: ; CODE XREF: sub_4169A0+Bj 004169BE mov al, byte_42F595 004169C3 test al, al 004169C5 jz short loc_4169D8 004169C7 push offset aYouUsedACheatM ; "You used a cheat (Mulligan or Aimer) so"... 004169CC call sub_4034D0 004169D1 add esp, 4 004169D4 add esp, 48h 004169D7 retn |
I'm confident that byte_42F595 is "cheat_used". We could put 0 into "cheat_used" at each reference,
but that is a number of references. We'll rather make the JZ after the TEST into a JMP. Go to 169BE
in your hex editor and replace the 74 with EB. It will now generate a code for you!
Overall, this was very simplistic but took a bit of digging in the code. I was planning on making
a keygen for whatever score you choose, but the algorithm is very long so it would just be a waste
of time. If someone wants to do this, I would like to see an essay on it :) Also, it is up to you
to remove the annoying messages when you try to use the aimer or mulligan. I would also like to
see an essay if someone besides myself completes this task, I would also like to see an essay on that.
If you need to contact me, you can E-Mail me at muaddib(at)immortaldescendants(dot)org or catch me
on IRC in #cracking4newbies and #pravus (slightly more friendly at times ;), among other channels.
Greetings go out to Carpathia, Zen, WarezPup, noptical, Nitrus, Dead-Mike, vman_, Volatility, amante4,
FatBoyJoe, NeOXQuiCK (nhoe), Dawai, C_DKnight, f0dder, FLeBBHuE, gaHn, jroger, PoiznFree, SeiZe_M,
NoodleSpa, Hutch, Iczelion, JosephCo, radical, sortof, Quantico, barcode_, g0dmonkey, Xorolc, Kwai_Lo,
Crudd, BMonkey, _Bonkers_, and anyone who I forgot. Hmm...a greetz list...haven't written one of those in a while ;)
Part 4 - Closing
More seriously (and sadly)... RIP Unixfu 1983-2001 - you will be remembered. Unixfu died of a drug overdose early in the month of July, 2001. He overdosed on DXM (dextromethorphan hydrobromide) which he had been taking for some time. I strongly advocate the use of drugs for personal exploration, but only with research and responsibility, which sadly, I didn't stress enough to Unixfu. Unixfu, we will all remember you. Sincere condolences to your family and friends in this tough time. |
Written by Muad'Dib on Thursday, July 19, 2001
muaddib(at)immortaldescendants(dot)org
Links:
http://crackmes.cjb.net - Practice cracking!
http://muaddib.immortaldescendants.org - Random Crap
http://protools.cjb.net - Get some tools!
http://www.erowid.org - Do your research.
http://tsehp.cjb.net - Great essays!
http://fraviamb.cjb.net - A forum (I got the idea for this essay from the "Mini-Project" board.