IV] SERIAL FISHING ET SELFKEYGENING


1) un peu de théorie

Nous allons partir à la péche au sérial. Dans le cours précédent, nous avons identifié
la routine de verification du sérial. Dans ce tutorial, je montrerais une autre méthode
pour arriver au même endroit.

On va utiliser les fonctions de l'API pour windows. Quand un programme veut afficher
une boite de message, il utilise par exemple la fonction MessageBoxA. Pour récupérer les données
entrées au clavier par l'utilisateur et pour connaitre le nb de caractère entrées, le programme
utilise la fonction GetDlgItemTextA. Cette fonction demande des paramétres pour savoir dans
l'ordre, quel est le nb maximum de caractères à recuperer, ou mettre le texte récupéré, l'identifiant du
controle, la handle de la fenetre. Le programme va transférer ces paramétres par la pile.
A la fin, la fonction retourne dans le registre EAX le nb de caractères saisis et stocke le texte a l'adresse indiquée.

Voila comment cette fonction se présente:

push 29 ......................................--> le nb maximum de caractères en hexadecimal (soit 41 en décimal)

push 4d81e0...............................--> adresse ou elle va mettre le texte

push 0c80...................................--> identifiant du controle

push 880....................................--> handle de la fenetre ou se trouve le controle

Call dword ptr DS: [<&USER32.getdlgitemtexta].....--> appel de la fonction getdlgitemtexta

si on saisi comme nom loloko, la fonction met loloko à l'adresse 4d81e0 et eax est égal au nb
de caractères saisis c'est à dire 6. Pour recupérer le sérial, la fonction getdlgitemtexta doit
être appelée à nouveau

On va donc mettre un breakpoint sur cette fonction. De cette façon, on arrivera avant la routine
qui calcule le bon sérial en fonction du nom, et compare le sérial qu'on a entré avec le bon sérial.

2) la pratique

Pour mettre un breakpoint sur une fonction, cliquez sur le menu View puis sur Executable modules.
Selectionnez le programme winzip, clic droit et selectionnez view names. Vous obtenez une liste des
fonctions (si les fonctions ne sont pas triées par ordre alphabétique, clic droit et sort by names)
Faites un clic droit sur la fonction getdlgitemtexta et selectionnez "set breakpoint on every références".


loloko

loloko

pressez F9, Winzip apparait avec le nagscreen et cliquez sur "Enter registration code", rentrez loloko
comme nom et comme serial 123456. Ollydbg break sur le premier GetDlgItemTextA, remontez 3 lignes
plus haut et vous voyez sur la partie droite que le nom a été mis dans un buffer qui correspond a l'adresse
4E6574, et eax est à 6 dans les registres (soit le nb de caractères du nom loloko). Rappuyer sur F9.
On arrive en 40DD19 sur le deuxième getdlgitemtexta. Le serial est mis dans un buffer qui correspond
à l'adresse 4E65A0 et eax est à 6 (le nb de caracteres du serial)

getdlgitemtexta serial winzip 9.0


appuyez sur F8 jusqu'a ce qu'on soit à l'adresse 40DD3F. La, ou retrouve le call de verification du sérial
du tut précedent. si al=0 à la fin du call, le serial est faux, si al =1 le serial est valide.

Si on rentre dans cette routine avec F7, on pourra sans doute voir à un moment donné le bon serial dans
les registres ou dans la pile. Appuyer sur F7 pour rentrer dans le CALL, puis sur F8 pour tracer en regardant
les registres. A la ligne 40DAFE, vous pouvez voir le serial pour la premiere fois dans la pile.

.
registres et piles


Remarque1: pour loloko, le bon serial est C460066B, mais il y a aussi un autre sérial valide que l'on peut
voir dans les registres 50272164. Pour un nom, il y a donc deux serials possibles.

Remarque2: si vous voulez savoir ou winzip stocke vos informations d'enregistrement (nom et serial) mettez
un breakpoint sur la fonction RegSetValueExA --> le nom est d'abord stocké dans la base de registre, puis
le serial number. Pour acceder à vos informations d'enregistrement, clic sur l'icone demarrer de Windows, allez
dans executer et tapez regedit (vous vous trouvez alors dans la base de registre)
Dans HKEY_Current_User\Software\Nico Mak Computing\Winzip\WinIni et dans 
HKEY_LOCAL_MACHINE\Software\Nico Mak Computing\Winzip\WinIni vous retrouvez votre nom et serial
De la même façon, Pour un utilisateur non enregistré, on a la date d'installation, la derniere date d'utilisation et le
nb de jours d'utilisation dans: HKEY_Current_User\Software\Nico Mak Computing\Winzip\rrs


base de registre.

3) faire un selfkeygen avec la message box

On va se compliquer un peu la tache. Ce qu'on veut, c'est modifier Winzip pour que dans la procédure
d'enregistrement, au lieu de nous dire que le code est est incorrect quand on saisi n'importe quoi,
il nous donne le bon sérial. Quand le serial est mauvais le programme saute en 40D361. On va expliquer
un peu ce qui se passe alors:

keygenerateur winzip 9.0

le programme execute d'abord un sous programme (call 40D624) puis il transmet comme paramétre l'index
de la data string "Incomplete or incorect information" (le push 28Edu tutorial 3). Il execute ensuite un
sous programme (call 46FE95) qui recupere l'adresse de la string data et la met dans eax.
C'est un troisieme call ( le call 45B054) qui va afficher le message d'erreur.
Pour afficher la boite de dialogue, le call 45AFDD a besoin ici de 4 arguments: l'index de la string, le texte à afficher,
un deuxième argument, un troisième argument --> on se rend compte que le prog veut 4 arguments et pas
3 comme affiché quand on regarde la pile juste avant l'execution du call.

Ce qu'on va faire, c'est simplement changer l'adresse du texte a afficher. A la ligne 40DAFE on avait regardé
la pile, et on avait  notre serial valide "C460066B".

Par contre il y a un problème, winzip efface le contenu du vrai sérial à la fin de la routine de verification.
Il faut donc se debrouiller pour stocker ce serial dans une adresse memoire vide avant que winzip l'efface.
A la ligne 40DAFE ou on voit le serial, on va rediriger le code vers un bout de code a nous qui va se charger de
sauver le serial valide dans une adresse memoire sure. Il nous faut donc une zonne vide pour ecrire notre bout de code
--> on choisi l'adresse 4C21A0 pour ecrire notre bout de code.  Il nous faut aussi une zonne memoire vide pour
stocker le serial valide --> on choisi l'adresse 4EDD00 pour stocker le serial
  

A la ligne 40DAFE (la ou on voit notre serial dans la pile pour la premiere fois), on a le bout de code suivant:
l'instruction d'aprés LEA EAX, DWORD [ebp-340] met l'adresse qui contient le serial dans eax.

codejump

on va remplacer le CALL par un JMP "notre code" (jmp 4C21A0)

jmp notre code

A l'adresse 4C21A0, on ecrit notre bout de code pour stocker le serial valide en 4EDD00

code

Notre bout de code sauvegarde d'abord les registres avec Pushad (car on va utiliser ecx et edx et on veut
pouvoir les retablir à l'identique aprés). Ensuite il faut recuperer le serial. On a EAX = 12ED98 et cette adresse
contient notre serial. On ne peut pas copier notre serial en 4EDD00 avec une seule instruction.
Si on utilise mov ecx, eax, ça va copier 12ED98 dans ecx donc c'est pas bon. On veux copier le contenu de eax
dans ecx donc on utilise des braquets pour eax --> mov ecx, [eax]. Mais de cette façon, on recupere juste les
4 premier caracteres du serial dans ecx --> ECX = 43 34 36 30 --> soit en Ascii "C460". Il faut donc recuperer
la derniere partie du serial dans un autre registre par exemple EDX. On recupere les 4 derniers caracteres du
serial avec l'instruciton mov edx, [eax+4]. Ensuite, on copie nos deux parties de serial ecx et edx
dans 4EDD00 et 4EDD04 respectivement. On restaure les registres avec Popad. On execute le call ecrasé par
notre jump 'notre code" et on retourne juste aprés notre jump "notre code" grace à un jmp. L'adresse 4EDD00
contient le sérial valide aprés notre bout de code:

serial dump

C'est pas fini, il faut remplacer l'adresse qui pointe vers le message "Incomplete or Incorret Information" par notre adresse
4EDD00 qui pointe vers le serial valide. On va ecraser le call 46FE95 et le push eax pour mettre notre push 4EDD00:
Remarque: avec la modif ollydbg se rend bien compte qu'il y a 4 arguments (clic droit , analysis, analysis code)

modif message d'erreur


On execute winzip et quand on rentre comme nom loloko et comme serial 123456, on a une drole de fenetre qui s'affiche
. On a reussi à faire notre keygénérateur...

winzip 9.0 cracking


4) faire un selfkeygen avec SendDlgItemtextA

Un selfkeygen avec une messagebox, c'est cool, mais si on veut recuperer le serial dans le bloc note pour le coller
quelque part, c'est pas possible. C'est pour ça que ça serait sympa de recuperer le serial valide dans le champ texte
qui nous sert à ecrire le faux serial. On a vu dans le cours 3 que la fonction GetDlgItemTextA sert à recuperer ce qui se
trouve dans un champ texte. Il existe une autre fonction trés semblable SetDlgItemTextA qui sert elle à affecter du texte
dans un champ texte.

Voila la fonction GetDlgItemTextA qui recupere le serial:

getdlgitemtexta serial

La fonction SetDlgItemTextA demande elle trois parametres:
- l'adresse du texte à afficher --> 4EDD00
- Control ID du champ texte --> C81
- handler de la fenetre --> dans notre cas, EBX contient encore le handler de la fenetre

On va garder notre routine qui stocke notre serial valide en 4EDD00. Par contre, on va remplacer le code qui affiche
notre serial dans une message box par notre fonction SetDlgItemTextA. Les modifications sont en rouge:

0040DD8F  CALL 0040D624
0040DD94  PUSH 004EDD00             ; /Text = "C460066B"
0040DD99  PUSH 0C81                        ; |ControlID = C81 (3201.)
0040DD9E  PUSH EBX                         ; |hWnd
0040DD9F  CALL [004C44E8]            ; \SetDlgItemTextA
0040DDA5  NOP
0040DDA6  NOP
0040DDA7  NOP
0040DDA8  NOP
0040DDA9  NOP
0040DDAA  INC DWORD PTR DS:[4E40C0]

Dans les imports, on voit que la fonction SetDlgItemTextA peut être appelée par un CALL [004C44E8]
On a aussi noppé la ligne suivante (0040DD42  ADD ESP,10) car sinon on a une erreur de pile.
Et voila le résultat:


setdlgitemtexta



cours precedent                                                                                                                               cours suivant