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

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

	 difficulty level : 4
	 tools used : softice
_________________________________________________________________________________________________
  tutorial

	 bpx getdlgitemtexta and getwindowtexta. it doesn' t work. bpx hmemcpy. it doesn' t work
either. bpx sendmessagea. it breaks. you see this :

00401197                 push    offset unk_4020F0
0040119C                 push    3Dh
0040119E                 push    0Dh
004011A0                 push    ds:dword_4020DC
004011A6                 call    j_SendMessageA
004011AB                 cmp     eax, 5
004011AE                 jl      loc_40139B
004011B4                 mov     [ebp+var_4], eax
004011B7                 push    offset unk_402170
004011BC                 push    3Dh
004011BE                 push    0Dh
004011C0                 push    ds:dword_4020E0
004011C6                 call    j_SendMessageA
004011CB                 cmp     eax, 5
004011CE                 jl      loc_4013B4
004011D4                 mov     [ebp+var_8], eax
004011D7                 push    offset unk_4021F0
004011DC                 push    32h
004011DE                 push    0Dh
004011E0                 push    ds:dword_4020E4
004011E6                 call    j_SendMessageA

	so name and company must be at least 5 characters long. then you see this :

004011EB                 mov     ds:word_402370, 0Ah
004011F4                 push    3
004011F6                 xor     edx, edx
004011F8                 imul    eax, 7B5h
004011FE                 pop     ebx
004011FF                 div     ebx
00401201                 lea     eax, [eax-66C2h]
00401207                 cmp     eax, 1
0040120A                 sbb     eax, eax
0040120C                 jz      loc_401382

	so (seriallen*07b5h)/3 must be 066cdh, so seriallen must be 028h (40d) characters long.
then we see this :

00401212                 mov     edi, offset unk_402372
00401217                 mov     esi, offset unk_4021F0
0040121C                 push    esi
0040121D                 call    j_CharUpperA

	so it converts our serial to upper case. then we see this :

00401225 loc_401225:                             ; CODE XREF: sub_401187+CDj
00401225                 lodsw
00401227                 and     ax, 7F7Fh
0040122B                 sub     ax, 3030h
0040122F                 cmp     al, 19h
00401231                 ja      loc_401382
00401237                 cmp     ah, 19h
0040123A                 ja      loc_401382
00401240                 movzx   ebx, ah
00401243                 movzx   eax, al
00401246                 mov     al, ds:byte_401258[eax]
0040124C                 or      al, ds:byte_401273[ebx]
00401252                 stosb
00401253                 dec     ecx
00401254                 jg      short loc_401225
00401256                 jmp     short loc_40128E

	so it converts our serial to hexadecimal. then we see this :

0040128E loc_40128E:                             ; CODE XREF: sub_401187+CFj
0040128E                 mov     edi, offset unk_402230
00401293                 xor     eax, eax
00401295                 push    5
00401297                 pop     ecx
00401298                 repe stosd
0040129A                 dec     eax
0040129B                 mov     esi, offset unk_4020F0
004012A0                 mov     edi, offset unk_402230
004012A5                 mov     ecx, [ebp+var_4]
004012A8                 xor     edx, edx
004012AA 
004012AA loc_4012AA:                             ; CODE XREF: sub_401187+159j
004012AA                 lodsb
004012AB                 xor     ah, al
004012AD                 imul    eax, 89177313h
004012B3                 and     eax, 55AA55AAh
004012B8                 imul    eax, 12299381h
004012BE                 xor     eax, 0AA55AA11h
004012C3                 imul    eax, 61h
004012C6                 xor     ah, al
004012C8                 or      eax, 10030118h
004012CD                 imul    eax, 988279h
004012D3                 rcl     eax, cl
004012D5                 xor     [edi+edx], eax
004012D8                 add     edx, 3
004012DB                 and     edx, 0Fh
004012DE                 inc     edx
004012DF                 dec     ecx
004012E0                 jg      short loc_4012AA
004012E2                 mov     esi, offset unk_402170
004012E7                 mov     edi, offset unk_402230
004012EC                 mov     ecx, [ebp+var_8]
004012EF                 xor     edx, edx
004012F1 
004012F1 loc_4012F1:                             ; CODE XREF: sub_401187+1A0j
004012F1                 lodsb
004012F2                 sub     ah, al
004012F4                 imul    eax, 89157313h
004012FA                 and     eax, 55AA55AAh
004012FF                 imul    eax, 12299387h
00401305                 or      eax, 0AA55AA11h
0040130A                 imul    eax, 61h
0040130D                 xor     eax, 10010114h
00401312                 imul    eax, 7918279h
00401318                 xor     ah, al
0040131A                 rcr     eax, cl
0040131C                 xor     [edi+edx], eax
0040131F                 add     edx, 3
00401322                 and     edx, 0Fh
00401325                 inc     edx
00401326                 dec     ecx
00401327                 jg      short loc_4012F1
00401329                 sub     eax, [edi+8]
0040132C                 imul    eax, 34814815h
00401332                 add     [edi+10h], eax
00401335                 shr     eax, 0Bh
00401338                 and     eax, 3
0040133B                 mov     [edi], al

	so it computes a hash of the name and company. then we see this :

0040133D                 push    offset unk_402270
00401342                 push    offset word_402370
00401347                 push    offset unk_402000
0040134C                 call    sub_4013CD
00401351                 push    5
00401353                 pop     ecx
00401354                 mov     esi, offset unk_402272
00401359                 mov     edi, offset unk_402230
0040135E 
0040135E loc_40135E:                             ; CODE XREF: sub_401187+1E0j
0040135E                 lodsd
0040135F                 xor     [edi], eax
00401361                 jnz     short loc_401382
00401363                 add     edi, 4
00401366                 dec     ecx
00401367                 jg      short loc_40135E
00401369                 push    0
0040136B                 push    offset aWellDone ; "Well done"
00401370                 push    offset aTheEnteredRegi ; "The entered Registration code is correc"...
00401375                 push    ds:dword_4020D8
0040137B                 call    j_MessageBoxA

	so it calls a procedure. the parameters pushed to the procedure are :

00402270: 0a00 a3e9eef4 4c8efdef 704895d6 4d9efa2c 8ef620fc
00402370: 0a00 serial
00402000: 0a00 d2e9bf9b 3d258e47 9d8cc23c 7a33e1f8 ebb3adb1

	then check if the hash is the same as the result. if yes, we are regged. so we look at
the proc. it allocates some space, then copy the numbers to this space. then we see this :

00401446                 push    [ebp+var_4]
00401449                 call    sub_4014E5
0040144E                 push    [ebp+var_8]
00401451                 call    sub_4014E5

	these procs copy the numbers in reverse order, like a bignum. then we see this :

00401456                 mov     esi, [ebp+var_8]
00401459                 mov     edi, [ebp+var_C]
0040145C                 movzx   ecx, word ptr [esi]
0040145F                 inc     ecx
00401460                 repe movsw
00401463                 push    10h
00401465                 pop     edi
00401466 
00401466 loc_401466:                             ; CODE XREF: sub_4013CD+B6j
00401466                 push    [ebp+var_C]
00401469                 push    [ebp+var_C]
0040146C                 call    sub_4019C0
00401471                 push    [ebp+var_C]
00401474                 push    [ebp+var_10]
00401477                 push    [ebp+var_4]
0040147A                 push    [ebp+var_C]
0040147D                 call    sub_401529
00401482                 dec     edi
00401483                 jg      short loc_401466

	i saw a source of rsa in asm that the egoiste made on his site, and we recognize bigsqr
and bigdiv. so it does 010h (16d) times :

			004019c0: bigsqr : serial=serial^2
			00401529: bigdiv : serial=serial mod (d2e9....)

	so serial=serial^65536 mod (d2e9....). then we see this :

00401485                 push    [ebp+var_C]
00401488                 push    [ebp+var_8]
0040148B                 push    [ebp+var_C]
0040148E                 call    sub_401B87
00401493                 push    [ebp+var_14]
00401496                 push    [ebp+var_10]
00401499                 push    [ebp+var_4]
0040149C                 push    [ebp+var_C]
0040149F                 call    sub_401529

	we recognize that 00401b87 is bigmul, so it multiplies again serial with the original
serial, then compute serial mod (d2e9....). so it computes serial^65537 mod (d2e9....). and this
must be the hash of the name and company. so we recognize the rsa encryption scheme :

n=0d2e9bf9b3d258e479d8cc23c7a33e1f8ebb3adb1h
d=65537

	and our serial is the encrypted hash. so we have to factorize p and find the encryption
key. we find :
n=0d49caa009dadb2128673h * 0fdf4549df6ace8640e4bh
e=0c6546e0c11acce2543dd1150c4ce7a05a4c8fa3dh
_________________________________________________________________________________________________
  final words

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

