CrackMe v. 1.00
by aLoNg3x
Tutorial de Lucifer48 [Immortal Descendants]
(1 août 1999)
Le crackme est en delphi... cette fichue icone...
Je remplis mon nom (Nome) et mon serial (Codice), c'est cool j'apprend l'italien :)
(j'ai préalablement mis un bpx hmemcpy), le schéma est ultra classique:
XXXX:00442C9C CALL 004232C0 ;on sort d'ici
XXXX:00442CA1 MOV EAX,[EBP-08]
XXXX:00442CA4 LEA EDX,[EBP-04]
...
XXXX:00442D07 MOV EAX,[EBP-10] ;nom
XXXX:00442D0A POP EDX ;serial
XXXX:00442D0B CALL 00442A3C ;vérification du serial
XXXX:00442D10 TEST AL,AL
XXXX:00442D12 JZ 00442D23 ;jump = mauvais serial
Voilà une petite traduction en Borland C++ Builder (v4.0) de ce qui ce passe dans
le call 00442A3C:
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1KeyUp(TObject *Sender, WORD &Key,
TShiftState Shift)
{
int i, result=0;
AnsiString name;
name=Edit1->Text; /* Edit1: edit box for the name */
if ((name!="")&&(name.Length()>5)&&(name.Length()<11))
{
for(i=1; i<name.Length(); i++)
result += name[i+1]*name[i]*i;
result = result + name.Length() - 666;
Edit2->Text=result;
}
else
Edit2->Text=""; /* Edit2: edit box for the serial */
}
//---------------------------------------------------------------------------
J'obtiens la registration suivante:
Name/ Lucifer48
Serial/ 290812
Avec ça, le boutton "OK" est enablé, je click dessus et rien ! Le boutton "OK" est grayé à nouveau.
J'essaye de voir ce qui se passe lorsque j'appuie sur ok, et rien d'interessant...
Apparement c'est pas la vraie vérification...
La vérification du serial est faite lorsque l'on appuie sur le boutton "Cancella";
c'est exactement le même schéma (même disposition) que ci-dessus:
...
XXXX:00442EE3 MOV EAX,[EBP-04] ;nom
XXXX:00442EE6 POP EDX ;edx contient la valeur du serial en héxa
XXXX:00442EE7 CALL 00442AF4 ;vérification
XXXX:00442EEC TEST AL,AL
XXXX:00442EEE JZ 00442F0C ;jump = mauvais serial
Petit tour du côté du call 00442AF4:
XXXX:00442B3A CALL 00442A20 ;EAX! i.e: je veux dire: factorielle(eax)
XXXX:00442B3F MOV ESI,EAX ;sauvegarde du résultat
...
XXXX:00442B4F MOV EDX,00000001
XXXX:00442B54 MOV ECX,[EBP-04] ;adresse du nom
XXXX:00442B57 MOVZX ECX,BYTE PTR [EDX+ECX-01] ;lit un à un les caractères du nom
XXXX:00442B5C IMUL ECX,ESI
XXXX:00442B5F ADD EBX,ECX
XXXX:00442B61 INC EDX
XXXX:00442B62 DEC EAX
XXXX:00442B63 JNZ 00442B54 ;boucle de la taille du nom
XXXX:00442B65 SUB EBX,[EBP-08] ;le serial (en héxa)
XXXX:00442B68 CMP EBX,00007A69
XXXX:00442B6E JNZ 00442B74 ;doit être égal...
Voilà une petite partie de keygen:
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1KeyUp(TObject *Sender, WORD &Key,
TShiftState Shift)
{
int i, f, result=0;
AnsiString name;
name=Edit1->Text; /* Edit1: edit box for the name */
if ((name!="")&&(name.Length()>5)&&(name.Length()<11))
{
f=fact((name[5]%7)+2); /* fact(n) = 1*2*...*(n-1)*n */
for(i=1; i<=name.Length(); i++)
result = result + name[i]*f;
result -= 0x7a69;
Edit2->Text=result;
}
else
Edit2->Text=""; /* Edit2: edit box for the serial */
}
//---------------------------------------------------------------------------
En appuyant sur le boutton "Cancella"; celui-ci disparait. On a passé une étape ! Reste encore un
boutton.
J'obtiens la registration suivante:
Name/ Lucifer48
Serial/ 560503
Note: Ca ne pose pas de problème d'entrer des nombres négatifs.
(exemple: Name/ L48 [ID] Serial/ -30255 )
Remarque: J'aimerais dire quelques mots concernant la façon dont delphi a compilé la fonction
factorielle (petit tour du côté du call 00442A20):
XXXX:00442A20 PUSH EBX ;13 lignes de code seulement !!
XXXX:00442A21 MOV EBX,EAX ;et rien de superflu, pour une fois !!
XXXX:00442A23 TEST EBX,EBX
XXXX:00442A25 JNZ 00442A2E
XXXX:00442A27 MOV EAX,000000001 ;
XXXX:00442A2C POP EBX ;condition d'arret
XXXX:00442A2D RET :
XXXX:00442A2E MOV EAX,EBX
XXXX:00442A30 DEC EAX
XXXX:00442A31 CALL 00442A20
XXXX:00442A36 IMUL EBX ;partie récursive
XXXX:00442A38 POP EBX ;(résultat de la multiplication EDX:EAX, avec EDX dword..
XXXX:00442A39 RET ; ..de poids fort)
On retrouve bien ce schéma avec les langages de haut niveau:
Continuons le crackme, reste à enlever le boutton "OK" (exactement la même démarche que tout à
l'heure).
XXXX:00442DBD MOV EAX,[EBP-04] ;nom
XXXX:00442DC0 POP EDX ;serial (en héxa)
XXXX:00442DC1 CALL 004232C0 ;vérification du serial
XXXX:00442DC6 TEST AL,AL
XXXX:00442DC8 JZ 00442DD7 ;jump = mauvais serial
Dans le call 004232C0:
XXXX:00442C09 MOVZX EAX,BYTE PTR [ESI+EAX-01]
XXXX:00442C0E IMUL EAX ;EAX^2
XXXX:00442C10 MOVSX EAX,AX ;si AX>7FFF alors EAX=(EAX or $FFFF0000)
XXXX:00442C13 IMUL ESI
XXXX:00442C15 MOV ECX,00000019 ;il aurait fallu mettre 1A pour le "Z"
XXXX:00442C1A CDQ
XXXX:00442C1B IDIV ECX
XXXX:00442C1D ADD EDX,41
XXXX:00442C20 POP EAX
XXXX:00442C21 MOV [EAX],DL ;adresse du serial
XXXX:00442C23 DEC ESI ;on part du dernier caractère du serial
XXXX:00442C24 TEST ESI,ESI
XXXX:00442C26 JNZ 00442BF9 ;boucle (de la longueur du serial)
XXXX:00442C28 MOV EAX,[EBP-0C] ;serial "transformé"
XXXX:00442C2B MOV EDX,[EBP-04] ;nom
XXXX:00442C2E CALL 00403B44 ;comparaison des deux chaines
XXXX:00442C33 JNZ 00442C4C ;jump = mauvais serial
En regardant la boucle on voit que le nom ne doit comporter que des majuscules (de 41h à 59h, on
peut même pas mettre de Z dans le nom...) Et bien sûr, le serial et le nom ont même nombre de
caractères.
Trouvons (ou essayons de trouver...) un serial pour mon nom:
L U C I F E R
4C 55 43 49 46 45 52
Je rappelle que l'on ne peut entrer que des chiffres pour le serial.
(X7^2 * 7) mod 19 + 41 = 52 <=> (X7^2 * 7) mod 19 = 11
(X6^2 * 6) mod 19 + 41 = 45 <=> (X6^2 * 6) mod 19 = 04
(X5^2 * 5) mod 19 + 41 = 46 <=> (X5^2 * 5) mod 19 = 05
(X4^2 * 4) mod 19 + 41 = 49 <=> (X4^2 * 4) mod 19 = 08
(X3^2 * 3) mod 19 + 41 = 43 <=> (X3^2 * 3) mod 19 = 02
(X2^2 * 2) mod 19 + 41 = 55 <=> (X2^2 * 2) mod 19 = 14
(X1^2 * 1) mod 19 + 41 = 4C <=> (X1^2 * 1) mod 19 = 0B
J'ai fait un petit programme sur ma calculatrice qui essaye les 10 (unique) possibilités (de 30h à
39h):
Pour X7: j'obtiens: { 3h, 7h, 0h, 7h, 3h, Dh, Ch, 0h, 2h, 12h }
Pour X6: j'obtiens: { 18h, 6h, 0h, 6h, 18h, 4h, 15h, 0h, 10h, 13h }
Pour X5: j'obtiens: { 14h, 5h, 0h, 5h, 14h, 14h, 5h, 0h, 5h, 14h }
Pour X4: j'obtiens: { 10h, 4h, 0h, 4h, 10h, Bh, Eh, 0h, 13h, 15h }
Pour X3: j'obtiens: { Ch, 3h, 0h, 3h, Ch, 2h, 17h, 0h, 8h, 16h }
Pour X2: j'obtiens: { 8h, 2h, 0h, 2h, 8h, 12h, 7h, 0h, 16h, 17h }
Pour X1: j'obtiens: { 4h, 1h, 0h, 1h, 4h, 9h, 10h, 0h, Bh, 18h }
On voit tout de suite que X7, X4 et X2 sont impossible à résoudre ! C'est une grosse erreur de
conception de l'auteur...
Caractères acceptables (toujours dans l'ordre):
Pour X7: "D","H","A","H","D","N","M","A","C","S"
Pour X6: "Y","G","A","G","Y","E","V","A","Q","T"
Pour X5: "U","F","A","F","U","U","F","A","F","U"
Pour X4: "Q","E","A","E","Q","L","O","A","T","V"
Pour X3: "M","D","A","D","M","C","X","A","I","W"
Pour X2: "I","C","A","C","I","S","H","A","W","X"
Pour X1: "E","B","A","B","E","J","Q","A","L","Y"
Avec ça, je ne peut pas faire mon nom... Je peut faire
Name/ LICQFED
Serial/ 8050150 (ou 8050350 ou...)
Ou plus simplement:
Name/ AAAAAA
Serial/ 222222
Remarque: Juste histoire d'être complet, on peut mettre un caractère "-" comme premier
caractère du serial. Donc 2Dh devient "A".
Le boutton "OK" disparait à son tour...
Greetings: All ID members (Volatility, Torn@do, ...), Eternal Bliss, ACiD BuRN, LaZaRuS,
Duelist, people on #cracking4newbies, ...
(c) Lucifer48. All rights reversed