Keygenning Roger Wilco MK id3

Requirements:
1: Softice
2:
Roger Wilco Mk id3
3: Windasm

 

Info...
Target:
Roger Wilco Mk id3
Author: ThrawN
Group : EViDENCE
Level : Medium

Note:
This tutorial will assume you have previous knowledge in keygenning and understanding important ASM functions.

Introduction:

Roger Wilco is a very popular app in the online gaming industry. Thus its a good target for us to analize. Note that this tutorial os more focused on explaining the algo rather than getting in deep with each part.

Music Listened whilst writing tutorial: Moonwalker by dee mark From Deep Trance Volume2 <- w00t and Alice Dejay - The lonely one


Getting Started:

Unfortunatly i had to choose windasm over ida for this app, as ida was misinterprating large bits of important code.
If you enter bullshit information as registration it will biatch at you. Make sure you enter a valid email as well and not a ramdom sequence of characters ;). Take note of the error message and backtrace it in windasm until you get to SendMessageA. It would be a good idea to set a breakpoint in sice on 00407188 and trace in sice from there.
Lets analize this code:
-----------
* Reference To: USER32.SendMessageA, Ord:0214h
|
:00407188 8B358C124100 mov esi, dword ptr [0041128C] <- SendMessageA is moved into esi.
:0040718E 8D8C2410020000 lea ecx, dword ptr [esp+00000210]
:00407195 51 push ecx
:00407196 6804010000 push 00000104
:0040719B 6A0D push 0000000D
:0040719D 52 push edx
:0040719E FFD6 call esi <- Call SendMessageA
:004071A0 8B0D986A4100 mov ecx, dword ptr [00416A98]
:004071A6 8D442408 lea eax, dword ptr [esp+08]
:004071AA 50 push eax
:004071AB 6804010000 push 00000104
:004071B0 6A0D push 0000000D
:004071B2 51 push ecx
:004071B3 FFD6 call esi <- Call SendMessageA
:004071B5 A19C6A4100 mov eax, dword ptr [00416A9C]
:004071BA 8D94240C010000 lea edx, dword ptr [esp+0000010C]
:004071C1 52 push edx
:004071C2 6804010000 push 00000104
:004071C7 6A0D push 0000000D
:004071C9 50 push eax
:004071CA FFD6 call esi <- Call SendMessageA
:004071CC 8D4C2408 lea ecx, dword ptr [esp+08]
:004071D0 85C9 test ecx, ecx
:004071D2 0F8465010000 je 0040733D <- Invalid email jump. This one applies if you did not enter one.
:004071D8 8D7C2408 lea edi, dword ptr [esp+08] <- Move our email into EDI
:004071DC 83C9FF or ecx, FFFFFFFF
:004071DF 33C0 xor eax, eax
:004071E1 F2 repnz <- some check, wont fail if you enter a valid email
:004071E2 AE scasb
:004071E3 F7D1 not ecx
:004071E5 49 dec ecx
:004071E6 0F8451010000 je 0040733D <- Bad email? jump if so:)

* Reference To: MSVCRT.strchr, Ord:02B7h
|
:004071EC 8B353C114100 mov esi, dword ptr [0041113C] <- Move strchr into esi, function used to check for valid email. STRCHR requires 2 paramters.
:004071F2 8D542408 lea edx, dword ptr [esp+08] <- Move our email in EDX
:004071F6 6A40 push 00000040 <- Push character '@' (040h)
:004071F8 52 push edx <- Push our email
:004071F9 FFD6 call esi <- Call STRCHR to check for a @ somewhere in email. Should return with position in EAX. Otherwise if it didnt find it it returns at the end of the email and is 00h.
:004071FB 83C408 add esp, 00000008 <- Important to prevent unbalanced stack (thanks noodlespa!)
:004071FE 85C0 test eax, eax <- Did we find a @?
:00407200 0F8437010000 je 0040733D <- If not then get fucken lost cracker!
:00407206 6A2E push 0000002E <- Push character '.' (02eh)
:00407208 8D44240C lea eax, dword ptr [esp+0C]
:0040720C 6A40 push 00000040 <- Push character '@' (040h)
:0040720E 50 push eax
:0040720F FFD6 call esi <- This will return with the @ position again BECAUSE when it searches for the '.', it makes sure its the . after the @ symbol and not one before:)
:00407211 83C408 add esp, 00000008
:00407214 50 push eax
:00407215 FFD6 call esi <- Will return with the . position in eax this time :)
:00407217 83C408 add esp, 00000008
:0040721A 85C0 test eax, eax <- was there a '.' found?
:0040721C 0F841B010000 je 0040733D <- Jump if no :)
:00407222 8D8C240C010000 lea ecx, dword ptr [esp+0000010C] <- Move our entered serial # into ECX
:00407229 85C9 test ecx, ecx <- Test ECX to see if we entered a serial
:0040722B 0F84E5000000 je 00407316 <- If we didnt then jump to bad serial msg.
:00407231 8DBC240C010000 lea edi, dword ptr [esp+0000010C] <- Move our fake serial into EDI
:00407238 83C9FF or ecx, FFFFFFFF <- Basicly ECX=FFFFFFFF so the search below searches that much :)
:0040723B 33C0 xor eax, eax <- Clean EAX up
:0040723D F2 repnz <- Begin count of characters in our serial
:0040723E AE scasb <- End count of characters in our serial
:0040723F F7D1 not ecx <- ECX contains length of serial+1
:00407241 49 dec ecx <- ECX now contains our TRUE length :)
:00407242 0F84CE000000 je 00407316 <- If 0 then Bad ASS jump :)
:00407248 8D7C2408 lea edi, dword ptr [esp+08] <- Move our email into EDI
:0040724C 83C9FF or ecx, FFFFFFFF <- Basicly ECX=FFFFFFFF so the search below searches that much :)
:0040724F F2 repnz <- Begin Count
:00407250 AE scasb <- End count
:00407251 F7D1 not ecx <- ECX contains the length of our email+1
:00407253 49 dec ecx <- True length of our email
:00407254 0F84BC000000 je 00407316 <- If 0 then bad ass jump again
:0040725A 8D542408 lea edx, dword ptr [esp+08] <- Move our email into EDX
:0040725E 53 push ebx <- EBX contains our email length
:0040725F 52 push edx
:00407260 E8FBFCFFFF call 00406F60 <- The ALL important main ALGO
:00407265 83C404 add esp, 00000004
:00407268 8BF0 mov esi, eax
--------------------
Lets take a moment to reflect.
In the code above you can see clearly the checks it does from your email and serial you entered. They are simple to understand. You must enter a email and serial, and the email must contain "@" & "."
I apologize for the shit layout, as i usaly use IDA for this kind of debugging :((
Lets trace into the all important function at 00406F60. Hang on cause this is long.
--------------------

* Referenced by a CALL at Addresses:
|:00403C42 , :00407260 <- 2 calls here cause its called at startup also to verify the code in registry
|
:00406F60 83EC34 sub esp, 00000034
:00406F63 B90B000000 mov ecx, 0000000B
:00406F68 53 push ebx
:00406F69 56 push esi
:00406F6A 57 push edi

* Possible StringData Ref from Data Obj ->"3H49ha8eC6gQ95427Eb3ZfG2R7r84c5DTBq2dX6FS3sA" <- Take note, IMPORTANT constant
|
:00406F6B BE3C564100 mov esi, 0041563C <- Move the constant into ESI
:00406F70 8D7C2410 lea edi, dword ptr [esp+10]
:00406F74 8B5C2444 mov ebx, dword ptr [esp+44] <- our email
:00406F78 F3 repz
:00406F79 A5 movsd <- The constant that was in esi will be in the address that WAS IN EDI before this line. Basicly a mov command
:00406F7A 85DB test ebx, ebx <- EBX contains our email
:00406F7C A4 movsb
:00406F7D 0F8406010000 je 00407089 <- Is email still in ebx? Should be so no jump
:00406F83 8BFB mov edi, ebx <- Mov our email into edi
:00406F85 83C9FF or ecx, FFFFFFFF <- ECX=FFFFFFFF
:00406F88 33C0 xor eax, eax
:00406F8A F2 repnz
:00406F8B AE scasb <- Scan for end of email
:00406F8C F7D1 not ecx <- Email length+1 is in ecx
:00406F8E 49 dec ecx <- REAL length of email is here :)
:00406F8F 0F84F4000000 je 00407089 <-Make sure everything went fine, otherwise check fails.
:00406F95 8D7C2410 lea edi, dword ptr [esp+10] <- Mov constant (string) into EDI
:00406F99 83C9FF or ecx, FFFFFFFF <- ECX=FFFFFFFF
:00406F9C F2 repnz
:00406F9D AE scasb <- Scan for end of constant
:00406F9E F7D1 not ecx <- Length of constant+1 in ecx
:00406FA0 49 dec ecx <- REAL lengh of constant in ecx
:00406FA1 55 push ebp <- Bout to fuck with a system register, lets back it up :)
:00406FA2 8BE9 mov ebp, ecx <- Store lengh of constant in EBP
:00406FA4 8BFB mov edi, ebx <- Move our email back into EDI
:00406FA6 83C9FF or ecx, FFFFFFFF <- Bleh this again :)
:00406FA9 896C2448 mov dword ptr [esp+48], ebp <- Store constant length
:00406FAD F2 repnz
:00406FAE AE scasb
:00406FAF F7D1 not ecx
:00406FB1 49 dec ecx
:00406FB2 BF8C684100 mov edi, 0041688C <- 41688c is a buffer the program uses to store serial.
:00406FB7 894C2410 mov dword ptr [esp+10], ecx
:00406FBB A28C684100 mov byte ptr [0041688C], al
:00406FC0 8D1429 lea edx, dword ptr [ecx+ebp]
:00406FC3 83C9FF or ecx, FFFFFFFF
:00406FC6 F2 repnz
:00406FC7 AE scasb
:00406FC8 F7D1 not ecx
:00406FCA 49 dec ecx
:00406FCB 3BCA cmp ecx, edx
:00406FCD 733F jnb 0040700E

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407008(C) <- This is a small function used to increase our email string :)
|
:00406FCF 8BFB mov edi, ebx <- Move out email into EDI
:00406FD1 83C9FF or ecx, FFFFFFFF
:00406FD4 33C0 xor eax, eax
:00406FD6 F2 repnz <- Dont get confused by the amount of times we see this hear. Its not important, as long as you understand whats going on.
:00406FD7 AE scasb <- Scan for end of email
:00406FD8 F7D1 not ecx <- email length+1 in ecx
:00406FDA 2BF9 sub edi, ecx <- EDI will once again contain our email
:00406FDC 8BF7 mov esi, edi <- Put email into ESI
:00406FDE 8BE9 mov ebp, ecx <- Put email length+1 into EBP
:00406FE0 BF8C684100 mov edi, 0041688C <- Dam buffer where to put our shit into
:00406FE5 83C9FF or ecx, FFFFFFFF
:00406FE8 F2 repnz
:00406FE9 AE scasb <- dont worry bout this one
:00406FEA 8BCD mov ecx, ebp
:00406FEC 4F dec edi
:00406FED C1E902 shr ecx, 02
:00406FF0 F3 repz
:00406FF1 A5 movsd <- This will mov out email into the buffer, basicly adding it to the end of the prevous mov (EG. after 2 loops buffer will like: thrawn@sexy.comthrawn@sexy.com. More so with more loops)
:00406FF2 8BCD mov ecx, ebp <- emaillength+1 INTO ECX again
:00406FF4 83E103 and ecx, 00000003
:00406FF7 F3 repz
:00406FF8 A4 movsb
:00406FF9 BF8C684100 mov edi, 0041688C <- Buffer
:00406FFE 83C9FF or ecx, FFFFFFFF
:00407001 F2 repnz
:00407002 AE scasb <- Another scan
:00407003 F7D1 not ecx
:00407005 49 dec ecx <- Remove one from the counter
:00407006 3BCA cmp ecx, edx <- Have we finished? if so EDX will be below ECX.
:00407008 72C5 jb 00406FCF <- loop
:0040700A 8B6C2448 mov ebp, dword ptr [esp+48] <- Mov into EBP the lengh of the constant

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00406FCD(C)
|
:0040700E BF8C684100 mov edi, 0041688C <- Mov into EDI our email shit thats been added together.
:00407013 83C9FF or ecx, FFFFFFFF
:00407016 33C0 xor eax, eax
:00407018 F2 repnz <- For the record lets call the email added shit email+
:00407019 AE scasb <- Scan for the end of email crap
:0040701A F7D1 not ecx <- length of email+(+1)
:0040701C 49 dec ecx <- Real length of email+
:0040701D 33FF xor edi, edi <- Clean up
:0040701F 85C9 test ecx, ecx <- Test the legnth, make sure everythign went fine
:00407021 7E0F jle 00407032 <- If fuckup, then jump

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407030(C)
|
:00407023 33D2 xor edx, edx
:00407025 8A908C684100 mov dl, byte ptr [eax+0041688C] <- Get character from email+
:0040702B 03FA add edi, edx <- basicly it adds everycharacter from email+ together.
:0040702D 40 inc eax <- How many we have done
:0040702E 3BC1 cmp eax, ecx <- Have we done as much as the length?
:00407030 7CF1 jl 00407023 <- If not then loop

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407021(C)
|
:00407032 33F6 xor esi, esi
:00407034 85C9 test ecx, ecx <- Another check to make sure everything is fine
:00407036 7E29 jle 00407061 <- We finished if this jumps, but we aint so we dont want it to ;)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040705F(C)
|
:00407038 8B542410 mov edx, dword ptr [esp+10] <- Move into EDX our email length
:0040703C 33C0 xor eax, eax
:0040703E 8A868C684100 mov al, byte ptr [esi+0041688C] <- Get character from email+ which is in 0041688C
:00407044 2BC6 sub eax, esi <- Subtract esi from eax(character)
:00407046 03C7 add eax, edi <- Add EDI to character. EDI is the calculation of every character added together
:00407048 8D8410BD0B0000 lea eax, dword ptr [eax+edx+00000BBD] <- Ahh mov into eax, eax+edx(email length)+BBD(seed)
:0040704F 99 cdq <- Do dword conversion or clear EDX, whichever you prefer
:00407050 F7FD idiv ebp <- Fix new var in EDX
:00407052 46 inc esi <- Counter +1
:00407053 3BF1 cmp esi, ecx <- Does our counter equal the same as the email+ length?
:00407055 8A441414 mov al, byte ptr [esp+edx+14] <- get character from the constant. ESP+14=constant so its constant+edx = char. Then mov it into AL
:00407059 88868B684100 mov byte ptr [esi+0041688B], al <- Mov char and overwrite starting from email+
:0040705F 7CD7 jl 00407038 <- Jump if not all chars done

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407036(C)
| <- So at this stage a conplete serial can be viewed in 41688C. A few more small things need to be touched up ;)
:00407061 B02D mov al, 2D <- Mov into AL the char "-"
:00407063 6A13 push 00000013
:00407065 688C684100 push 0041688C
:0040706A A290684100 mov byte ptr [00416890], al <- mov al over the 5th character in our real serial
:0040706F A295684100 mov byte ptr [00416895], al <- mov al over the 10th character in our real serial
:00407074 A29A684100 mov byte ptr [0041689A], al <- mov al over the 15th character in our real serial
:00407079 E822000000 call 004070A0
:0040707E 83C408 add esp, 00000008
:00407081 5D pop ebp
:00407082 5F pop edi
:00407083 5E pop esi
:00407084 5B pop ebx
:00407085 83C434 add esp, 00000034
:00407088 C3 ret
The FINAL REAL serial should only be 19 characters long.

--------------------
Hope you understood this. I suspect if your new to keygenning this would have made absolutly no sence to you. Sorry :(. Email me if something is unclear.
Now that iv explained the algo lets make a keygen. This time i will not be supplying sourcecode, as i did this keygen in my template - which i wont give the source out public just yet. But the algo function your more than welcome to have a look at.

------------- Keygen ------------------
.data shit
totallength dd 256 dup(0) ; Large enough buffer :)
totalmail dd 256 dup(0)
tempdump dd 256 dup(0)
elength dd 256 dup(0)
string1 dB '3H49ha8eC6gQ95427Eb3ZfG2R7r84c5DTBq2dX6FS3sA'


Algo proc hDlg: DWORD
pushad
xor ebx, ebx
xor eax, eax
xor ecx, ecx
xor esi, esi
invoke GetWindowText, hwndEdit, ADDR lpBuffer, 256
mov elength, eax
add eax, 44
mov totallength, eax ;(length of seed)
mov esi, offset lpBuffer
mov eax, totallength
xor edx, edx
start:
push offset lpBuffer
push offset tempdump
call lstrcat
add edx, dword ptr [elength]
cmp edx, totallength
jbe start
mov totalmail, edx
mov esi, edx
xor ebx, ebx
xor eax, eax
xor edi, edi
addd:
movsx eax, byte ptr [tempdump+ebx]
inc ebx
add edi, eax
dec esi
jne addd
mov ecx, elength
mov ebx, 44
arrg:
movsx eax, byte ptr [tempdump+esi]
sub eax, esi
add eax, edi
lea eax, [ecx+eax+3005]
cdq
idiv ebx
mov al, byte ptr [edx+string1]
mov byte ptr [tempdump+esi], al
inc esi
cmp esi, totalmail
jb arrg
mov al, 2dh
mov byte ptr [tempdump+4], al
mov byte ptr [tempdump+9], al
mov byte ptr [tempdump+14], al
xor al, al
mov byte ptr [tempdump+19], al
;int 3 ; Heh int3 rule for debugging your own apps :P

skip:

invoke SetWindowText,hwndEdit2, offset tempdump


mov edi,offset tempdump ; This crap here is just to clean the buffer.
mov ecx,256
sub eax,eax
rep stosd

popad
ret

Algo endp


------------- Compiled in masm ---------------------

If theres something you didnt understand, you can also compile the keygen and debug it. Watch what happens and how it takes place :)


Conclusion:

Hope you have fun keygenning this fine app. I sure did. If you have any questions or even comments about this tutorial please feel free to email me.


Any questions? Mail me: thrawnc@hotmail.com
Visit my Home Page

Greetings fly out to:

y0ke (Thanks for letting me use this template) , CLASS, EViDENCE, iNSTiNCT, DiSTiNCT, eMINENCE, R!SC, M_, MrFrost, SP33D, Seifer666, Warezpup, BuLLeT, Carpathia, [Froost], DVS, PhANt0m, MeTaL, b00m, BlackEvil, ChiLar163, SeL, Dogsmack, iNFiNiTY, Issvar, LadyWarez, Lag00rs, LordOfLA, Meyitzo, Mindphzer, MrJezus, n]-[va, NeTsurFer, NoodleSpa, OutCast3k, philius, Point-X, Punisher, redback, Shiva, Spacenett, stripper, sutek, tE!, The_Morph, TheScream, TheSilent, TheVirus, TiVe, zelkor.