[cRYPTO KEYGENME  v1.0 by bLaCk-eye ]
by Amenesia//tkm!

  It is packed with FSG (PEiD)... 

seg001:0041C306 loc_0_41C306: 
seg001:0041C306                 dec     byte ptr [esi]
seg001:0041C308                 jz      near ptr dword_0_401000
seg001:0041C30E                 push    esi

So we just have to replace the "jz OEP" by an infinte loop, then dump and rebuild the import table...



Looking for interesting API  ( GetDlgItemText, GetWindowTextA,... ) , we find:

seg000:00401B1B                 push    64h
seg000:00401B1D                 push    esi      ; Buffer <= Information entrée
seg000:00401B1E                 push    ebx
seg000:00401B1F                 GetWindowTextA
 

seg000:00401B05                 push    ebx             ; hWnd
seg000:00401B06                 call    GetWindowTextLengthA
seg000:00401B0B                 cmp     eax, 0Ah
seg000:00401B0E                 jbe     loc_0_401BF0

So the length of the KEy has to be >=  10...
 

seg000:00401B24                 xor     ebx, ebx
seg000:00401B26                 xchg    eax, ecx
seg000:00401B27                 lea     edi, [ebp+var_DC]
seg000:00401B2D 
seg000:00401B2D loc_0_401B2D: 
seg000:00401B2D                 movsx   eax, byte ptr [ebx+esi]
seg000:00401B31                 cmp     al, 23h                    ;  car == "#" ?
seg000:00401B33                 jz      short loc_0_401B3B
seg000:00401B35                 mov     [ebx+edi], al
seg000:00401B38                 inc     ebx
seg000:00401B39                 jmp     short loc_0_401B3D
seg000:00401B3B loc_0_401B3B: 
seg000:00401B3B                 jmp     short loc_0_401B3F
seg000:00401B3D loc_0_401B3D: 
seg000:00401B3D                 loop    loc_0_401B2D
seg000:00401B3F 

Here we can see, that the  KEy is composed of 2 parts separated by a "#". The first part is copied...
 
 

seg000:00401B3F loc_0_401B3F: 
seg000:00401B3F                 xor     al, al
seg000:00401B41                 mov     [ebx+edi], al
seg000:00401B44                 mov     [ebp+var_E0], ebx
seg000:00401B4A                 push    offset dword_0_4042C8
seg000:00401B4F                 push    ebx                    ; 1st part length
seg000:00401B50                 push    edi                    ; 1st part
seg000:00401B51                 call    MD5

Then, the 1st part is 'hashed' using a modified-MD5 ( just rip it :) )
 

seg000:00401B56                 mov     eax, ds:dword_0_4042C8
seg000:00401B5B                 xor     eax, ds:dword_0_4042D4
seg000:00401B61                 and     eax, ds:dword_0_4042CC
seg000:00401B67                 imul    eax, ds:dword_0_4042D0
seg000:00401B6E                 mov     [ebp+var_E4], eax

Then the 160 bits result is used to create a new number:
K = ( ( hash[0] xor hash[3] ) and hash[1] ) * hash[2]
 

seg000:00401B74                 lea     ebx, ds:4042B8h
seg000:00401B7A                 mov     edx, [ebx+8]
seg000:00401B7D                 push    edx
seg000:00401B7E                 push    eax             ; key
seg000:00401B7F                 call    bigCreat

Input a big-number (Big1) from K.  ( It seems to be roy's biglib... ) 
 

seg000:00401B84                 mov     edi, esi
seg000:00401B86                 add     edi, [ebp+var_E0]
seg000:00401B8C                 inc     edi
seg000:00401B8D                 mov     edx, [ebx+0Ch]
seg000:00401B90                 push    edx             ;  Big
seg000:00401B91                 push    10h             ; base
seg000:00401B93                 push    edi             ; 2nd part
seg000:00401B94                 call    bigIn

Input a big-number ( Big2 ) from the second part of the KEy (base 16).

seg000:00401B99                 push    dword ptr [ebx+0Ch] ; > BigR
seg000:00401B9C                 push    dword ptr [ebx]     ; < DB10266AB0FD5B
seg000:00401B9E                 push    dword ptr [ebx+0Ch] ; < Big2
seg000:00401BA1                 push    dword ptr [ebx+4]   ; < CC3183A81DF91
seg000:00401BA4                 call    bigPowMod

It's quite easy to recognize bigPowMod ( comparing code with roy's biglib src )
So: BigR = CC3183A81DF91^Big2 mod DB10266AB0FD5B

seg000:00401BA9                 push    dword ptr [ebx+0Ch] ; < BigR
seg000:00401BAC                 push    dword ptr [ebx+8]   ; < Big1
seg000:00401BAF                 call    bigCmp
seg000:00401BB4                 or      eax, eax
seg000:00401BB6                 jnz     NOTREGISTRED

In other words, the serial is valid if  Big1 == CC3183A81DF91^Big2 mod DB10266AB0FD5B
We can't reverse the hash-part so to find a valid serail we have to solve the discret logarithm problem

The order of the generated group is DB10266AB0FD5A = 2*9D*9C7*1244426C27... so we can use Pohlig-Hellman algorithm (  Pollard rho algorithm takes 15min ) to find quickly the solution. ( read  "Handbook of Applied Cryptography" )



Key Amenesia//tkm!#779EE69AD541C3