exploitation buffer overflow introduction · 2017. 2. 22. · assembleur x86. mémoire physique...
TRANSCRIPT
Exploitation Buffer Overflow
Introduction
# whoami
# Bogdan NICORICI
# Security Engineer @ SCRT
# CTF’er @ Fourchette Bombe# https://fourchette-bombe.com
# https://ctftime.org/team/1833
# Linux ninja
# Twitter: @0xboogy
# Blog: blog.reverser.ninja
Buffer Overflow ?
Buffer Overflow ?
# Définition (wikipedia)# Un dépassement de tampon ou débordement de tampon (en anglais, buffer overflow) est un bug par lequel
un processus, lors de l'écriture dans un tampon, écrit à l'extérieur de l'espace alloué au tampon, écrasant ainsi des informations nécessaires au processus.
# 1996 – Aujourd’hui, toujours une des vulnérabilités les plus exploitées
# Compris et partiellement documenté publiquement en 1972
# L'exploitation documentée la plus ancienne d'un débordement de tampon en 1988 (Morris Worm)
# L’exploitation varie en fonction de l’architecture, OS et région mémoire.
# Buffer Overflows:
# Stack based
# Heap based
# Exploitation
# Écrasement d’une variable qui altère le fonctionnement du programme
# Écrasement de l’adresse de retour dans la «stack frame»
# Écrasement d’un pointeur de fonction
# Écrasement d’une variable ou l’adresse de retour d’une autre «stack frame» (utilisé par la fonction qui détient la stack frame)
Fonctions C dangereuses
• Comment sont effectuées les erreurs de débordement de mémoire tampon ?
• Le problème réside dans les fonctions C natives, qui ne se soucient pas de faire des contrôles de
longueur de «buffer» appropriée.
• Liste de quelques fonctions non sécurisée et leur équivalent sécurisé s’il existe:
o gets() -> fgets() – lire des caractèreso strcpy() -> strncpy() – copier le contenu du «buffer»o strcat() -> strncat() – concaténation des «buffers»o sprintf() -> snprintf() – remplis le «buffer» avec des données de différents typeso (f)scanf() – lire sur STDINo getwd() – retourne le répertoire actuel de travailo realpath() – retourne le chemin complet «absolute»
Registres x86
• Les registres à but général:• eax, ebx, ecx, edx, edi, esi
• Les registres spéciaux:• ebp, esp: gestion de la pile (stack)• eip: pointeur d’instruction• eflags: fanions (flags)
• Un registre est de 32 bits (4 bytes sur x86)
• On peut accéder à différentes parties du registre.• %eax est un dword (4 bytes)• %ax est le mot de la partie basse de %eax (2 bytes)• %al est le byte de partie basse de %ax (1 byte)• %ah est le byte de partie haute de %ax (1 byte)
MSB LSB%EAX
MSB LSB%AX
MSB LSB%AL
MSB LSB%AH
MSB LSB%EAX
Registres x86_64
Source: stackoverflow.com
Assembleur x86
• Les instructions
o Modifications mov, lea, push, pop. . .
o Contrôle cmp, call, int, ret, jmp. . .
o Arithmétiques add, sub, mul, div, inc, dec ...
o Logiques and, or, xor, not. . .
o NOP (no operation)
Assembleur x86
Mémoire physique -> virtuelle
Source: hackndo.com
Les segments d’un ELF en mémoire
.plt
.text
.rodata
.got
.got.plt
.data
.bss
heap
Shared-objects
Kernel
0x00000000
0x7fffffff Stack
PIENXSSP
RELROASLR
.text le code du programme
.bss variables globales & s tatiques non-initialisées
.data variables globales & s tatiques initialisées
stack variables locales, adresses de retour, arguments des fonctions, interrupteurs …
heap al location variable (mémoire)
0xffffffff
Pile / Stack «cdecl convention»
…
High
Low
Début de la Pile
Argument b
Argument a
Ad. de retour (EIP)
Dir
ecti
on
de
la P
ile
Saved EBP
Var1
Fin de la Pile
Bar(a, b)
Foo()
ESP
EBP
Var2
Local Var 1
Local var 2
Var3
EBP- 4
EBP- 8
EBP- 12
void bar(char *a, char *b) {
char var1[5];
char var2[5];
char var3[5];
strcpy(var2, b);
}
void foo() {
bar("AAAA", "BBBB");
}
SSP
EBP- 16
Pile / Stack «cdecl convention»
…
High
Low
Début de la Pile
Argument b
Argument a
Ad. de retour (EIP)
Dir
ecti
on
de
la P
ile
Saved EBP
Var1
Fin de la Pile
Bar(a, b)
Foo()
ESP
EBP
Var2
Local Var 1
Local var 2
Var3
EBP- 4
EBP- 8
EBP- 12
void bar(char *a, char *b) {
char var1[5];
char var2[5];
char var3[5];
strcpy(var2, b);
}
void foo() {
bar("AAAA", "BBBB");
}
SSP
EBP- 16
Pile / Stack «cdecl convention»
…
High
Low
Début de la Pile
Argument b
Argument a
Ad. de retour (EIP)
Dir
ecti
on
de
la P
ile
Saved EBP
Var1
Fin de la Pile
Bar(a, b)
Foo()
ESP
EBP
BBBB
Local Var 1
Local var 2
Var3
EBP- 4
EBP- 8
EBP- 12
void bar(char *a, char *b) {
char var1[5];
char var2[5];
char var3[5];
strcpy(var2, b);
}
void foo() {
bar("AAAA", "BBBB");
}
EBP- 16
Pile / Stack «cdecl convention»
…
High
Low
Début de la Pile
Argument b
Argument a
Ad. de retour (EIP)
Dir
ecti
on
de
la P
ile
Saved EBP
BBBB
Fin de la Pile
Bar(a, b)
Foo()
ESP
EBP
BBBB
Local Var 1
Local var 2
Var3
EBP- 4
EBP- 8
EBP- 12
void bar(char *a, char *b) {
char var1[5];
char var2[5];
char var3[5];
strcpy(var2, b);
}
void foo() {
bar("AAAA", "BBBBBBBB");
}
EBP- 16
Pile / Stack «cdecl convention»
…
High
Low
Début de la Pile
Argument b
Argument a
BBBB
Dir
ecti
on
de
la P
ile
BBBB
BBBB
Fin de la Pile
Bar(a, b)
Foo()
ESP
EBP
BBBB
Local Var 1
Local var 2
Var3
EBP- 4
EBP- 8
EBP- 12
void bar(char *a, char *b) {
char var1[5];
char var2[5];
char var3[5];
strcpy(var2, b);
}
void foo() {
bar("AAAA", "BBBBBB…");
}
EBP- 16
Pile / Stack «cdecl convention»
…
High
Low
Début de la Pile
Argument b
Argument a
\x42\x42\x42\x42
Dir
ecti
on
de
la P
ile
\x42\x42\x42\x42
\x42\x42\x42\x42
Fin de la Pile
Bar(a, b)
Foo()
ESP
EBP
\x42\x42\x42\x42
Local Var 1
Local var 2
Var3
EBP- 4
EBP- 8
EBP- 12
void bar(char *a, char *b) {
char var1[5];
char var2[5];
char var3[5];
strcpy(var2, b);
}
void foo() {
bar("AAAA", "BBBBBB…");
}
EBP- 16
EIP: 0x42424242
Pile/Stack overflow
Appel avec AAAAAAAAAAAAAAAAAAAA\x08\x35\xC0\x80
Appel avec ‘’hello’’
Source: wikipedia
Little-endian
Source: wikipedia
0x41424344 => \x44\x43\x42\x41
Big-endian & little-endian
Source: wikipedia
Big-endian & little-endian
Outils
# GDB – Intro débugger
# break execve – pose un breakpoint sur la fonction execve
# break *0xbadec0de – pose un breakpoint sur l’adresse 0xbadec0de
# run args $(python -c 'print "A"*256'`) – exécute le programme avec les arguments données
# Stepi/nexti – exécute la prochaine instruction (si rentre dans les call)
# info reg – affiche les registres
# info frame – donne des infos sur la stack frame en cours
# catch exec/fork – break lors d’un fork ou d’un exec*
# x/[N] (x, bx, hx, gx)inspecte la mémoire pour N byte, work, double word(DWORD) ou quad word(QWORD)
# x/s – string (jusqu’au \x00)
# x/i – instruction (désassemble)
# x/d – décimal
# display/5i $pc – à chaque step, GDB affiche les 5 prochaines instructions
# backtrace (bt) – list les stack frames depuis le début du programme
# Peda https://github.com/longld/peda
# Pwndbg https://github.com/pwndbg/pwndbg
# GEF https://github.com/hugsy/gef
# Radare2 https://radare.org/r/ (portable reversing framework)
Exploit time
Références
Références• “Hacking: The Art of Exploitation”, Jon Erickson• “The Shellcoder’s Handbook: Discovering and Exploiting Security Holes”, Chris Anley, John
Heasman, Felix Lindner, Gerardo Richarte• http://phrack.org
Apprendre• https://w3challs.com – basic, classic, hardened, shellcoding• https://root-me.org – basic, classic, hardened, shellcoding• http://smashthestack.org – wargaming• https://www.hackthissite.org – basic, stegano, programming, forensic• http://overthewire.org - wargaming• http://pwnable.kr – hardened• http://webhacking.kr• https://exploit-exercises.com/protostar• https://picoctf.com• https://www.vulnhub.com• https://ctftime.org – Calendrier des CTF• https://github.com/Hack-with-Github/Awesome-Hacking