Vous êtes sur la page 1sur 30

Assembleur x86

Développement bas-niveau sur un système Linux


Sommaire

 Vocabulaire
 Les différentes architectures
 Les outils
 Les registres
 Les instructions basiques
 Les appels système
 TP et corrections
 L'ordonnancement mémoire
Vocabulaire (1/3)

 Assembleur (assembly) : langages de programmation : 1 ligne = 1 instruction


processeur​

 Assembleur (assembler) : équivalent du compilateur pour le C​

 Mnémonique : instruction assembleur​

 Opcode : code machine correspondant à un mnémonique​

 Opérande : paramètre passé à l’instruction


Vocabulaire (2/3)

 Immédiat : valeur passée directement à une instruction : add eax, 4


 Indirect : valeur stockée dans un espace mémoire : add eax, [ebx]
 Registre : espace mémoire contenu dans chaque processeur : add eax, ebx

 Syntaxe Intel : le bien – add eax, 4


 Syntaxe AT&T : le mal – add $4, %eax
Vocabulaire (3/3)

 Shellcode : code machine injecté dans un buffer overflow. Doit respecter


certaines conditions particulières.

 Polymorphisme : routine d’encodage et de décodage du shellcode afin d’éviter


la détection par les IDS/IPS/AV

 Métamorphisme : programme permettant d’utiliser des équivalences entre les


instructions afin de modifier le flux d’exécution du programme tout en gardant
les fonctionnalités – mov eax, 0 == xor eax, eax == sub eax, eax == etc.
Définition

 « L’assembleur » n’existe pas, il existe un assembleur par architecture

 Langage le plus proche du code machine

 Différentes instructions peuvent avoir le même code machine :


 xchg eax, eax == nop == \x90

 Une même instruction peut avoir plusieurs code machine :


 add eax, ebx == add r/m32, r32 == \x01\xD8​
 add eax, ebx == add r32, r/m32 == \x03\xC3​
Les différentes architectures

 Il existe de nombreuses architectures différentes pour les processeurs :


 x86 a.k.a IA-32
 x86_64 a.k.a AMD-64
 Itanium a.k.a IA-64
 ARM
 MIPS
 PowerPC
 Etc
Les différents types d’architectures

 Reduced Instruction Set Computer (RISC) : ARM par exemple


 Contient peu d’instructions, peu complexes
 Nécessite moins de puissance car moins de transistors
 Souvent utilisé dans les appareils mobiles
 Ne supporte souvent pas de rétrocompatibilité
Les différents types d’architectures

 Complex Instruction Set Computer (CISC) : x86 et x86_64 par exemple


 Peut contenir plusieurs milliers d’instructions
 Beaucoup de transistors pour encoder toutes ces instructions
 Souvent utilisé dans les ordinateurs
 Rétrocompatibilité depuis 1978 pour x86
 Comporte des jeux d’instructions spécifiques : AES-NI ; opérations vectorielles, etc
Les outils

 nasm : netwide assembler – nasm –f elf32 *.asm


 ld : linker (le même que celui utilisé par GCC) – ld –m elf_i386 *.o
 objdump : désassembleur – objdump –M intel -d
 gdb : débugger, permet de visualiser et éditer la mémoire et les registres
pendant le runtime
 m2elf : pour écrire directement du code machine et le convertir en exécutable
valide
Les registres - Définition

 Un registre est un emplacement de stockage de données stocké dans chaque


processeur (chaque cœur a ses propres registres)

 Il existe des GPR (General purpose register), ainsi que des registres ayant des
rôles bien définis : ESP, EIP, etc.
Les registres - Tailles

 Byte (B) = 8 bits


 Word (W) = 16 bits
 DoubleWord (DWord ou DW) = 32 bits
 QuadWord (Qword ou QW) = 64 bits (nous n’allons pas les utiliser…)

 Les registres vectoriels sont plus grands : 128 ; 256 ; 512 bits et sont
respectivement appelés XMM, YMM et ZMM (…eux non plus)
Les registres - Tailles
Les registres - Liste

 eax ; ebx ; ecx ; edx : GPR


 edi ; esi : GPR ; registres d’index (destination / source index)
 ebp ; esp : registres liés à la stack (base pointer et stack pointer)
 eip : Instruction pointer, pointe sur la prochaine instruction à exécuter
 Flags : registre contenant des flags permettant de maitriser le contrôle de flux
Instructions basiques : contrôle de
l’exécution
 Instruction « call » : se comporte comme un appel de fonctions
 Création d’une nouvelle stack frame de manière implicite
 Retour obligatoire à la fin de la fonction
Instructions basiques : contrôle de
l’exécution
Instructions basiques : contrôle de
l’exécution
 Instruction « jmp »
 Effectue seulement un saut vers une autre adresse
 Equivalent à un contrôle de flux classique (if…else, while, etc.)
 Peut prendre en paramètre des labels, des registres contenant des adresses
mémoires valides, etc.
 Il existe énormément de jump conditionnels​
Instructions basiques : déplacement de
données
 Instruction « mov »
 Permet de déplacer une données d’un immédiat, une adresse mémoire ou un
registre vers une adresse mémoire ou un registre
 Il n’est pas possible de déplacer une donnée entre deux emplacements mémoire
 Instruction dite « Turing Complete »
 Les mov conditionnels sont peu utilisés
Instructions basiques : déplacement de
données
 Instructions « push » et « pop »
 Push : met une valeur sur le haut de la stack
 Pop : met la valeur stockée en haut de la stack dans un emplacement mémoire ou
un registre
Instructions basiques : opérations
arithmétiques et logiques
 add
 sub
 mul
 div
 inc
 dec
 or
 and
 xor
Appels système

 Interruption système permettant à un process du user land d’avoir accès à des


fonctionnalités du kernel land

 Permet de réaliser des actions nécessitant des privilèges

 Le mnémonique à utiliser est « int » (interruption) et le paramètre « 0x80 », ou


« 80h », qui spécifie qu’il faut réaliser un appel système.
Appels système

 Le numéro du syscall doit être stocké dans le registre eax.


 Il faut placer les paramètres dans les bons registres (dans l’ordre) :
 ebx
 ecx
 edx
 esi
 edi
Appels système
Appels système
Appels système
Appels
système
TP

 Implémenter un programme qui réalise l’opération « 4 + 4 » et qui affiche le


résultat
 Implémenter un programme qui réalise l’opération « 8 + 8 » et qui affiche le
résultat
 Implémenter un « 4 * 4 » qui affiche le résultat, sans utiliser d’opérations
arithmétiques
 Les programmes doivent se terminer correctement et utiliser le syscall « write »

Vous aimerez peut-être aussi