New 2 Cracking
~~~~~~~~~~~~~~

Tutorial Type  : Tutorial
Tutorial Topic : Keygenme #2 by ParaBytes
Written by     : ParaBytes
Date           : Mar. 24th, 2002.
Utilities      : W32Dasm/Debugger/Compiler to build the keygen
Music          : Bob Marley, Exodus or Natural Mystic (Alboms of course)
Remarks        : Could it be, no remarks ?!?!? :)



"Let's rave!" (tKC)

Open the keygenme, insert serial, name (ParaBytes/31337)
check, "Bad Data..."
ok...
lets start on the w32dasm, check on SDR for Bad Data...

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040129C(C), :004012B6(C), :004012CC(C), :004012D6(C), :004012DA(C)
|:00401306(C), :00401318(C)
|
:00401332 6A00                    push 00000000

* Possible StringData Ref from Data Obj ->"KeyGenMe #2 New2Cracking"
                                  |
:00401334 6800304000              push 00403000

* Possible StringData Ref from Data Obj ->"Bad Data.."
                                  |
:00401339 6862304000              push 00403062
:0040133E FF7508                  push [ebp+08]

* Reference To: USER32.MessageBoxA, Ord:01BBh
                                  |
:00401341 E892020000              Call 004015D8

ok, so we know that 7 jumps, all conditionals, will send you to that place...
so, lets review the code, check the imports functions,
search for USER32.GetWindowTextA or USER32.GetDlgItemTextA so we will know where
the code is reading the data from the text boxes...

found GetWindowTextA, 3 times, one for Name, one for Serial and one is the import address

so how we know what is what ?
easy !
the import address is a jmp to address memory
and if you notice, the text area's have strings, so maybe the data readed from the text boxes
is getting into these strings places ??

well, lets see :

:00401288 6A21                    push 00000021

* Possible StringData Ref from Data Obj ->"Name Here... "
                                  |
:0040128A 686D304000              push 0040306D
:0040128F FF35B8304000            push dword ptr [004030B8]

* Reference To: USER32.GetWindowTextA, Ord:015Bh
                                  |
:00401295 E826030000              Call 004015C0                 <--- get name, take 32 chars
:0040129A 84C0                    test al, al                   <--- name lenght = 0 ?
:0040129C 0F8490000000            je 00401332                   <--- if yes, go to bad boy
:004012A2 6A09                    push 00000009

* Possible StringData Ref from Data Obj ->"Serial Here... "
                                  |
:004012A4 6897304000              push 00403097                 --Same addresses------------\
:004012A9 FF35BC304000            push dword ptr [004030BC]                                 |
                                                                                            |
* Reference To: USER32.GetWindowTextA, Ord:015Bh                                            |
                                  |                                                         |
:004012AF E80C030000              Call 004015C0                 <--- get serial, 8 chars    |
:004012B4 84C0                    test al, al                   <--- serial lenght =0 ?     |
:004012B6 747A                    je 00401332                   <--- if yes, go to bad boy \|/
:004012B8 8D3597304000            lea esi, dword ptr [00403097] <--- that put serial address on esi
:004012BE 50                      push eax                      <--- that serial length
:004012BF 56                      push esi                      <--- that serial

* Reference To: USER32.CharUpperBuffA, Ord:002Fh
                                  |
:004012C0 E8D7020000              Call 0040159C                 <--- serial is UPCASED

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004012D2(U), :004012DC(U)
|
:004012C5 AC                      lodsb                         <--- put the letter from serial to al

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040125F(C)
|
:004012C6 84C0                    test al, al                   <--- al = 0 ? (end of string)
:004012C8 7414                    je 004012DE                   <--- yes ? exit the loop.
:004012CA 3C30                    cmp al, 30                    <--- is it '0' ?
:004012CC 7C64                    jl 00401332                   <--- if the code is less, go to bad boy
:004012CE 3C39                    cmp al, 39                    <--- is it '9' ?
:004012D0 7F02                    jg 004012D4                   <--- if code more, goto other check
:004012D2 EBF1                    jmp 004012C5                  <--- jmp to next char
                                                                                              /|\
* Referenced by a (U)nconditional or (C)onditional Jump at Address:                            |
|:004012D0(C)                                                                                  |
|                                                                                              |
:004012D4 3C41                    cmp al, 41                    <--- is it 'A' ? (all upcased) |
:004012D6 7C5A                    jl 00401332                   <--- if less, bad boy, cant be number
:004012D8 3C46                    cmp al, 46                    <--- if it 'F' ?
:004012DA 7F56                    jg 00401332                   <--- code is greater ? bad boy !
:004012DC EBE7                    jmp 004012C5                  <--- goto next char

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004012C8(C)
|
:004012DE 8D356D304000            lea esi, dword ptr [0040306D] <--- esi points to name
:004012E4 33D2                    xor edx, edx                  <--- edx = 0 (might be checksum init)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004012F8(U)
|
:004012E6 33C0                    xor eax, eax                  <--- clear eax
:004012E8 AC                      lodsb                         <--- move char code to al
:004012E9 84C0                    test al, al                   <--- al = 0 ? (end of string..)
:004012EB 740D                    je 004012FA                   <--- get out of loop
:004012ED 34FF                    xor al, FF                    <--- inverse the bits on the code
:004012EF F6D0                    not al                        <--- inverse again, cancel the Xor al,FF
:004012F1 03D0                    add edx, eax                  <--- add to checksum
:004012F3 C1C208                  rol edx, 08                   <--- rol a byte
:004012F6 D1EA                    shr edx, 1                    <--- div 2
:004012F8 EBEC                    jmp 004012E6                  <--- goto next char

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004012EB(C)
|

* Possible StringData Ref from Data Obj ->"Serial Here... "
                                  |
:004012FA 6897304000              push 00403097                 <--- push serial address
:004012FF E84F020000              call 00401553                 <--- somewhere, write the address..
:00401304 84C0                    test al, al                   <--- returned 0 ?
:00401306 742A                    je 00401332                   <--- if does, go bad boy !
:00401308 B916000000              mov ecx, 00000016             <--- mov ecx,16h - 22              
:0040130D D3C0                    rol eax, cl                   <--- we dono what in eax, rol..  <-<-<-\
:0040130F 33C2                    xor eax, edx                  <--- xor eax,edx                       |
:00401311 F7D0                    not eax                       <--- inverse bits on eax              /|\
:00401313 40                      inc eax                       <--- add one                           |
:00401314 E2F7                    loop 0040130D                 <--- loop until ecx=0 ->->->->->->->->-/
:00401316 33C2                    xor eax, edx                  <--- eax = edx
:00401318 7518                    jne 00401332                  <--- if not, go home..
:0040131A 6A00                    push 00000000

* Possible StringData Ref from Data Obj ->"KeyGenMe #2 New2Cracking"
                                  |
:0040131C 6800304000              push 00403000

* Possible StringData Ref from Data Obj ->"Good Serial !!!"
                                  |
:00401321 6852304000              push 00403052
:00401326 FF7508                  push [ebp+08]

* Reference To: USER32.MessageBoxA, Ord:01BBh
                                  |
:00401329 E8AA020000              Call 004015D8
:0040132E C9                      leave
:0040132F C21000                  ret 0010


ok, so its doing a checksum of the name, 
doing another thing with eax and the serial (call 00401553)
and checking with rol's and xor's

so, lets debug..
set breakpoint on offset 004012FF
insert name/serial (ParaBytes/12345678)
check, breaked ?
lets step over, if we still donno whats going there, we will run agani the check and trace in.
hmmmm, my eax now is 12354678
so it maybe taking the serial, which is hex string (now we know why to check for 1-9 and A-F)
and make it on eax !!
so the thing on eax is the serial we entered,
but what is on edx ??
and how we fish serial from that algo ?!?!!?

well, check 'lil above, on the name checksum..
edx is the checksum :)

so all we need is to reverse the algo, and build the keygen !

well, lets think...

to reverse it, we need to start from the end,
what SHOULD be on the end, 
eax SHOULD be equals to edx 
so,
make the checksum (nothing to reverse there, just copy-paste)
and do :

mov eax,edx

now, the check is rol'ing using cl, so we MUST reverse the loop, from 0 to 16h
so,

checksum code...
will put checksum of the name on edx

      mov eax,edx
      xor ecx,ecx
@calcserial:
      inc ecx         <--- loop is dec ecx, so we inc on start, and check if we passed the needed size
      cmp ecx,17h
      jz @endofcalc
      dec eax         <--- the last offset is inc eax, so we need to start with dec eax
      not eax         <--- not is self-reversing, like xor
      xor eax,edx     <--- (read the line above)
      ror eax,cl      <--- rol is left, we need to rotate eax RIGHT (opposite of LEFT), with cl
      jmp @calcserial <--- goto the start of calc process

now, after that, we have the serial in eax...
convert it to string, with wsprintf, or self routine (like i did)
and put it on screen (if console)
or in messagebox, or in edit control...

that all :)
we reversed the algorythem..

*** remember, every code line can be reversed ***
*** just learn what is the opposite of what.. ***

i hope you know 'lil more about advanced keygen creation :)

here, a serial i've generated with my keygen :

Name ::::: Keygnme #2 Tutorial 
Serial ::: 52FC39C1

that all folks...

Greets :
~~~~~~~~
death, tnx for finding bugs in my keygen (though i did the work alone :))
JNS, Batalram, tnx for giving me hex2dw routines and inspiring me to build my own :) 
               (if anyone wants them, tell me)
PhANt0m, tnx for teaching me algo reversing :)
Qwerton, PhoX, TheFoX, tKC, SantMat, Invoker, NCU, New2Cracking, FaNt0m, GogaMoga, hackwizz, Anvile,
sinny, Dawai, and more and more and more (sorry if i forgot you, i'm tired :P)

Contact me :
~~~~~~~~~~~~
E-Mail : Lewsers@Hotmail.com
IRC    : EFNet / #New2Cracking
Here ;p

Cya,

ParaBytes, The One And Only :)

------------------------------------
Adversiting :
~~~~~~~~~~~~~

if you can write GOOD tutorials
and code some basic languages 
(ASM - DELPHI - VC++ - NOT VB)
and want to join New2Cracking Team,
come to #New2Cracking on EFNet
and find ParaBytes.

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