SCP A System Call Protector against Buffer Overflow
SCP: A System Call Protector against Buffer Overflow Attacks dove 邱秉誠
Outline u u u u Introduction Attacking Method Related Work SCP System Design Experimental Result Conclusion Future Work 2
Introduction (1) u Buffer Overflow Attack • Easily launched • Huge amount of targets • Strongly damage • The most dangerous threat in the internet 3
Introduction (2) u u Many countermeasures were published But also were defeated Developing an efficient and effective approach becomes a critical and emergent issue 4
Attacking Method (1) u Stack Overflow Attack • Overflow the return address to launch injected code (shell code) 5
Attacking Method (2) u Return-into-libc Attack Overwrite the return address to execute system() function call High Address Pointer to system()’s arg “/bin/sh” Fake RA ESP system() EIP (RA) EBP Low Address String format: AAA… buffer address to system()’s return address pointer to system()’s arg 6
Attacking Method (3) u Heap Overflow Attack • Similar to stack overflow, but on the heap area 7
Attacking Method (4) u Scanning Code Attack • After overflow, scan the process image to find patterns and then jump into it • Usually used to bypass some protections 8
Related Work (1) u Some Countermeasures • Stack. Guard / Stack. Shield • Address Obfuscation • Exec Shield • Binary Obfuscation • Point. Guard™ • Instruction Set Randomization • RAD 9
Related Work (2) u Stack. Guard -- add canary word before return u Stack. Shield --copy return address to confirm address when return High Address return address … canary word … Buffer Low Address u Low Address Saved return address Bypassing Stack. Guard and Stack. Shield 10
Related Work (3) u Address Obfuscation • Pa. X ASLR project - Randomize the base address of memory regions -- Randomize the base address of stack/heap -- Randomize the starting address of dynamiclinked libraries -- Randomize the locations of routines and static data • ASLP • Internal fragmentation problem • Derandomization Attack 11
Related Work (4) u Bound Checking • Bound Checking for C • Require source code / recompile • Runtime overhead are huge - 4 x / 5 x when best case - 10 x general case - 100 x worst case 12
Related Work (5) u Exec Shield • Data/Stack section non-executable • Code section non-writable • Compatibility problem - ELF file format -- Add PT_GNU_STACK and PT_GNU_HEAP - Nested function - Recompile / porting - sigreturn() system call • Return into libc attack can be launched 13
Related Work (6) u Binary Obfuscation • Change ELF layout (add new section) • Add new system call to notify the return address • Insert junk code in binary object ØAttacker may use the new system call ØReturn into libc attack / scanning code attack can be launched 14
Related Work (7) u Point. Guard™ • Encrypt pointer, decrypt when reference object 15
Related Work (8) u Instruction Set Randomization • Hardware solution, encrypt / decrypt CPU instructions Ø porting binaries 16
Related Work (9) u RAD • Return Address Defender • Compiler solution • Push return address to RAR when prologue • Pop return address from RAR when eprologue Ø Need recompile 17
SCP System Design (1) u Principles • Prevent attacker from executing int 80 offered by attacker • Prevent attacker from executing int 80 existed in system u Goal • • • Low overhead Efficient to protect Do not require source code Compatibility Use less system resource Easy to maintain 18
SCP System Design (2) u Assumptions • Malicious code have to use system call to damage system • vulnerable program is dynamic linked 19
SCP System Design (3) u System overview • protect int 0 x 80’s return address movl sys#, %eax movl arg 1, %ebx … int $0 x 80 • Use secure enter kernel instead of all sysenter (int $0 x 80) 20
SCP System Design (4) u The system call path 21
SCP System Design (5) u The system call path High Address Kernel Space ( kernel ) sys_open() 5. return User Space ( libc wrapper routine ) __libc_open() ( GOT entry ) Address of __libc_open 6. return Low Address ( PLT ) jmp *GOT[__libc_open] ( user program ) open(); 4. trap into kernel 3. call wrapper routine 2. lookup GOT 1. go to PLT 22
SCP System Design (6) u Pseudo Code (a) Secure Enter Kernel save_all_registers; page = 0; size = 0; if ( page == 0 ) { page = mmap 2(); size = copy_trap_code(page); notify_kernel(size+6); } restore_all_registers; call page; (b) Trap Code restore_sys#_in_eax; int $0 x 80; (sysenter) return_to_libc; machine code: x 8 Bx 44x 24x 04 x. CDx 80 x 83x. C 4x 08 x. C 3 23
SCP System Design (7) u New system call path (with SCP system) High Address 6. return 5. trap into kernel ( trap page ) int $0 x 80 4. call trap page 7. return ( kernel ) sys_open() sys_read() ( libc wrapper routine ) __libc_open() __libc_read() ( GOT entry ) Address of __libc_open Address of __libc_read 8. return ( PLT ) jmp *GOT[__libc_open] jmp *GOT[__libc_read] ( user program ) open(); read(); Low Address Kernel Space User Space 3. call wrapper routine 2. lookup GOT 1. go to PLT 24
SCP System Design (8) u Example with SCP system (lazy binding) 4. Call printf() Glibc: printf() here 3. Load libc. so. 6 Loader (ld-linux. so. 2) 2. Loading program 6. No rm al sys 5. Not ify ker tem c a nel th ll e RA 1. Notify kernel the RA t co c e j In kernel de program 25
SCP System Design (9) u Example with SCP system (lazy binding) 4. Call printf() Glibc: printf() here 3. Load libc. so. 6 Loader (ld-linux. so. 2) 2. Loading program 6. No rm al sys 5. Not ify ker tem c a nel th ll e RA 1. Notify kernel the RA t co c e j In kernel de program 26
SCP System Design (10) u Modify kernel • Add new system call notify_kernel() - It can only be called 2 times per process • Add new structures in task_struct to restore addresses - loader_return_address - syscall_return_address • do_fork() - Addresses copied from parent process • sys_execve() - loader_return_address = 0 - syscall_return_address = 0 27
SCP System Design (11) u Introduce fake pages 28
SCP System Design (12) u Attack analysis • Attacker can launch scanning code attack to trace real int $0 x 80 (user program) system_call (PLT) (GOT) (libc) wrapper routine (heap) int $0 x 80 • Possible solution: - Non-readable but executable code segment - … future work 29
SCP System Design (13) u SCP system analysis • Allow executable stack - General debugger support - Nested function - Do not require ELF modified - Do not require to recompile • Allow execute programs without ASLR - No internal fragment problem - Process crashes are decided by process owners - Easy to maintain 30
Experimental Result (1) u Efficiency test • Buffer overflow attack with injected code 31
Experimental Result (2) u Efficiency test • Calling notify_kernel test 32
Experimental Result (3) u Micro test • 10, 000 times per system call System Call Original libc & Kernel Secure libc & Secure Kernel Increment (usec) mmap 4. 83598861 5. 04285570 4. 28 % open 5. 70100183 12. 31045995 115. 93 % read 4. 44757121 4. 65731530 4. 72 % write 28. 61905470 28. 86815789 0. 87 % 33
Experimental Result (4) u Original libc & kernel execve(". /micro-test. open", [". /micro-test. open"], % time seconds usecs/calls errors ----------- ----49. 40 828. 885786 41 20000000 25. 81 432. 1044308 43 10000003 1 24. 59 411. 1630811 41 10000002 0. 04 0. 700248 1 0. 04 0. 700211 1 0. 04 0. 700202 1 0. 02 0. 402909 201455 2 0. 02 0. 400418 200209 2 0. 01 0. 201221 33537 6 0. 01 0. 100622 33541 3 ----------- ----100. 00 1677. 766736 40000021 1 [/* 29 vars */]) = 0 syscall --------gettimeofday open close brk mprotect read write munmap old_mmap fstat 64 --------total 34
avg timediff = 0. 0000073216265842318534575253186069687672 sec = 7. 32162658 usec Command exited with non-zero status 81 Command being timed: ". /micro-test. open" User time (seconds): 0. 69 System time (seconds): 122. 31 Percent of CPU this job got: 100% Elapsed (wall clock) time (h: mm: ss or m: ss): 2: 03. 00 Average shared text size (kbytes): 0 Average unshared data size (kbytes): 0 Average stack size (kbytes): 0 Average total size (kbytes): 0 Maximum resident set size (kbytes): 0 Average resident set size (kbytes): 0 Major (requiring I/O) page faults: 82 Minor (reclaiming a frame) page faults: 7 Voluntary context switches: 0 Involuntary context switches: 0 Swaps: 0 File system inputs: 0 File system outputs: 0 Socket messages sent: 0 Socket messages received: 0 Signals delivered: 0 Page size (bytes): 4096 Exit status: 81 35
Experimental Result (5) u Modified libc & kernel execve(". /micro-test. open", [". /micro-test. open"], % time seconds usecs/calls errors ----------- ----47. 44 821. 1515639 41 20000000 28. 54 494. 834607 49 10000003 1 23. 82 412. 936479 41 10000002 0. 04 0. 700382 1 0. 04 0. 700380 1 0. 02 0. 403299 201650 2 0. 02 0. 400813 200407 2 0. 02 0. 400782 200391 2 0. 02 0. 400761 200381 2 0. 01 0. 202308 33718 6 0. 01 0. 101257 33752 3 0. 01 0. 101186 33729 3 ----------- ----100. 00 1733. 697893 40000027 1 [/* 29 vars */]) = 0 syscall --------gettimeofday open close read brk write mmap 2 munmap utimes old_mmap mprotect fstat 64 --------total 36
avg timediff = 0. 0000123534624044317750067014868853298992 sec = 12. 35346240 usec Command exited with non-zero status 82 Command being timed: ". /micro-test. open" User time (seconds): 0. 68 System time (seconds): 173. 26 Percent of CPU this job got: 99% Elapsed (wall clock) time (h: mm: ss or m: ss): 2: 53. 94 Average shared text size (kbytes): 0 Average unshared data size (kbytes): 0 Average stack size (kbytes): 0 Average total size (kbytes): 0 Maximum resident set size (kbytes): 0 Average resident set size (kbytes): 0 Major (requiring I/O) page faults: 104 Minor (reclaiming a frame) page faults: 13 Voluntary context switches: 0 Involuntary context switches: 0 Swaps: 0 File system inputs: 0 File system outputs: 0 Socket messages sent: 0 Socket messages received: 0 Signals delivered: 0 Page size (bytes): 4096 Exit status: 82 37
Experimental Result (5) u Macro test • 100, 000 times per command Command Original libc & Kernel (sec) Secure libc & Secure Kernel Increment (sec) ls 0. 00781023 0. 00922095 18. 06 % make 0. 01481522 0. 01697969 14. 61 % sysctl 0. 02905236 0. 03447007 18. 65 % tar 0. 00804451 0. 00940219 16. 88 % gcc 0. 98855523 1. 00293709 01. 45 % 38
Conclusion u We propose a new method to protect system calls by registering valid int 80 on premise • Without recompile • Allow executable stack • Use ASLR optionally • Compatible with other protections 39
Future Work u More secure • Implement “executable but non-readable” region in segment section on i 386 • The NX Bit chip • AMD 64 CPU 40
u u Thanks Q&A 41
- Slides: 41