IamSickOfInventingNewNames CrackMe
by LaZaRuS


Tutorial de Lucifer48 [Immortal Descendants]
(24 Octobre 1999)



Encore un énorme crackme écrit en C++ builder. Le code n'est pas difficule à comprendre, on va juste expliquer ici comment résoudre l'algorithme en quelques secondes. Et on va aussi montrer qu'il y a largement plus que 2400 combinaisons possibles. Allons-y !

Petit bpx hmemcpy comme d'habitude pour rentrer dans le code.
XXXX:004015D9  LEA  EAX, [EBP-04]		;d *eax : mon serial
XXXX:004015DC  CALL 00454090			;taille du serial, résultat en eax
XXXX:004015E1  CMP  EAX, 14			;20 caractères pour le serial
XXXX:004015E4  JNZ  004016DA			;jmp = mauvaise taille
On arrive à la première des trois boucles:
XXXX:004015EC  MOV  [EBP-38], EDX		;edx=0
XXXX:004015EF  MOV  DWORD PTR [EBP-3C], 1	;initialise l'indice de boucle
XXXX:004015F6  LEA  EAX, [EBP-04]		;d *eax : mon serial
XXXX:004015F9  MOV  EDX, [EBP-3C]
XXXX:004015FC  CALL 0040172C			;équivalent à: MOV EAX,[EAX+EDX]
XXXX:00401601  MOVSX ECX, BYTE PTR [EAX]	;lit un à un les caractères du serial
XXXX:00401604  ADD  [EBP-38], ECX		;addition du tout
XXXX:00401607  INC  DWORD PTR [EBP-3C]
XXXX:0040160A  CMP  DWORD PTR [EBP-3C], 15
XXXX:0040160E  JL   004015F6
Cette boucle additionne donc tous les caractères du serial (résultat en dword ptr [EBP-38]). Passons à la suite (deuxième boucle).
XXXX:00401620  MOV  EDX, [EBP-44]		;indice de boucle
XXXX:00401623  ADD  EDX, EDX
XXXX:00401625  INC  EDX
XXXX:00401626  LEA  EAX, [EBP-04]		;d *eax : mon serial
XXXX:00401629  CALL 0040172C			;positionne le serial sur le edx-ème caractère
XXXX:0040162E  MOV  BL, [EAX]			;lecture d'un caractère
...
XXXX:0040163B  CALL 0040172C
XXXX:00401640  XOR  BL, [EAX]			;xor avec le caractère suivant
XXXX:00401642  MOVSX ECX, BL
...
XXXX:00401648  MOV  [EAX*4+EBP-70], ECX		;les dword sont gardés en mémoire
...
XXXX:00401653  ADD  [EBP-40], ECX		;addition de ces 10 dword
XXXX:00401656  INC  DWORD PTR [EBP-44]
XXXX:00401659  CMP  DWORD PTR [EBP-44], 0A
XXXX:0040165D  JL   00401620
Cette précédente boucle XORise deux à deux les caractères et sauvegarde le résultat en mémoire (pour la troisième boucle). Ces dix dword sont additionnés et le résultat est stocké en dword ptr [EBP-40]. Dernière boucle:
XXXX:0040167C  MOV  ECX, [EDX*4+EBP-70]		;lit un des 10 dword
XXXX:00401680  MOV  EAX, [EBP-48]		;indice de boucle
XXXX:00401683  ADD  EAX, EAX
XXXX:00401685  ADD  ECX, [EAX*4+EBP-6C]		;on l'additionne avec le suivant
...
XXXX:0040169D  IMUL EAX, [EBP-74]		;multiplication des 5 nouveaux dword
XXXX:004016A1  MOV  [EBP-74], EAX
XXXX:004016A4  INC  DWORD PTR [EBP-48], 
XXXX:004016A7  CMP  DWORD PTR [EBP-48], 05
XXXX:004016AB  JL   00401677
Les 10 dword obtenus à l'issue de la deuxième boucle sont additionnés deux à deux pour former 5 nouveaux dword, qui sont multipliés entre eux; ce qui donne: dword ptr [EBP-74]. Voilà maintenant la comparaison:
XXXX:004016AD  MOV  EDX, [EBP-38]
XXXX:004016B0  OR   EDX, [EBP-40]
XXXX:004016B3  OR   EDX, [EBP-74]
XXXX:004016B6  MOV  [EBP-34], EDX
XXXX:004016B9  CMP  DWORD PTR [EBP-34], 024AFFCF
XXXX:004016C0  JNZ  004016DA
Résumons la situation:

Les 20 octets du serial: x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20
                       : ----- ----- ----- ----- ------ ------- ------- ------- ------- -------
Xor 2 par 2            :  y1    y2    y3    y4     y5     y6      y7      y8      y9      y10

dword ptr [EBP-38]= x1+x2+x3+...+x20
dword ptr [EBP-40]= y1+y2+y3+...+y10
dword ptr [EBP-74]= (y1+y2)*(y3+y4)*(y5+y6)*(y7+y8)*(y9+y10)

on doit avoir: [EBP-38] OR [EBP-40] OR [EBP-74] = 024AFFCF

Un peu d'intuition (plutôt du bon sens) nous amène à dire que, même dans le pire des cas:
[EBP-38] OR [EBP-40] < 1000h

On fait, dans un premier temps, on va chercher à trouver: z1*z2*z3*z4*z5 = 024AF??? (en faisant le
changement de variable évident z1=y1+y2; z2=... ).
Ci-joint dans le fichier .zip ma source pour trouver 5 valeurs susceptibles de convenir. Au bout de quelques secondes, on trouve une première combinaison:
y1+y2 = 3Fh
y3+y4 = 3Ah
y5+y6 = 2Fh
y7+y8 = 20h
y9+y10 = 7h

y1+y2+y3+y4+y5+y6+y7+y8+y9+y10 = 000000CFh

(y1+y2)*(y3+y4)*(y5+y6)*(y7+y8)*(y9+y10) = 024AFEC0h

000000CFh OR 024AFEC0h = 024AFECFh
Wow, à un bit près c'est presque parfait ! Il reste maintenant à trouver les x1, ..., x20 de telle façon que 024AFECFh OR [EBP-38] = 024AFFCF. Voilà mon résultat:
x1= 7Ah ('z')     x8= 6Bh ('k')     x15=43h ('C')
x2= 65h ('e')     x9= 4Fh ('O')     x16=53h ('S')
x3= 79h ('y')     x10=58h ('X')     x17=4Ah ('J')
x4= 59h ('Y')     x11=49h ('I')     x18=4Eh ('N')
x5= 77h ('w')     x12=51h ('Q')     x19=44h ('D')
x6= 6Ah ('j')     x13=42h ('B')     x20=47h ('G')
x7= 76h ('v')     x14=52h ('R')                       dword ptr [EBP-38] = 701h
Serial: zeyYwjvkOXIQBRCSJNDG

Juste un dernier mot sur le nombre de combinaisons: à la base, on peut permuter les 5 paquets (= quatre caractères), ce qui fait déjà 5!=120 possibilités. Un paquet peut se disposer de 8 façons possibles (en effet, on peut permuter x1x2 et x3x4 et chacun de ces sous-paquets (composés de 2 caractères) peuvent prendre deux positions (ex: x1x2 et x2x1) ). Ce qui fait: 8*120 = 960 et n'oublions pas qu'il y a 5 paquets, ce qui fait au total: 5*8*120 = 4800 possibilités (rien que pour mon serial). Et je suis sûr qu'il est possible de trouver (avec un peu de patience) un autre serial (composé de chiffres et de symboles) qui n'aurait aucun ou très peu de caractères en commum avec celui ci-dessus.


Greetings: All ID members (Volatility, Torn@do, alpine, ...), SiFLyiNG, Eternal Bliss, ACiD BuRN, LaZaRuS, ... and wonderful people in #cracking4newbies & #win32asm (LLama, WazerPup, X-Calibre, MisterE, ...).



(c) Lucifer48. All rights reserved & reversed