Exploitation 101

Buffer Overflow

 

Par Israël Hallé

Adapté par Olivier Arteau

Réadapté par Israël Hallé

Plan de la présentation

  • Concept de base
  • Vulnérabilité Buffer overflow
  • Return Oriented Programming
  • Outils et trucs pouvant aider au reversing ou à l'exploitation d'un programme

Concept Important

  • Registre du CPU
  • Appel de fonction
  • Structure de la pile

Registre du CPU

  • Instruction Pointer (RIP)
  • Stack Pointer (RSP)
  • Base Pointeur (RBP)
  • General Purpose Register (RDI, RSI, RAX, et cie)
    • 64 bits: RDI, RSI, RAX, RBX, RCX, RDX
    • 32 bits: EDI, ESI, EAX, EBX, ECX, EDX
    • 16 bits: DI, SI, AX, BX, CX, DX
    • 8 bits: AL, AH, BL, BH, CL, CH, DL, DH 

call, ret

  • call fn
    • push $rip
    • jmp fn
  • ret
    • pop $rip

Appel de fonction (C)

int hello(int a, int* b, int c)
{
  int hello_var = 0xdeadbeef;
  return 0xf00;
}

int main()
{
  int main_var = 0x0;
  int result = 
    hello(main_var, &main_var, 0x123456);
  return 0;
}

Appel de fonction (x86)

main

hello

Appel de fonction (Pile)

int hello(int a, int* b, int c);
hello(main_var, &main_var, 0x123456);

                0x7fffffff
                     + +----------+
Main return address  | |0x00804e00|
                     | +----------+
Saved base stack     | |0x7fff3ed0| <--+
                     | +----------+    |
Main local vars      | |...       |    |
                     | +----------+    |
c                    | |0         |    |
                     | +----------+    |
b                    | |0x7fff3ebc|    |
                     | +----------+    |
a                    | |0x12345678|    |
                     | +----------+    |
hello return address | |0x00804f56|    |
                     | +----------+    |
Saved base stack     | |0x7fff3ea0| ---+
                     | +----------+
Hello local vars     | |...       |
                     v +----------+
                0x00000000

​

x86-64

  • Registre 64 bits:

    • RIP, RBP, RSP, RDI, RSI, RAX, RBX, RCX, RDX, R10, R8-15

  • Appel de fonction (Linux)

    • Arguments passé via registre:

      • RDI, RSI, RDX, RCX, R8, R9, stack

  • Pointeur 8 bytes

Buffer Overflow

int main()
{
  int some_var = 0;
  char buffer[12];
  fgets(buffer, 9001, stdin);
  return 0;
}

Stack avant fgets

0x7fffffff
     + +---------+
     | |Saved RIP| ^
     | +---------+ |
     | |Saved RBP| |
     | +---------+ |
     | |some_var | |
     | +---------+ |
     | |         | |
     | |         | |
     | |buffer   | + fgets(buffer, ...)
     v +---------+
0x00000000

 

Stack après fgets

0x7fffffff
     + +---------+
     | |AAAA     | ^
     | +---------+ |
     | |AAAA     | |
     | +---------+ |
     | |AAAA     | |
     | +---------+ |
     | |AAAA     | |
     | |AAAA     | |
     | |AAAA     | | fgets(buffer, ...)
     v +---------+
0x00000000



​

Cause Courante

  • Classique CTF:
    • char dst[100];
      read(0, dst, 200);
  • Fonction sans limites:
    • strcpy(src, dst); gets(dst); scanf("%s", dst)
  • Débordement d'entier:
    • x > z
    • z + y < z ??
    • 0xffffffff > 0x1000 (32 bits)
    • 0xffffffff + 1 < 0x1000 (32bits)
  • Signé / non-signé
    • ​if​ ( x < 0x1000)
          memcpy(src, dst, x); // x = -1, woops

Return Oriented Programming

  • ROP
  • La Stack les addresses de retour et paramètres des fonctions
  • Buffer Overflow permet de réécrire la Stack
  • Il est donc possible de retourner dans des fonctions tout en contrôlant les paramètres

ROP Gadgets

  • Fragment d'instructions finissant par un saut ou une instruction de retour dont la destination est contrôlé par l'attaquant.
  • Exécution en chaîne de plusieurs fragments pour créer un "programme"
Examples:
pop rdi;
pop esi;
pop rdx;
ret;

Pop; pop; ret

  • Gadgets courant et pratiques
  • Séries d'instructions qui permet de « dérouler » la Stack
  • Permet de chaîner plusieurs appels de fonction avec des arguments valide

Chaîne de fonction

void a(int a1, int a2, int a3) {} 
void b() {} 
void c(int c1, int c2) {}
8048455: 83 c4 0c add esp,0xc 8048458: 5b       pop ebx 
8048459: 5e       pop esi 
804845a: 5f       pop edi 
804845b: 5d       pop ebp 
804845c: c3       ret

Objectif: Exécuter les fonctions dans l'ordre suivant:

  • a(1,2,3);
  • b();
  • c(4,5);

Trouver les Gadgets

  • https://github.com/JonathanSalwan/ROPgadget
  • Logiciel de recherche de Gadget ROP
  • ./ROPGadget --binary your_bin
  • Permet même de générer un ROP pour
    execve('/bin/sh', 0, 0);
  • ./ROPGadget --binary your_bin --ropchain

Limitation

  • Executable ASLR (fPIE)
    • Leak une adresse ou .PLT table
  • Peu de gadget disponible
    • Linked library! Libc is big...

pwntools

  • Suite d'outils en python très complète fais spécialement pour les CTFs et l'exploit

  • https://github.com/Gallopsled/pwntools

pwntools

  • Code de base

from pwn import *

context(arch = 'amd64', os = 'linux')

r = remote('192.168.4.178', 1239)

data = r.readline() # Réception

r.send(data)           # Envoie

r.interactive()         # Le terminal devient l'entrée et la sortie

Question?

Action!

Baby step: Dump ./flag.txt

Bonus: Pop a shell

Made with Slides.com