Yet More Bufger Overfmows 1
Changelog Corrections made in this version not in fjrst posting: 1 April 2017: slide 41: a few more %c’s would be needed to skip format string part 1
last time: pointer subterfuge “pointer subterfuge” overwrite a pointer overwritten pointer used to overwrite/access somewhere else many ways this translates into exploit 3
last time: targets for pointers many “targets” for attacker change important data directly change return addresses, then have return happen change function pointer, then have it called typically: rely on code address being used soon same as stack smashing — but not necessairily return address which is used — depends on context difgerent situations will make difgerent ones easier/possible 4
last time: frame pointer overwrite way ofg-by-one errors were a problem many idea: frame pointer often next to bufger frame pointer used to locate return address changing frame pointer efgectively changes return address 5
beyond normal bufger overfmows pretty much every memory error is a problem will look at exploiting: ofg-by-one bufger overfmows (!) heap bufger overfmows double-frees use-after-free integer overfmows in size calculations 6
beyond normal bufger overfmows pretty much every memory error is a problem will look at exploiting: ofg-by-one bufger overfmows (!) heap bufger overfmows double-frees use-after-free integer overfmows in size calculations 7
easy heap overfmows struct foo { char buffer[100]; void (*func_ptr)( void ); }; increasing addresses buffer func_ptr 8
heap overfmow: adjacent allocations the heap bufger overfmowing result of first ’s vtable first ’s buffer second ’s vtable second ’s buffer increasing addresses attacker_controlled); class V { V *second = new V(...); V *first = new V(...); ... }; ... virtual void ...; public : char buffer[100]; 9 strcpy(first − >buffer,
heap overfmow: adjacent allocations the heap bufger overfmowing result of first ’s vtable first ’s buffer second ’s vtable second ’s buffer increasing addresses attacker_controlled); class V { V *second = new V(...); V *first = new V(...); ... }; ... virtual void ...; public : char buffer[100]; 9 strcpy(first − >buffer,
heap smashing “lucky” adjancent objects same things possible on stack but stack overfmows had nice generic “stack smashing” is there an equivalent for the heap? yes (mostly) 10
diversion: implementing malloc/new many ways to implement malloc/new we will talk about one common technique 11
heap object size/free size/free prev next free space free size/free prev next free space new’d object struct AllocInfo { size/free prev next (deleted obj.) free space }; AllocInfo *next; AllocInfo *prev; int size; bool free; 12
implementing free() int free( void *object) { ... block_after = object + object_size; /* unlink from list */ } ... } arbitrary memory write 13 if (block_after − >free) { new_block − >size += block_after − >size; block_after − >prev − >next = block_after − >next; block_after − >next − >prev = block_after − >prev;
implementing free() int free( void *object) { ... block_after = object + object_size; /* unlink from list */ } ... } arbitrary memory write 13 if (block_after − >free) { new_block − >size += block_after − >size; block_after − >prev − >next = block_after − >next; block_after − >next − >prev = block_after − >prev;
vulnerable code next next prev size/free (or system() ?) shellcode GOT entry: fopen GOT entry: printf GOT entry: malloc GOT entry: free size/free prev free space char *buffer = malloc(100); size/free alloc’d object size/free prev next free space ... free(other_thing); free(buffer); ... strcpy(buffer, attacker_supplied); ... 14
vulnerable code next next prev size/free (or system() ?) shellcode GOT entry: fopen GOT entry: printf GOT entry: malloc GOT entry: free size/free prev free space char *buffer = malloc(100); size/free alloc’d object size/free prev next free space ... free(other_thing); free(buffer); ... strcpy(buffer, attacker_supplied); ... 14
vulnerable code next next prev size/free (or system() ?) shellcode GOT entry: fopen GOT entry: printf GOT entry: malloc GOT entry: free size/free prev free space char *buffer = malloc(100); size/free alloc’d object size/free prev next free space ... free(other_thing); free(buffer); ... strcpy(buffer, attacker_supplied); ... 14
beyond normal bufger overfmows pretty much every memory error is a problem will look at exploiting: ofg-by-one bufger overfmows (!) heap bufger overfmows double-frees use-after-free integer overfmows in size calculations 15
double-frees ... because double-free made loop in linked list malloc returns something still on free list size next prev thing alloc’d object size alloc’d object size prev next free space strcpy(q, attacker_controlled2); free(thing); chosen address // // q points to attacker- char *q = malloc(...); malloc(...); strcpy(p, attacker_controlled); blocks // on list of avail. // // p points to next/prev char *p = malloc(...); free(thing); 16
double-frees ... because double-free made loop in linked list malloc returns something still on free list size next prev thing/p alloc’d object size alloc’d object size prev next free space strcpy(q, attacker_controlled2); free(thing); chosen address // // q points to attacker- char *q = malloc(...); malloc(...); strcpy(p, attacker_controlled); blocks // on list of avail. // // p points to next/prev char *p = malloc(...); free(thing); 16
double-frees ... because double-free made loop in linked list malloc returns something still on free list size next prev thing/p alloc’d object size alloc’d object size prev next free space strcpy(q, attacker_controlled2); free(thing); chosen address // // q points to attacker- char *q = malloc(...); malloc(...); strcpy(p, attacker_controlled); blocks // on list of avail. // // p points to next/prev char *p = malloc(...); free(thing); 16
double-free expansion // malloc/new 3: third malloc first/second malloc GOT entry: free (original fjrst free) (global) fjrst_free size next / double free’d object strcpy(result3, ...); result3 = first_free; 17 // free/delete 1: // malloc/new 2: strcpy(result1, ...); // + overwrite: result1 = first_free; // malloc/new 1: first_free = chunk // free/delete 2: first_free = chunk; double_freed − >next = first_free; double_freed − >next = first_free; first_free = first_free − >next; first_free = first_free − >next;
double-free expansion // malloc/new 3: third malloc first/second malloc GOT entry: free (original fjrst free) (global) fjrst_free size next / double free’d object strcpy(result3, ...); result3 = first_free; 17 // free/delete 1: // malloc/new 2: strcpy(result1, ...); // + overwrite: result1 = first_free; // malloc/new 1: first_free = chunk // free/delete 2: first_free = chunk; double_freed − >next = first_free; double_freed − >next = first_free; first_free = first_free − >next; first_free = first_free − >next;
double-free expansion // malloc/new 3: third malloc first/second malloc GOT entry: free (original fjrst free) (global) fjrst_free size next / double free’d object strcpy(result3, ...); result3 = first_free; 17 // free/delete 1: // malloc/new 2: strcpy(result1, ...); // + overwrite: result1 = first_free; // malloc/new 1: first_free = chunk // free/delete 2: first_free = chunk; double_freed − >next = first_free; double_freed − >next = first_free; first_free = first_free − >next; first_free = first_free − >next;
double-free expansion // malloc/new 3: third malloc first/second malloc GOT entry: free (original fjrst free) (global) fjrst_free size next / double free’d object strcpy(result3, ...); result3 = first_free; 17 // free/delete 1: // malloc/new 2: strcpy(result1, ...); // + overwrite: result1 = first_free; // malloc/new 1: first_free = chunk // free/delete 2: first_free = chunk; double_freed − >next = first_free; double_freed − >next = first_free; first_free = first_free − >next; first_free = first_free − >next;
double-free expansion // malloc/new 3: third malloc first/second malloc GOT entry: free (original fjrst free) (global) fjrst_free size next / double free’d object strcpy(result3, ...); result3 = first_free; 17 // free/delete 1: // malloc/new 2: strcpy(result1, ...); // + overwrite: result1 = first_free; // malloc/new 1: first_free = chunk // free/delete 2: first_free = chunk; double_freed − >next = first_free; double_freed − >next = first_free; first_free = first_free − >next; first_free = first_free − >next;
double-free notes this attack has apparently not been possible for a while most malloc/new’s check for double-frees explicitly (e.g., look for a bit in size data) prevents this issue — also catches programmer errors pretty cheap 18
beyond normal bufger overfmows pretty much every memory error is a problem will look at exploiting: ofg-by-one bufger overfmows (!) heap bufger overfmows double-frees use-after-free integer overfmows in size calculations 19
Recommend
More recommend