Comprendre l'assembleur

Un ordinateur est une machine qui traite les informations d’une façon automatique, ces informations peuvent être de différents type (image, son, nombre…), donc ce qu’il faut savoir c’est qu’une information se présente dans l’ordinateur comme une suite ordonnée de 0 et 1.

Mais comment un ordinateur traite un programme ? Vous avez déjà écrit un programme dans un langage binaire, je pense que ça sera impossible vous n’aurez devant vous que des ligne de 0 et 1 ! Donc on a chercher a trouver une codification plus facile a manier, alors surgit l’hexadécimal plus facile que le binaire, mais pose un autres problème, les codes écris en hexadécimal reste aussi très difficile a déchiffrer, exemple : l’addition est représenter en hexadécimal par C6,  je ne pense pas que vous l’avez devinez  mais si je vous dit ADD, la je vois que tout le monde la vite compris ADD c’est l’abréviation de addition elle est plus facile à retenir. Vous venez de connaître le langage assembleur, c’est un ensemble de code ou abréviation (facile a retenir) du genre ADD, MOV, XOR… qui n’est rien d’autre que la "surcouche" du langage machine donc c’est le langage de bas niveau c’est lui qui est le plus proche de la machine : quand vous écrivait un programme en langage assembleur il est traduit directement en langage machine. Mais si vous écrivait un programme avec un langage évolué (Delphi, Visual Basic, Fortran, Langage C, Visual C++ et pleins d’autres) l’ordinateur  ne peut pas le comprendre donc il doit être traduit en langage machine grâce a un compilateur ou interpréteur, mais ce-ci n’est pas l’objectif de ce cours.

Pour information l’hexadécimal est un système de numérotation ou les nombres sont représentés à l’aide de 16 chiffres, pour cela on prend les chiffres arabes (0 1 2 3 4 5 6 7 8 9) et les six premiers caractères alphabétique (A B C D E F). Vous me direz pourquoi prendre des caractères alphabétiques ? La réponse est simple il y a pas d’autres chiffres que 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 dix en total, on a pas inventer d’autres  donc on les prends de l’alphabet elle doit aussi servir non ? On obtient ça à la fin :

Décimal Binaire Hexadécimal
0 0000 0
1 0001 1
2 0010 2
3 0011 3
4 0100 4
5 0101 5
6 0110 6
7 0111 7
8 1000 8
9 1001 9
10 1010 A
11 1011 B
12 1100 C
13 1101 D
14 1110 E
15 1111 F

NOTE : si je vous donne un nombre, par exemple 354, pouvez vous savoir si c’est un nombre décimal ou hexadécimal ?! Bien sur que non  donc pour enlever ce conflit on met après le nombre le caractère h pour l’hexadécimal et un d pour dire que c’est du décimal. Donc ça nous donne : 354h le petit h (ou d) ne fait pas partie du nombre 354 (il ne faut pas le noter, c’est qu’un signe pour dire que c’est de l’hexadécimal).

 Les instructions Assembleur :

Vous avez maintenant une idée sur ce qu’est l’assembleur,  mais avant d’aborder les instructions assembleur il faut savoir ce qu’est un bit, octet, registre…
Un bit peut être décrit comme étant la plus petite unité de la mémoire, et un octet est constitué de 8 bits, [1 Ko (kilo octets) = 210 octets = 1024 octets].

Ce que vous devez encore savoir c’est qu’un registre est un espace mémoire ou on peut stocker des valeurs, donc ces emplacements ou se trouvent les octets sont des adresses mémoires, segment & offset : imaginez un tableau, par quoi est-il constituer ? des lignes et des colonnes, donc un espace mémoire c’est comme une cellule dans un tableau, si on veut donner une adresse pour cette cellule, elle doit être constituer de deux adresses celle de la colonne et l’autre de la ligne, dans notre cas l’adresse de la colonne (partie haute) c’est le segment et l’adresse de la ligne c’est l’offset, en général ça s’écrit comme ça : segment:[offset] mais pas obligatoirement. Il existe plusieurs type de registres et avec chacun un but bien précis (ça dépend)

Sur ce cours je ne vous donne pas toutes les instructions mais l’essentiel à connaître:

L’instruction MOV :

Cette instruction copie une source a une destination, elle s’écrit sous cette forme MOV [destination],[source] je donne un exemple : mov eax,00000001 donc cette ligne permet de mettre dans le registre eax la valeur 1

* eax est un registre 32 bits
* al registre de 8 bits (niveau bas du registre eax)

Revenons a notre exemple mov eax,01 il sera représenter comme suit : eax=00000001 retenez bien que c’est q’un simple exemple et que eax peut avoir d’autres valeurs.

L’instruction CALL :

Cette instruction appelle une procédure (sous routine) : une routine de génération du code d’enregistrement par exemple, le CALL peut aussi appeler une boite de dialogue (nag) si vous ne savez pas ce qu’est un nag alors passez voir la rubrique Protection sur le site, il y a une liste des protections software (standards).
Un CALL s’écrit toujours de cette façon : call [adresse] sachez bien qu’un call est  suivi d’une adresse du genre CALL 004465B8.
(pas toujours)
A la fin de la procédure que le CALL appel il y a toujours un RET. Qui revient a la ligne juste après le call, nous verrons tout ça sur les prochains cours, il faut juste bien suivre.

L’instruction PUSH & POP :

L’instruction PUSH permet de mettre une valeur dans la pile, PUSH [valeur]
& POP permet de prendre une valeur depuis la pile et de la mettre dans un registre, POP [registre]

* esp est un registre pointeur 32 bits

L’instruction CMP :

Cette instruction permet de comparer entre deux variables CMP [variable],[variable]
Donc pour comparer eax et ebx cette instruction soustrait eax à edx (eax-ebx), à noter qu’aucune variable n’est modifié mais seulement un indicateur dit FLAG.

Exemple :   CMP EAX,EBX
                JNE 00406543
La 1ère ligne compare eax et ebx (eax-ebx) si eax-ebx=0 cela voudra dire que l’indicateur de l’instruction JNE sera mis à zéro (jne = saut si pas égal à 0) devinez la suite ;-)
Cette instruction est toujours suivit d’un saut conditionnel.

* flag c’est un indicateur que des instructions utilises (tel que les sauts conditionnels) afin de vérifié le résultat d’une opération, donc une instruction dépend de la valeur trouvé dans un indicateur.

L’instruction J[?] Les sauts conditionnels :

Il y a beaucoup de sauts conditionnels leurs travail c’est de sauter a une adresse précise, je prend comme exemple JE saute si égal, donc si la condition est vrais le saut s’effectue à la partie souhaiter du programme, donc ce qu’i faut comprendre c’est qu’un saut (conditionnel) ne peut s’effectué sauf si la valeur que contient l’indicateur est vérifié. L’instruction CMP que nous avons vue précédemment compare entre deux valeurs mais elle ne modifie aucune (des valeurs) ce qu’elle modifie c’est l’indicateur, et cette valeur qu’il contiendra, influencera directement sur le saut ! Comme l’explique le tableau suivant :

Instructions Assembleur

Code Hexadécimal

Description

Indicateurs

JNE 75 ou 0F85 Saute si pas égal (non égalité) ZF=0
JE 74 ou 0F84 Saute si égal (égalité) ZF=1
JA 0F87 Saute si au dessus (supérieur) CF=0  et ZF=0
JNA 0F86 Saute si ce n’est pas au dessus (non supérieur) CF=1 ou ZF=1
JL 0F8C Saute si c’est inférieur SF!=OF
JLE 0F8D Saute si c'est inférieur ou égal ZF=1 ou SF!=OF
JB 0F82 Saute si en dessous (inférieur) CF=1
JNB 0F83 Saute si pas en dessous (non inférieur) CF=0
JG 0F8F Saute si plus grand ZF=0  et SF=OF
JNG 0F8E Saute si pas plus grand ZF=1 ou SF!=OF

Exemple : JE 00402A3F (saute si égal, à l’adresse 00402A3F)
Il y a encore d’autres mais c’est suffisant, une autre chose le JLE JGE JG JL sont utilisé très souvent pour la limitation du temps dans les logiciels

* ZF [Zero Flag ] si le résultat est nul cet indicateur sera mis à 1
* CF [Carry Flag] est le bit de retenue.
* SF [Signe Flag] dans le cas d’un
résultat signé il est mis à 1
* OF [
Overflow  ] Flag utilisé dans le cas d’un dépassement

l’instruction XOR : [90h]

C’est le ou exclusif  dans le principe est simple:

0 xor 0 donne 0
0 xor 1 donne 1
1 xor 0 donne 1
1 xor 1 donne 0

Ce qui veut dire que xor modifie le bit d’une variable tel que le registre eax voila un exemple :
xor eax, eax  cette instruction permet de forcer eax à 0.

L’instruction JMP : [EBh]

Ici c’est le contraire d’un saut conditionnel abordé en haut, car c’est un saut inconditionnel. Qu’est ce qu’il fait ? il saute tout simplement mais pas n’importe ou puisqu’il est toujours suivi de l’adresse vers laquelle il doit sauter  exemple : JMP 0040564B

L’instruction NOP : [90h]

Comme son nom indique (no operation) elle ne fait rien, ouais rien, mais quel intérêt ? Vous verrez par la suite dans les prochains cours son utilité (indispensable).

Cours précédant :
<< Introduction au Cracking

Cours suivant :
Bien débuter >>