Outils utilisés : | WinDbg v6.1 (ou n'importe quel autre debugger) Damn Hash Calculator v1.51 WinHex v10.9 |
1. Premières
analyses
2. Recherche de la routine
de calcul du serial
3. Réalisation du keygen
4. Salutations
00401000 6800304000 push
0x403000 00401005 e84c050000 call image00400000+0x1556 (00401556) ; dexor les chaines 0040100a 684f104000 push 0x40104f 0040100f 64ff3500000000 push dword ptr fs:[00000000] 00401016 64892500000000 mov fs:[00000000],esp 0040101d bd00484342 mov ebp,0x42434800 ;BCHK 00401022 66b80400 mov ax,0x4 00401026 cc int 3 00401027 6a00 push 0x0 |
1) on remarque que toutes les chaines sont chiffrées.
2) la protection antidebugger utilisé est la méthode BCHK
On continue en traçant:
00401029 682f314000 push
0x40312f 0040102e 6812314000 push 0x403112 00401033 6a00 push 0x0 00401035 e88c0e0000 call image00400000+0x1ec6 (00401ec6) ;MessageBoxA 0040103a 648f0500000000 pop fs:[00000000] 00401041 83c404 add esp,0x4 00401044 53 push ebx 00401045 bbf61e4000 mov ebx,0x401ef6 0040104a 6a00 push 0x0 0040104c ffd3 call ebx ; ExitProcess 0040104e 5b pop ebx 0040104f c705a5314000a21e4000 mov dword ptr [image00400000+0x31a5 (004031a5)],0x401ea2 |
00401476 e8330a0000 call
image00400000+0x1eae (00401eae) ; GetWindowTextA 0040147b 83f806 cmp eax,0x6 0040147e 0f86b4000000 jbe image00400000+0x1538 (00401538) ; si serial <= 6 on part 00401484 6878324000 push 0x403278 ; pointeur 00401489 50 push eax ; longueur de username 0040148a 68b1314000 push 0x4031b1 ; pointeur 0040148f e8e6000000 call image00400000+0x157a (0040157a) ; hash |
004015ce c70601234567 mov dword ptr
[esi],0x67452301 ; sha1,md5,ripemd? 004015d4 c7460489abcdef mov dword ptr [esi+0x4],0xefcdab89 004015db c74608fedcba98 mov dword ptr [esi+0x8],0x98badcfe 004015e2 c7460c76543210 mov dword ptr [esi+0xc],0x10325476 |
On voit tout de suite l'initialisation d'un hash sha1, md5 ou ripemd donc on avance assez loin jusqu'à 00401db4 après le loop.
00401db4 8b7510 mov esi,[ebp+0x10] ss:0023:0012fd0c=00403278
; hash 00401dba ff7608 push dword ptr [esi+0x8] ; formatage 00401dbd ff7604 push dword ptr [esi+0x4] ; .... 00401dc0 ff36 push dword ptr [esi] ; .... 00401dc2 6865324000 push 0x403265 00401dc7 ff7508 push dword ptr [ebp+0x8] 00401dca e8bb000000 call image00400000+0x1e8a (00401e8a) ; wsprintf |
Le hash va être convertit en hexadécimal grâce à
wsprintf.
On sort du call et on affiche le contenu de l'adresse 0x4031b1
qui était en paramêtre tout à l'heure :
004031b1 61 63
35 32 35 62 32 36-36 39 36 35 35 61 32 37 ac525b2669655a27 004031c1 37 36 32 65 63 33 37 63-61 66 33 64 66 37 39 66 762ec37caf3df79f 004031d1 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 004031e1 00 00 00 00 00 00 00 00-38 00 00 00 00 00 00 00 ........8....... 004031f1 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 00403201 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 00403211 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 00403221 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ |
SHA-160
: 20272A9CC15821ECA19C9519DF159B712837E200 SHA-256 : E82E2A82C17801C83B60C1F180B7592BABF0D3DA55D1F12AEF250FE1E6211834 SHA-384 : 5E093AE8FEE836257B21D991A99B0DF6CDEC962ED6530E298ED1A3D8D25159EE1FEA334A1D.... MD5 : AC525B2669655A27762EC37CAF3DF79F RIPEMD-160 : 9036960028D8E3B89306A2E017211AEC3C53D7BC |
Nous avons donc affaire à du md5.
note : ripemd-128 n'est apparement pas implémenté
dans damn hash calculator.
Continuons :
00401494 33c0 xor eax,eax 00401496 33c9 xor ecx,ecx 00401498 33d2 xor edx,edx 0040149a 8a81b1314000 mov al,[ecx+0x4031b1] ; prend le caractère courrant du hash 004014a0 83f839 cmp eax,0x39 004014a3 7607 jbe image00400000+0x14ac (004014ac) ; si <= 0x39 on ne retiens pas ce caractère 004014a5 8882ed314000 mov [edx+0x4031ed],al ; place le caractère courrant dans 0x4031ed 004014ab 42 inc edx 004014ac 41 inc ecx 004014ad 80b9b131400000 cmp byte ptr [ecx+0x4031b1],0x0 004014b4 75e4 jnz image00400000+0x149a (0040149a) |
Après cette routine on déduit que du hash il ne restera que
les caractères dont les valeurs ascii sont supérieurs à
0x39, pour moi : acbaeccafdff (on appellera ça hash_s).
Ensuite le programme fait un deuxième GetWindowTextA pour récupèrer
notre serial et on voit ceci :
004014c9 68ed314000 push 0x4031ed 004014ce e8350a0000 call image00400000+0x1f08 (00401f08) ; lstrlen 004014d3 5b pop ebx 004014d4 3bd8 cmp ebx,eax 004014d6 7560 jnz image00400000+0x1538 (00401538) ; si hash_s est != longueur serial on part |
Je n'ai entré que 9 char au lieu de 12, je retape mon serial en entrant 12 fois le caractère 9 et je reviens à l'étape ou nous sommes.
004014da
33c9 xor ecx,ecx 004014dc 8a8129324000 mov al,[ecx+0x403229] ; caractère courant du serial dans al 004014e2 3c30 cmp al,0x30 004014e4 7c52 jl image00400000+0x1538 (00401538) ; < 0x30 on part 004014e6 3c39 cmp al,0x39 004014e8 7f4e jg image00400000+0x1538 (00401538) ; > 0x39 on part 004014ea 41 inc ecx 004014eb 80b92932400000 cmp byte ptr [ecx+0x403229],0x0 004014f2 75e8 jnz image00400000+0x14dc (004014dc) |
004014f4 33c0 xor eax,eax 004014f6 b930000000 mov ecx,0x30 ; ecx=0x30 004014fb 33db xor ebx,ebx 004014fd 8a8329324000 mov al,[ebx+0x403229] ; al = char courant de serial 00401503 99 cdq 00401504 f7f9 idiv ecx ; edx=eax%0x30 00401506 8a83ed314000 mov al,[ebx+0x4031ed] ; al = char courant hash_s 0040150c 03c2 add eax,edx ; eax=eax+edx 0040150e 83f866 cmp eax,0x66 00401511 7525 jnz image00400000+0x1538 (00401538) ; si eax!=0x66 on sort 00401513 43 inc ebx 00401514 80bb2932400000 cmp byte ptr [ebx+0x403229],0x0 0040151b 75e0 jnz image00400000+0x14fd (004014fd) |
void
GenerateKey(char
*name,
char *serial) { int i=0; struct md5_context ctx; unsigned char md5sum[16]; char buf[32], *p; if (lstrlen(name) <= 6) { lstrcpy(serial, "Pas assez de caractère man"); return; } md5_starts(&ctx); md5_update(&ctx, (uint8 *)name, lstrlen(name)); md5_finish(&ctx, md5sum); for (i=0; i<16; i++) wsprintf(buf+i*2, "%02x", md5sum[i]); p = serial; for (i=0; i<sizeof(buf); i++) if (buf[i] > 0x39) wsprintf(p++, "%d", 0x66-buf[i]); (*p++) = NULL; return; } |