Changer un crackme en keygen
par superjuju, le vendredi 13 juin 2003
Introduction
Ceci est mon premier cours, je suis moi-même un cracker débutant mais j'avais envie de faire quelque chose par moi même alors voila ce tut ...
En fait j'avais commencé le cracking il y a déja 3 ans de cela mais bon j'ai du m'arrêter entre-temps par manque de temps ( ahhh viva la prépa ! ) mais depuis que les concours sont finis j'ai pris un coup de speed j'ai eu envie de m'y remettre... Bon allons y !
Je pars sur le principe que tu connais déja quelque chose à l'art ancestral du cracking alors je vais pas tout détailler. Si jamais tu t'estimes doué ne reste pas par ici tu perds ton temps. Va plutot lire quelques cours sur le manual unpacking ou sur les dongles ... Mais si tu ne sais pas ce que signifient ces mots barbares reste par là j'espère que j'arriverai a t'apprendre quelque chose... sur des choses bien plus simples !
Outils nécessaires
Analyse du programme
Alors on lance le proggy, et on observe : c'est un classique name / sérial.
On clique sur info : ah voila enfin quelque chose d'interressant : " Write in Delphi 2.0 in july 1999. " Bon la date on s'en bat les cahouettes mais savoir que c'est en Delphi risque d'être utile : en effet le Delphi est un langage un peu différent des autres : il n'utilise pas les API windows (ou du moins pas directement j'en sais rien). Tout ce que je sais c'est que les BPX MessageBoxA ou BPX GetDlgItemTextA ne marchent pas sous SoftIce.. Mais on s'en fout on va utiliser W32Dasm uniquement :-) L'autre problême avec Delphi c'est sous W32Dasm justement : les strings refs ne sont pas accessibles en général ... :-( Mais bon c'est notre jour de chance (va voir la date en haut !!!) içi ca va marcher .... :-)))
On rentre un nom bidon : superjuju ( j'ai passé des années à trouver un pseudo aussi débile !) et un s/n bidon : 121212. Paf une boite nous pète à la face : "Nop! Keep working !" Ben bien sur on va pas trouver le bon sérial du premier coup ! ah c'est chiant de se faire insulter par un p'tit crackme alors qu'on a même pas encore commencé à le cracker... On va régler ca !!!
Programme des réjouissances :
Essaye de faire les manips en même temps que moi c'est plus efficace pour retenir.
1. Crack simple
On va s'faire ca vite fais bien fait ! Alors on lance W32Dasm et on désassemble le crackme. Un petit clic sur les string refs, on cherche "Nop! Keep working!" et on arrive là :
* Referenced by a (U)nconditional or (C)onditional
Jump at Address:
|:00427277(C)
|
:004272CE 8BC3 mov
eax, ebx
:004272D0 F7EB imul
ebx
:004272D2 8BD8 mov
ebx, eax
:004272D4 8D55EC lea
edx, dword ptr [ebp-14]
:004272D7 8BC3 mov
eax, ebx
:004272D9 E80EE2FDFF call
004054EC
:004272DE 8B45EC
mov eax, dword ptr [ebp-14]
:004272E1 50 push
eax
:004272E2 8D55F0 lea
edx, dword ptr [ebp-10]
:004272E5 8B87BC010000 mov
eax, dword ptr [edi+000001BC]
:004272EB E8D8A7FEFF call
00411AC8
:004272F0 8B55F0 mov
edx, dword ptr [ebp-10]
:004272F3 58 pop
eax
:004272F4 E897C1FDFF call
00403490 ;
teste le code entré
:004272F9 7517 jne
00427312 ;
saute vers le message d'erreur si il
:004272FB 6A00 push
00000000
est faux.
:004272FD 668B0D54734200 mov
cx, word ptr [00427354]
:00427304 B202 mov
dl, 02
* Possible StringData Ref from Code Obj ->"Well
done! The serial is correct!"
|
:00427306 B894734200 mov
eax, 00427394
:0042730B E89CF9FFFF call
00426CAC
:00427310 EB15 jmp
00427327
* Referenced by a (U)nconditional or (C)onditional
Jump at Address:
|:004272F9(C) ;
intéressant
|
:00427312 6A00 push
00000000
:00427314 668B0D54734200 mov
cx, word ptr [00427354]
:0042731B B202
mov dl, 02
* Possible StringData Ref from Code Obj ->"Nop!
Keep working."
|
:0042731D B8C0734200
mov eax, 004273C0
:00427322 E885F9FFFF call
00426CAC ;
affichage du message d'erreur
Bon ben c'est très simple : en 004272F9 , si le code entré est faux on saute vers le message d'erreur ! Comment lutter contre ca ?? En fait c'est ce saut qui fout sa merde alors noppons le ! Dans un éditeur hexadécimal on remplace 7517 par 9090 ! On relance... Et voilou yapalou !!
2. Recherche d'un sérial valide
Ce qu'on viens de faire c'était juste pour se mettre en bouche, alors attaquons les choses sérieuses !
On va se servir du debugger de W32Dasm ca ira bien mieux que SoftIce surtout qu'on a déja tout sous la main ! Alors on va se servir un peu de l'un de nos neurones (pas trop hein) pour comprendre un peu mieux ce qui se passe dans le programme.
Déja on n'est pas aidé car le programme est en Delphi : on ne
connait pas le nom des fonctions que l'on appelle : un Call MessageBoxA est
beaucoup plus clair qu'un Call 00421546 !!!
Je rappelle la partie du code qui va nous servir :
* Referenced by a (U)nconditional or (C)onditional
Jump at Address:
|:00427277(C)
|
:004272CE 8BC3 mov
eax, ebx
:004272D0 F7EB imul
ebx
:004272D2 8BD8 mov
ebx, eax
:004272D4 8D55EC lea
edx, dword ptr [ebp-14]
:004272D7 8BC3 mov
eax, ebx
:004272D9 E80EE2FDFF call
004054EC
:004272DE 8B45EC
mov eax, dword ptr [ebp-14] ;
change la valeur de eax
:004272E1 50 push
eax ;
empile eax
:004272E2 8D55F0 lea
edx, dword ptr [ebp-10]
:004272E5 8B87BC010000 mov
eax, dword ptr [edi+000001BC]
:004272EB E8D8A7FEFF call
00411AC8
:004272F0 8B55F0 mov
edx, dword ptr [ebp-10]
:004272F3 58 pop
eax ;
dépile eax
:004272F4 E897C1FDFF call
00403490 ;
teste le code entré
:004272F9 7517 jne
00427312 ;
saute vers le message d'erreur si il
:004272FB 6A00 push
00000000
est faux.
:004272FD 668B0D54734200 mov
cx, word ptr [00427354]
:00427304 B202 mov
dl, 02
Pour comprendre ce qu'il se passe, le mieux est de remonter le code !
On part du jne 00427312 : saute vers le message d'erreur
Une ligne plus haut, on a un call 00411AC8 : on en déduis que c'est le call qui compare le bon code et le faux.
Encore plus haut, un pop eax : on dépile eax (ce qui implique qu'on l'a empilé un peu plus haut bien sur) : ca servira de parametre à la fonction suivante, notre fameux call! Mais dis donc, n'y aurait-il pas quelque chose d'interressant dans ce eax ??? Ca mérite d'y jeter un coup d'oeil... Lançons le débugger ( CTRL + L ), allons ligne 004272F3 et posons un ptit breakpoint avec F2. Ainsi dès qu'on arrivera sur cette ligne W32Dasm breakera ( zoli néologisme ...) et on pourra voir ce qu'il y a dans eax!
On clique sur run (ou on appuie sur F9) et paf le crackme se lance. On rentre un pseudo : superjuju, un code bidon : 121212 et on valide! Et si tout a bien marché tu devrais arriver dans W32Dasm.
Va voir la valeur de eax en cliquant sur le ptit bouton marqué eax dessus (jvais pas faire un cours sur le debugger de W32Dasm je le connais pas assez !). Pour l'instant ya une merde c'est normal on ne l'a pas encore dépilé ! On appuie sur F8 pour tracer (executer la ligne en cours) et là oh magie un nombre louche apparait !
Pour moi j'ai 252996160. On quitte le debugger (terminate), on teste et ... ca marche !!! Ce qui est normal d'ailleurs car on a analysé le code avant d'essayer de partir n'importe comment comme je fait d'habitude :))
3. Transformer le crackme en keygen
Après les banalités d'usage, je propose de ne pas s'arrêter là en si bon chemin! Essayons de faire un keygen :)) Ou plutot pour ne pas se faire chier à chercher la routine qui calcule le code, à la comprendre et la reprogrammer (ce dont je suis incapable d'ailleurs !) utilisons le crackme. Je propose de procéder ainsi : remplacer le fuckin' " Nop! Keep working! " par le numéro de série correspondant au nom entré ! Oui mais comment faire te demandes-tu ? Mais c'est très simple voyons ! il suffit encore une fois de regarder le code !
:004272DE 8B45EC
mov eax, dword ptr [ebp-14] ;
change la valeur de eax
:004272E1 50 push
eax ;
empile eax
Je récapépette : à la 2ème ligne dans eax on a le bon code. A la 1ère on met dans eax la valeur de dword ptr [ebp-14]. On en déduis que dword ptr [ebp-14] contient le bon code ... ce qui peut d'ailleurs etre vérifié avec le débugger.
Bon ya juste un truc qui peut foirer : le bon code sera t'il encore dans un coin de la mémoire quand on affiche le message d'erreur ? Et oui ! C'est notre jour de chance je te le rappelle ! On vérifie avec le debugger que dword ptr [ebp-14] contient encore le bon code quand le message s'affiche. Alors ya juste à changer le message par dword ptr [ebp-14].
Pour faire ceci regardons de plus près l'affichage de la boite :
:00427312 6A00 push
00000000
:00427314 668B0D54734200 mov
cx, word ptr [00427354]
:0042731B B202
mov dl, 02
* Possible StringData Ref from Code Obj ->"Nop!
Keep working."
|
:0042731D B8C0734200
mov eax, 004273C0
:00427322 E885F9FFFF call
00426CAC
On déduit par l'habitude d'utiliser W32Dasm que le message d'erreur est conservé à l'adresse 004273C0 ( voir la StringData Ref )
Ainsi on met dans eax le message d'erreur, et on appelle le call 00426CAC qui est l'affichage de la boite. Donc eax contient le message que l'on va afficher. Il serait interressant de changer la valeur de eax à dword ptr [ebp-14] pour afficher le numéro de série au lieu de ce foutu message d'erreur. Comment faire? Je prétend qu'il suffit de remplacer le mov eax, 004273C0 par mov eax, dword ptr [ebp-14]. Oui mais comment faire ?? Inverser un saut ou nopper un call on sait faire par coeur, mais les mov machin chose on connais pas le code ascii ??? Ah bon? regarde un peu plus haut, ligne 004272DE ! ohhh et oui c'est exactement ce que l'on veut ! et en plus cette instruction ne prend que 3 octets alors que le vieux call en prend 5 ! Donc ca va rentrer ! Quand je te dis que c'est notre jour de chance !!!!
Patch à réaliser : remplacer B8C0734200 par 8B45EC9090.
On lance le crackme, on met un nom, un code bidon, et hop une fenêtre s'affiche avec un serial ! On l'essaye, ca marche !!!!!
Conclusion
Bon ben voila c'était mon premier cours, j'espere que tout va bien que tu as tout bien compris, etc ... Ah ca prend plus de temps que je l'imaginais de faire un tut :) . Mes remerciments sont pour tout ceux qui font des tuts sans lesquels je ne saurais même pas ce qu'est qu'un crack !!! En particulier à la scene francaise :) Ya trop de noms pour que je les cite tous !!!
superjuju