cum sa creezi un generator de coduri

12
Difficulty: Medium Learn how to create a keygen for mIRC v5.7 Creator: m101 The basic purpose of this tutorial is to teach you how to find an algorithm in assembly, and create a keygen to create working keys for it. The target of this tutorial is mIRC 5.7. I have chosen this program for its simplicity in key creation. For this tutorial you require Win32DASM at a minimum, and for extra verification, softice. First open up mIRC and try to register it. "Sorry, your registration name and number don't match blah blah blah". Kill mIRC and open up Win32DASM and decompile mirc32.exe. Open up the dead listing in Refs > String Data References and go through till you find the message you got from a failed registration. Double click it and you will find yourself in the following code: :00498B79 6A00 push 00000000 * Possible Reference to String Resource ID=01912: "mIRC Registration!" | :00498B7B 6878070000 push 00000778 :00498B80 E8F365F8FF call 0041F178 :00498B85 50 push eax :00498B86 6A00 push 00000000 * Possible Reference to String Resource ID=01913: "Sorry, your registration name and number don't match! Pleas" | :00498B88 6879070000 push 00000779 :00498B8D E8E665F8FF call 0041F178 :00498B92 50 push eax :00498B93 8B4508 mov eax, dword ptr [ebp+08] :00498B96 50 push eax

Upload: bonykeysey

Post on 16-Apr-2017

219 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: Cum Sa Creezi Un Generator de Coduri

Difficulty: MediumLearn how to create a keygen for mIRC v5.7Creator: m101

The basic purpose of this tutorial is to teach you how to find an algorithm in assembly, and create a keygen to create working keys for it. The target of this tutorial is mIRC 5.7. I have chosen this program for its simplicity in key creation. For this tutorial you require Win32DASM at a minimum, and for extra verification, softice.

First open up mIRC and try to register it. "Sorry, your registration name and number don't match blah blah blah". Kill mIRC and open up Win32DASM and decompile mirc32.exe. Open up the dead listing in Refs > String Data References and go through till you find the message you got from a failed registration. Double click it and you will find yourself in the following code::00498B79 6A00 push 00000000

* Possible Reference to String Resource ID=01912: "mIRC Registration!" |:00498B7B 6878070000 push 00000778:00498B80 E8F365F8FF call 0041F178:00498B85 50 push eax:00498B86 6A00 push 00000000

* Possible Reference to String Resource ID=01913: "Sorry, your registration name and number don't match! Pleas" |:00498B88 6879070000 push 00000779:00498B8D E8E665F8FF call 0041F178:00498B92 50 push eax:00498B93 8B4508 mov eax, dword ptr [ebp+08]:00498B96 50 push eax

Trace this back to its call at the following code::00498A8A 52 push edx

* Reference To: USER32.SendDlgItemMessageA, Ord:0000h |:00498A8B E841800500 Call 004F0AD1:00498A90 68334A5000 push 00504A33:00498A95 684C465000 push 0050464C:00498A9A E8E5FBFFFF call 00498684:00498A9F 85C0 test eax, eax:00498AA1 0F849B000000 je 00498B42:00498AA7 BE3C9D4F00 mov esi, 004F9D3C

Page 2: Cum Sa Creezi Un Generator de Coduri

:00498AAC BF4C465000 mov edi, 0050464C

Notice the SendDlgItemMessageA? Well if you open up softice, you can set a breakpoint on it and you will find yourself at this code after the second call. To make this all really easy for you, you should comment the code, but because you are probably really slack, ive done it for you::00498A90 68334A5000 push 00504A33 <serial:00498A95 684C465000 push 0050464C <username:00498A9A E8E5FBFFFF call 00498684 <username and serial operations:00498A9F 85C0 test eax, eax <test eax:00498AA1 0F849B000000 je 00498B42 <bad cracker if eax=1:00498AA7 BE3C9D4F00 mov esi, 004F9D3C

As you can see, the username and serial are pushed then a call is made to some operations on the pushed values. The result must result in eax being 0 or the routine will fail and we will get an 'unregistered' result. At this point you could patch the code to trick mIRC into being registered, but only until you restard, which ofcourse is totally useless to us. Follow the code through the call and you will get this:* Referenced by a CALL at Addresses:|:004987DF , :004988B2 , :00498A9A |:00498684 55 push ebp:00498685 8BEC mov ebp, esp:00498687 53 push ebx

*CUT*

:004986D6 83E103 and ecx, 00000003:004986D9 F3 repz:004986DA A4 movsb:004986DB 5E pop esi <serial:004986DC 68204A5100 push 00514A20 <serial:004986E1 6820495100 push 00514920 <username:004986E6 E8A1FEFFFF call 0049858C <must return eax=1 <<<first check!!!:004986EB 85C0 test eax, eax:004986ED 7407 je 004986F6 <eax must be true to perform second check!!!:004986EF B801000000 mov eax, 00000001 <bad cracker:004986F4 EB74 jmp 0049876A

Well as you can see, our serial is pushed, and if the result is wrong the serial will fail. So lets check out the the call there and see what it does for us:

Page 3: Cum Sa Creezi Un Generator de Coduri

:0049858C 55 push ebp:0049858D 8BEC mov ebp, esp:0049858F 83C4F4 add esp, FFFFFFF4:00498592 53 push ebx:00498593 56 push esi:00498594 57 push edi:00498595 8B750C mov esi, dword ptr [ebp+0C]:00498598 8B4508 mov eax, dword ptr [ebp+08]:0049859B 50 push eax:0049859C E8778DF6FF call 00401318 <strlen on username:004985A1 59 pop ecx:004985A2 83F805 cmp eax, 00000005 <is username = 5?:004985A5 7307 jnb 004985AE <if equal or larger jump to good cracker:004985A7 33C0 xor eax, eax

<bad cracker:004985A9 E9CA000000 jmp 00498678Very interesting, as you can see, it performs a strlen operation on the username and returns its length. If the username isnt atleast five characters then the the function returns false and we get an 'unregistered' message. If you follow the 'bad cracker' jump then you get the following code:* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:0049866D(C)|:00498673 B801000000 mov eax, 00000001 <good cracker

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:|:004985A9(U), :004985C1(U), :004985DE(U), :00498631(U), :00498671(U)<all bad crackers|:00498678 5F pop edi:00498679 5E pop esi:0049867A 5B pop ebx:0049867B 8BE5 mov esp, ebp:0049867D 5D pop ebp:0049867E C20800 ret 0008

Now this is interesting to us, check out all those unconditional jumps. All of them return bad cracker apart from the one call. The next peice of code basically checks for the split in the serial:* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:004985A5(C)|:004985AE 6A2D push 0000002D <check for "-" in serial:004985B0 56 push esi <serial:004985B1 E8C28CF6FF call 00401278:004985B6 83C408 add esp, 00000008

Page 4: Cum Sa Creezi Un Generator de Coduri

:004985B9 8BD8 mov ebx, eax:004985BB 85DB test ebx, ebx:004985BD 7507 jne 004985C6:004985BF 33C0 xor eax, eax

<bad cracker:004985C1 E9B2000000 jmp 00498678

See that 2D? It refers to "-". This is one thing you must remember, its all over most protections. Follow the code through and you will get this:* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:004985BD(C)|:004985C6 C60300 mov byte ptr [ebx], 00 <remove the "-" from the string:004985C9 56 push esi:004985CA E84514F7FF call 00409A14 <check for "-" problems in string and generate checksums:004985CF 59 pop ecx:004985D0 8945FC mov dword ptr [ebp-04], eax:004985D3 C6032D mov byte ptr [ebx], 2D:004985D6 43 inc ebx:004985D7 803B00 cmp byte ptr [ebx], 00:004985DA 7507 jne 004985E3

<good cracker:004985DC 33C0 xor eax, eax

<bad cracker:004985DE E995000000 jmp 00498678

This should all be pretty self explanitory to you, so just keep following the code:* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:004985DA(C)|:004985E3 53 push ebx:004985E4 E82B14F7FF call 00409A14:004985E9 59 pop ecx:004985EA 8945F8 mov dword ptr [ebp-08], eax:004985ED 8B5508 mov edx, dword ptr [ebp+08]:004985F0 52 push edx:004985F1 E8228DF6FF call 00401318

<username length:004985F6 59 pop ecx

<username:004985F7 8945F4 mov dword ptr [ebp-0C], eax:004985FA 33C0 xor eax, eax

<eax = 0:004985FC 33DB xor ebx, ebx

<ebx = 0:004985FE BA03000000 mov edx, 00000003:00498603 8B4D08 mov ecx, dword ptr [ebp+08]<ecx = username:00498606 83C103 add ecx, 00000003

<set pointer to 4th character

Page 5: Cum Sa Creezi Un Generator de Coduri

:00498609 3B55F4 cmp edx, dword ptr [ebp-0C]:0049860C 7D1C jge 0049862ANow we are into the point where the real serial is created. As you can see more string lengths are called and it leads onto the main key creation code:* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:00498628(C)|:0049860E 0FB631 movzx esi, byte ptr [ecx]

<set esi to the 4th byte of username:00498611 0FAF34859C9C4F00 imul esi, dword ptr [4*eax+004F9C9C]

<multiply byte by table value:00498619 03DE add ebx, esi

<ebx = ebx + (byte * table_value):0049861B 40 inc eax<next byte of table:0049861C 83F826 cmp eax, 00000026<26 characters of table read read?:0049861F 7E02 jle 00498623

<if not, then continue:00498621 33C0 xor eax, eax

<else set counter to 0

* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:0049861F(C)|:00498623 42 inc edx

<edx = edx + 1:00498624 41 inc ecx

<next character of username:00498625 3B55F4 cmp edx, dword ptr [ebp-0C]<end of username?:00498628 7CE4 jl 0049860E <if more then loop

* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:0049860C(C)|:0049862A 3B5DFC cmp ebx, dword ptr [ebp-04]

<compare result with serial:0049862D 7404 je 00498633

<good cracker:0049862F 33C0 xor eax, eax<bad cracker:00498631 EB45 jmp 00498678Ok, so what the hell does this do? It generates the first half of the serial, something like '1234-XXXXXX'. The second half is generated next. Basically as you can see, it takes the fourth value of the username, multiplies it by a value from a table, then adds the result to ebx to create the serial, but ofcourse the serial is in hex so you will have to convert it for use. Each loop a new value is taken from the table and the next

Page 6: Cum Sa Creezi Un Generator de Coduri

character is taken to be processed. I bet your wondering about that table? Well its like an array of all the values, if you check it in softice, you will find the following values:0B 06 11 0C 0C 0E 05 0C 10 0A 0B 06 0E 0E 04 0B 06 0E 0E 04 0B 09 0C 0B 0A 08 0A 0A 10 08 04 06 0A 0C 10 08 0A 04 10 00

Only the first twenty six values are used. Next we have the creation of the second half of the serial:* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:0049862D(C)|:00498633 33C0 xor eax, eax

<reset eax:00498635 33DB xor ebx, ebx

<reset ebx:00498637 BA03000000 mov edx, 00000003:0049863C 8B4D08 mov ecx, dword ptr [ebp+08]<set ecx to username:0049863F 83C103 add ecx, 00000003

<move to 4th character:00498642 3B55F4 cmp edx, dword ptr [ebp-0C]:00498645 7D23 jge 0049866A

* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:00498668(C)|:00498647 0FB631 movzx esi, byte ptr [ecx]

<set esi to 4th byte:0049864A 0FB679FF movzx edi, byte ptr [ecx-01]<set edi to 3rd byte:0049864E 0FAFF7 imul esi, edi<esi = esi * edi:00498651 0FAF34859C9C4F00 imul esi, dword ptr [4*eax+004F9C9C]

<esi = esi * byte from table:00498659 03DE add ebx, esi

<ebx = ebx + esi:0049865B 40 inc eax<next byte in table:0049865C 83F826 cmp eax, 00000026<is table upto 26?:0049865F 7E02 jle 00498663

<no, then continue:00498661 33C0 xor eax, eax

<else set eax = 0

* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:0049865F(C)|:00498663 42 inc edx

<edx = edx+1:00498664 41 inc ecx

<next byte in character:00498665 3B55F4 cmp edx, dword ptr [ebp-0C]<end of username?

Page 7: Cum Sa Creezi Un Generator de Coduri

:00498668 7CDD jl 00498647<no, then loop

* Referenced by a (U)nconditional or (C)onditional Jump at Address:|:00498645(C)|:0049866A 3B5DF8 cmp ebx, dword ptr [ebp-08]<compare second half of serial:0049866D 7404 je 00498673

<good cracker:0049866F 33C0 xor eax, eax

<bad cracker:00498671 EB05 jmp 00498678Next the algorithm takes the third character, multiplies it by the fourth value and then multiplies the result by the values from the table. After that the fourth and fifth value are taken and so on until the checksum is entirely created. From now, i dont know if im just being lazy or not, but ive created the keygen entirely in assembly with debug to prove it can be done. To code a keygen, all you really have to do is translate the assembly code into another language. The following keygen is only able to do small five letter keys, and nothing that returns too higher a value, also the result still has to be converted into decimal.------------------------------------------------

debuga 100mov byte ptr [500],4e ;Nmov byte ptr [501],61 ;amov byte ptr [502],6d ;mmov byte ptr [503],65 ;emov byte ptr [504],3a ;:mov byte ptr [505],24 ;$mov ah,09 ;string modelea dx,[500] ;set string start [0500]int 21 ;print stringlea di,[5ff] ;set first input;loopstosb ;save inputxor ax,ax ;clear for loopint 16 ;input user to alcmp al,0d ;check for enterjnz 12a ;if enter loopmov al,24 ;set last char $stosb ;save $;setup table values at [0800]mov word ptr [800],0bmov word ptr [802],06mov word ptr [804],11mov word ptr [806],0c

Page 8: Cum Sa Creezi Un Generator de Coduri

mov word ptr [808],0cmov word ptr [80a],0emov word ptr [80c],05mov word ptr [80e],0cmov word ptr [810],10mov word ptr [812],0amov word ptr [814],0bmov word ptr [816],06mov word ptr [818],0emov word ptr [81a],0emov word ptr [81c],04mov word ptr [81e],0bmov word ptr [820],06mov word ptr [822],0emov word ptr [824],0emov word ptr [826],04mov word ptr [828],0bmov word ptr [82a],09mov word ptr [82c],0cmov word ptr [82e],0bmov word ptr [830],0amov word ptr [832],08mov word ptr [834],0amov word ptr [836],0amov word ptr [838],10mov word ptr [83a],08mov word ptr [83c],04mov word ptr [83e],06mov word ptr [840],0amov word ptr [842],0cmov word ptr [844],10mov word ptr [846],08mov word ptr [848],0amov word ptr [84a],04mov word ptr [84c],10mov word ptr [84e],00;continue with first checksumsub di,1 ;calculate user lengthmov word ptr [900],di ;place length in [0900]xor bx,bx ;clear bxxor cx,cx ;clear cxlea si,[603] ;set si to 3rd characterlea di,[800] ;set di to 1st value;loopxor ax,ax ;clear axlodsb ;load username from simov cx,ax ;set cx = input from sixor ax,ax ;clear axxchg di,si ;switch di and si valueslodsb ;load table from siinc si ;skip space in tablexchg si,di ;switch values backmul cx ;multiply char by tableadd bx, ax ;accumulate valuesmov dx,[900] ;set dx = user lengthcmp si,dx ;last character?jl 239 ;if so loop

Page 9: Cum Sa Creezi Un Generator de Coduri

push bx ;add 1st value to stackxor ax,ax ;clear axxor bx,bx ;clear bxxor cx,cx ;clear cxxor dx,dx ;clear dxxor si,si ;clear sixor di,di ;clear dilea si,[602] ;point si to 3rd charlea di,[800] ;point di to tablexor ax,ax ;clear ax;looplodsb ;load unername from simov cx,ax ;set cx = characterxor ax,ax ;clear axlodsb ;load next char from simov dx,ax ;set dx = next characterdec si ;si = si - 1xor ax,ax ;clear axxchg di,si ;switch di and silodsb ;load table from siinc si ;skip space in tablexchg si,di ;switch si and di backpush ax ;store value temporarilymov ax,cx ;set ax = charactermul dx ;multiply two charactersmov cx,ax ;set result to cxpop ax ;restore ax from stackmul cx ;multiply by table valueadd bx, ax ;accumulate valuesxor ax,ax ;clear axxor cx,cx ;clear cxmov dx,[900] ;set dx to user lengthdec dx ;dx = dx - 1cmp si,dx ;last character?jl 269 ;if so loopxor cx,cx ;clear cxxor dx,dx ;clear dxpop ax ;restore 1st checksumint 20 ;quit

g =100 298

------------------------------------------------

AX will contain the first half of the string, and BX the second half, convert them and you will be given something like '1234-56789'. Just to you you how easy it is to do it in other languages, here is the first checksum in C:------------------------------------------------

for (i=4;i<=strlen(username);i++){ j=(i-4)%26; value=value+username[i-1]*table_values[j];

Page 10: Cum Sa Creezi Un Generator de Coduri

}

------------------------------------------------

When you first create a keygen, it can be a real bitch to understand what the code is doing, and how to implement it. You however will find that after a few tries, you will get used to it and be able to create keygens without too much problems. Just remember to comment the code and you wont have much problems at all ;)