
				  .@@  @@     .@@.   @@  @@   .@@
				 @@    @@    @@  @@  @@  @@  @@
				 @@    @@    @@  @@  @@  @@  @@
				 @@@@  @@    @@@@'   @@  @@  @@
				 @@    @@    @@      @@  @@  @@
				 @@    @@    @@      @@  @@  @@
				 **    **    **      **  **  **
				 	'   '     ''   

				    	f   l	e   u	r   
_________________________________________________________________________________________________
  informations - tmg official keygenme 3

	 difficulty level : 4
	 tools used : softice
_________________________________________________________________________________________________
  tutorial

	 enter a user name and registration code, bpx getdlgitemtexta and getwindowtexta. it
doesn' t work. bpx hmemcpy. it doesn' t work either. bpx senddlgitemmessagea. it breaks.

0040101E                 push    eax
0040101F                 push    41h
00401021                 push    0Dh
00401023                 push    3F1h
00401028                 push    edi
00401029                 call    esi ; SendDlgItemMessageA
0040102B                 cmp     eax, 5
0040102E                 mov     [esp+20Ch+var_1EC], eax
00401032                 jnb     short loc_401052
00401034                 push    10h
00401036                 push    offset aError   ; "Error"
0040103B                 push    offset aLengthOfUserna ; "Length of Username is invalid."
00401040                 push    edi
00401041                 call    ds:MessageBoxA

	so we have to enter at least 5 characters for the name. then we see this :

00401052 loc_401052:                             ; CODE XREF: sub_401000+32j
00401052                 lea     ecx, [esp+20Ch+var_1D8]
00401056                 push    ecx
00401057                 push    41h
00401059                 push    0Dh
0040105B                 push    3F2h
00401060                 push    edi
00401061                 call    esi ; SendDlgItemMessageA
00401063                 cmp     eax, 20h
00401066                 jz      short loc_401086
00401068                 push    10h
0040106A                 push    offset aError   ; "Error"
0040106F                 push    offset aLengthOfRegist ; "Length of Registration code is invalid."
00401074                 push    edi
00401075                 call    ds:MessageBoxA

	so the length of the registration code is 020h (32d). then we see this :

00401086 loc_401086:                             ; CODE XREF: sub_401000+66j
00401086                 xor     edx, edx
00401088 
00401088 loc_401088:                             ; CODE XREF: sub_401000+A7j
00401088                 mov     cl, [esp+edx+20Ch+var_1D8]
0040108C                 cmp     cl, 30h
0040108F                 jnb     short loc_401092
00401091                 dec     eax
00401092 
00401092 loc_401092:                             ; CODE XREF: sub_401000+8Fj
00401092                 cmp     cl, 46h
00401095                 jbe     short loc_401098
00401097                 dec     eax
00401098 
00401098 loc_401098:                             ; CODE XREF: sub_401000+95j
00401098                 cmp     cl, 39h
0040109B                 jbe     short loc_4010A3
0040109D                 cmp     cl, 41h
004010A0                 jnb     short loc_4010A3
004010A2                 dec     eax
004010A3 
004010A3 loc_4010A3:                             ; CODE XREF: sub_401000+9Bj
004010A3                                         ; sub_401000+A0j
004010A3                 inc     edx
004010A4                 cmp     edx, 20h
004010A7                 jb      short loc_401088
004010A9                 cmp     eax, 20h
004010AC                 jz      short loc_4010CC
004010AE                 push    10h
004010B0                 push    offset aBadLuck ; "Bad luck"
004010B5                 push    offset aWildGuessingWo ; "Wild guessing won't help you too much :"...
004010BA                 push    edi
004010BB                 call    ds:MessageBoxA

	so our serial can be only [0..9][A..F]. then we see this :

004010CC loc_4010CC:                             ; CODE XREF: sub_401000+ACj
004010CC                 mov     edx, [esp+20Ch+var_1C8]
004010D0                 mov     eax, [esp+20Ch+var_1C4]
004010D4                 mov     ecx, [esp+20Ch+var_1C0]
004010D8                 mov     [esp+20Ch+var_158], edx
004010DF                 mov     edx, [esp+20Ch+var_1BC]
004010E3                 push    0
004010E5                 mov     [esp+210h+var_154], eax
004010EC                 mov     [esp+210h+var_150], ecx
004010F3                 mov     [esp+210h+var_14C], edx
004010FA                 mov     [esp+210h+var_148], 0
00401102                 mov     byte ptr [esp+210h+var_1C8], 0

	so it separates the serial in two parts : the first 16 characters and the last ones. then
we see lot of calls that look like bignumbers initialization. the we see this :

0040116B                 mov     edi, eax
0040116D                 lea     eax, [esp+20Ch+var_D8]
00401174                 push    eax
00401175                 call    sub_401880
0040117A                 mov     ecx, [esp+210h+var_1EC]
0040117E                 add     esp, 4
00401181                 lea     edx, [esp+20Ch+var_80]
00401188                 lea     eax, [esp+20Ch+var_D8]
0040118F                 push    ecx
00401190                 push    edx
00401191                 push    eax
00401192                 call    sub_4018B0
00401197                 add     esp, 0Ch
0040119A                 lea     ecx, [esp+20Ch+var_D8]
004011A1                 lea     edx, [esp+20Ch+var_1E8]
004011A5                 push    ecx
004011A6                 push    edx
004011A7                 call    sub_401960

	this performs an md5 hash on the username. then wee see this :

004011AC                 mov     eax, dword_40CE08
004011B1                 add     esp, 8
004011B4                 lea     edx, [esp+20Ch+var_1E8]
004011B8                 mov     dword ptr [eax+22Ch], 100h
004011C2                 mov     ecx, dword_40CE08
004011C8                 push    edx
004011C9                 push    ebp
004011CA                 mov     dword ptr [ecx+23Ch], 10h
004011D4                 call    sub_404D60

	this puts the md5 hash in a bignum. we can assume that the mov dword ptr [eax+22Ch], 100h
means that the current conversion base is 0100h (256d). we can recognize the miracl library
(there are references in the exe). you better download it. then we see this :

004011D9                 mov     eax, dword_40CE08
004011DE                 add     esp, 8
004011E1                 push    offset a37a218f214c32d ; "37A218F214C32D79"
004011E6                 push    esi
004011E7                 mov     dword ptr [eax+22Ch], 10h
004011F1                 call    sub_404D60

	this puts 37A218F214C32D79 in a bignum. then we see this :

004011F6                 add     esp, 8
004011F9                 push    ebp
004011FA                 push    esi
004011FB                 push    3
004011FD                 push    ebp
004011FE                 call    sub_404BE0

	if you see the result, we can guess that this computes md5hash^3 mod (37A218F214C32D79).
if we take a look to the miracl.h file, we see this :

extern void  power(_MIPT_ big,long,big,big);

	it' s the only prototype that correspond to our function. in the documentation, we see
this :

power(x,n,z,w)
w=x^n mod z

	so it computes hashnum=md5hash^3 mod (37A218F214C32D79). then we see this :

00401206                 mov     edx, [esp+20Ch+var_1FC]
0040120A                 lea     ecx, [esp+20Ch+var_1D8]
0040120E                 push    ecx
0040120F                 push    edx
00401210                 call    sub_404D60
00401215                 mov     ecx, [esp+214h+var_1F0]
00401219                 add     esp, 8
0040121C                 lea     eax, [esp+20Ch+var_158]
00401223                 push    eax
00401224                 push    ecx
00401225                 call    sub_404D60

	this puts the two parts of our serial in two bignums. then we see this :

0040122A                 add     esp, 8
0040122D                 push    offset aC9d94f46d0984f ; "C9D94F46D0984F42"
00401232                 push    esi
00401233                 call    sub_404D60
00401238                 mov     edx, [esp+214h+var_1F8]
0040123C                 add     esp, 8
0040123F                 push    offset a91d4d6ef46b05c ; "91D4D6EF46B05C78"
00401244                 push    edx
00401245                 call    sub_404D60
0040124A                 mov     eax, [esp+214h+var_1F4]
0040124E                 add     esp, 8
00401251                 push    offset a4b45042b684bcb ; "4B45042B684BCBD1"
00401256                 push    eax
00401257                 call    sub_404D60

	so it puts some values in bignums. then we see this :

0040125F                 push    esi
00401260                 push    1
00401262                 push    esi
00401263                 call    sub_404AB0

	this adds 1 to C9D94F46D0984F42. then we see this :

00401268                 mov     ecx, [esp+218h+var_1F0]
0040126C                 mov     edx, [esp+218h+var_1FC]
00401270                 add     esp, 0Ch
00401273                 push    ebx
00401274                 push    esi
00401275                 push    ecx
00401276                 push    edx
00401277                 call    sub_404440

	so this function can be one of these :

extern void  powmod(_MIPT_ big,big,big,big);
extern void  nres_lucas(_MIPT_ big,big,big,big);

	we can guess that it is powmod. so if we look at the documentation we see this :

powmod(x,y,z,w)
w=x^y mod z

	so it computes result1=serial1^serial2 mod (C9D94F46D0984F43). then we see this :

0040127C                 mov     eax, [esp+21Ch+var_1FC]
00401280                 mov     ecx, [esp+21Ch+var_1F8]
00401284                 add     esp, 10h
00401287                 push    edi
00401288                 push    esi
00401289                 push    eax
0040128A                 push    ecx
0040128B                 call    sub_404440

	so it computes result2=91D4D6EF46B05C78^serial1 mod (C9D94F46D0984F43). then we see
this :

00401293                 push    edi
00401294                 push    esi
00401295                 push    esi
00401296                 push    edi
00401297                 push    edi
00401298                 push    ebx
00401299                 call    sub_404010

	so this is mad. we see this :

mad(x,y,z,w,q,r)
on exit q=(x.y+z)/w and r contains the remainder. if w and q are not distinct variables then only
the remainder is returned; if q and r are not distinct then only the quotient is returned. the
addition of z is not done if x and z (or y and z) are the same

	so it computes result3=result1*result2 mod (C9D94F46D0984F43). then we see this :

0040129E                 mov     edx, [esp+224h+var_1F4]
004012A2                 add     esp, 18h
004012A5                 push    ebx
004012A6                 push    esi
004012A7                 push    ebp
004012A8                 push    edx
004012A9                 call    sub_404440

	so it computes result4=4B45042B684BCBD1^hashnum mod (C9D94F46D0984F43). then we see
this :

004012AE                 add     esp, 10h
004012B1                 push    edi
004012B2                 push    ebx
004012B3                 call    sub_403170

	this is compare. so result4 and result3 must be the same for us to be regged. we
recognize the elgamal signature scheme, the message signed being hashnum :

public key :
p prime
g < p
y=g^x mod (p)

private key :
x < p

signature :
k (random, relatively prime to p-1)
a (signature) = g^k mod (p)
b (signature) so that M=(xa+kb) mod (p-1)

verification :
the signature is valid if (y^a)(a^b) mod (p) = g^M mod (p)

	so we have :

p=0C9D94F46D0984F43h
g=04B45042B684BCBD1h
y=091D4D6EF46B05C78h
a=serial1
b=serial2
M=md5hash^3 mod (037A218F214C32D79h)

	so we have to solve the discreet logarithm problem, that is, we have to find x such that
y=g^x mod (p). we find x=06C18DA28FDD8FEF1h, then we choose k=1 to simplify our work. then
serial1 is fixed (serial1=04B45042B684BCBD1h), then we only have to compute serial2=M-x*serial1
mod (p-1).
_________________________________________________________________________________________________
  final words

	 it was a nice keygenme with cryptography.
_________________________________________________________________________________________________
  roy|fleur

