Sujet :
Introduction au Reversing
Intro:
Le cracking est disons l'art de faire sauter les
sécurités d'un programme afin de pouvoir l'utiliser librement et gratuitement.
Tandis que le reversing est l'art de modifier un programme afin de lui ajouter
des fonctions ou bien d'optimiser certaines routines ou encore de détourner un
programme pour d'autres applications que celles pour lequel il a été conçu ou
pourquoi pas encore de le customiser selon nos désirs.
Bref, si le cracking n'exige pas de grandes connaissances en programmation et
en assembleur, le reversing lui en requiert quelques bonnes bases.
Je vous invite donc à consulter les cours d'Iczelion sur la programmation en
W32asm qui sont tout simplement les meilleurs.( www.w32asm.fr ).
Une bonne connaissance des API ainsi que du fonctionnement de Windows est aussi
nécessaire, pour ça le mieux étant de vous mettre à la programmation.
Thème :
Pour cette introduction on va commencer par
simple et rapide, le programme que nous allons reverser est le Bloc-Note de
Windows celui-ci étant une très bonne base pour s'entraîner. Nous allons tout
simplement ajouté à celui-ci un message qui s'affichera au lancement du prog.
pour nous souhaiter la bienvenue.
Outils nécessaire :
- W32Dasm9x
- Hiew 6.xx
Plan d'attaque :
Voici le schéma que nous allons suivre pour la
réalisation de ce projet :
- 1/ Chercher un endroit libre dans l'exécutable
et y insérer notre code
- 2/ Trouver l'Entry-Point du programme
- 3/ Mettre un jump à l'Entry-Point pour sauter directement vers notre code et
relever les instructions que notre jump écrasera
- 4/ A la fin de notre code mettre les instructions que nous avons écrasés et
mettre un jump qui retourne au programme normal (après notre jump a l'entry
point)
Ainsi notre programme au lancement sautera
directement vers nos instructions qui afficheront une MessageBox ensuite le
programme reprendra sont cours normal.
1/ Chercher un endroit libre dans l'exécutable
et y insérer notre code
A l'aide d'un éditeur Hexadécimal ouvrez
notepad.exe.
Les emplacement vides sont repérer par des 00, donc on cherche une parcelle de
00 suffisamment grande pour contenir quelques lignes de codes.
Pour cet exemple je me suis placé à l'offset D954
A cette adresse on va inscrire notre message de bienvenue, on se place dans
la partie ascii de notre editeur et on tape Bienvenue Netix.
On se placera ensuite à l'offset D970 pour y mettre les instructions.
Pour cela on va se servir Hiew qui nous permet d'écrire directement les
instructions en assembleur plutot que d'encoder avec des valeurs Hexadécimales.
- On ouvre Hiew
- on repère l'exécutable
- F4 puis Décode
- F5 puis l'adresse de notre code ( image base + offset ) 400000 + D970 =>
.40D970 ( pas oublier le . avant l'adresse )
Nous voulons afficher une MessageBox qui
contiendra notre texte "Bienvenue Netix". Voici le prototype de l'API
MessageBox :
int
MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);
int
désigne un entier qui recevra une valeur de retour de cette fonction pour
déterminer quel bouton à été pressé pour cette MessageBox , pour cette exemple
nous ne nous en serviront pas.
hWnd désigne le propriétaire de cette fenêtre ici nous mettrons 0 pour
aucun
lpText est un pointeur qui contiendra l'adresse de notre message ( l
offset de Bienvenue Netix )
lpCaption est un pointeur qui contiendra l'adresse de notre titre pour
la MessageBox ( on mettra le même pour notre message )
uType est un entier qui détermine le type de notre MessageBox ( l'icône,
quel type de boutons, etc...) ici on va mettre 0 pour obtenir une boite simple
Ces 4 valeurs sont les arguments de la fonction MessageBox
, en assembleur pour passer les argument a une fonction on les pousse dans
l'odre dans la pile juste avant le call de la fonction
push 0
push 40D954 // notre texte
push 40D954 // le titre de la boite de message
push 0 // le type de boite 0 = simple
call MessageBox // appelle la fonction
Maintenant nous allons repéré dans le programme
la syntaxe en Hexadecimal du call pour une messagebox.
A l'aide de W32Dasm on recherche dans les Imports User32.MessageBoxA puis on
clique dessus plusieurs fois , remarquez tout les call pour cette fonction ont
la même syntaxe en hexadécimal on la note donc.
de retour sous Hiew a l'offset de notre
code (.40d970) on fait :
- F3 pour passer en mode édition
- F2 pour passer en mode assembleur
- on entre donc nos instructions :
- push 0 (puis touche Entrer pour chaque instructions)
- push 40D954
- push 40D954
- push 0
- Touche Echap pour quitter le mode assembleur
- on entre la suite Hexadécimal pour notre call : FF15A8644000
- il nous reste plus qu'a mettre un jmp pour sauter au début normal du
programme.
2/ Trouver l'Entry-Point du programme
Rien de plus simple.
Dans le menu de W32dasm faite GOTO puis GOTO PROGRAM ENTRY POINT. Vous
arriver directement a l'adresse de celui-ci que l'on note.
Ici 4010CC
L'Entry-Point est l'adresse de la première
instruction qui va s'effectuer lors du lancement du prog.
3/ Mettre un jump à l'Entry-Point pour sauter
directement vers notre code
Tout d'abord on note les instructions qui vont
êtres écrasés par notre jump nous les replaceront a la fin de notre code ce qui
nous evitera le plantage .
Sous Hiew on fait :
Goto
(adresse de l'Entry-Point (.4010CC)) on passe en mode assembleur et on tape jmp
D970
D970 étant l'offset de la première instruction de
notre code repéré a l'aide d'un éditeur Hexa.
4/ A la fin de notre code mettre un jump qui
retourne juste après l'Entry-Point
Avant de retourné vers l'Entry-point on replace
les instructions que notre jump a écrasé soit en Hexa :
55
8BEC
83EC44
56
ensuite en mode assembleur on place notre jump
jmp 10D3
10D3 est l'offset ou le programme reprend sa
partie normale juste après notre jump a l'entry-point vers notre code.
Ce qui au
final donne ceci :
Listing Original |
//******************** Program Entry Point ******** :004010CC 55
push ebp
| ß La on placera notre jump :004010CD 8BEC
mov ebp, esp
| Ces 4 instructions
seront copié a la fin de notre :004010CF 83EC44
sub esp, 00000044
|
code :004010D2 56
push esi
| :004010D3 FF15E0634000 Call dword ptr [004063E0] ß notre code
reviendra par un jump ici :004010D9 8BF0
mov esi, eax |
Listing Modifié vu sous Hiew |
//******************** Program
Entry Point ******** :004010CC E99FC80000 jmp .40D970 ß Notre jump :004010D1 44
inc esp
| :004010D2 56
push esi | ces 2 instructions sont
apparues suite au changement créer
par notre jump mais on s’en fiche pas mal puisque qu’elles ne
seront jamais exécuter car notre après notre code un jump
reviendra juste après celles-ci. :004010D3 FF15E0634000 Call GetCommandLine ;USER32.dll
ß C’est Ici le retour de notre code :004010D9 8BF0
mov esi, eax ........ ........ //********************* Notre
Code ************* .0040D970 6A00
push 00
| .0040D972 6854D94000 push
0040D954 | Les 4 paramètres sur la pile
pour la message box .0040D977 6854D94000 push 0040D954 | .0040D97C 6A00
push 00
| .0040D97E FF15A8644000
Call MessageBoxA ;
User32.dll ß appelle la
MessageBox .0040D984 55
push ebp
| .0040D985 8BEC
mov ebp, esp
| Les 4 Instructions
qu’il y avait a l’entry point .0040D987 83EC44
sub esp, 00000044
| .0040D98A 56
push esi
| .0040D98B E94337FFFF jmp .4010D3 ß On
retourne au déroulement normal du prog.
|
PS: N'essayer pas de trouver votre code sous
W32dasm , il n'y figurera pas du fait que les sections n'ont pas été modifié
suite au rajout de notre code mais ceci
fait partis d'un prochain tutorial sur les sections et le PE-header