
Hardware-assisted Run-time Protection N. Asokan†‡ https://asokan.org/asokan/ @nasokan Acknowledgements: Thomas Nyman‡, Hans Liljestrand†, Lachlan J Gunn‡, Jan-Erik Ekberg‡, § †) University of Waterloo, ‡) Aalto University, §) Huawei Technologies You will be learning Part 1: Memory-related run-time attacks • Common attack techniques against C/C++ Part 2: Hardware-assisted defenses • Emerging mechanisms in CotS processors Part 3: Theory of run-time attacks • What are “weird machines”? 2 Example: Buffer overflows caused by missing bounds checks Software Developer 08048464 <main>: 8048464: 55 push %ebp 8048465: 89 e5 mov %esp,%ebp 8048467: 68 20 85 04 08 push $0x8048520 804846c: e8 9f fe ff ff call 8048310 <puts@plt> 8048471: 83 c4 04 add $0x4,%esp 8048474: 8b 45 0c mov 0xc(%ebp),%eax 8048477: 83 c0 04 add $0x4,%eax 804847a: 8b 00 mov (%eax),%eax 804847c: 50 push %eax 804847d: 0804843be8 b9 <doit>:ff ff ff call 804843b <doit> int main(int argc, char *argv[]) 8048482: 804843b:83 c4 04 55 add $0x4,%esp push %ebp { 8048485: 804843c:68 31 85 04 8908 e5push $0x8048531 mov %esp,%ebp puts("So... The End..."); 804848a: 804843e:e8 81 fe ff 83ff eccall 0c 8048310 sub <puts@plt>$0xc,%esp doit(argv[1]); 804848f: 8048441:83 c4 04 8d 45add f4 $0x4,%esp lea -0xc(%ebp),%eax 8048492: b8 00 00 00 00 mov $0x0,%eax puts("or... maybe not?"); Source Executable 8048444: 89 45 fc mov %eax,-0x4(%ebp) 8048497: 8048447:c9 ff 75leave 08 pushl 0x8(%ebp) 8048498: 804844a:c3 8d 45ret f4 lea -0xc(%ebp),%eax return 0; code File 8048499: 804844d:66 90 50 xchg %ax,%ax push %eax } 804849b: 804844e:66 90 e8 adxchg fe ff %ax,%ax ff call 8048300 <strcpy@plt> void doit(char *str) 804849d: 8048453:66 90 83 c4xchg 08 %ax,%ax add $0x8,%esp { 804849f: 8048456:90 ff 75nop fc pushl -0x4(%ebp) char buf[8]; 8048459: e8 b2 fe ff ff call 8048310 <puts@plt> 804845e: 83 c4 04 add $0x4,%esp char *ptr = buf; 8048461: 90 nop Compiler & Linker 8048462: c9 leave strcpy(buf, str); 8048463: c3 ret puts(ptr); } missing bounds-checks in call to strcpy! 3 void doit(char *str) { char buf[8]; Run-time behaviour char *ptr = buf; strcpy(buf, str); puts(ptr); User } 0xffffffff parent stack frame $ ./a.out “Hello !” Kernel Space Kernel space 0xc0000000 Stack (grows down) =TASK_SIZE 08048464 <main>: ... User Space 8048474: 8b 45 0c mov 0xc(%ebp),%eax 8048477: 83 c0 04 add $0x4,%eax 0xbfffceb8 804847a: 8b 00 mov (%eax),%eax arguments: 0xbfffd18a (argv[1]) 804847c: 50 push %eax 0xbfffceb4 804847d: e8 b9 ff ff ff call 804843b <doit> return address: 0x08048482 (saved eip) 0xbfffceb0 Memory Mapping 8048482:0804843b83 <doit>:c4 04 add $0x4,%esp frame pointer: 0xbfffceb8 (saved ebp) Region 8048485:804843b:68 31 8555 04 08 push push$0x8048531 %ebp 0xbfffceac 0x40000000 804848a:804843c:e8 81 fe89 ffe5 ff call mov8048310 %esp,%ebp <puts@plt> ptr: 0xbfffcea0 (&buf) 804848f: 83 c4 04 add $0x4,%esp 0xbfffcea8 804843e: 83 ec 0c sub $0xc,%esp ’\0’ ’!’ ’ ’ ’O’ 8048492:8048441:b8 00 008d 0045 00f4 mov lea$0x0,%eax-0xc(%ebp),%eax 0xbfffcea4 8048497:8048444:c9 89 45 fc leave mov %eax,-0x4(%ebp) buf: ’L’ ’L’ ’E’ ’H’ 8048498: c3 ret 0xbfffcea0 8048447: ff 75 08 pushl 0x8(%ebp) 0xbfffcea0 (ptr) Heap (grows up) 8048499: 66 90 xchg %ax,%ax arguments: 804844a: 8d 45 f4 lea -0xc(%ebp),%eax 0xbfffce9c Bss segment 804849b:804844d:66 90 50 xchg push%ax,%ax%eax 0xbfffd18a (str) 0xbfffce98 804849d:804844e:66 90 e8 ad fe xchgff ff call%ax,%ax8048300 <strcpy@plt> strcpy stack frame Data segment 804849f:8048453:90 83 c4 08 nop add $0x8,%esp 8048456: ff 75 fc pushl -0x4(%ebp) Text segment 8048459: e8 b2 fe ff ff call 8048310 <puts@plt> 804845e: 83 c4 04 add $0x4,%esp 0x0804000 8048461: 90 nop 0x00000000 8048462: c9 leave 8048463: c3 ret 4 void doit(char *str) { char buf[8]; Control-flow hijacking char *ptr = buf; strcpy(buf, str); puts(ptr); $ ./a.out $(perl -e 'print "A"x8 \ } .""\x??\x??\x04\x08" \ 0xffffffff ."A"x4"A"x4 \ parent stack frame Kernel Space Kernel space .""\x64\x84\x04\x08"')x08" 0xc0000000 Stack (grows down) =TASK_SIZE libc init: User Space 0xbfffceb8 arguments: 0xbfffd18a (argv[1]) 08048464: 0xbfffceb4 return address: 0x080484640x08048482 (saved (main) eip) <main>: 0xbfffceb0 Memory Mapping frame pointer: 0xffffceb8’A’ ’A’ (saved’A’ ebp)’A’ Region 0xbfffceac 0x40000000 ptr: 0x0804????0xffffcea0 (&buf) (data) 0xbfffcea8 0804843b: ’A’’\0’ ’A’’!’ ’A’’ ’ ’A’’O’ <doit>: 0xbfffcea4 buf: ’A’’L’ ’A’’L’ ’A’’E’ ’A’’H’ 0xbfffcea0 0xbfffcea0 (ptr) Heap (grows up) 0xbfffce9c 0xbfffd18a (str) Bss segment 0x8048300: 8048310: strcpy stack frame Data segment <strcpy>: puts: Text segment 0x08040000 0x00000000 corrupt code pointer / control flow 5 Memory-related run-time attacks Memory-related run-time attacks Software written in memory unsafe languages such as C/C++ • Suffer from various memory-related errors Memory errors may allow run-time attacks to compromise program behaviour • Control-flow hijacking / code injection • Return-Oriented Programming (ROP) • Non-control-data attacks • Data-Oriented Programming (DOP) 7 Run-time attacks compromise program behaviour Adversary exploits bug 1 if (authenticated != true) then: call unprivileged() else: call privileged() 1 … 2 unprivileged() { … } 3 3 privileged() { … } 2 3 shellcode … 8 (i) Code-injection attacks Exploit memory error (e.g. buffer overflow) to: • Inject shellcode into writable memory (usually stack) • Corrupt code pointer (usually return address) to redirect execution flow to shellcode shellcode Countermeasures: • Stack canaries (1990) frame- badreturn return address address record frame-pointer Detect sequential overwrites that corrupt ret. addr. FP • W X memory access control policy (2003) stackframe Prevent⊕ execution of shellcode by ensuring that buffer memory pages are either writable or executable SP Elias Levy (as Aleph One), Smashing the stack for fun and profit, Phrack 7 (1996) Cowan et al., StackGuard: Automatic adaptive detection and prevention of buffer-overflow attacks, USENIX Security (1998) 9 Szekeres et al., SoK: Eternal War in Memory, IEEE SP (2013) void doit(char *str) { char buf[8]; Classic code-injection char *ptr = buf; strcpy(buf, str); $ ./a.out $(perl -e 'print "A"x8 \ puts(ptr); } .""\x??\x??\x04\x08" \ ."A"x4"A"x4 \ 0xffffffff parent stack frame .""\xb8\xce\xff\xfb"xfb" \ Kernel space ..""\x80\xcd" ..""\x40“ \ 0xc0000000 ..""\xc0\x31" ..""\x80\xcd" \ 0xbfffcebc Stack (grows down) =TASK_SIZE libc init: ..""\x0b\xb0" ..""\xc2\x89" \ ..""\xc1\x89" ..""\xe3\x89" \ shellcode 0xbfffceb8 ..""\x6e\x69\x62\x2f\x68" \ 0xffffd18a (argv[1]) 08048464: 0xbfffceb4 ..""\x68\x73\x2f\x2f\x68" \ 0xbfffceb80x08048482 (saved eip) <main>: ..""\x50" ..""\xc0\x31") 0xbfffceb0 Memory Mapping 0xffffceb8’A’ ’A’ (saved’A’ ebp)’A’ Region 0xbfffceac 0x40000000 0x0804????0xffffcea0 (&buf) (data) 0xbfffcea8 0804843b: ’A’’\0’ ’A’’!’ ’A’’ ’ ’A’’O’ <doit>: :0xffffceb8 0xbfffcea4 :<shellcode> ’A’’L’ ’A’’L’ ’A’’E’ ’A’’H’ 0xbfffcea0 0xbfffcea0 (ptr) Heap (grows up) 0xbfffce9c 0xbfffd18a (str) Bss segment 0x8048300: 8048310: strcpy stack frame Data segment <strcpy>: puts: Text segment 0x0804000 0x00000000 10 Return-oriented programming (high-level idea) Re t u r n o r ien t ed Pro g ra mm ing 11 Return-oriented programming Attacker arranges call stack with code pointers to existing code sequences (“gadgets”) • Given a suitable gadget set, arbitrary return-oriented programs can be constructed … push edi Adversary leave ret exploits bug … cmp eax,edi leave ret … … mov eax,[ebp+0x8] cmp [esi+0x74],edi leave … leave ret add $0x4,%esp ret leave 12 ret (ii) Code-reuse attacks … gadget 3: Exploit memory error without injecting code: br <puts> ret • Corrupt code pointer (usually return address) to … address of gadget 3 redirect execution flow to existing code: gadget 2: • Library functions (return-into-libc) forged data load x0, x0 • Pre-existing instruction sequences (gadgets) address of gadget 2 ret … forged data function:gadget 1: Countermeasures: frame- addressaddressreturn ofof address functiongadget 1 …load x0, sp record frame-pointer ret • Control-flow Integrity (2005) FP Detect control-flow transfers outside static SP+size control-flow graph or mismatched returns stack frame buffer (shadow stack) SP • Address space randomization (2001) Hide locations of useful gadgets in memory A. Peslyak (as Solar Designer), Getting around non-executable stack (and fix), Bugtraq (1997) H. Shacham, The geometry of innocent flesh on the bone: return-into-libc without function calls (on the x86), ACM CCS (2007) T. Kornau, Return Oriented Programming for the ARM Architecture, MSc Thesis, RUB (2009) 13 M. Abadi, Control-flow integrity, ACM CCS (2005) CFI: High-level idea CFI check at A CFI violation at D Allowed edges: (A,B), (A,F) A Disallowed edge: (F,D) CFI check at B CFI check at D Allowed edges: (B,A), (B,C), (B,D) B Allowed edges: (D,B), (D,G) CFI check at C CFI check at F Allowed edges: (C,B), (C,G) C D F Allowed edges: (F,A) CFI check at G G Allowed edges: (G,C), (G,D) Legend: intended forward-edge in CFG initial node in CFG intended backward-edge in CFG node in CFG malicious edge not part of CFG 15 Shadow Stack: High-level idea “Shadow stack” Adversary A tampers with shadow stack →C B A→B C 16 void doit(char *str) { char buf[8]; Non-control data attack char *ptr = buf; strcpy(buf, str); puts(ptr); $ ./a.out $(perl -e 'print "A"x8 \ } .""\x08\xb0\xc4\x09" ) 0xffffffff parent stack frame Kernel space 0xc0000000 Stack (grows down) =TASK_SIZE libc init: 0xbfffceb80xffffceb8 arguments: 0xbfffd18a (argv[1]) 08048464: 0xbfffceb4 return address: 0x08048482 (saved eip) <main>: 0xbfffceb0
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages84 Page
-
File Size-