Dans cet exemple on va donc s'attaquer aux progs qui demande un serial mais où ya pas de boutons du style "vérifier" ou "ok" qui lancent la procédure de vérification. Il est toujours utile de savoir comment les prendre car quand on en connaît un, on sait tous les faire :) Peut être qu'au bout d'un moment je vous aurais donné tous les exemples "types" ;)
En fait si le prog ne nous propose pas de vérifier le sérial c'est qu'il le vérifie sans cesse, tant que l'on interragi avec le prog (tant que la fenêtre est active sous windows). Deux possibilités : soit le prog vérifie (sans cesse) la taille du serial puis si c'est bon il vérifie le code en lui même. Ou alors il vérifie direct la validité du code.
Mais quelque soit le cas, nous utilisons toujours là même méthode : on fait un break la où le prog lit ce qu'on lui passe puis on trace jusqu'à la procédure en question.

Bon dans ce tut j'utilise WinDbg qui, il faut l'avouer est carrèment bien :) Microsoft l'ami des crackers et de la gratuité ? Je sais ça donne faux :) Mais bon le fait est là : winDbg est la solution de choix pour débugger sous XP.

Donc on ouvre winDbg, Choose Executable > Crakme2.exe. il nous propose un 'save Workbase information' on dit non. On clique sur le bouton des registres (celui avec un 0 et un x) pour faire apparaître la fenêtre correspondante. on clique sur 'Customize' pour définir l'ordre d'affichage des registres (pour moi : eax ebx ecx edx edi esi ebp esp eip passent en premier).
On fait ensuite Window > Tile Horizontally car la fenêtre du dead listing a tendance à se cacher derrière les autres.
On tape 'g' pour lancer le crackme. on le déplace à droite de l'écran parce que sinon il va nous faire chier pour lire ce qu'on fait (quand on débugge on peut plus le bouger). On entre notre code ('SIRIUS_BLACK' mais c'est mis automatiquement en majuscules) et on clique pas sur le bouton car yen a pas !!! (ben oui ca vous change de d'habitude :)

On passe sous winbg et on clique sur le 4ème bouton avec une feuille de papier (ya des espèces de vagues à côté) pour breaker. On entre alors 'bp GetWindowTextA' car c'est l'API qui va lire notre serial. On relance ('g') et on clique sur la fenêtre du crackme. BAM !! On break !!! Je vous avait prévenu qu'il tournait en boucle :p
On fait un Shift+F11 pour sortir du call (WinDbg est vraiment pompé sur Softice).
On voit ça :

push [ebp+0x08]
call 0040121C (GetDlgItemTextA) <-- c'est là d'où on vient
shl eax, 0x3
xor eax, 0x12
cmp eax, 0x52
jne 00401125 <-- saute vers BAD BOY
push 0042012
call 004010AA
cmp dl, 0x1
jne 00401125 --> saute vers BAD BOY
GOOD BOY

Juste quand on sort du premier call, dans eax ya la longueur de notre code : Ch (h comme hexa) soit 12d (d comme décimal). Cette valeur est décalée de trois bits sur bits sur la gauche (l comme left) puis xoré avec 12h. si le résultat vaut 52h alors on a la bonne longueur.
Avec SIRIUS_BLACK, la longueur est 12d soit 1100b (b comme binaire). On décale de 3 bits sur la gauche, ca nous donne 1100000b. Ensuite on xor avec 12h --> 72h.
Le résultat n'est pas 52h, c'est pas la bonne longueur.
Alors on réfléchie en sens inverse : à la fin on doit avoir 52h. Comme le xor est une opération réversible (je veux dire que (A xor B) xor B donne A) alors on peut trouver la valeur attendu avant le xor. 52 xor 12 ça donne 40h soit 1000000b. Puis on fait l'inverse du shl : un shr (décalage sur la droite) de 3 crans.
On obtient 1000b soit 8d. Le crackme attend donc un code de longueur 8.

On racourci notre code ('SIRIUS_B') et on recommence. Maitenant on arrive sur le second call. Notre code est placé sur la pile.
Après quelques saut on arrive ici :

mov eax, 402012 <-- adresse de notre code
mov ecx, [ecx] <-- ecx prend le contenu du code ou plutôt les 4 derniers caractères car 1-Un registre fait 32 bits et 2-Les chaines de caractères sont stockées à l'envers dans la mémoire. Si bien que ecx prend 'IRIS' soit 49,52,49,53 en hexa.
...
xor cl, al <-- al vaut 52h et cl est le premier caractère du code ('S'). Le résultat est cl=01. La code est donc devenu 49,52,49,01
mov dl, al <-- eax=52
...
shl edx, 8 <-- décalage de 8 bits, 52 devient 5200
or dx, ax <-- dx = 5200 or 52 = 5252
xor cx, dx <-- cx = cx xor dx = 4901 xor 5252 = 1b53. Le code devient donc 49,52,1b,53
shl edx, 10 <-- 5252 devient 52520000
or edx, eax <-- edx = 52520000 or 5252 = 52525252
xor ecx, edx <-- ecx = 49521b53 xor 52525252 = 1b004901
cmp ecx, 07114501 <-- résultat attendu
jnz 0040111F

Il faut donc avoir 07114501 à la fin.
Reprenons depuis le début : Notre code est mis dans un registre donc on prend que les 4 premiers caractères.
Le résultat est xoré avec 00000052
Le résultat est xoré avec 00005252
Le résultat est xoré avec 52525252
Comme le xor est réversible notre code est en fin de compte xoré avec 52520052.
Il faut obtenir 07114501. On xor ce nombre avec 52520052 et on obtient 55434553 soit 'UCES'. Comme la string est à l'envers on en déduit que le début du bon code est 'SECU'. Or le code est sur 8 lettres. Je refléchi au premier mot qui satisfait ça : SECURITY, je l'entre, c'est bon !!