.---. .---. .----------. | \ / | .-. | | | |\ \ / /| | | | .--------. .-----------. .---------. .-------. | .-------' | | \ \ / / | | `-' | .------' `----. .----' | .-------' | ,---. | | | | | \ \/ / | | .-. | | | | | | | | | | | `----. | | \__/ | | | | \ \ | | | `----. | `---' | | ,----' | | | | | | \ `-----. | | | ,----' | .---' | | | | | | | | `----. | | | | | | , \ | | | | | | | | | | | | | | | |\ \ | | | | | | | | | | | | | | | | \ \ | '-------. | | | | | | .------' | | | | '------. | | \ \ | | `--' `--' `-' `--------' `-' `--------' `-' `-' `----------' .----------------------. .-----------| Proudly Presents |-----------. .--------------+----------------------------------------------+--------------. | A cracking tutor for: | | xReminder v1.02 | `----------------------------------------------------------------------------' This program used a protection scheme unknown to me, and so it deserved a cracking tutor. The program just needs a serial number. This time is takes more work to calculate the serial than finding the protection scheme. If you like maths you should certainly download the program and start cracking right now. Programs I have used: - SoftIce V3.2 - W32dasm V8.9 - xReminder v1.02 (http://www.geocities.com/SiliconValley/Hills/7349/) - not necessary, but might come in handy: Base Calculator http://biosys12.ee.unsw.edu.au/personal/software/basecalc/ .-----------------------------------------------------------------------------------------------. `-----------------------------------------------------------------------------------------------' Fire w32dasm and take a look at Refs - String data references. You should notice: "String Resource ID=59148: "This is not a valid registration. You may have used an inval" Double click on this string and you ge transported to 4023BF. Now take a look at the code: .-----------------------------------------------------------------------------------------------. | Part of the code | `-----------------------------------------------------------------------------------------------' :004023A8 8BC8 mov ecx, eax :004023AA E8E1A60000 call 0040CA90 :004023AF 3D0BE70000 cmp eax, 0000E70B <--------- important call :004023B4 7443 je 004023F9 <--------- if eax = E70B, register :004023B6 8D4C2404 lea ecx, dword ptr [esp+04] :004023BA E8A23C0200 call 00426061 * Possible Reference to String Resource ID=59148: "This is not a valid registration. You may have used an inval" | :004023BF 680CE70000 push 0000E70C :004023C4 8D4C2408 lea ecx, dword ptr [esp+08] .......... * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004023B4(C) | :004023F9 8BCE mov ecx, esi <--------- go on registering :004023FB E8894F0200 call 00427389 .-----------------------------------------------------------------------------------------------. `-----------------------------------------------------------------------------------------------' I have already explained this part of the code. You shouldn't have problems with this. The fun is just beginning....... Now follow the important call. And scroll a little downwards. You MIGHT notice this: :0040CAE6 83F813 cmp eax, 00000013 <------ check is s/n is 13h(19d) char long :0040CAE9 740C je 0040CAF7 <------ if so, go on :0040CAEB 33C0 xor eax, eax if not, unregister :0040CAED 5F pop edi :0040CAEE 5E pop esi :0040CAEF 5D pop ebp :0040CAF0 5B pop ebx :0040CAF1 83C414 add esp, 00000014 :0040CAF4 C20800 ret 0008 As I said 'You MIGHT notice this' I won't blame you for not seeing this. I overlooked this part myself. If you overlook this part you might go tracing. This is a boring job. Anyway, you are reading this tutorial so you won't overlook this part. Now start xReminder, go to the registration screen and place a breakpoint at GetWindowTextA(SoftIce). Enter a s/n (1234567890123456789) and press enter. You get kicked into SoftIce. Press F12 to get into prot32. Now place a breakpoint just before the 'important call'. BPX 4023A8 Disable the breakpoint at GetWindowTextA and continue the program. Place another BPX at 40CAE6 Press CTRL-D or F5 again and you should arrive 40CEA6. EAX should be 13h. Continue and arrive at 40CAEF7. Now here is a big block of code. You might want to take some time to explore this important part of the protection scheme. Just trace a few times through it to look what kind of protection this is. Notice this part: :0040CB2C 8BD0 mov edx, eax <------- put 1st 4 char of sn in :0040CB2E 880D3ABC4400 mov byte ptr [0044BC3A], cl EDX :0040CB34 81E257494E2D and edx, 2D4E4957 <------- 2D4E4957 = -NIW :0040CB3A 3BD0 cmp edx, eax <------- compare edx, eax :0040CB3C 7404 je 0040CB42 <------- must be the same to :0040CB3E 8B5C2410 mov ebx, dword ptr [esp+10] register * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CB3C(C) | :0040CB42 C744241401000000 mov [esp+14], 00000001 Take a look at the 'and edx, 2D4E4957' The first 4 characters of your s/n get 'and-ed' with -NIW 2D4E4957 AND 2D4E4957 returns 2D4E4957. So the first 4 characters of our serial should be -NIW IN REVERSED ORDER. If you type '? edx' at 40CB2E you should get '4321' as answer. So -NIW should also be reversed: WIN- Now we know the serial looks like this: WIN-123456789012345 I would advice you to do some more tracing, get a hand of the protection. Take a look at the end of the protection scheme: :0040CC12 8BD3 mov edx, ebx <----- ebx +EFFFFF01 must be 0 :0040CC14 8D8301FFFFEF lea eax, dword ptr [ebx+EFFFFF01] <---- eax must be zero :0040CC1A 81E2FF000010 and edx, 100000FF :0040CC20 5F pop edi :0040CC21 81EAFF000010 sub edx, 100000FF :0040CC27 5E pop esi :0040CC28 F7DA neg edx :0040CC2A 1BD2 sbb edx, edx :0040CC2C 5D pop ebp :0040CC2D F7D2 not edx :0040CC2F 23D3 and edx, ebx :0040CC31 5B pop ebx :0040CC32 F7D8 neg eax <------ eax must be 0 :0040CC34 1BC0 sbb eax, eax <------ eax must be 0 :0040CC36 891524BC4400 mov dword ptr [0044BC24], edx :0040CC3C F7D8 neg eax <------ neg eax must be 0 :0040CC3E 050BE70000 add eax, 0000E70B <------ ?register? :0040CC43 83C414 add esp, 00000014 :0040CC46 C20800 ret 0008 <------ EAX must be E70B to register. This is the last part of the big block, an end. Notice that at 40CC3E EAX+E70B must be zero. So EAX must also be zero. Now do some arithmetic yourself. At 40CC12 EBX + EFFFFF01 must be zero => ebx = 0 - EFFFFF01 => ebx = 100000FF. EBX must be 100000FF to register, so take anther look at the code, only this part of the code modifies EBX: :0040CB51 8A8728BC4400 mov al, byte ptr [edi+0044BC28] <------ load char from s/n :0040CB57 3C2D cmp al, 2D <------ is char 2d(-)? :0040CB59 8844242C mov byte ptr [esp+2C], al :0040CB5D 7428 je 0040CB87 <------ if so, jump * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CB5D(C) | :0040CB87 8BC6 mov eax, esi <------ arrive here from jump :0040CB89 83C9FF or ecx, FFFFFFFF :0040CB8C 83E800 sub eax, 00000000 :0040CB8F 7414 je 0040CBA5 <------ jump 1 :0040CB91 48 dec eax :0040CB92 740A je 0040CB9E <------ jump 2 :0040CB94 48 dec eax :0040CB95 7513 jne 0040CBAA <------ jump 3 :0040CB97 B958000000 mov ecx, 00000058 :0040CB9C EB0C jmp 0040CBAA <------ jump 4 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CB92(C) | :0040CB9E B956000000 mov ecx, 00000056 :0040CBA3 EB05 jmp 0040CBAA * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CB8F(C) | :0040CBA5 B94B000000 mov ecx, 0000004B * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:0040CB95(C), :0040CB9C(U), :0040CBA3(U) | ,-- jumps arrive here :0040CBAA 8B44B414 mov eax, dword ptr [esp+4*esi+14] <---- put value in EAX :0040CBAE 33D2 xor edx, edx :0040CBB0 F7F1 div ecx <------ IMPORTANT :0040CBB2 85D2 test edx, edx :0040CBB4 750C jne 0040CBC2 <------ EDX must be zero :0040CBB6 8D4E02 lea ecx, dword ptr [esi+02] :0040CBB9 B801000000 mov eax, 00000001 :0040CBBE D3E0 shl eax, cl :0040CBC0 0BD8 or ebx, eax <------ modify ebx * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CBB4(C) | :0040CBC2 46 inc esi <------ ESI counts 2d(-) in s/n :0040CBC3 83FE04 cmp esi, 00000004 exept the WIN- :0040CBC6 7412 je 0040CBDA /\ :0040CBC8 C744B41401000000 mov [esp+4*esi+14], 00000001 || As I said before, you might want to trace through the code. We now know the programs checks if there are - (that is 2D hexadecimal) in the serial. Now let me tell you something about the DIV function: EAX gets DIVided by ECX, in other words: EAX tells how many times ECX goes into EAX. The MODulo gets stored in EDX, in other words: the rest of the division gets stored in EDX. This might be a bit confusing so i'll give you an example in *!DECIMAL!*: mov eax, 100 mov ecx, 15 div ecx The result: eax = 6, edx = 10, ecx = 15 In a formula: EAX(before) = (EAX(after) * ecx) + EDX Enough explaination of the div(?) Let's go on. EDX must be zero to modify EBX. Now lets take a look how [esp+4*esi+14] gets calculated: :0040CB51 8A8728BC4400 mov al, byte ptr [edi+0044BC28] <----- put char of s/n in AL :0040CB57 3C2D cmp al, 2D <----- check if al = 2d(-) :0040CB59 8844242C mov byte ptr [esp+2C], al <----- store eax :0040CB5D 7428 je 0040CB87 <----- jump if eax = 2d :0040CB5F 8B44242C mov eax, dword ptr [esp+2C] <----- retrieve eax :0040CB63 8B4CB414 mov ecx, dword ptr [esp+4*esi+14] <----- restore [esp+4*esi+14] :0040CB67 25FF000000 and eax, 000000FF <----- not important :0040CB6C 03E8 add ebp, eax <----- add eax to ebp :0040CB6E 81F900040000 cmp ecx, 00000400 <----- check if ecx > 400h :0040CB74 7309 jnb 0040CB7F <----- if ecx >= jump :0040CB76 0FAFC8 imul ecx, eax <----- if not imul :0040CB79 894CB414 mov dword ptr [esp+4*esi+14], ecx <----- store ecx :0040CB7D EB51 jmp 0040CBD0 <----- jump * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CBB4(C) | :0040CBC2 46 inc esi :0040CBC3 83FE04 cmp esi, 00000004 :0040CBC6 7412 je 0040CBDA :0040CBC8 C744B41401000000 mov [esp+4*esi+14], 00000001 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CB74(C) | :0040CB7F 03C8 add ecx, eax <----- add eax to ecx :0040CB81 894CB414 mov dword ptr [esp+4*esi+14], ecx <----- store ecx :0040CB85 EB49 jmp 0040CBD0 <----- jump * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:0040CB7D(U), :0040CB85(U) | :0040CBD0 47 inc edi <----- increase counter :0040CBD1 83FF13 cmp edi, 00000013 /location in s/n :0040CBD4 0F8277FFFFFF jb 0040CB51 <----- if edi < 13h jump Well, that should be enough explaination. By now you should have an idea of how to register the program. The serial must start with WIN- and you will probably need some 2d(-). To modify EBX [esp+4*esi+14] must go EXACLY(EDX must be zero) into x times into ECX. Now lets modify that EBX register to register the program, use a serial like this: WIN-123-456-789-012 Here is a part of the code(again), i wrote the values next to the code for the 1st, 2nd, 3rd and 4th time: 1st time | 2nd time | 3rd time | 4th t :0040CB51 mov al, byte ptr [edi+0044BC28] <----- al = 31h | al = 32h | al = 33h | al = 2d :0040CB57 cmp al, 2D <----- compare :0040CB59 mov byte ptr [esp+2C], al <----- store :0040CB5D je 0040CB87 <----- no jump | no jump | no jump | JUMP!! :0040CB5F mov eax, dword ptr [esp+2C] <----- retrieve :0040CB63 mov ecx, dword ptr [esp+4*esi+14] <----- ecx = 1h | ecx = 31h| ecx = 32h :0040CB67 and eax, 000000FF <----- not important :0040CB6C add ebp, eax <----- ebp = 31h| ebp = 63h| ebp = 96h :0040CB6E cmp ecx, 00000400 <----- compare :0040CB74 jnb 0040CB7F <----- no jump | no jump | JUMP!! :0040CB76 imul ecx, eax <----- ecx = 31h| ecx = 992h :0040CB79 mov dword ptr [esp+4*esi+14], ecx <----- store :0040CB7D jmp 0040CBD0 <----- jump * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CB74(C) | :0040CB7F add ecx, eax <----------------------- | ecx = 992 + 33=9C5h :0040CB81 mov dword ptr [esp+4*esi+14], ecx <----- store ecx :0040CB85 jmp 0040CBD0 <----- jump Now follow that JUMP!!! * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CB5D(C) | ,----- ESI = 0 because this :0040CB87 8BC6 mov eax, esi <------ is the first 2d(-) :0040CB89 83C9FF or ecx, FFFFFFFF <------ ecx = FFFFFFFF :0040CB8C 83E800 sub eax, 00000000 <------ eax = 0 :0040CB8F 7414 je 0040CBA5 <------ JUMP!! * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CB8F(C) | :0040CBA5 B94B000000 mov ecx, 0000004B <------ ecx = 4Bh * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:0040CB95(C), :0040CB9C(U), :0040CBA3(U) | :0040CBAA 8B44B414 mov eax, dword ptr [esp+4*esi+14] <---- eax = 9C5h :0040CBAE 33D2 xor edx, edx :0040CBB0 F7F1 div ecx <------ Divide :0040CBB2 85D2 test edx, edx eax = 21h, edx = 1Ah :0040CBB4 750C jne 0040CBC2 <------ EDX not zero :( Jump :0040CBB6 8D4E02 lea ecx, dword ptr [esi+02] :0040CBB9 B801000000 mov eax, 00000001 :0040CBBE D3E0 shl eax, cl :0040CBC0 0BD8 or ebx, eax <------ modify ebx * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CBB4(C) | :0040CBC2 46 inc esi <------ ESI = 1h :0040CBC3 83FE04 cmp esi, 00000004 <------ compare :0040CBC6 7412 je 0040CBDA <------ no jump :0040CBC8 C744B41401000000 mov [esp+4*esi+14], 00000001 <------ [esp+4*esi+14] = 1h Bah, we didn't register, because we used the wrong serial. Let me tell you again (SHORT) how the calculation goes and how we should register: (1st digit * 2nd digit) + 3rd digit digit = x * 4B Now THAT was REALLY SHORT, now we only have to figure out 4 variables. This can easily done by guessing. X must be a value bigger then 930h because (30 * 30) + 30h = 930h Lets say x = 22h. Then: (1st * 2nd) + 3rd = 9F6h ; what could those digits be? (32 * 32 ) + 32 = 9F6h!!!!!! ; OK, we got them!!!! You might say that this is a hell of a work, and yes i agree with you. But I have done this with the '? 32 *32+32' command in SoftIce. Now go figure out the other parts of the s/n yourself, I have put the answers at the bottom of this text file. I have put the other calculation problems hereunder to help you a bit. Also mind this part: :0040CB87 8BC6 mov eax, esi <---- esi counts 2d(-) :0040CB89 83C9FF or ecx, FFFFFFFF :0040CB8C 83E800 sub eax, 00000000 :0040CB8F 7414 je 0040CBA5 <---- 1st time :0040CB91 48 dec eax :0040CB92 740A je 0040CB9E <---- 2nd time :0040CB94 48 dec eax :0040CB95 7513 jne 0040CBAA <---- 3th time :0040CB97 B958000000 mov ecx, 00000058 <---- 3th time :0040CB9C EB0C jmp 0040CBAA * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CB92(C) | :0040CB9E B956000000 mov ecx, 00000056 <---- 2nd time :0040CBA3 EB05 jmp 0040CBAA * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040CB8F(C) | :0040CBA5 B94B000000 mov ecx, 0000004B <---- 1st time Well, here are all the arithmetic problems: WIN-123-456-789-012 ( 1st digit * 2nd digit) + 3rd digit digit = x * 4Bh WIN-123-456-789-012 ( 4th digit * 5th digit) + 6th digit digit = x * 56h WIN-123-456-789-012 ( 7th digit * 8th digit) + 9th digit digit = x * 58h WIN-123-456-789-012 (10th digit * 11th digit) + 12rd digit digit = x * 55h I hope you got through this tutor, it was a pretty tough one. Anyway you should have registered it by now. I hope you enjoyed reading this tutor, if you do: let me know. Thanks. Next tutor will cover patching in Pascal. .-----------------------------------------------------------------------------------------------. `-----------------------------------------------------------------------------------------------' Well, I hope you learned SOMETHING from this tutor. If you have any comments, questions, need help or whatever, mail me at MisterE@freemail.nl OR look for me at EFNET => #cracking4newbies or #cracking .-----------------------------------------------------------------------------------------------. | GREETZ | `-----------------------------------------------------------------------------------------------' Still the same greetz: Greetz go to: everyone on #cracking4newbies - #tno - #inside98 .-----------------------------------------------------------------------------------------------. `-----------------------------------------------------------------------------------------------' The answer: WIN-222-440-060-277