Solution du crackme Elooo n°2

Ici dans le listing ci-dessous j'utilise comme serial ScHaP, afin de comprendre la routine.

004010B6 |. E8 85000000 CALL                                                            ;// GetDlgItemTextA c'est l'API permettant de récupérer le serial.
004010BB |. 33F6 XOR ESI,ESI                                                           ;// esi = 0
004010BD |. 8D05 00304000 LEA EAX,DWORD PTR DS:[403000] ;//load effective adress du serial dans eax.

;===== Début 1ère boucle =====
004010C3 |> 83FE 08 /CMP ESI,8                                                                    ;//compare esi=0 avec 8
004010C6 |. 7C 02 |JL SHORT elooo2.004010CA                                           ;//saute car la comparaison avant donne un résultat inférieur à 8 étant donné que esi est initalisé à 0
004010C8 |. 33F6 |XOR ESI,ESI                                                                     ;//esi=0
004010CA |> 8A96 32304000 |MOV DL,BYTE PTR DS:[ESI+403032]       ;//met le byte référencé par le pointeur du Data Segment[ESI+403032]=03
004010D0 |. 3010 |XOR BYTE PTR DS:[EAX],DL                                       ;// xor DL par le premier byte du sérial référencer par le pointeur DS:[EAX]=53('S') avec DL=03
004010D2 |. 46 |INC ESI                                                                              ;//Incrémente esi donc esi+1 > esi=1
004010D3 |. 40 |INC EAX                                                                           ;//Incrémente eax donc eax+1 > eax=00403000+1=00403001, permet de passer au deuxième byte du serial.
004010D4 |. 8038 00 |CMP BYTE PTR DS:[EAX],0                                ;//Compare le byte référencé par le pointeur du DS:[EAX] avec 0.
004010D7 |.^ 75 EA \JNZ SHORT elooo2.004010C3                             ;//Jump if not zero. Donc ici le résultat de la comparaison est fausse donc elle vaut 1 donc on retourne
                                                                                                               ;//au début de la boucle.
;===== fin 1ère boucle =====


;===== Début 2ème boucle =====
004010C3 |> /83FE 08 /CMP ESI,8                                                                     ;//compare esi=1 avec 8
004010C6 |. |7C 02 |JL SHORT elooo2.004010CA                                           ;;//saute car la comparaison avant donne un résultat inférieur à 8 étant donné que esi est initalisé à 1.
004010C8 |. |33F6 |XOR ESI,ESI                                                                      ;//esi=0
004010CA |> |8A96 32304000 |MOV DL,BYTE PTR DS:[ESI+403032]        ;// met le byte référencé par le pointeur du Data Segment[ESI+403032]=07
004010D0 |. |3010 |XOR BYTE PTR DS:[EAX],DL                                        ;// Xor le byte référencé par le pointeur du DS:[EAX]=63('c') avec DL=07
004010D2 |. |46 |INC ESI                                                                               ;//Incrémente esi donc esi+1 > esi=1+1=2
004010D3 |. |40 |INC EAX                                                                            ;//Incrémente eax donc eax+1 > eax=00403001+1=00403002, permet de passer au troisième byte du serial.
004010D4 |. |8038 00 |CMP BYTE PTR DS:[EAX],0                                  ;//Compare le byte référencé par le pointeur du DS:[EAX]=48('H') avec 0.
004010D7 |.^\75 EA \JNZ SHORT elooo2.004010C3                                ;//Jump if not zero. Donc ici le résultat de la comparaison est fausse donc elle vaut 1 donc on retourne
                                                                                                                   ;//au début de la boucle.
;===== fin 2ème boucle =====


;===== Début 3ème boucle =====
004010C3 |> /83FE 08 /CMP ESI,8 ;                                                     ;//compare esi=2 avec 8
004010C6 |. |7C 02 |JL SHORT elooo2.004010CA                             ;//saute car la comparaison avant donne un résultat inférieur à 8 étant donné que esi est initalisé à 2.
004010C8 |. |33F6 |XOR ESI,ESI                                                       ;//ESI=0
004010CA |> |8A96 32304000 |MOV DL,BYTE PTR DS:[ESI+403032] ;// met le byte référencé par le pointeur du Data Segment[ESI+403032]=02
004010D0 |. |3010 |XOR BYTE PTR DS:[EAX],DL                                 ;// Xor le byte référencé par le pointeur du DS:[EAX]=48('H') avec DL=02
004010D2 |. |46 |INC ESI                                                                        ;//Incrémente esi donc esi+1 > esi=2+1=3
004010D3 |. |40 |INC EAX                                                                    ;//Incrémente eax donc eax+1 > eax=00403002+1=00403003 ascii('JaP')
004010D4 |. |8038 00 |CMP BYTE PTR DS:[EAX],0                          ;//Compare le byte référencé par le pointeur du DS:[EAX]=61('a') avec 0.
004010D7 |.^\75 EA \JNZ SHORT elooo2.004010C3                        ;//Jump if not zero. Donc ici le résultat de la comparaison est fausse donc elle vaut 1 donc on retourne
                                                                                                           ;//au début de la boucle.
;===== fin 3ème boucle =====


;===== Début 4ème boucle =====
004010C3 |> /83FE 08 /CMP ESI,8                                                              ;//compare esi=3 avec 8
004010C6 |. |7C 02 |JL SHORT elooo2.004010CA                                     ;//saute car la comparaison avant donne un résultat inférieur à 8 étant donné que esi est initalisé à 3
004010C8 |. |33F6 |XOR ESI,ESI                                                               ;//ESI=0
004010CA |> |8A96 32304000 |MOV DL,BYTE PTR DS:[ESI+403032] ;// met le byte référencé par le pointeur du Data Segment[ESI+403032]=06
004010D0 |. |3010 |XOR BYTE PTR DS:[EAX],DL                                 ;// Xor le byte référencé par le pointeur du DS:[EAX]=61('a') avec DL=06
004010D2 |. |46 |INC ESI                                                                       ;//Incrémente esi donc esi+1 > esi=3+1=4
004010D3 |. |40 |INC EAX                                                                    ;//Incrémente eax donc eax+1 > eax=00403003+1=00403004 ascii('gP')
004010D4 |. |8038 00 |CMP BYTE PTR DS:[EAX],0                          ;//Compare le byte référencé par le pointeur du DS:[EAX]=50('P') avec 0.
004010D7 |.^\75 EA \JNZ SHORT elooo2.004010C3                        ;//Jump if not zero. Donc ici le résultat de la comparaison est fausse donc elle vaut 1 donc on retourne
                                                                                                           ;//au début de la boucle.
;===== fin 4ème boucle =====


;===== Début 5ème boucle =====
004010C3 |> /83FE 08 /CMP ESI,8                                                              ;//compare esi=4 avec 8
004010C6 |. |7C 02 |JL SHORT elooo2.004010CA                                     ;//saute car la comparaison avant donne un résultat inférieur à 8 étant donné que esi est initalisé à 4
004010C8 |. |33F6 |XOR ESI,ESI                                                               ;//ESI=0
004010CA |> |8A96 32304000 |MOV DL,BYTE PTR DS:[ESI+403032] ;// met le byte référencé par le pointeur du Data Segment[ESI+403032]=09
004010D0 |. |3010 |XOR BYTE PTR DS:[EAX],DL                                 ;// Xor le byte référencé par le pointeur du DS:[EAX]=50('P') avec DL=09
004010D2 |. |46 |INC ESI                                                                        ;//Incrémente esi donc esi+1 > esi=4+1=5
004010D3 |. |40 |INC EAX                                                                     ;//Incrémente eax donc eax+1 > eax=00403004+1=00403005 ascii('gP')
004010D4 |. |8038 00 |CMP BYTE PTR DS:[EAX],0                           ;//Compare le byte référencé par le pointeur du DS:[EAX]=00 avec 0.
004010D7 |.^\75 EA \JNZ SHORT elooo2.004010C3                         ;//Jump if not zero. Donc ici le résultat de la comparaison est vrai donc elle vaut 0 donc on continue
                                                                                                            ;//ci-dessous. et on sort de la boucle ;)
;===== fin 5ème boucle =====

004010D9 |. 68 3B304000 PUSH elooo2.0040303B              ;// met sur la pile la String 2 = "`k=p(`w6jRan``PNVM$+QjQ<%,grai"
004010DE |. 68 00304000 PUSH elooo2.00403000             ;// met sur la pile la String 1 = "PdJgY"
004010E3 |. E8 82000000 CALL                                        ;// Ici la fonction de lstrcmpA compare deux chaînes de caractères.
004010E8 |. 85C0 TEST EAX,EAX                                  ;// Test eax,eax=1
004010EA |. 75 14 JNZ SHORT elooo2.00401100         ;//Saute si le résultat renvoyer par test eax,eax=1, ici donc on saute à l'adresse 0x00401100

004010EC |. 6A 00 PUSH 0          ; Style = MB_OK|MB_APPLMODAL
004010EE |. 68 5D304000 PUSH elooo2.0040305D          ; Title = "... "
004010F3 |. 68 5A304000 PUSH elooo2.0040305A          ; Text = "OK"
004010F8 |. FF75 08 PUSH DWORD PTR SS:[EBP+8]        ; hOwner
004010FB |. E8 4C000000 CALL        ; MessageBoxA << 00401100 |> 33C0 XOR EAX,EAX         ;// Initialisation eax=0 00401102 |. BF 00304000 MOV EDI,elooo2.00403000                                                                                     ;// Met le contenu de l'adresse 00403000 (PdJgY) dans edi(0012FBA4)
00401107 |. B9 32000000 MOV ECX,32                                                     ;// Met 32 dans ecx (valant pour le moment 02020707).
0040110C |. F3:AA REP STOS BYTE PTR ES:[EDI]                                 ;//Répète l'opération sur la string puis Stock le byte de la String dans le pointeur référencer par
                                                                                                                   ;//le pointeur de l'extra segment:[EDI]
                                                                                                                 ;//ecx=32h soit 50d et ES:[EDI]=50('P')
0040110E |. EB 1A JMP SHORT elooo2.0040112A                             ;//Saut court à l'adresse 0x0040112A
00401110 |> 66:3D EA03 CMP AX,3EA                                            ;//Compare 3EA avec AX=0000.
00401114 |. 75 14 JNZ SHORT elooo2.0040112A                           ;// Saute si c'est pas zéro
00401116 |. 50 PUSH EAX
00401117 |. FF75 08 PUSH DWORD PTR SS:[EBP+8]
0040111A |. E8 1B000000 CALL ; \EndDialog
0040111F |. EB 09 JMP SHORT elooo2.0040112A
00401121 |> B8 00000000 MOV EAX,0
00401126 |. C9 LEAVE
00401127 |. C2 1000 RETN 10
0040112A |> B8 01000000 MOV EAX,1                         ;//met 1 dans eax et
0040112F |. C9 LEAVE                                                   ;//quitte
00401130 \. C2 1000 RETN 10



1°)Méthodologie:

Rappel:

lstrcmp Function :

L'API lstrcmp permet de comparer deux chaînes de caractères. Cette fonction est sensible à "la casse", celà signifie qu'elle fait attention aux majucules et minuscules.

Syntax:

int lstrcmp( LPCTSTR lpString1,
LPCTSTR lpString2
);

Return Value:
Les valeurs de retours sont:

- Positif si la string 1 est supèrieure à la string 2.
- Négatif si la string 1 est inférieure à la string 2.
- zéro si la string 1 est égale à la string 2.

On convertit la string ascii en base 16 (hexadécimale):

ascii: ` k = p ( ` w 6 j R a n ` ` P N V M $ + Q j Q < % , g r a i
hexa: 60 6B 3D 70 28 60 77 36 6A 52 61 6E 60 60 50 4E 56 4D 24 2B 51 6A 51 3C 25 2C 67 72 61 69

La génération du sérial est très simple:
Dans ce CrackMe DL prend des valeurs 3,7,2,6,9,5,4,1, qui sont répétées, puis on fait un XOR entre DL et la valeur en hexadécimal de chacun des bytes de la string fixe.
(Voir détails ci-dessous)


La routine du sérial :
========================================
DL=3 xor 60=63= c donne ` après le xor
========================================

DL=7 xor 6B=6C= l donne k après le xor
========================================

DL=2 xor 3D=3F= ? donne = après le xor
========================================

DL=6 xor 70=76= v donne p après le xor
========================================

DL=9 xor 28=21= ! donne ( après le xor
========================================

DL=5 xor 60=65= e donne ` après le xor
========================================

DL=4 xor 77=73= s donne w après le xor
========================================

DL=1 xor 36=37= 7 donne 6 après le xor
========================================

DL=3 xor 6A=69= i donne j après le xor
========================================

DL=7 xor 52=55= U donne R après le xor
========================================

DL=2 xor 61=63= c donne a après le xor
========================================

DL=6 xor 6E=68= h donne n après le xor
========================================

DL=9 xor 60=69= i donne ` après le xor
========================================

DL=5 xor 60=65= e donne ` après le xor
========================================

DL=4 xor 50=54= T donne P après le xor
========================================

DL=1 xor 4E=4F= O donne N après le xor
========================================

DL=3 xor 56=55= U donne V après le xor
========================================

DL=7 xor 4D=4A= J donne M après le xor
========================================

DL=2 xor 24=26= & donne $ après le xor
========================================

DL=6 xor 2B=2D= - donne + après le xor
========================================

DL=9 xor 51=58= X donne Q après le xor
========================================

DL=5 xor 6A=6F= o donne J après le xor
========================================

DL=4 xor 51=55= U donne Q après le xor
========================================

DL=1 xor 3C=3D= = donne < après le xor
========================================

DL=3 xor 25=26= & donne % après le xor
========================================

DL=7 xor 2C=2B= + donne , après le xor
========================================

DL=2 xor 67=65= e donne g après le xor
========================================

DL=6 xor 72=74= t donne r après le xor
========================================

DL=9 xor 61=68= h donne a après le xor
========================================

DL=5 xor 69=6C= m donne l après le xor

========================================


On récupère toutes les lettres en bleues et on obtient :
Le Serial = cl?v!es7iUchieTOUJ&-XoU=&+ethl


Une fois le sérial trouver j'ai tester à nouveaux en posant un breakpoint sur GetDlgItemText, et j'ai vérifier que tout les caractères étaient identiques.



Sur la Photo ci-dessous vous voyez le résultat que renvoie l'api lorsque que les deux strings sont identiques.

Voila, j'espère que ce petit tutorial vous aurra aider.
bonne chance pour la suite ;)
Amicalement votre humble serviteur [ScHaP_999|TNL] ;)