cours/content/secu_logicielle/5_appel_fonction/index.md

111 lines
2.8 KiB
Markdown

---
title: "Sécurité logicielle : L'assembleur - appel de fonction"
date: 2023-02-10
tags: ["assembleur", "intel", "mémoire"]
categories: ["Sécurité logicielle", "Cours"]
---
L'instruction poour l'appel de fonction est `call`, elle est équivalent un
```asm
pushl %eip+5
jump f
```
On sauvegarde l'adresse de retour sur la pile et un effectue un saut dans le
code. Lors du retour, nous effetuerons alors :
```
popl %eip
jumpl (%esp)
addl $4 %esp
```
## Passage de paramètres (en 32 bits)
Le passage de paramètre n'est pas spécifié dans la dosumentation des processeur,
mais dans une documentation à part et relative à chaque systèmes (Linux, MacOS,
FreeBSD, OpenBSD, etc.)
Prenons l'exemple de la fonction `x=f(42, 52)` :
```asm
pushl $52 # on commence par le paramètre le plus à droite
pushl $42
call f
```
N'oublions pas que lors de lappel de fonction, l'adresse de retour est
positionnée sur la pile, vous avons donc:
|adresse|contenu|
|----|----|
|0xff| 52 |
|0xfb| 42 |
|0xf8| retour|
Voici maintenant le code de notre fonction :
```asm
f:
movl 4(%esp) %eax # Attendre l'adresse 0xfb
addl 8(%esp) %eax
ret # retour de notre fonction, résultat dans eax
```
Il faut penser à netoyyer la pile **dans la fonction appelante**
## Les variables locales
Elle se positionnent sur la pile après l'adresse de retour. Il faudra bien
évidement le prendre en compte lors du calcul du décalage lors del
accès au paramètres:
|adresse|contenu|
|----|----|
|0xf0| 52 |
|0xfc| 42 |
|0xf8| retour|
|0xf4| 94|
```asm
f:
subl $4, %esp
movl 8(%esp), %eax # Attendre l'adresse 0xfb
addl 12(%esp), %eax
movl %eax, (%esp)
...
addl $4, %esp
ret # retour de notre fonction, résultat dans eax
```
## Le Base Pointer
Lors de l'entrée dans une fonction, nous sauvegardons l'adresse contenue dans
`ebp` sur la pile puis on copie l'adresse contenue dans `esp` dans `epb`,
```asm
f:
pushl %ebp ; on sauvegarde l'adresse contenue dans %ebp sur la pile
movl %esp, %ebp ; puis copier l'adresse courante d'%esp dans %ebp
```
Sur l'architecture x86, ces deux instructions peuvent être remplacées par le
mnémonique `enter`.
Il nous est mainteant possible de retrouver simplement les paramètres passées à
notre fonction par rapport à `ebp` tout en instanciant des variables locales sur
la pile que nous retrouverons en fonction d'`esp`. **C'est à la fonction appelée
de mettre en place le *base pointer***
À la fin de notre fonction, nous allons positionner le retour dans `%eax` et
remettre les choses en places:
```asm
;[...]
movl -4(%ebp), %eax ; on met notre valeur de retour dans %eax
movl %ebp, %esp ; on restaure %esp
popl %ebp ; on pop le haut de la pile dans %ebp on restaure ainsi
; sa valeur avant l'appel de notre fonction
ret
```