.---. .---. .----------. | \ / | .-. | | | |\ \ / /| | | | .--------. .-----------. .---------. .-------. | .-------' | | \ \ / / | | `-' | .------' `----. .----' | .-------' | ,---. | | | | | \ \/ / | | .-. | | | | | | | | | | | `----. | | \__/ | | | | \ \ | | | `----. | `---' | | ,----' | | | | | | \ `-----. | | | ,----' | .---' | | | | | | | | `----. | | | | | | , \ | | | | | | | | | | | | | | | |\ \ | | | | | | | | | | | | | | | | \ \ | '-------. | | | | | | .------' | | | | '------. | | \ \ | | `--' `--' `-' `--------' `-' `--------' `-' `-' `----------' .----------------------. .-----------| Proudly Presents |-----------. .--------------+----------------------------------------------+--------------. | A cracking tutor for: | | FxEdit V2.8 | `----------------------------------------------------------------------------' This program is fairly easy to crack. And because I am learning Pascal I have written a keygen for you. I included the source for the keygen and the compiled version. Programs I have used: - SoftIce V3.2 - FxEdit v2.8 (http://www.execpc.com/~sbd) .-----------------------------------------------------------------------------------------------. `-----------------------------------------------------------------------------------------------' Hello all you (wanna-be) crackers. After a long time i decided to write another tutor. This program has a nice protection scheme and this way it nominated itself for a cracking tutor. In this tutor i'll show you the way to get the s/n the easy (dumb) way and the smart(er) way. At the end I have put my own keygen for this program. .-----------------------------------------------------------------------------------------------. `-----------------------------------------------------------------------------------------------' Well, let's start. First: using Softiceplace a breakpoint at getdlgitemtexta, by typing: bpx getdlgitemtexta Now go to the registration form and enter you name. I used: name: MisterE [tNO] company name: [tNO] s/n enter: 123454 Hit the ok button. You get kicked into SoftIce. Press F11 to get out of the getdlgitemtexta API. When you trace one step (F8) and look in the EAX register by typing 'd eax' you should see your name. Press F5 or CTRL-d another two times to load get the company name and your s/n. Again press F11 and trace one step. You should end up here: :00409EB5 8B2DA0F64200 mov ebp, [USER32!GetDlgItemTextA] <= move GetDlgItemTexta in :00409EBB 6A65 push 00000065 ebp :00409EBD 8D5E32 lea ebx, dword ptr [esi+32] :00409EC0 57 push edi :00409EC1 FFD5 call ebp <= get your name :00409EC3 6A32 push 00000032 :00409EC5 53 push ebx :00409EC6 6A66 push 00000066 :00409EC8 57 push edi :00409EC9 FFD5 call ebp <= get company name :00409ECB 8D442410 lea eax, dword ptr [esp+10] :00409ECF 6800010000 push 00000100 :00409ED4 50 push eax :00409ED5 6A67 push 00000067 :00409ED7 57 push edi :00409ED8 FFD5 call ebp <= get your serial number :00409EDA 8D442410 lea eax, dword ptr [esp+10] <= you are here :00409EDE 50 push eax Now you have to do some tracing. This is the hardest part: you have to notice when something important happens. At 409EDE type 'd eax' it is you serial. Now notice what happens when you step over (F10) the first call, EAX changes. You should know what this value means. If you don't: type '? eax'. It is our s/n!!!! TIP: allways use the same serial, so you know what you s/n is in hexadecimal (123454 decimal = 1E23E hexadecimal). Back to the code. Look ahead, you should notice the compare mnemonic (CMP). If you would trace ahead without stepping into to calls (F10) and would type 'd eax' at the cmp, you would see the serial. You CRACKED the program ........ NOT, or actually 'yes'. You did get the right s/n. But it would be much nicer if you even learnt something (more?). Examining the protection sceme: at 409EE4 do some tracing, till you get at the 'important call I' Step into this call (F8) :00409EDF E8FC7A0000 call 004119E0 <= step over this one :00409EE4 83C404 add esp, 00000004 :00409EE7 8BE8 mov ebp, eax :00409EE9 6898C94100 push 0041C998 :00409EEE 56 push esi :00409EEF FF15D0F54200 Call dword ptr [0042F5D0] <= important call I :00409EF5 85C0 test eax, eax :00409EF7 7524 jne 00409F1D :00409EF9 6884C94100 push 0041C984 :00409EFE 53 push ebx :00409EFF FF15D0F54200 Call dword ptr [0042F5D0] <= important call II :00409F05 85C0 test eax, eax :00409F07 7514 jne 00409F1D :00409F09 81FD8D030000 cmp ebp, 0000038D :00409F0F 750C jne 00409F1D :00409F11 53 push ebx :00409F12 56 push esi :00409F13 E8485F0000 call 0040FE60 :00409F18 83C408 add esp, 00000008 :00409F1B 8BE8 mov ebp, eax :00409F1D 53 push ebx :00409F1E 56 push esi :00409F1F E83C5F0000 call 0040FE60 :00409F24 83C408 add esp, 00000008 :00409F27 3BC5 cmp eax, ebp <= interesting: a cmp :00409F29 741E je 00409F49 <= jump if equal to 'registered' Into the call. You end up here: :0040FE60 8B442404 mov eax, dword ptr [esp+04] <= here :0040FE64 56 push esi :0040FE65 8B3554C64100 mov esi, dword ptr [0041C654] :0040FE6B 50 push eax :0040FE6C 81CE78030000 or esi, 00000378 :0040FE72 E859100000 call 00410ED0 <= trace into this call :0040FE77 83C404 add esp, 00000004 :0040FE7A 03F0 add esi, eax :0040FE7C 8B44240C mov eax, dword ptr [esp+0C] :0040FE80 50 push eax :0040FE81 E84A100000 call 00410ED0 :0040FE86 83C404 add esp, 00000004 :0040FE89 03C6 add eax, esi :0040FE8B 5E pop esi :0040FE8C C3 ret End up here: :00410ED0 53 push ebx <= here :00410ED1 56 push esi :00410ED2 8B74240C mov esi, dword ptr [esp+0C] :00410ED6 57 push edi :00410ED7 55 push ebp :00410ED8 33FF xor edi, edi :00410EDA 56 push esi :00410EDB FF1510F54200 Call [KERNEL32!lstrlenA] <= step over this, it get's the :00410EE1 85F6 test esi, esi =\ length of your name (D = 13dec) :00410EE3 7432 je 00410F17 '----> Did you enter a name? :00410EE5 85C0 test eax, eax :00410EE7 742E je 00410F17 :00410EE9 B900000000 mov ecx, 00000000 :00410EEE 7E27 jle 00410F17 Here is the encryption routine for the s/n. The program looks up a table. :00410EF0 0FBE9C0864F84100 movsx ebx, byte ptr [eax+ecx+0041F864] <= get char from table1 :00410EF8 0FBE2C31 movsx ebp, byte ptr [ecx+esi] <= get char from name :00410EFC 8D5101 lea edx, dword ptr [ecx+01] :00410EFF 0FAFDD imul ebx, ebp :00410F02 0FBE899CF84100 movsx ecx, byte ptr [ecx+0041F89C] <= get char from table2 :00410F09 0FAFD9 imul ebx, ecx :00410F0C 0FAFDA imul ebx, edx :00410F0F 03FB add edi, ebx :00410F11 8BCA mov ecx, edx :00410F13 3BD0 cmp edx, eax <= did all the chars of :00410F15 7CD9 jl 00410EF0 the name? :00410F17 8BC7 mov eax, edi :00410F19 5D pop ebp :00410F1A 5F pop edi :00410F1B 5E pop esi :00410F1C 5B pop ebx :00410F1D C3 ret The program uses two tables, as you can see when you type 'd eax+ecx+0041F864' at 00410EF0 and 'd ecx+0041f89c' at 00410F02 Here are the tables: table1: serB&nz|mfM1/5(!sd$Mq.{s]+sFjtKpzSdtzoXqmb^Al@dv:s?x/ table2: |b!pz*ls;rn|lf$vi^Axpe)rx5aic&9/2m5lsi4@0dmZw94cmqpfhw The encryption routine is pretty self-explanatory. It calculates the ASCII value of a char and does some imul and calculates the first part of the s/n. Trace until you RETurn from the call, you end up here: :0040FE60 8B442404 mov eax, dword ptr [esp+04] <= here :0040FE64 56 push esi :0040FE65 8B3554C64100 mov esi, dword ptr [0041C654] :0040FE6B 50 push eax :0040FE6C 81CE78030000 or esi, 00000378 :0040FE72 E859100000 call 00410ED0 <= calculate s/n for name :0040FE77 83C404 add esp, 00000004 :0040FE7A 03F0 add esi, eax <= add FEDAAFFF to the s/n :0040FE7C 8B44240C mov eax, dword ptr [esp+0C] :0040FE80 50 push eax :0040FE81 E84A100000 call 00410ED0 <= calculate s/n for company :0040FE86 83C404 add esp, 00000004 name :0040FE89 03C6 add eax, esi <= add s/n for company name :0040FE8B 5E pop esi :0040FE8C C3 ret Trace until you RETurn. End up here: :00409F24 83C408 add esp, 00000008 <= here :00409F27 3BC5 cmp eax, ebp <= Got the right s/n? :00409F29 741E je 00409F49 <= jump if equal to 'registered' .-----------------------------------------------------------------------------------------------. `-----------------------------------------------------------------------------------------------' Well, that's it for today. Hope you enjoyed my tutorial. I've added the source for a keygen, you can find it at the end of this text file. I encountered two problems when I created this keygen: 1) runtime error 200: division by zero <= Softice seems to cause this error, I don't know what to do against it. :-( 2) adding FEDAAFFF(4275744767) to the serial. This value is too big for a longint. Does somebody know how to avoid this other that I did in the keygen? .-----------------------------------------------------------------------------------------------. | The keygenerator | `-----------------------------------------------------------------------------------------------' program keygen_fxedit(input, output) ; uses crt ; var edi, ebp, ebx, esi : longint ; var length_name, length_company_name, counter, counter2 : byte ; var name, company_name, table1, table2, serial : string ; label bad_boy ; begin table1 := 'serB&nz|mfM1/5(!sd$Mq.{s]+sFjtKpzSdtzoXqmb^Al@dv:s?x/' ; table2 := '|b!pz*ls;rn|lf$vi^Axpe)rx5aic&9/2m5lsi4@0dmZw94cmqpfhw' ; clrscr ; writeln('ÚÄÄÄÄÄÄÄ ° ÄÄÄ Ü ÄÄÄÄÄÄÄ ° ÄÄÄÄÄÄÄÄÄÄÄÄ¿'); writeln('þßÛÛ²ßÛÛÛ²ßÛÛ²ßÛÛ²Ü Ü²Û² ß²ÛÛ²ßÛÛÛ²ß ³'); writeln('³ ß° ÛÛÛ² Û° ÛÛÛß²Ü ÛÛÛ² ÛÛÛ² ÛÛÛ² ³'); writeln('³ °ÛÛÛ² °ÛÛÛ ÛÛÛÛÛ² °ÛÛÛ² ÛÛÛ² ³'); writeln('³ ܲÛÛÛ²Ü Ü²ÛÛÛ²Ü ß²Û۲ܲÛÛ۲ܲÛÛ²Ü ³'); writeln('ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ßß² ÄÄÄÄÄÄÄÄÄÄÄÄÙ'); writeln('Key Generator for FXEdit v2.8'); writeln('Written by MisterE (7th July 1998)'); writeln('') ; write('What is your name? ') ; readln(name) ; (* get name *) write('Company name? ') ; readln(company_name) ; (* get comapny name *) length_name := length(name) ; (* get length of name *) length_company_name := length(company_name) ; (* get length of company name *) if (length_name > 25) or (length_company_name > 26) then goto bad_boy ; counter2 := 1 ; for counter := length_name to 2*length_name do (* calculate serial for name *) begin ebx := ord(table1[counter]) * ord(name[counter2]) ; ebx := ebx * ord(table2[counter2]) ; ebx := ebx * counter2 ; counter2 := counter2 + 1 ; edi := edi + ebx ; end ; counter2 := 1 ; ebx := 0 ; for counter := length_company_name to 2*length_company_name do (* calculate serial for *) begin (* company name*) ebx := ord(table1[counter]) * ord(company_name[counter2]) ; ebx := ebx * ord(table2[counter2]) ; ebx := ebx * counter2 ; counter2 := counter2 + 1 ; esi := esi + ebx ; end ; edi := edi + esi ; (* add company s/n and name s/n *) if edi > 19222529 then writeln('the sn is: ', (edi - 19222529)) ; (* print the stuff *) if edi < 19222529 then writeln('the serial is: 4', (edi + 275744767)) ; bad_boy: if (length_name > 25) or (length_company_name > 26) then writeln('(Company)Name must be shorter than 26 char!!') ; readkey ; end . .-----------------------------------------------------------------------------------------------. `-----------------------------------------------------------------------------------------------' 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 | `-----------------------------------------------------------------------------------------------' Well, can rather be short with this: Greetz go to: everyone on #cracking4newbies - #tno - #inside98 .-----------------------------------------------------------------------------------------------. `-----------------------------------------------------------------------------------------------'successful unlock!