Cours n°3 - Vous aimez la pêche?

 

        Ce dont vous avez besoin : Olly, PEID et le crackme : FishMe1

       

Analyse du logiciel

        PEID ne trouve toujours rien, ce n'est pas grave de toute façon c'est encore de l'assembleur.

 

Observation

        On lance notre petit crackme. Une zone de texte et un bouton pour vérifier qui est désactivé. Bon dans des cas comme celui-ci, soit le serial est unique soit il est calculé grâce à quelque chose d'extérieur au programme (Nom de l'utilisateur du PC par exemple).

 

Analyse du code

        Je n'ai pas codé la protection la plus difficile qu'il soit, loin de là. Ici la difficulté réside surtout dans le fait qu'il y ait plus de code que dans les crackmes précédents. En effet, une gestion de fenêtre demande plus de programmation qu'une simple MsgBox. Mais on est encore loin de ce à quoi peut ressembler un programme écrit en VB par exemple!

        Je me doute que vous n'avez pas lu tous les liens que j'ai proposé dans l'introduction, c'est pourquoi je vais vite faire un rappel sur les dialogbox.

        L'apparence des dialogbox est créée à partir d'un fichier ressource (.rc), que l'on peut facilement compiler grâce à un éditeur de ressources comme ResEd.

        Grâce aux dialogbox, c'est Windows qui gère toute l'initialisation des contrôles (boutons, zone de texte,...) de notre fenêtre (d'autres choses diffèrent aussi mais je ne connais pas tout).

        Lorsqu'un évènement se produit sur la fenêtre (clic, déplacement, dimensionnement, ...) Windows envoie un message à la procédure de notre fenêtre, indiquant l'événement qui s'est produit ainsi que les paramètres de cet évènement (par exemple lors d'un clic, il envoie l'ID du contrôle cliqué en paramètre).

        Les événements non gérés par notre procédure sont gérés par Windows (à condition de retourner FALSE dans eax).

        Enfin tout ceci ne vous concerne pas vraiment mais en sachant ce qui est nécessaire à la gestion d'une dialogbox, il est plus facile de comprendre ce qui concerne le test du serial ou pas.

        Si vous voulez vraiment en savoir plus, lisez les tutos d'Iczelion. Sinon voici une source d'une dialogbox commentée. Regardez à la fois la source et l'exécutable (dans Olly) pour bien voir la structure de base d'une dialogbox (une fenêtre "normale" n'a pas une structure totalement différente).

       

        Bon revenons à nos moutons. C'est surtout le cracking qui vous intéresse je suppose alors c'est partit pour le serial Fishing ;).

        Ici pas question d'exécuter en pas à pas, vous allez rentrer dans les APis et vous n'arriverez à rien. Travaillons logiquement!

        Si vous avez un peu analysé la source que j'ai fournie, vous avez vu que lors de l'appel de l'API DialogBoxParam, on fournissait aussi l'adresse de la procédure liée à la dialogbox.

       

        Nous savons donc que notre procédure se trouve en 00401028.

        Si nous regardons en 401028, nous voyons que mis à pars les constantes qui ont été remplacée par leurs valeurs effectives et les .IF, .ELSEIF,... qui ont été remplacé par des CMP... JE, JZ, ... nous retrouvons une structure semblable à celle que je vous ai donné dans la source.

        En jetant un coup d'oeil rapide aux définitions des APIs qu'Olly nous fournit et en gardant en tête qu'un bouton est désactivé, nous voyons des choses intéressantes:

       

        (1) Une msgbox qui nous indique qu'on à réussi.

              Si vous avez besoin d'infos lisez les cours précédents.

        (2) Une fonction qui récupère un texte d'un contrôle.

               ¤ Count = le nombre de caractères qui seront récupérés (souvent la taille du buffer)

               ¤ Buffer = adresse du buffer (Où va être enregistré le texte qui se trouve dans la zone de texte)  

               ¤ ControlID = ID du contrôle dont on veut récupérer le texte (son nom en gros, pour trouver l'ID d'un contrôle j'expliquerai après)       

               ¤ hWnd = handle de notre dialogbox (qui permet de la distinguer parmi les autres fenêtres)

               S'il n'y a pas eu de problèmes, elle retourne dans eax la longueur du texte récupéré.

        (3) Une fonction qui active ou désactive un contrôle (Pour Windows, une fenêtre ou un contrôle est une fenêtre).

               ¤ Enable = valeur booléenne (qui ne prend que 2 valeurs : VRAI ou FAUX) qui indique si le contrôle est disponible ou pas.

               ¤ hWnd = handle du contrôle à rendre disponible ou pas

        Pour voir un peu mieux ce qui se passe posons un BP (Break point en appuyant sur F2) juste en dessous du Call GetDlgItemTextA en 004010BC. J'ai posé mon BP ici parce que c'est le point de départ. On ne saurait pas tester un serial sans l'avoir récupéré de la zone de texte! Appuyez sur F9 (Play). Cherchez la fenêtre (elle n'est pas dans la barre des tâches) et appuyez sur '1' par exemple. Attention Olly va breaker directement donc vous ne saurez rentrer qu'un caractère à la fois. Ceci nous apprend que la fonction GetDlgItemText est appelée à chaque fois que l'on rentre un caractère dans la zone de texte. Ça pourrait être aussi la fenêtre qui renvoie chaque frappe du clavier mais comme on teste l'ID de la zone de texte (CMP AX,0C9 en 40109F) avant d'appeler GetDlgItemText c'est donc la zone de texte qui joue ici (Vous comprendrez mieux par après).

 

        Je vais vous donner 2-3 raccourcis d'Olly supplémentaires assez intéressants:

        Si vous voulez voir où saute un saut, voir ce qu'il y a dans un CALL,... (je ne parle pas ici d'exécution, je parle lorsque vous lisez le code), cliquez sur la ligne du saut, du call ou autre et appuyez sur ENTER.

        Si vous voulez revenir en arrière (après avoir poussé sur ENTER par exemple, appuyez sur '-').

 

        Regardons ce qui suit :

    On pousse 4 choses dans la pile :

    1) 6 (correspond justement à la longueur de la chaîne qui suit ("Serial") )

    2) 403000 (Olly comprend que ce n'est pas un nombre mais bien un pointeur vers la chaîne de caractères  "Serial" qui se trouve en 403000)

    3) eax est la valeur retournée par la fonction GetDlgItemText qui se trouve juste au dessus. Ça correspond à la longueur de la chaîne de caractère qui se trouvait dans la zone de texte.

    4) 403020 est justement l'adresse du buffer dans lequel on a placé le texte de la zone de texte (Jetter un oeil à la fonction GetDlgItemText en 004010B7 pour vérifier)

    Après le CALL, on teste si eax vaut 0 (OR eax,eax).

    S'il vaut 0, on ne saute pas, donc EnableWindow sera à FALSE et donc notre bouton (Olly l'indique clairement) ne sera pas disponible.

    Donc pour pouvoir activer le bouton il faut que eax soit différent de 0 après le CALL 00401000.

    Voyons ce que le call 00401000 fait. Appuyez sur F8 jusqu'à arriver à la ligne du CALL 401000. Sur cette ligne appuyez sur F7 pour rentrer dans le CALL.

     Voici la fonction :

    J'ai commenté sans regarder le reste, si vous regardez l'ordre de ce qui a été poussé dans la pile, vous retrouverez facilement à quoi correspondent le premier paramètre, le 2eme,...

    Voici donc ce que fait la fonction : On copie le pointeur de tête de pile dans EBP (EBP pointe donc sur le sommet de la pile) ceci afin de pouvoir accéder facilement aux paramètres passés à la fonction.

    On pousse ensuite dans la pile les registres qui seront modifiés par la fonction sauf eax vu qu'il doit contenir une valeur de retour (lorsque l'on crée une fonction c'est mieux que les valeurs restent identiques avant et après l'appel de la fonction, c'est pour cela qu'on sauve les registres que l'on modifie).

    On met ensuite eax à 0.

    Après on compare l'avant-dernier paramètre (si vous regardez ce qui est placé dans la pile avant l'appel de la fonction vous verrez que cet avant-dernier paramètre est la longueur du serial entré) et le premier (la longueur du bon serial), si ces longueurs sont différentes on saute et eax vaudra 0.

    Ensuite on place dans EDI le dernier paramètre (l'adresse du buffer), dans ESI le 2eme paramètre (l'adresse du bon serial) et dans ECX la longueur du serial.

    On décrémente ECX d'une unité. En effet le premier caractère commence en 0, donc si la longueur est 2 par exemple je dois commencer en 1 et non en 2 (donc longueur -1)

    La fonction qui suit (REPE instruction) répète instruction jusqu'à ce que ZF = 0 ou CX=0. A chaque itération (exécution) CX est décrémenté.

    CMPS sert à comparer byte à byte 2 caractères. Elle positionne le ZF à 1 si les caractères comparés sont égaux et à 0 s'ils ne le sont pas.

    Donc REPE CMPS compare 2 chaînes jusqu'a ce qu'un caractère soit différent ou qu'on soit arrivé à la fin de la chaîne (val dans ECX).

    Ensuite si le ZF est à 0 (donc il y a eu un caractère différent), on saute et EAX ne sera pas mis à 1, sinon on ne saute pas et on force EAX à 1.

    Pour finir, on dépile et on quitte la fonction.

 

    On vient donc de voir que le serial doit être égal à .... "Serial" !  ;)

 

 

Bon crack,                  

Crisanar         

[ << Cours n°2 ] [ Cours n°4 >> ]

 

Dernière mise à jour le 13/08/2004 18:46