Slide 1

Slide 1 text

Buffer Overflow nae @ NCTUCSC & BambooFox 1

Slide 2

Slide 2 text

前⾔言 • 環境 • Glibc - 2.24 • Kernel - 4.8.0-59 • 64 • 內容會以 32 位元為主,較好說明與理理解 2

Slide 3

Slide 3 text

Outline • Background Knowledge • Stack Frame • Function Calling Convention • Buffer Overflow • Exploit • Shellcode • Return to text • Return to libc • Bypass stack guard 3

Slide 4

Slide 4 text

Stack Frame • Stack: LIFO (Last In First Out) Last Second First Last Second First PUSH POP Low Address High Address Stack growth 4

Slide 5

Slide 5 text

Function Call & Stack 1. Call Function 2. Back to main to continue execution 5

Slide 6

Slide 6 text

Function Call & Stack • Function 跑完後,程式需要回到原本呼叫 function 的下⼀一 ⾏行行去執⾏行行,⽽而程式就是利利⽤用 stack 來來記錄下⼀一⾏行行指令 Back to here to continue Jump to 0x0804840b to execute Func 6

Slide 7

Slide 7 text

Function Call & Stack • Caller Part • ESP: Stack Pointer • void Func(int a, int b) • … Stack ESP growth Low High push b push a call Func 7

Slide 8

Slide 8 text

Function Call & Stack • Caller Part • ESP: Stack Pointer • void Func(int a, int b) • … b Stack ESP growth Low High push b push a call Func 8

Slide 9

Slide 9 text

Function Call & Stack • Caller Part • ESP: Stack Pointer • void Func(int a, int b) • … a b Stack ESP growth Low High push b push a call Func 9

Slide 10

Slide 10 text

Function Call & Stack • Caller Part • Return Address: call Func 下⼀一⾏行行 指令的位址 • void Func(int a, int b) • … Return Address a b Stack ESP growth Low High push b push a call Func 10

Slide 11

Slide 11 text

Function Call & Stack • Callee Part • 此時的 EBP 記錄著 main stack frame base 的位址 • void Func(int a, int b)
 char buf[12]; Previous ebp Return Address a b Stack ESP growth Low High push ebp mov ebp, esp sub esp, 0xc ======= Main Stack Frame Func Stack Frame 11

Slide 12

Slide 12 text

Function Call & Stack • Callee Part • 此時的 EBP 記錄著 Func stack frame base 的位址 • void Func(int a, int b)
 char buf[12]; Previous ebp Return Address a b Stack EBP = ESP growth Low High push ebp mov ebp, esp sub esp, 0xc ======= Main Stack Frame Func Stack Frame 12

Slide 13

Slide 13 text

Function Call & Stack • Callee Part • void Func(int a, int b)
 char buf[12]; buf[0]~[3] buf[4]~[7] buf[8]~[11] Previous ebp Return Address a b Stack EBP growth Low High push ebp mov ebp, esp sub esp, 0xc 13 ESP buffer

Slide 14

Slide 14 text

Function Call & Stack • void Func(int a, int b)
 char buf[12]; buf[0]~[3] buf[4]~[7] buf[8]~[11] Previous ebp Return Address a b Stack EBP growth Low High push ebp mov ebp, esp sub esp, 0xc … 14 buffer EBP + 0x4 EBP + 0x8 EBP + 0xc EBP - 0x4 EBP - 0x8 EBP - 0xc

Slide 15

Slide 15 text

Buffer Overflow • 程式本⾝身沒有正確檢查輸入的⼤大⼩小,如果輸入的⼤大⼩小比 buffer 還要⼤大就會蓋到其他變數影響程式的執⾏行行 (控制變數 or 控制程式流程) 15

Slide 16

Slide 16 text

Buffer Overflow • Unsafe Function • gets -> fgets • scanf -> never use scanf(“%s”) • strcpy -> strncpy • … • Buffer Overflow 其實有很多種,根據不同的 memory 位址有不同的稱呼 • stack overflow • heap overflow 16

Slide 17

Slide 17 text

Stack Overflow • void Func(int a, int b)
 char buf[12];
 gets(buf); buf[0]~[3] buf[4]~[7] buf[8]~[11] Previous ebp Return Address a b Stack EBP growth Low High 17 ESP buffer

Slide 18

Slide 18 text

Stack Overflow • aaaaaaaaaaaa(a * 12) aaaa aaaa aaaa Previous ebp Return Address a b Stack EBP growth Low High 18 ESP buffer

Slide 19

Slide 19 text

Stack Overflow 19 aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa growth Low High buffer Stack

Slide 20

Slide 20 text

Stack Overflow 20 https://www.linkedin.com/pulse/buffer-overflow-exploits-protection-mechanisms-roman- postanciuc

Slide 21

Slide 21 text

Stack Overflow • aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa (a*100) aaaa(pre ebp) aaaa(ret addr) aaaa aaaa Stack ESP = EBP growth Low High 21 … mov esp, ebp pop ebp ret

Slide 22

Slide 22 text

Stack Overflow • aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa (a*100) aaaa(ret addr) aaaa aaaa Stack ESP growth Low High 22 … mov esp, ebp pop ebp ; ebp == 0x61616161 ret

Slide 23

Slide 23 text

Stack Overflow • aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa (a*100) aaaa aaaa Stack ESP growth Low High 23 … mov esp, ebp pop ebp ; ebp == 0x61616161 ret (pop eip) ; eip == 0x61616161

Slide 24

Slide 24 text

Stack Overflow • 程式會到 0x61616161 的位址拿指令執⾏行行 24

Slide 25

Slide 25 text

Stack Overflow • 計算 offset 25

Slide 26

Slide 26 text

Stack Overflow • 計算 offset • 中間少了了 d & e • stack alignment 26 aaaa bbbb cccc ffff gggg hhhh iiii EBP growth High buffer EBP + 0x4 EBP + 0x8 EBP + 0xc EBP - 0x4 EBP - 0x8 EBP - 0xc Stack Low

Slide 27

Slide 27 text

Stack Overflow • 計算 offset • 通靈 • ⽤用 gdb • cyclic in pwntools 27 aaaa bbbb cccc ffff gggg hhhh iiii EBP growth High buffer EBP + 0x4 EBP + 0x8 EBP + 0xc EBP - 0x4 EBP - 0x8 EBP - 0xc Stack Low

Slide 28

Slide 28 text

Stack Overflow • 蓋到 return address 所 需的 offset • 12 (buf) • 8 (alignment) • 4 (ebp) • 12 + 8 + 4 = 24 bytes 28 aaaa bbbb cccc ffff gggg hhhh iiii EBP growth High buffer EBP + 0x4 EBP + 0x8 EBP + 0xc EBP - 0x4 EBP - 0x8 EBP - 0xc Stack Low

Slide 29

Slide 29 text

Exploit • Shellcode • Return to text • Return to libc • Bypass stack guard 29

Slide 30

Slide 30 text

Exploit • Shellcode • 其實就是⼀一段 machine code,⽽而 machine code 就是 CPU 可以直接解讀的資料 • 把 input data 當成 code 來來跑 • 長得⼤大概像這樣 30 \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80

Slide 31

Slide 31 text

Exploit • Shellcode • 這段 shellcode 翻成 assembly 就會是 31 \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80

Slide 32

Slide 32 text

Exploit • Shellcode • 找⼀一個 buffer 把 shellcode 寫上去 • 利利⽤用 buffer overflow 把 return address 覆寫, 讓程式跳到 shellcode 上去執⾏行行 32 aaaa aaaa aaaa aaaa \xc0\x9f\x04\x08 a b Stack EBP growth Low High ESP buffer 0x08049fc0 shellcode

Slide 33

Slide 33 text

Protection • DEP (Data Execution Prevention) • ASLR (Address Space Layout Randomization) • Stack Guard (Stack Canary) • RELRO (Relocation Read Only) • PIE (Position Independent Executable) 33

Slide 34

Slide 34 text

• DEP (Data Execution Prevention) • 放在 data buffer 上的 shellcode 沒有執⾏行行的權限 • ❌ stack • ❌ heap • ❌ .data • ❌ .bss 34 Protection

Slide 35

Slide 35 text

• DEP (Data Execution Prevention) • DEP 開啟/關閉 • gcc -z execstack • execstack --set-execstack • execstack --clear-execstack • 檢查 Program Header - GNU_STACK • 35 Protection readelf --program-headers ${binary}

Slide 36

Slide 36 text

• ASLR (Address Space Layout Randomization) • Depends on system • Linux - • 預設是 2 • 0 - 關掉 ASLR • 1 - stack, shared library, mmap() • 2 - 除了了 1 的保護之外還加上 brk() 所管理理的記憶體位址 36 Protection cat /proc/sys/kernel/randomize_va_space

Slide 37

Slide 37 text

• Stack Guard (Stack Canary) • ⼀一個亂數,在 function call 時放上 stack • 在 return address & ebp 被 push 上 stack 後,再放上 去 • 在 return 前檢查 canary 是不是正確的 37 Protection

Slide 38

Slide 38 text

• Stack Guard (Stack Canary) • 開啟/關閉 • gcc -fstack-protector / gcc -fno-stack-protector • 檢查 function symbol • 38 Protection readelf -s ${binary} | grep __stack_chk_fail

Slide 39

Slide 39 text

• Stack Guard (Stack Canary) 39 Protection

Slide 40

Slide 40 text

• Stack Guard (Stack Canary) 40 Protection http://www.troll.me/2011/12/16/you-shall-not-pass-gandalf/you-shall-not-pass-16/

Slide 41

Slide 41 text

• Stack Guard (Stack Canary) 41 Protection

Slide 42

Slide 42 text

• RELRO (Relocation Read Only) • Disable • .got / .got.plt 可寫 • Partial • .got.plt 可寫 • Full • .got / .got.plt 不可寫 • 在 load time 時就把所有 library function 解析完 42 Protection

Slide 43

Slide 43 text

• RELRO (Relocation Read Only) • Default 是 Partial • 開啟 Full / 關閉 • gcc -Wl,-z,relro,-z,now / gcc -Wl,-z,norelro • 檢查 dynamic tag • DT_BIND_NOW - Full • GNU_RELRO - Partial 43 Protection

Slide 44

Slide 44 text

• PIE (Position Independent Executable) • 預設不會開啟 (GCC 6 以前) • 開啟的話,text & data 段也會是受 ASLR 影響,造成撰 寫 exploit 時更更困難 44 Protection

Slide 45

Slide 45 text

• PIE (Position Independent Executable) • 開啟 / 關閉 • gcc -fPIC -pie / gcc -no-pie • 檢查 ELF header • DYN (shared object file) 45 Protection readelf -h ${binary} | grep Type

Slide 46

Slide 46 text

• 檢查保護機制 • 多種檢查⼀一次滿⾜足 • checksec in pwntools 46 Protection

Slide 47

Slide 47 text

Exploit • Shellcode • Return to text • Return to libc • Bypass stack guard 47

Slide 48

Slide 48 text

Exploit • 有了了 DEP,shellcode 沒辦法執⾏行行,但是沒關係... 48

Slide 49

Slide 49 text

Exploit • Return to text • 利利⽤用程式本⾝身的 code (⼀一定可執⾏行行) • 沒有 PIE 的保護下,code 的位置是固定的 49

Slide 50

Slide 50 text

Exploit • Return to text • Demo 50

Slide 51

Slide 51 text

Exploit 51 aaaa aaaa …. aaaa aaaa(ebp) 0x804846d(ret addr) aaaa aaaa growth Low High buffer Stack

Slide 52

Slide 52 text

• Return to text • Endianness (位元組順序) Exploit 52 https://upload.wikimedia.org/wikipedia/en/7/77/Big-little_endian.png

Slide 53

Slide 53 text

• Return to text • Endianness (位元組順序) • 在 x86 的架構下,是 little endian Exploit 53 Low High Low High

Slide 54

Slide 54 text

• Return to text • 在⼤大多數情況下 binary 內有的 code 無法完成整個 exploit • Return to libc + ROP Exploit 54

Slide 55

Slide 55 text

Exploit • Shellcode • Return to text • Return to libc • Linking • Lazy Binding • Bypass stack guard 55

Slide 56

Slide 56 text

Linking 56 hello.c Preprocess Compilation Assembly Linking hello.c Preprocess Compilation Assembly Linking libc.a Static Dynamic hello.o hello.o

Slide 57

Slide 57 text

• Linking • 靜態連結 Static Linking • ⼀一開始就會直接把所有 library function 的 machine code 放在 ELF 中 • 動態連結 Dynamic Linking • 把 library function 標記為⼀一個動態連結的符號 • shared object 跟著執⾏行行檔⼀一起載入記憶體 Linking 57

Slide 58

Slide 58 text

• Dynamic Linking Linking 58

Slide 59

Slide 59 text

• 在⼀一⽀支程式裡,某些 library function 可能結束前都不會呼 叫到 Lazy Binding 59 here

Slide 60

Slide 60 text

• 因此,dynamic linking 的 ELF 使⽤用了了 lazy binding 這個機 制,第⼀一次呼叫 library function 的時候才會去解析出真正 的位址 Lazy Binding 60

Slide 61

Slide 61 text

• ELF 使⽤用 PLT (Procedure Linkage Table) 的⽅方式來來實作 Lazy Binding 61 : 0x400450: jmp Foo@got 0x400456: push n 0x40045b: push module ID 0x400461: jmp _dl_runtime_resolve : 0x400456

Slide 62

Slide 62 text

• ELF 使⽤用 PLT (Procedure Linkage Table) 的⽅方式來來實作 Lazy Binding 62 : 0x400450: jmp Foo@got 0x400456: push n 0x40045b: push module ID 0x400461: jmp _dl_runtime_resolve : 0x400456

Slide 63

Slide 63 text

• ELF 使⽤用 PLT (Procedure Linkage Table) 的⽅方式來來實作 Lazy Binding 63 : 0x400450: jmp Foo@got 0x400456: push n 0x40045b: push module ID 0x400461: jmp _dl_runtime_resolve : 0x400456

Slide 64

Slide 64 text

• ELF 使⽤用 PLT (Procedure Linkage Table) 的⽅方式來來實作 Lazy Binding 64 : 0x400450: jmp Foo@got 0x400456: push n 0x40045b: push module ID 0x400461: jmp _dl_runtime_resolve : 0x400456

Slide 65

Slide 65 text

• ELF 使⽤用 PLT (Procedure Linkage Table) 的⽅方式來來實作 Lazy Binding 65 : 0x400450: jmp Foo@got 0x400456: push n 0x40045b: push module ID 0x400461: jmp _dl_runtime_resolve : 0x7ffff7a66666 0x7ffff7a66666 : …

Slide 66

Slide 66 text

• ELF 使⽤用 PLT (Procedure Linkage Table) 的⽅方式來來實作 Lazy Binding 66 : 0x400450: jmp Foo@got 0x400456: push n 0x40045b: push module ID 0x400461: jmp _dl_runtime_resolve : 0x7ffff7a66666 0x7ffff7a66666 : …

Slide 67

Slide 67 text

• ELF 使⽤用 PLT (Procedure Linkage Table) 的⽅方式來來實作 • n • Foo 在 .rel.plt 的索引 • module ID • 引⽤用的 library name Lazy Binding 67 : 0x400450: jmp Foo@got 0x400456: push n 0x40045b: push module ID 0x400461: jmp _dl_runtime_resolve

Slide 68

Slide 68 text

• ELF 使⽤用 PLT (Procedure Linkage Table) 的⽅方式來來實作 • Reuse code Lazy Binding 68 : 0x400440: push module ID 0x400446: jmp _dl_runtime_resolve : 0x400450: jmp Foo@got 0x400456: push n 0x40045b: jmp PLT0

Slide 69

Slide 69 text

• 詳情請洽 Angelboy - Execution p.17 Lazy Binding 69

Slide 70

Slide 70 text

• Return to libc • 除了了 binary 本⾝身的 code,shared library 的 code 也可以 利利⽤用 • system • execve • … Exploit 70

Slide 71

Slide 71 text

• Return to libc • 因為 ASLR 的緣故,libc 每次載入位址不固定,需要搭配 information leak • 拿到某個在 libc 裡的位址便便可以算出此次的 base address • 之後就可以加上想要的 function offset 隨意使⽤用任⼀一 library function • 在同⼀一個 libc 裡,function offset 是固定的 Exploit 71

Slide 72

Slide 72 text

• Return to libc • 尋找 libc address • GOT • stack • e.g., return address of main • heap • e.g., main_arena Exploit 72

Slide 73

Slide 73 text

• Return to libc • 尋找 library function offset Exploit 73 readelf -s /path/of/libc | grep ${function_name}

Slide 74

Slide 74 text

• Return to libc • 獲得 libc base 之後 • 在 stack 上偽造 function call • GOT hijack • … Exploit 74

Slide 75

Slide 75 text

• Return to libc • 在 stack 上偽造 function call • 限制 • overflow • 任意寫 Exploit 75 aaaa aaaa aaaa aaaa system (ret addr) fake return address address of “/bin/sh” Stack growth Low High ESP buffer Fake Frame

Slide 76

Slide 76 text

• Return to libc • GOT hijack • 限制 • 任意寫 • gets(buf) -> system(buf) Exploit 76 : 0x400450: jmp gets@got 0x400456: push n 0x40045b: jmp PLT0 : 0x7ffff7a6dead 0x7ffff7a6dead : …

Slide 77

Slide 77 text

Exploit • Shellcode • Return to text • Return to libc • Linking • Lazy Binding • Bypass stack guard 77

Slide 78

Slide 78 text

Exploit • Bypass stack guard • leak canary • GOT hijack • … 78

Slide 79

Slide 79 text

Exploit • Bypass stack guard • leak canary • 某些 function 在讀完輸入之後不會放上 null byte,可 以利利⽤用這點去做 information leak (canary, libc, stack) • read() • strcpy() • strncpy() 79

Slide 80

Slide 80 text

• Bypass stack guard • leak canary • canary 的尾端⼀一定是 null byte Exploit 80 0xdead1200 (canary) ebp return address arg1 arg2 Stack growth Low High ESP buffer

Slide 81

Slide 81 text

• Bypass stack guard • leak canary • 這時如果有個輸出 function (e.g., printf(“%s”, buf)),程 式便便會從 buf 開頭⼀一路路印, 直到遇到 null byte • a*12 + 0x61 + 0x12 + 0xad + 0xde + … Exploit 81 aaaa aaaa aaaa 0xdead1261 (canary) ebp return address arg1 arg2 Stack growth Low High ESP buffer

Slide 82

Slide 82 text

• Bypass stack guard • GOT hijack • 限制 • 任意寫 • 將 __stack_chk_fail 的 GOT entry 內容改掉,這時可以根據修改的內容決定不同的利利⽤用⽅方式 • NOP • 直接 overflow,疊 ROP • one_gadget • system • 偽造 function call (不需要疊 return address) • … Exploit 82

Slide 83

Slide 83 text

Reference • http://l4ys.tw/ROP_bamboofox.pdf • AngelBoy • 程式設計師的⾃自我修養 • https://goo.gl/wKFGfn • https://en.wikipedia.org/wiki/ Executable_space_protection#Windows • https://en.wikipedia.org/wiki/ Address_space_layout_randomization 83