• STATISTIQUES
  • Il y a eu un total de 0 membres et 31218 visiteurs sur le site dans les dernières 24h pour un total de 31 218 personnes!
    Membres: 2 605
    Discussions: 3 579
    Messages: 32 816
    Tutoriels: 78
    Téléchargements: 38
    Sites dans l'annuaire: 58


  • ANNUAIRE
  • [FR] Le site du zero
    Découvrez gratuitement la programmation (C, C++, PHP, MySQL, XHTML, CSS...), Linux, le Mapping, la modé...
    Programmation
    [FR] Hackfest
    Le Hackfest est un évènement de sécurité et de piratage informatique au Québec reg...
    Hacking
    [FR] dcode
    dcode.fr est le site indispensable pour décoder des messages, tricher aux jeux de lettres, résoudre des énigmes...
    Outils / Add-on
    [FR] Zenk-Security
    La communauté zenk-security a pour objet principal la sécurité informatique, nous sommes des tou...
    Hacking
    [FR] Microcontest
    Cryptographie: 7, Mathématiques: 8, Image Son Vidéo: 5, Intelligence artificielle: 3, Réseau: 2, Divers: 7, Phy...
    Challenges
    [EN] Listbrain Version 3
    Site proposant 66 challenges présentés dans une liste mélangée.
    Challenges
    [FR] Newbie Contest
    Crackme: 35, Cryptographie: 49, Hacking: 27, Javascript/Java: 17, Logique: 31, Programmation: 23, Stéganographie: 53
    Challenges

  • DONATION
  • Si vous avez trouvé ce site internet utile, nous vous invitons à nous faire un don du montant de votre choix via Paypal. Ce don servira à financer notre hébergement.

    MERCI!




Résolution LaFarges crackme #2

Voici une nouvelle résolution de keygenme.

Le keygenme est téléchargeable : ici

Voici ses caractéristiques:

Difficulty: 1 - Very easy, for newbies
Platform: Windows
Language: Assembler
D'après les votes sur le site : Crackme is quite nice.

Ce keygenme est facile à comprendre. Cependant, les nombreuses manipulations de chaîne (pseudo et une chaîne intégrée au programme) rendent casse-tête le codage du kengen, réalisé ici en C (je ne me suis pas encore mis au rip routine Undecided ).

Je le conseille au débutant en reverse et en programmation car il permet de s'exercer et de bien gérer la mémoire des variables (choix des types de variables adaptés aux utilisations faites).

Présentation du keygenme

[Image: la_farge_1.png]

Présentation classique, une musique pas très agréable vient nous chatouiller les oreilles.

Correction


Nous regardons les fonctions (ctrl+n), puis nous cliquons sur user32.MessageBoxA pour faire un "Set breakpoint on every reference"

Nous lançons le programme.
Le programme nous demande un pseudo et un mot de passe. Nous cliquons sur OK.
On breakpoint en 004012e3, si nous continuons, nous avons le message "Nope, that's the right code !".

Juste au dessus, en 004012cd, nous remarquons le placement d'un breakpoint, avec comme message "Yes, that's the right code !". Encore en dessus, nous avons des fonctions lstrcmpA. Nous montons plus haut, un breakpoint est placé en 0040115a avec le message "Username must have at least 4 chars".

Nous voyons le véritable sérial apparaître en 00401288

Nous venons de trouver le début et la fin de notre routine......

Nous voyons juste au dessus:
Code :
00401149       JA SHORT crackme.00401163

Ce saut (si supérieur) vérifie que le pseudo entré, fait bien plus de 3 caractère. Nous fesons "ENTRER" sur cette ligne et nous nous retrouvons en 00401163, nous y plaçons un breakpoint. Nous lançons le programme, on break, puis on avance avec la touche f8 jusqu'à avoir le message d'erreur.

Nous observons de nombreuses boucles
Boucle 1 : 0040117a à 00401197
Boucle 2 : 004011a3 à 004011c7
Boucle 3 : 004011d1 à 004011f0
Boucle 4 : 004011fa à 0040121e
Boucle 5 : 00401236 à 0040124b
Boucle 6 : 004012ea à 0040126a
Boucle 7 : 00401278 à 00401286

Nous allons donc analyser chacune de ces boucles et les coder.

Boucle 1

Code :
0040117A   > 8A0C16         MOV CL,BYTE PTR DS:[ESI+EDX]             ;  commencement boucle , un caractère du pseudo est pris à partir de 0040634a (2eme caractère du pseudo)
0040117D   . 8AD9           MOV BL,CL                                ;  on met la valeur de la lettre prise (qui est dans ecx) dans ebx
0040117F   . 3298 28634000  XOR BL,BYTE PTR DS:[EAX+406328]          ;  on fait valeur du caractère du pseudo ^ caractère d'une chaine
00401185   . 40             INC EAX ; eax++
00401186   . 83F8 05        CMP EAX,5 ; on compare eax avec 5
00401189   . 881C32         MOV BYTE PTR DS:[EDX+ESI],BL             ;  on met la valeur calculée (du xor) dans le pseudo
0040118C   . 8888 27634000  MOV BYTE PTR DS:[EAX+406327],CL          ;  on met la valeur du caractère pseudo (non calculée) dans la chaîne
00401192   . 75 02          JNZ SHORT crackme.00401196   ; si eax n'est pas égale à 5 on remet le compteur à 0 pour la chaîne
00401194   . 33C0           XOR EAX,EAX                            ; on remet eax à 0
00401196   > 46             INC ESI                                     ; esi++
00401197   . 3BF5           CMP ESI,EBP                              ;

Durant cette boucle, nous voyons une manipulation de la chaîne du pseudo placée en 00406349 ( clic droit dans la fenêtre de dump >>> go to >> 00406349) ainsi que d'une chaîne de caractère placée en 00406328 ( clic droit dans la fenêtre de dump >>> go to >> 00406328)

[Image: la_farge_3.png]
Fenêtre de dump

Voici le code C équivalent à cette boucle:

Code :
for(count = 0 ; count != longueur_login ; count++)
{
valeur_int = name[count +1];   // MOV CL,BYTE PTR DS:[ESI+EDX]
    name[count+1] = (name[count+1] ^ tab[count2])   ; //XOR BL,BYTE PTR DS:[EAX+406328]
    tab[count2] = valeur_int; MOV BYTE PTR DS:[EAX+406327],CL
    count2++;    // INC EAX

    count2 = count2 % 5 ;     // CMP EAX,5

}

name est le pseudo
tab est la chaîne de caractère
count2 est le compteur lié à la chaîne qui est remis à 0 quand il est égale à 5
count est un compteur pour le pseudo

Boucle 2


Code :
004011A3   > 8A9F 2D634000  MOV BL,BYTE PTR DS:[EDI+40632D]          ;  commencement de la 2nd boucle / mise dans ebx du 6eme caractère de la  chaîne
004011A9   . 8BF5           MOV ESI,EBP                              ;  on met ebp dans esi
004011AB   . 2BF1           SUB ESI,ECX                              ;  esi = esi - ecx
004011AD   . 4E             DEC ESI                                  ;  esi = esi - 1
004011AE   . 8A0432         MOV AL,BYTE PTR DS:[EDX+ESI]             ;  on met la lettre pseudo dans eax
004011B1   . 32D8           XOR BL,AL                                ;  caractère chaine ^ caractère pseudo (dans ebx on met le resultat)
004011B3   . 47             INC EDI                                  ;  edi = edi + 1
004011B4   . 881C32         MOV BYTE PTR DS:[EDX+ESI],BL             ;  on prend la valeur de ebx et on le met dans caractère du pseudo
004011B7   . 8887 2C634000  MOV BYTE PTR DS:[EDI+40632C],AL          ;  on prend la valeur dans eax et on la met dans la chaine
004011BD   . 83FF 05        CMP EDI,5                                ;  quand le compteur est à 5 on revient au debut de la chaine
004011C0   . 75 02          JNZ SHORT crackme.004011C4
004011C2   . 33FF           XOR EDI,EDI
004011C4   > 41             INC ECX                                  ;  ecx = ecx + 1
004011C5   . 3BCD           CMP ECX,EBP                              ;  on compare ecx avec ebp ( ebp = lg du pseudo)
004011C7   .^72 DA          JB SHORT crackme.004011A3                ;  fin 2nd boucle

Voici l'équivalent en C:
Code :
for (count = 0 ; count != longueur_login -1 ; count++)
{

    valeur = tab[5 + count2];  // MOV BL,BYTE PTR DS:[EDI+40632D]  
    eax = name[longueur_login - (count)- 1];  // MOV AL,BYTE PTR DS:[EDX+ESI]

    valeur = valeur ^ eax ; //  XOR BL,AL

    name[longueur_login - (count+1)] = valeur ; // MOV BYTE PTR DS:[EDX+ESI],BL
    tab[5+ count2] = eax ;   //MOV BYTE PTR DS:[EDI+40632C],A
    count2++;             //INC EDI

    count2 = count2 % 5 ;   //CMP EDI,5
}


Boucle 3


Code :
004011D1   > 8A043A         MOV AL,BYTE PTR DS:[EDX+EDI]             ;  commencement 3eme boucle ; on prend un caractère du pseudo (on commence par le 2eme) et on le met dans eax
004011D4   . 8A8E 32634000  MOV CL,BYTE PTR DS:[ESI+406332]          ;  on prend le 5eme caractère de chaine et on le met dans ecx
004011DA   . 32C8           XOR CL,AL                                ;  ecx = caractère chaine ^ caractère pseudo
004011DC   . 46             INC ESI                                  ;  esi++
004011DD   . 880C3A         MOV BYTE PTR DS:[EDX+EDI],CL             ;  on met le resultat du calcul (ecx) dans le pseudo
004011E0   . 8886 31634000  MOV BYTE PTR DS:[ESI+406331],AL          ;  on met la valeur du caractere pseudo non calcule (eax) dans la chaine
004011E6   . 83FE 05        CMP ESI,5                                ;  esi est count2
004011E9   . 75 02          JNZ SHORT crackme.004011ED
004011EB   . 33F6           XOR ESI,ESI
004011ED   > 47             INC EDI                                  ;  edi est count
004011EE   . 3BFD           CMP EDI,EBP
004011F0   .^72 DF          JB SHORT crackme.004011D1                ;  fin 3eme boucle

Boucle 4


Code :
004011FA   > 8A9F 37634000  MOV BL,BYTE PTR DS:[EDI+406337]          ;  commencement 4eme boucle on prend le 10eme caractère de la chaine et on le met dans ebx
00401200   . 8BF5           MOV ESI,EBP                              ;  on met la longueur du pseudo dans esi
00401202   . 2BF1           SUB ESI,ECX                              ;  esi = esi - ecx
00401204   . 4E             DEC ESI
00401205   . 8A0432         MOV AL,BYTE PTR DS:[EDX+ESI]             ;  on prend le caractère pseudo en commencant par le dernier et on le met dans eax
00401208   . 32D8           XOR BL,AL                                ;  caractère chaine ^ caractère pseudo
0040120A   . 47             INC EDI ; edi++
0040120B   . 881C32         MOV BYTE PTR DS:[EDX+ESI],BL             ;  met le resultat dans le pseudo
0040120E   . 8887 36634000  MOV BYTE PTR DS:[EDI+406336],AL          ;  on met le pseudo (eax) dans la chaine
00401214   . 83FF 05        CMP EDI,5
00401217   . 75 02          JNZ SHORT crackme.0040121B
00401219   . 33FF           XOR EDI,EDI
0040121B   > 41             INC ECX
0040121C   . 3BCD           CMP ECX,EBP
0040121E   .^72 DA          JB SHORT crackme.004011FA                ;  fin 4eme boucle

L'équivalent en C

Code :
for (count = 0 ; count != longueur_login -1 ; count++)
{

    valeur = tab[15 + count2];  // MOV BL,BYTE PTR DS:[EDI+406337]
    eax = name[longueur_login - (count)- 1];  // MOV AL,BYTE PTR DS:[EDX+ESI]
    valeur = valeur ^ eax ;  //XOR BL,AL
    name[longueur_login - (count+1)] = valeur ; // MOV BYTE PTR DS:[EDX+ESI],BL
    tab[15+ count2] = eax ;  //MOV BYTE PTR DS:[EDI+406336],AL
    count2++;

   count2 = count2 % 5;  //CMP EDI,5
}

Boucle 5


Code :
00401236   > 8BC8           MOV ECX,EAX                              ;  5eme boucle
00401238   . 83E1 03        AND ECX,3                                ;  ecx & 3
0040123B   . 8A1C0F         MOV BL,BYTE PTR DS:[EDI+ECX]             ;  prend un caractère de la chaine et le met dans ebx
0040123E   . 8D340F         LEA ESI,DWORD PTR DS:[EDI+ECX]
00401241   . 8A0C02         MOV CL,BYTE PTR DS:[EDX+EAX]             ;  prend le caractere pseudo en commencant par le 2eme et on le met dans ecx
00401244   . 02D9           ADD BL,CL
00401246   . 40             INC EAX                                  ;  additionne pseudo + chaine
00401247   . 3BC5           CMP EAX,EBP
00401249   . 881E           MOV BYTE PTR DS:[ESI],BL                 ;  met le caractere pseudo dans la chaine
0040124B   .^72 E9          JB SHORT crackme.00401236                ;  fin 5eme boucle

L'équivalent en C

Code :
or (count=0 ; count !=longueur_login -1 ; count++)
{
    count2 = count2 & 3 ;          // AND ECX,3  
    valeur = tab[29 + count2];    //MOV BL,BYTE PTR DS:[EDI+ECX]
    tab[29 + count2] = tab[29 + count2] + name[1+count];   // ADD BL,CL
    count2++;
}

Boucle 6


La Boucle 6 est différente des autre boucle, elle permet de calculé le pseudo.

Code :
0040125A   > 33D2           XOR EDX,EDX                              ;  6eme boucle
0040125C   . F7F1           DIV ECX
0040125E   . 80C2 30        ADD DL,30
00401261   . 8893 49654000  MOV BYTE PTR DS:[EBX+406549],DL
00401267   . 43             INC EBX
00401268   . 85C0           TEST EAX,EAX
0040126A   .^75 EE          JNZ SHORT crackme.0040125A               ;  fin 6eme boucle

Plus haut, nous voyons que ecx est égale à 0x0a.
et eax est d'après le code suivant:
Code :
00401253   . A1 45634000    MOV EAX,DWORD PTR DS:[406345]

eax est égale au dword (4 octets) en 00406345

Donc avec le login "maurice", si nous faisons un breakpoint sur 00401253, et qu'ensuite, nous nous rendons en 00406345 (dans la fenêtre de dump), le dword est de:
88 10 07 23

La lecture se faisant à l'envers, il nous faut une variable égale à 0x23071088

Ensuite cette valeur (0x23071088) est divisée par 0x0a, le résultat va en eax, le reste de la division va en edx.
La boucle continue tant que eax n'est pas égale à 0.
Il est nécessaire de mettre la valeur initiale eax dans un unsigned long.

Voici l'équivalent en C:
Code :
while(eax !=0)
{


    reste = eax % 0x0a ;
    eax = eax / 0x0a ;
    reste = reste + 0x30 ;
    serial[count2] = reste;
    

    count2++;

}

Voici en bonus la fonction pour inversé 88 10 07 23 en 0x23071088

Code :
for(count = 0 ; count !=4 ; count++)
{
    eax = eax + (tab[count + 29] << (8 * count2));
    count2++;
    printf("\neax : %x", eax);

}

La dernière boucle est simple elle permet d'inverser la chaine (variable serial dans la boucle 6), le résultat est le serial final.

En pièce jointe, je met mon keygen Tongue