Tutorial by Mr. Squash, mrsquash0@hotmail.com Written by a newbie Purpose: To show how to calculate a valid s/n for PhoX's crackme 5.1 By bpx getwindowtexta you will easily find the protection. After si breaks push F11: (code ripped with w32dasm) * Reference To: USER32.GetWindowTextA, Ord:0000h :0040119E E800010000 Call 004012A3 :004011A3 FF3544204000 push dword ptr [00402044] <- you will end up here :004011A9 E85D000000 call 0040120B ;check if the serial is valid :004011AE 83F801 cmp eax, 00000001 :004011B1 751E jne 004011D1 :004011B3 6A30 push 00000030 * Possible StringData Ref from Data Obj ->"Good For U!" ;Well, looks like if eax=1 the :004011B5 6881204000 push 00402081 ;serial is valid * Possible StringData Ref from Data Obj ->"U Did It!!" .. ************************ Check_If_The_Serial_Is_Valid: :0040120B C8000000 enter 0000, 00 :0040120F 53 push ebx :00401210 52 push edx :00401211 33C0 xor eax, eax :00401213 B8A6204000 mov eax, 004020A6 ;eax=the serial that you entered :00401218 803800 cmp byte ptr [eax], 00 ;any serial entered? :0040121B 7460 je 0040127D :0040121D 33DB xor ebx, ebx :0040121F 33D2 xor edx, edx Lp: :00401221 8A18 mov bl, byte ptr [eax] ;get letter from string :00401223 C1C308 rol ebx, 08 ;<< 8, ex. 00000031 -> 00003100 :00401226 03D3 add edx, ebx ;add this value to edx :00401228 40 inc eax :00401229 803800 cmp byte ptr [eax], 00 :0040122C 75F3 jne Lp :0040122E 52 push edx ;value to convert, ex. 8e910281 -> '8e910281' * Possible StringData Ref from Data Obj ->"%lX" :0040122F 6854204000 push 00402054 :00401234 68BF204000 push 004020BF ;buffer to hold the converted value * Reference To: USER32.wsprintfA, Ord:0000h :00401239 E88F000000 Call 004012CD ;conv the hex value in edx to ascii :0040123E BBBF204000 mov ebx, 004020BF ;ebx points to our converted string * What the following lines does is to check if our converted string match this string: '8DCAF368' (right s/n) * - if this is the case, the serial is valid... :00401243 803B38 cmp byte ptr [ebx], 38 ;8 :00401246 7535 jne 0040127D :00401248 807B0144 cmp byte ptr [ebx+01], 44 ;D :0040124C 752F jne 0040127D :0040124E 807B0243 cmp byte ptr [ebx+02], 43 ;... :00401252 7529 jne 0040127D :00401254 807B0341 cmp byte ptr [ebx+03], 41 :00401258 7523 jne 0040127D :0040125A 807B0446 cmp byte ptr [ebx+04], 46 :0040125E 751D jne 0040127D :00401260 807B0533 cmp byte ptr [ebx+05], 33 :00401264 7517 jne 0040127D :00401266 807B0636 cmp byte ptr [ebx+06], 36 :0040126A 7511 jne 0040127D :0040126C 807B0738 cmp byte ptr [ebx+07], 38 ;8 :00401270 750B jne 0040127D :00401272 B801000000 mov eax, 00000001 ;eax=1, serial is valid :00401277 5A pop edx :00401278 5B pop ebx :00401279 C9 leave :0040127A C20400 ret 0004 **** :0040127D 33C0 xor eax, eax ;eax=0, sorry serial is NOT valid :0040127F 5A pop edx :00401280 5B pop ebx :00401281 C9 leave :00401282 C20400 ret 0004 These 3 lines of code creates the value from the entered input: :00401221 8A18 mov bl, byte ptr [eax] ;get letter from string :00401223 C1C308 rol ebx, 08 ;<< 8, ex. 00000031 -> 00003100 :00401226 03D3 add edx, ebx ;add this value to edx We know that we must end up with a value in edx that match 8DCAF368 Example, if we enter '1234567' as serial, we end up with this value : edx=00000000 ebx=00000000 Pass 1: Add '1' = 31h ebx=00000031 ;mov bl, byte ptr [eax] ebx=00003100 ;rol ebx, 08 edx=00003100 ;add edx, ebx Pass 2: Add '2' = 32h ebx=00003132 ebx=00313200 edx=00316300 Pass 3: Add '3' = 33h ebx=00313233 ebx=31323300 edx=31639600 Pass 4: Add '4' = 34h ebx=31323334 ebx=32333431 edx=6396CA31 Pass 5: Add '5' = 35h ebx=32333435 ebx=33343532 edx=96CAFF63 Pass 6: Add '6' = 36h ebx=33343536 ebx=34353633 edx=CB003596 Pass 7: Add '7' = 37h ebx=34353637 ebx=35363734 edx=00366CCA <- Final value Our problem is now to go from 00366CCA to the original string from which this value was calculated (ie. reversing the protection scheme). With the knowledge that I have gathered so far (remember, I'm a newbie..) I cannot see how this can be done - If I should be wrong here I would like very much to hear from you, I can be reached via my email address: mrsquash0@hotmail.com. Our problems are: When we load a new digit/letter in ebx we erase whatever value that was here before (ie. the lower 8 bits of ebx are changed - with no relation to what it was before). Another problem is that we go beyond the limit of edx, ie. ffffffff, and start over from 0. But there is a solution to our problem, because this type of protection can have more than 1 valid s/n. For this crackme a valid s/n can be computed like this: 8D CA F3 68 <- the value found in the crackme |__|_ __| | | | F3 - CA = 29 = ')' *** Then I perform two logical operands on this value: 1) ror 8 2) and ffffffff00h (-100h) After this I get: 68 8D CA 00 |__|_ __| | | | CA - 8D = 3D = '=' *** 1) ror 8 2) and ffffffff00h (-100h) 00 68 8D 00 |__|_ __| | | | 8D - 68 = 25 = '%' *** 1) ror 8 2) and ffffffff00h (-100h) 00 00 68 00 |__|_ __| | | | 68 - 00 = 68 = 'h' *** 1) ror 8 2) and ffffffff00h (-100h) 00 00 00 00 DONE So from this I get: ')=%h' - reverse this and it is a valid serial. This means that if you enter 'h%=)' (without quotes) as the s/n you'll get the goood messagebox saying that you're a goood cracker :) Problem by solving the problem like this: If the program had some disabled functions that would only be available in the registered version and the code within these functions were encrypted with a key from another s/n calculation routine (with the original s/n string as starting point) we would have a serious problem. Because the valid s/n we have calculated would NOT give the same result as the original s/n if it was to put through another algorithm. I repeat: I am not 100% (only 99%) sure that you cannot (in some way) go from 8DCAF368 to the original string that this value was computed from. If you know of a way, you are MORE than welcome to send me a mail : mrsquash0@hotmail.com , thanks !