Pointer Subterfuge COEN 296 A Pointer Subterfuge n
Pointer Subterfuge COEN 296 A
Pointer Subterfuge n Pointer Subterfuge is a general expression for exploits that modify a pointer’s value. n n Function pointers are overwritten to transfer control to an attacker supplied shellcode. Data pointers can also be changed to modify the program flow according to the attacker’s wishes.
Pointer Subterfuge n Using a buffer overflow: n n n Buffer must be allocated in the same segment as the target pointer. Buffer must have a lower memory address than the target pointer. Buffer must be susceptible to a buffer overflow exploit.
Pointer Subterfuge n UNIX executables: n Data Segment n n BSS Segment n n All uninitialized global variables Stack n n All initialized global variables and constants All automatic variables Heap n All dynamically allocated variables
Pointer Subterfuge 1. static int GLOBAL_INIT = 1; /* data segment, global 2. static int global_uninit; /* BSS segment, global 3. 4. void main(int argc, char **argv) { /* stack, local 5. int local_init = 1; /* stack, local 6. int local_uninit; /* stack, local 7. static int local_static_init = 1; /* data seg, local 8. static int local_static_uninit; /* BSS segment, local /* storage for buff_ptr is stack, local /* allocated memory is heap, local 9. int *buff_ptr = (int*) malloc(sizeof(int)); } */ */ */
Pointer Subterfuge void good_function(const char *str) { //do something } int main(int argc, char **argv) { if (argc !=2){ printf("Usage: prog_name <string 1>n"); exit(-1); } static char buff [BUFFSIZE]; static void (*func. Ptr)(const char *str); func. Ptr = &good_function; strncpy(buff, argv[1], strlen(argv[1])); (void)(*func. Ptr)(argv[2]); return 0; }
Pointer Subterfuge n Program vulnerable to buffer overflow n n Variables buff and funct. Ptr are uninitialized and static Both stored in BSS segment Attacker can choose function and argument to execute This vulnerability happens in BSS
Pointer Subterfuge void good_function(const char *str) { //do something } int main(int argc, char **argv) { if (argc !=2){ printf("Usage: prog_name <string 1>n"); exit(-1); } static char buff [BUFFSIZE]; static void (*func. Ptr)(const char *str); func. Ptr = &good_function; strncpy(buff, argv[1], strlen(argv[1])); (void)(*func. Ptr)(argv[2]); return 0; }
Function Pointer Example 1. void good_function(const char *str) {. . . } 2. void main(int argc, char **argv) { 3. static char buff[BUFFSIZE]; The static character 4. static void (*func. Ptr)(const char *str); array buff 5. func. Ptr = &good_function; 6. strncpy(buff, argv[1], strlen(argv[1])); 7. (void)(*func. Ptr)(argv[2]); 8. } func. Ptr declared are both uninitialized and stored in the BSS segment.
Function Pointer Example 1. void good_function(const char *str) {. . . } 2. void main(int argc, char **argv) { 3. static char buff[BUFFSIZE]; 4. static void (*func. Ptr)(const char *str); 5. func. Ptr = &good_function; 6. strncpy(buff, argv[1], strlen(argv[1])); 7. (void)(*func. Ptr)(argv[2]); 8. } A buffer overflow occurs when the length of argv[1] exceeds BUFFSIZE.
Function Pointer Example 1. void good_function(const char *str) {. . . } 2. void main(int argc, char **argv) { 3. static char buff[BUFFSIZE]; 4. static void (*func. Ptr)(const char *str); 5. func. Ptr = &good_function; 6. strncpy(buff, argv[1], strlen(argv[1])); 7. (void)(*func. Ptr)(argv[2]); 8. } When the program invokes the function identified by func. Ptr, the shellcode is invoked instead of good_function().
Data Pointers Example void foo(void * arg, size_t len) char buff[100]; long val = …; long *ptr = …; memcpy(buff, arg, len); *ptr = val; … return; } { Buffer is vulnerable to overflow. Both val and ptr are located after the buffer and can be overwritten. This allows a buffer overflow to write an arbitrary address in memory.
Data Pointers n n Arbitrary memory writes can change the control flow. Exploits are easier if the length of a pointer is equal to the length of data. n Intel 32 Architectures: n sizeof(void*) = sizeof(int) = sizeof(long) = 4 B.
Instruction Pointer Modification n Instruction Counter (IC) (a. k. a Program Counter (PC)) contains address of next instruction to be executed. n n n Intel: EIP register. IC cannot be directly manipulated. IC is incremented or changed by a number of instructions: n n jmp Conditional jumps call ret
Instruction Pointer Modification n Arbitrary code execution attacks need to change IP n But can only so indirectly.
Instruction Pointer Modification int _tmain(int argc, _TCHAR* argv[]) { if (argc !=1){ printf("Usage: prog_namen"); Invoke good function through a pointer. exit(-1); } static void (*func. Ptr)(const char *str); func. Ptr = &good_function; Invoke good function (void)(*func. Ptr)("hi "); directly. good_function("there!n"); return 0; }
Instruction Pointer Modification (void)(*func. Ptr)(“hi “); 00424178 mov esi, esp 0042417 A push offset string "hi" (46802 Ch) 0042417 F call dword ptr [func. Ptr (478400 h)] 00424185 add esp, 4 00424188 cmp esi, esp First invocation of good function. Machine code is ff 15 00 84 47 00. The last four bytes are the address of the called function. good_function(“there!n”); Second invocation of 0042418 F push offset string "there!n" (468020 h) good function. 00424194 call good_function (422479 h) Machine code is 00424199 add esp, 4 e 8 e 0 e 2 ff ff. The last four bytes are the relative address of Note: Relative addressing adds / subtracts to the called function. current IP
Instruction Pointer Modification n Static invocation uses an immediate value for the address of the function. n n Address is encoded in the instruction. Address is calculated and put into IC. It cannot be changed without changing the executable. Invocation through function pointer is indirect. n Future value of IC is in a memory location that can be changed.
Instruction Pointer Modification n Controlling the IC allows attacker to select code to be executed. n n Function invocations that cannot be resolved at compile time are vulnerable Exploit easy if attacker can write arbitrary values at an arbitrary location
Instruction Pointer Modification Big Red Button: Attacker can write arbitrary data at arbitrary location
Targets for Instruction Pointer Modification: Global Offset Table n Windows and Linux use a similar mechanism for linking and transferring control for library functions. n n Windows’ is not exploitable. Linux’ is.
Targets for Instruction Pointer Modification: Global Offset Table n ELF (executable & linking format) n Default binary format for n n n Linux Solaris 2. x SVR 4 Adopted by TIS (Tool Interface Standards Committee) Global Offset Table (GOT) n n n Included in process space of ELF binaries. GOT contains absolute addresses. Allows easy dynamic linking.
Targets for Instruction Pointer Modification: Global Offset Table n GOT n n n Initially, GOT entry contains address of RTL (runtime linker) If that function is called, the RTL resolves the real address of the intended function and puts it into GOT. Subsequent calls invoke the function directly.
Targets for Instruction Pointer Modification: Global Offset Table # RTL GOT # RTL Invoke RTL # RTL printf RTL resolves address. # RTL … # RTL main RTL writes address into GOT Program calls printf First call to printf Go to GOT and invoke function there … …
Targets for Instruction Pointer Modification: Global Offset Table n Address of a GOT entry is fixed in the ELF executable. n n It does not vary between executable process images. Use objdump to obtain the address of a GOT entry.
Targets for Instruction Pointer Modification: Global Offset Table % objdump --dynamic-reloc test-prog format: file format elf 32 -i 386 DYNAMIC RELOCATION RECORDS OFFSET TYPE 08049 bc 0 R_386_GLOB_DAT 08049 ba 8 R_386_JUMP_SLOT 08049 bac R_386_JUMP_SLOT 08049 bb 0 R_386_JUMP_SLOT 08049 bb 4 R_386_JUMP_SLOT 08049 bb 8 R_386_JUMP_SLOT 08049 bbc R_386_JUMP_SLOT VALUE __gmon_start__ __libc_start_main strcat printf exit sprintf The strcpy offsets specified for each R_386_JUMP_SLOT relocation record contain the address of the specified function (or the RTL linking function)
Targets for Instruction Pointer Modification: Global Offset Table n How to use GOT? n n n Attacker needs to provide their own shellcode. Attacker needs to be able to write an arbitrary value to an arbitrary address. Attack: n Attacker overwrites GOT entry (that is going to be used) with the address of their shellcode.
Targets for Instruction Pointer Modification: . dtors n gcc allows attributes n keyword is __attribute__ static void start(void) __attribute__ ((constructor)); static void stop(void) __attribute__ ((destructor)); n constructor attribute: n n destructor attribute: n n function will be executed before main() function will be executed just after main() exits. ELF places these in the. ctors and the. dtors sections.
Targets for Instruction Pointer Modification: . dtors static void create(void) __attribute__ ((constructor)); static void destroy (void) __attribute__ ((destructor)); int main(int argc, char *argv[]) { printf("create: %p. n", create); printf("destroy: %p. n", destroy); exit(EXIT_SUCCESS); } void create(void) { printf("create called. n"); } void destroy(void) { printf("destroy called. n"); } create called. create: 0 x 80483 a 0. destroy: 0 x 80483 b 8. destroy called.
Targets for Instruction Pointer Modification: . dtors n Both sections have the following layout: n n n 0 xffff {function-address} 0 x 0000 The. ctors and. dtors sections are mapped into the process address space and are writable by default. Constructors have not been used in exploits because they are called before the main program. The focus is on destructors and the. dtors section. The contents of the. dtors section in the executable image can be examined with the objdump command.
Targets for Instruction Pointer Modification: . dtors n n Attacker transfers control by overwriting the address of a function pointer in the. dtors section. Given a binary: n Attacker finds exact position for overwrite by analyzing ELF image.
Targets for Instruction Pointer Modification: . dtors n n . dtors section is always present If no destructor is specified: n n n 00 00 ff ff . dtors consists of head and tail tag 12 34 56 78 with no function address between them Attacker overwrites tail tag with address of shell code 00 00 After executing shell code n n Following words interpreted as function addresses to execute Until crash 01 00 00 60 12 34 56 78 Empty. dtors section Attacked. dtors section: Execute shell code at 01 00 00 60, then call 12 34 56 78, …
Targets for Instruction Pointer Modification: . dtors n For an attacker, overwriting the. dtors section has advantages over other targets: n n . dtors is always present and mapped into memory. However: n n The. dtors target only exists in programs that have been compiled and linked with GCC. It is difficult to find a location to inject the shellcode onto so that it remains in memory after main() has exited.
Targets for Instruction Pointer Modification: Virtual Functions n Important feature for OO programming. n n Allows dynamic binding (resolved during run-time) of function calls. Virtual function is: n n A member function of a class Declared with virtual keyword Usually has a different functionality in the derived class A function call is resolved at run-time
Targets for Instruction Pointer Modification: Virtual Functions #include <iostream> using namespace std; class a { public: void f(void) { cout << "base f" << endl; }; virtual void g(void) { cout << "base g" << endl; }; }; class b: public a { public: void f(void) { cout << "derived f" << endl; }; void g(void) { cout << "derived g" << endl; }; }; int main(int argc, char *argv[]) { a *my_b = new b(); my_b->f(); my_b->g(); return 0; }
Targets for Instruction Pointer Modification: Virtual Functions n Typical Implementation: n n Virtual Function Table (VTBL). Array of function pointers used at runtime for dispatching virtual function calls. Each individual object pointer points to the VTBL via a VPTR in the object header. VTBL contains pointers to all implementations of a virtual function. b-obj: VTBL: my_b code for g() VPTR g()
Targets for Instruction Pointer Modification: Virtual Functions n Attacks: overwrite function pointers in the VTBL or n change the VPTR to point to a new VTBL. n n Attacker can use an arbitrary memory write or a buffer overflow directly on the object.
Targets for Instruction Pointer Modification: atexit() on_exit() n atexit() n n n General utility defined in C 99 Registers a function to be called at normal program termination. C 99 allows registration of at least 32 functions.
Targets for Instruction Pointer Modification: atexit() on_exit() n n Similar functionality under Sun. OS Present in libc 4, libc 5, glibc
Targets for Instruction Pointer Modification: atexit() on_exit() #include <stdio. h> char *glob; void test(void) { printf("%s", glob); } int main(void) { atexit(test); glob = "Exiting. n"; }
Targets for Instruction Pointer Modification: atexit() on_exit() n n n atexit() adds a specific function to an array of functions to be called when exiting. exit() invokes each function in LIFO order. Array is allocated as a global symbol n n __atexit in BSD __exit_funcs in Linux
Targets for Instruction Pointer Modification: atexit() on_exit() (gdb) b main Breakpoint 1 at 0 x 80483 f 6: file atexit. c, line 6. (gdb) r Starting program: /home/rcs/book/dtors/atexit Breakpoint 1, main (argc=1, argv=0 xbfffe 744) at atexit. c: 6 6 atexit(test); (gdb) next 7 glob = "Exiting. n"; (gdb) x/12 x __exit_funcs 0 x 42130 ee 0 <init>: 0 x 00000003 0 x 00000004 0 x 4000 c 660 0 x 42130 ef 0 <init+16>: 0 x 00000000 0 x 00000004 0 x 0804844 c 0 x 42130 f 00 <init+32>: 0 x 00000000 0 x 00000004 0 x 080483 c 8 (gdb) x/4 x 0 x 4000 c 660 <_dl_fini>: 0 x 57 e 58955 0 x 5 ce 85356 0 x 81000054 0 x 0091 c 1 c 3 (gdb) x/3 x 0 x 0804844 c 0 x 804844 c <__libc_csu_fini>: 0 x 53 e 58955 0 x 9510 b 850 x 102 d 0804 (gdb) x/8 x 0 x 080483 c 8 0 x 80483 c 8 <test>: 0 x 83 e 58955 0 xec 8308 ec 0 x 2035 ff 08 0 x 68080496
Targets for Instruction Pointer Modification: atexit() on_exit() n n In the debug session, a breakpoint is set before the call to atexit() in main() and the program is run. The call to atexit() is then executed to register the test() function. After the test() function is registered, memory at __exit_funcs is displayed. Each function is contained in a structure consisting of four doublewords. n Last doubleword contains address of function.
Targets for Instruction Pointer Modification: atexit() on_exit() (gdb) b main Breakpoint 1 at 0 x 80483 f 6: file atexit. c, line 6. (gdb) r Starting program: /home/rcs/book/dtors/atexit Breakpoint 1, main (argc=1, argv=0 xbfffe 744) at atexit. c: 6 6 atexit(test); (gdb) next 7 glob = "Exiting. n"; (gdb) x/12 x __exit_funcs 0 x 42130 ee 0 <init>: 0 x 00000003 0 x 00000004 0 x 4000 c 660 0 x 42130 ef 0 <init+16>: 0 x 00000000 0 x 00000004 0 x 0804844 c 0 x 42130 f 00 <init+32>: 0 x 00000000 0 x 00000004 0 x 080483 c 8 (gdb) x/4 x 0 x 4000 c 660 <_dl_fini>: 0 x 57 e 58955 0 x 5 ce 85356 0 x 81000054 0 x 0091 c 1 c 3 (gdb) x/3 x 0 x 0804844 c 0 x 804844 c <__libc_csu_fini>: 0 x 53 e 58955 0 x 9510 b 850 x 102 d 0804 (gdb) x/8 x 0 x 080483 c 8 0 x 80483 c 8 <test>: 0 x 83 e 58955 0 xec 8308 ec 0 x 2035 ff 08 0 x 68080496
Targets for Instruction Pointer Modification: atexit() on_exit() n In the example: n Three function have been registered: n n _dl_fini() __libc_csu_fini() test() Attacker can overwrite any entry of the __exit_funcs structure.
Targets for Instruction Pointer Modification: longjmp() n C 99 defines alternate function call and return discipline n n Intended for dealing with errors and interrupts encountered in a low-level subroutine of a program setjmp() macro n n Saves calling environment longjmp(), siglongjmp() n Non-local jump to a saved stack context
Targets for Instruction Pointer Modification: longjmp() n longjmp() restores environment saved by the most recent invocation of setjmp() n Environment: n n All accessible objects You can give arguments to jmp_buf and setjmp() to distinguish between jump targets
Targets for Instruction Pointer Modification: longjmp() #include <setjmp. h> jmp_buf buf; void g(int n); void h(int n); int n = 6; void f(void){ setjmp(buf); g(n); } void g(int n){ h(n); } void h(int n) { longjmp(buf, 2); } int main (void){ f(); return 0; } n longjmp() example: n longjmp() returns control back to the point of the set_jmp() invocation.
Targets for Instruction Pointer Modification: longjmp() 1. typedef int __jmp_buf[6]; 2. 3. 4. 5. 6. 7. 8. #define #define JB_BX 0 JB_SI 1 JB_DI 2 JB_BP 3 JB_SP 4 JB_PC 5 JB_SIZE 24 9. typedef struct __jmp_buf_tag { 10. __jmp_buf __jmpbuf; 11. int __mask_was_saved; 12. __sigset_t __saved_mask; 13. } jmp_buf[1] n n Linux implementation of jmp_buf Notice the JB_PC field. This is the target of an attack. An arbitrary memory write can overwrite this field with the address of shellcode in the overflowing buffer.
Targets for Instruction Pointer Modification: longjmp() The movl instruction on line 2 restores the BP longjmp(env, i) movl i, %eax /* return i */ movl env. __jmpbuf[JB_BP], %ebp movl env. __jmpbuf[JB_SP], %esp jmp (env. __jmpbuf[JB_PC]) The movl instruction on line 3 restores the stack pointer (SP). Line 4 transfers control to the stored PC
Targets for Instruction Pointer Modification: Exception Handling n Exception n n Event outside of the normal operation of a procedure. Windows provides three types of exception handlers: n Vectored Exception Handling (VEH) n n n Structured Exception Handling (SEH) n n Added in Windows XP Called first to override SEH. Implemented as per-function or per-thread exception handling. System Default Exception Handling
Targets for Instruction Pointer Modification: Exception Handling n Exception n n Event outside of the normal operation of a procedure. Windows provides three types of exception handlers: n Vectored Exception Handling (VEH) n n n Structured Exception Handling (SEH) n n Added in Windows XP Called first to override SEH. Implemented as per-function or per-thread exception handling. System Default Exception Handling
Targets for Instruction Pointer Modification: Exception Handling n SEH n try { // Do stuff here } catch(…){ // Handle exception here } __finally { // Handle cleanup here } Implemented through try … catch blocks n n n Any exception raised in the try block is handled in the matching catch block. If the catch block cannot handle it, it is passed back to prior scope. __finally is a MS extension to C/C++ n Used to clean-up anything instantiated in the try block.
Targets for Instruction Pointer Modification: Exception Handling n SEH n n Uses the EXECPTION_REGISTRATION structure Located on stack. Previous EXECPTION_REGISTRATION prev is at a higher stack address. If the executable image header lists SAFE SEH handler addresses, the handler address must be listed as a SAFE SEH handler. Otherwise, any structured exception handler may be called. EXCEPTION_REGISTRATION struc prev dd handler dd _EXCEPTION_REGISTRATION ends ? ?
Targets for Instruction Pointer Modification: Exception Handling Stack Frame Initialization During Function Prologue in Visual C++ n Notice: n n Local variables followed immediately by exception handler address. This puts the exception handler address at risk from buffer overflow. push ebp mov ebp, esp and esp, 0 FFFFFFF 8 h push 0 FFFFh push ptr [Exception_Handler] mov eax, dword ptr fs: [0000 h] push eax mov dword ptr fs: [0], esp
Targets for Instruction Pointer Modification: Exception Handling Stack Frame with Exception Handler: Stack Offset Description Value -0 x 10 Handler [Exception Handler] -0 x 0 c Previous Handler fs: [0] at function start -8 Guard -1 -4 Saved ebp 0 Return Address
Targets for Instruction Pointer Modification: Exception Handling n n Local variables are immediately followed by exception handler address Overflow in a local variable will change the exception handler address
Targets for Instruction Pointer Modification: Exception Handling n Attacker can: n n Overwrite the exception handler address. (supra) Replace the pointer in the Thread Environment Block (TEB). n TEB contains lists of registered exception handlers. n n n Attacker mocks up a list entry as part of the payload. Modify the first exception handler field using an arbitrary memory write. Seems to be still possible despite recent Windows version checking validity of list entries.
Targets for Instruction Pointer Modification: Exception Handling n n Windows provides a global exception filter and handler for the entire process that is called if no previous exception handler can handle the exception. Implement an unhandled exception filter for the entire process to gracefully handle unexpected error conditions and for debugging. An unhandled exception filter function is assigned using the Set. Unhandled. Exception. Filter() function. If an attacker overwrites specific memory addresses through an arbitrary memory write, the unhandled exception filter can be redirected to run arbitrary code.
Targets for Instruction Pointer Modification: Mitigation Strategies n Eliminate vulnerabilities that allow memory to be improperly overwritten. n These mistakes arise from: n n n Overwriting data pointers (this presentation) Common errors managing dynamic memory Format string vulnerabilities.
Targets for Instruction Pointer Modification: Mitigation Strategies n Eliminate exposure. n W^X n n Reduce privileges of vulnerable processes. Memory segment can either be writable or executable, but not both. n n Difficult to implement. Does not work with targets such as atexit() that need to be both writable at runtime and executable.
Targets for Instruction Pointer Modification: Mitigation Strategies n Canaries n Does protect against n n Overflowing a buffer on a stack & overwrite stack pointer and other protected regions. Do not protect against n n Overflowing a stack by itself. Modification of n n n variables data pointers function pointers
Targets for Instruction Pointer Modification: Summary n Pointer subterfuge is a response to anti-stack smashing measures n n Canaries, Stack-Guard Method is a buffer overflow in the vicinity of a target pointer. n Function pointer overwrite: n n Attacker can move control to arbitrary code provided in the payload. Data pointer overwrite: n n Can result in arbitrary writes to arbitrary memory. These modify one of a large list of “juicy” targets.
- Slides: 63