Cours n°1

L'hexadécimal et les types de sauts


 

Comprendre l'hexadécimal

Tout d'abord ouvrez un programme avec WinDasm (si vous ne savez pas l'utiliser allez voir le cours précédent). Vous devez apercevoir des lignes semblables à celle-ci :


Exemple :

:0040100E E839000000 Call 0040104C
:00401013 83F807 cmp eax, 00000007
:00401016 EB1A jmp 00401032
:00401018 6A40 push 00000040

Le numéro en bleu est l'adresse de la ligne pour WinDasm.
Le nombre en blanc est l'instruction en hexadécimal correspondant aux instructions rouges. C'est cela qu'on recherchera dans l'éditeur hexadécimal et qu'on modifiera.
Les mots et nombres en rouge sont les instructions en assembleur du programme désassemblé. C'est en fait la "traduction" de l'instruction en hexadécimal en blanc.
 


En décimal vous comptez comme ça (ou du moins je l'espère...) :

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, ...

Et bien en hexadécimal il y a non pas 10 chiffres mais 16 (les 10 du décimal + les 6 lettres A,B,C,D,E,F) on compte donc de cette manière :

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10, 11, ...

Donc par exemple 15 en décimal s'écrira F en hexa, 16 => 10, 17 => 11, 26 => 1A, etc...

Les adresses de WinDasm sont en hexadécimal et dans l'ordre croissant, mais il ne les met pas toutes comme on peut le voir dans l'exemple ci-dessus. C'est tout simplement car l'adresse correspond en fait non pas à l'instruction mais au premier octet de l'instruction (un octet est composé de 2 chiffres hexadécimal) donc par exemple à l'adresse 401016 "EB1A" comporte 2 octets ainsi l'instruction "6A40" aura pour adresse 401016+2 soit 401018.


Qu'est-ce qu'un saut ?

Je vais en premier lieu vous montrer le schéma d'une protection utilisée la plupart du temps. Une fois le code rentré il le compare avec le bon code, si c'est pas le même il saute pour arriver vers le mauvais message sinon il affiche le bon message et continue sa route vers de nouvelles aventures en passant au dessus du mauvais message.



JNE est un saut conditionnel. Il saute si le code est faux dans ce cas là (saut si inégal) ou continue sa route si le code est bon.
JMP ( = Jump = Saut) est aussi un saut mais inconditionnel puisqu'il saute obligatoirement, même au bord d'un précipice il sautera quand même :-P ...

Et ça donne à peu près ça en assembleur (les adresses sont fictives et je n'ai pas mis l'intégralité de ce passage comme notamment les instructions pour afficher les messages pour ne garder que le nécessaire) :

:00401001 #### Teste si le code est bon
:00401002 75## jne 00401003

Le JNE saute uniquement si le code n'est pas bon.

* Possible StringData Ref from Data Obj ->"Le code est bon"

Windasm indique que "Le code est bon" est le message d'une boîte de dialogue.

:00401003 EB## jmp 00401005

Le JMP est un saut. Le numéro à sa droite est l'adresse où il va sauter.

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401002(U)


Il indique que la portion de code suivante est appelée par un saut conditionnel (l'adresse de celle-ci est à gauche du "(U)" : 00401002)

:00401004 #### push ####

* Possible StringData Ref from Data Obj ->"Le code n'est pas bon"

:00401005 #### ####

Après ces schémas, vous avez donc compris (du moins je l'espère) que c'est le jne qu'il faut changer. Mais vous allez me dire :


Comment change-t-on un saut conditionnel ?

Regardez le schéma en assembleur et plus précisément la ligne 00401002 avec le jne. Dans le code hexa, on voit 75##. Et bien le 75 c'est notre jne. Tout comme le jmp qui correspond à EB.

Voici une petite liste de sauts conditionnels que vous pourrez trouver le plus souvent :

Instruction Valeur hexa Description
jne 75 ou 0F85 Saut si inégal
je 74 ou 0F84 Saut si égal
jmp EB ou E9 Saut
nop 90 Pas d'opération

Pour modifier un saut, il suffira donc de rechercher sa valeur et de la modifier avec l'éditeur hexadécimal. Par exemple pour le schéma ci-dessus on mettra un je (il sautera à "Le code est bon" si le code est mauvais) ou nop (il ne sautera pas du tout et ira donc directement vers "Le code est bon") à la place de jne.

Pour information les 75, 74, EB sont des sauts courts et 0F85, 0F84, E9 des sauts longs. Après les sauts courts on a le nombre (en hexa) d'octets sautés (un octet est un nombre de 2 chiffres qui va donc en hexa de 00 à FF comme peut l'être 75 ou 90) et donc pour les sauts de plus de FF (soit 255 en décimal) octets on utilise des sauts longs à la suite desquelles on met l'adresse de destination. Par exemple EB02 représente un saut (JMP) de 2 octets.

Après la théorie place à la pratique, dans le cours n°2 nous essaierons de cracker un crack-me.

Passer au cours suivant >>>
[ Cracker un crackme ]