More Bufger Overfmows 1 on the homework due Friday + 1 week - - PowerPoint PPT Presentation

more bufger overfmows
SMART_READER_LITE
LIVE PREVIEW

More Bufger Overfmows 1 on the homework due Friday + 1 week - - PowerPoint PPT Presentation

More Bufger Overfmows 1 on the homework due Friday + 1 week questions? big hint in assignment: gets is what does bufger overfmow reading the assembly should be fairly straightforward probably easiest strategy in this case debugger can fjnd


slide-1
SLIDE 1

More Bufger Overfmows

1

slide-2
SLIDE 2
  • n the homework

due Friday + 1 week questions? big hint in assignment: gets is what does bufger overfmow reading the assembly should be fairly straightforward

probably easiest strategy in this case

debugger can fjnd stack addresses you need

2

slide-3
SLIDE 3

3

slide-4
SLIDE 4

techniques from Pincus and Baker

arc injection AKA return-oriented programming

more detail (+ assignment) later in semester

  • verwriting data pointers
  • verwriting function pointers
  • verwriting pointers to function pointers

(on heap) overwriting malloc’s data structures

4

slide-5
SLIDE 5
  • ther bufger overfmows?

examples last time: luck: “score” for quiz on stack next to answer “arc injection” — return to existing code data pointer on stack

5

slide-6
SLIDE 6

techniques from Pincus and Baker

arc injection AKA return-oriented programming

more detail (+ assignment) later in semester

  • verwriting data pointers
  • verwriting function pointers
  • verwriting pointers to function pointers

(on heap) overwriting malloc’s data structures

6

slide-7
SLIDE 7

return-to-somewhere

increasing addresses highest address (stack started here) lowest address (stack grows here)

return address for vulnerable: address of do_useful_stuff unused space (20 bytes) bufger (100 bytes) return address for scanf unused junk do_useful_stuff (already in program)

code is already in program??? how often does this happen??? …turns out “usually” — more later in semester

7

slide-8
SLIDE 8

return-to-somewhere

increasing addresses highest address (stack started here) lowest address (stack grows here)

return address for vulnerable: address of do_useful_stuff unused space (20 bytes) bufger (100 bytes) return address for scanf unused junk do_useful_stuff (already in program)

code is already in program??? how often does this happen??? …turns out “usually” — more later in semester

7

slide-9
SLIDE 9

techniques from Pincus and Baker

arc injection AKA return-oriented programming

more detail (+ assignment) later in semester

  • verwriting data pointers
  • verwriting function pointers
  • verwriting pointers to function pointers

(on heap) overwriting malloc’s data structures

8

slide-10
SLIDE 10

pointer subterfuge

void f2b(void *arg, size_t len) { char buffer[100]; long val = ...; /* assume on stack */ long *ptr = ...; /* assume on stack */ memcpy(buff, arg, len); /* overwrite ptr? */ *ptr = val; /* arbitrary memory write! */ }

adapted from Pincus and Baker, Figure 2

9

slide-11
SLIDE 11

pointer subterfuge

void f2b(void *arg, size_t len) { char buffer[100]; long val = ...; /* assume on stack */ long *ptr = ...; /* assume on stack */ memcpy(buff, arg, len); /* overwrite ptr? */ *ptr = val; /* arbitrary memory write! */ }

adapted from Pincus and Baker, Figure 2

9

slide-12
SLIDE 12

arbitrary memory write

bunch of scenarios that lead to single arbitrary memory write how can attacker exploit this?

  • verwrite return address directly
  • verwrite other function/code address pointer?
  • verwrite existing machine code (insert jump?)
  • verwrite another data pointer — copy more?

10

slide-13
SLIDE 13

arbitrary memory write

bunch of scenarios that lead to single arbitrary memory write how can attacker exploit this?

  • verwrite return address directly
  • verwrite other function/code address pointer?
  • verwrite existing machine code (insert jump?)
  • verwrite another data pointer — copy more?

10

slide-14
SLIDE 14

arbitrary memory write

bunch of scenarios that lead to single arbitrary memory write how can attacker exploit this?

  • verwrite return address directly
  • verwrite other function/code address pointer?
  • verwrite existing machine code (insert jump?)
  • verwrite another data pointer — copy more?

10

slide-15
SLIDE 15

skipping the canary

increasing addresses highest address (stack started here) lowest address (stack grows here)

return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf

machine code for the attacker to run

11

slide-16
SLIDE 16

skipping the canary

increasing addresses highest address (stack started here) lowest address (stack grows here)

return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf

machine code for the attacker to run

11

slide-17
SLIDE 17

skipping the canary

increasing addresses highest address (stack started here) lowest address (stack grows here)

return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf

machine code for the attacker to run

11

slide-18
SLIDE 18

fragility

problem: need to know exact address of return address discussed how stack location varies — this is tricky/unreliable

12

slide-19
SLIDE 19

arbitrary memory write

bunch of scenarios that lead to single arbitrary memory write how can attacker exploit this?

  • verwrite return address directly
  • verwrite other function/code address pointer?
  • verwrite existing machine code (insert jump?)
  • verwrite another data pointer — copy more?

13

slide-20
SLIDE 20

function pointers?

int (*compare)(char *, char *); if (sortCaseSensitive) { compare = compareStringsExactly; } else { compare = compareStringsInsensitive; } ... if ((*compare)(string1, string2) == CMP_LESS) { ... }

14

slide-21
SLIDE 21

function pointers are common?

used in dynamic linking (stubs!) in large C projects used to implement C++ virtual functions

15

slide-22
SLIDE 22

dynamic linking stubs

00000000004004a0 <__printf_chk@plt>: 4004a0: ff 25 82 0b 20 00 jmpq *0x200b82(%rip) # 601028 <_GLOBAL_OFFSET_TABLE_+0x28> 4004a6: 68 02 00 00 00 pushq $0x2 4004ab: e9 c0 ff ff ff jmpq 400470 <_init+0x28>

jumps to _GLOBAL_OFFSET_TABLE[5] _GLOBAL_OFFSET_TABLE[5] always at address 0x601028 _GLOBAL_OFFSET_TABLE[5] is probably writeable

if lazy binding — normally updated fjrst time printf called

16

slide-23
SLIDE 23

attacking the GOT

increasing addresses highest address (stack started here) lowest address (stack grows here)

return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf

global ofgset table

GOT entry: printf GOT entry: fopen GOT entry: exit

machine code for the attacker to run

17

slide-24
SLIDE 24

attacking the GOT

increasing addresses highest address (stack started here) lowest address (stack grows here)

return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf

global ofgset table

GOT entry: printf GOT entry: fopen GOT entry: exit

machine code for the attacker to run

17

slide-25
SLIDE 25

attacking the GOT

increasing addresses highest address (stack started here) lowest address (stack grows here)

return address for f2b stack canary ptr (8 bytes) val (8 bytes) bufger (100 bytes) return address for scanf

global ofgset table

GOT entry: printf GOT entry: fopen GOT entry: exit

machine code for the attacker to run

17

slide-26
SLIDE 26

function pointers are common?

used in dynamic linking (stubs!) in large C projects used to implement C++ virtual functions

18

slide-27
SLIDE 27

function pointer tables: Linux kernel (1)

struct file { union { struct llist_node fu_llist; struct rcu_head fu_rcuhead; } f_u; struct path f_path; struct inode *f_inode; /* cached value */ const struct file_operations *f_op; /* * Protects f_ep_links, f_flags. * Must not be taken from IRQ context. */ spinlock_t f_lock; atomic_long_t f_count; ... };

19

slide-28
SLIDE 28

function pointer tables: Linux kernel (2)

struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iterate) (struct file *, struct dir_context *); ... };

20

slide-29
SLIDE 29

function pointers are common?

used in dynamic linking (stubs!) in large C projects used to implement C++ virtual functions

21

slide-30
SLIDE 30

C++ inheritence

class InputStream { public: virtual int get() = 0; // Java: abstract int get(); ... }; class SeekableInputStream : public InputStream { public: virtual void seek(int offset) = 0; virtual int tell() = 0; }; class FileInputStream : public InputStream { public: int get(); void seek(int offset); int tell(); ... };

22

slide-31
SLIDE 31

C++ inheritence: memory layout

vtable pointer

InputStream

vtable pointer

SeekableInputStream

vtable pointer file_pointer

FileInputStream

slot for get slot for get slot for seek slot for tell FileInputStream::get FileinputStream::seek FileInputStream::tell

23

slide-32
SLIDE 32

C++ implementation (pseudo-code)

struct InputStream_vtable { int (*get)(InputStream* this); }; struct InputStream { InputStream_vtable *vtable; }; ... InputStream *s = ...; int c = (s−>vtable−>get)(s);

24

slide-33
SLIDE 33

C++ implementation (pseudo-code)

struct SeekableInputStream_vtable { struct InputStream_vtable as_InputStream; void (*seek)(SeekableInputStream* this, int offset); int (*tell)(SeekableInputStream* this); }; struct FileInputStream { SeekableInputStream_vtable *vtable; FILE *file_pointer; }; ... FileInputStream file_in = { the_FileInputStream_vtable, ... }; InputStream *s = (InputStream*) &file_in;

25

slide-34
SLIDE 34

C++ implementation (pseudo-code)

SeekableInputStream_vtable the_FileInputStream_vtable = { &FileInputStream_get, &FileInputStream_seek, &FileInputStream_tell, }; ... FileInputStream file_in = { the_FileInputStream_vtable, ... }; InputStream *s = (InputStream*) &file_in;

26

slide-35
SLIDE 35

attacking function pointer tables

  • ption 1: overwrite table entry directly

required/easy for Global Ofgset Table — fjxed location usually not possible for VTables — read-only memory

  • ption 2: create table in bufger (big list of pointers to shellcode),

point to bufger

useful when table pointer next to bufger (e.g. C++ object on stack next to bufger)

27

slide-36
SLIDE 36

case study (simplifjed)

bug in NTPd (Network Time Protocol Daemon) via Stepher Röttger, “Finding and exploiting ntpd vulnerabilities”

static void ctl_putdata( const char *dp, unsigned int dlen, int bin /* set to 1 when data is binary */ ) { ... memmove((char *)datapt, dp, (unsigned)dlen); datapt += dlen; datalinelen += dlen; }

28

slide-37
SLIDE 37

the target

memmove((char *)datapt, dp, (unsigned)dlen);

datapt (global variable) (other global variables) bufger (global array) strlen GOT entry system() stub

29

slide-38
SLIDE 38

more context

memmove((char *)datapt, dp, (unsigned)dlen); ... ... strlen(some_user_supplied_string) /* calls strlen@plt looks up global offset table entry! */

30

slide-39
SLIDE 39

the target

memmove((char *)datapt, dp, (unsigned)dlen);

datapt (global variable) (other global variables) bufger (global array) strlen GOT entry system() stub

31

slide-40
SLIDE 40
  • verall exploit
  • verwrite datapt to point to strlen GOT entry
  • verwrite value of strlen GOT entry

example target: system function

executes command-line command specifjed by argument

supply string to provide argument to “strlen”

32

slide-41
SLIDE 41

the target

memmove((char *)datapt, dp, (unsigned)dlen);

datapt (global variable) (other global variables) bufger (global array) strlen GOT entry system() stub

33

slide-42
SLIDE 42

the target

memmove((char *)datapt, dp, (unsigned)dlen);

datapt (global variable) (other global variables) bufger (global array) strlen GOT entry system() stub

33

slide-43
SLIDE 43
  • verall exploit: reality

real exploit was more complicated needed to defeat more mitigations needed to deal with not being able to write \0 actually tricky to send things that trigger bufger write

(meant to be local-only)

34

slide-44
SLIDE 44

beyond normal bufger overfmows

pretty much every memory error is a problem will look at exploiting:

  • fg-by-one bufger overfmows (!)

heap bufger overfmows double-frees use-after-free integer overfmows in size calculations

35

slide-45
SLIDE 45

beyond normal bufger overfmows

pretty much every memory error is a problem will look at exploiting:

  • fg-by-one bufger overfmows (!)

heap bufger overfmows double-frees use-after-free integer overfmows in size calculations

36

slide-46
SLIDE 46

preliminaries

frame pointers are commonly used in addition to stack pointers not something we’ve seen in x86-64 assembly

37

slide-47
SLIDE 47

frame pointers

increasing addresses

return address for foo saved %rbp local variables for foo

%rbp within foo %rsp within foo

38

slide-48
SLIDE 48

frame pointer code

foo: // prologue pushq %rbp movq %rsp, %rbp subq $120, %rsp ... ... ... movq %rbp, %rsp popq %rbp ret foo: // prologue pushq %rbp enter $120, $1 ... ... ... leave ret foo: // prologue sub $120, %rsp ... ... ... add $120, %rsp ret

39

slide-49
SLIDE 49

stack layout: two functions

increasing addresses

return address for foo saved %rbp local variables in foo

%rbp (foo) %rsp (foo)

return address for bar saved %rbp local variables for bar

%rbp (bar) %rsp (bar)

40

slide-50
SLIDE 50

stack layout: two functions

increasing addresses

return address for foo saved %rbp local variables in foo

%rbp (foo) %rsp (foo)

return address for bar saved %rbp local variables for bar

%rbp (bar) %rsp (bar)

40

slide-51
SLIDE 51

why frame pointers?

makes writing debuggers easier

  • therwise: need table of info about stack allocations

(just to get a stack trace)

easier for manual assembly writing

no need to track how large stack frame is

allows ‘dynamic’ allocation in middle of function

41

slide-52
SLIDE 52

why not frame pointers?

wastes a register debugging information is more sophisticated compiler has no trouble matching sizes in prologue/epilogue we use the heap, not the stack for dynamic allocations GCC option:

  • fomit-frame-pointer
  • fno-omit-frame-pointer

42

slide-53
SLIDE 53
  • fg-by-one-byte

int vulnerable( const char *attacker_controlled, int len) { char buffer[100]; for (int i = 0; i <= 100 && i <= len; ++i) { buffer[i] = attacker_controlled[i]; } } int other() { ... vulnerable(...); }

43

slide-54
SLIDE 54
  • fg-by-one-byte

int vulnerable( const char *attacker_controlled, int len) { char buffer[100]; for (int i = 0; i <= 100 && i <= len; ++i) { buffer[i] = attacker_controlled[i]; } } int other() { ... vulnerable(...); }

43

slide-55
SLIDE 55

vulnerable stack layout

increasing addresses

return address for other saved %rbp local variables in other

%rbp (other) %rsp (other)

return address for vulnerable saved %rbp buffer

%rbp (vulnerable) %rsp (vulnerable) %rbp (other)

return address for other saved %rbp

44

slide-56
SLIDE 56

vulnerable stack layout

increasing addresses

return address for other saved %rbp local variables in other

%rbp (other) %rsp (other)

return address for vulnerable saved %rbp buffer

%rbp (vulnerable) %rsp (vulnerable) %rbp (other)

return address for other saved %rbp

44

slide-57
SLIDE 57

vulnerable stack layout

increasing addresses

return address for other saved %rbp local variables in other

%rbp (other) %rsp (other)

return address for vulnerable saved %rbp buffer

%rbp (vulnerable) %rsp (vulnerable) %rbp (other)

return address for other saved %rbp

44

slide-58
SLIDE 58

vulnerable stack layout

increasing addresses

return address for other saved %rbp local variables in other

%rbp (other) %rsp (other)

return address for vulnerable saved %rbp buffer

%rbp (vulnerable) %rsp (vulnerable) %rbp (other)

return address for other saved %rbp

44

slide-59
SLIDE 59
  • fg-by-one frame pointer

little endian: change least sig. bit of frame pointer

  • fg-by-one byte: max adjustment 256

question: is that attacker controlled space?

what if you can only write 0 to last byte?

moves frame pointer to lower address

  • ften attacker-controlled address!

45

slide-60
SLIDE 60

frame pointer control

after controlling frame pointer, set return address of other then same idea as stack smashing — point to attacker controlled machine code can also control local variables of calling function

potentially useful even with stack canaries/no info. disclosure

46

slide-61
SLIDE 61

vulnerable code (real)

realpath — ../foo → /home/cr4bd/foo

remotely exploitable in wu-FTPd (File Transfer Protocol server)

bad length check — accounted for extra “/” wrong

char resolved[MAXPATHLEN]; ... if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) { errno = ENAMETOOLONG; goto err1; } if (rootd == 0) (void) strcat(resolved, "/"); (void) strcat(resolved, wbuf); ...

47

slide-62
SLIDE 62

vulnerable code (real)

realpath — ../foo → /home/cr4bd/foo

remotely exploitable in wu-FTPd (File Transfer Protocol server)

bad length check — accounted for extra “/” wrong

char resolved[MAXPATHLEN]; ... if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) { errno = ENAMETOOLONG; goto err1; } if (rootd == 0) (void) strcat(resolved, "/"); (void) strcat(resolved, wbuf); ...

47

slide-63
SLIDE 63

beyond normal bufger overfmows

pretty much every memory error is a problem will look at exploiting:

  • fg-by-one bufger overfmows (!)

heap bufger overfmows double-frees use-after-free integer overfmows in size calculations

48

slide-64
SLIDE 64

easy heap overfmows

struct foo { char buffer[100]; void (*func_ptr)(void); }; increasing addresses

buffer func_ptr

49

slide-65
SLIDE 65

heap overfmow: adjacent allocations

class V { char buffer[100]; public: virtual void ...; ... }; ... V *first = new V(...); V *second = new V(...); strcpy(first−>buffer, attacker_controlled);

the heap increasing addresses

second’s buffer second’s vtable first’s buffer first’s vtable result of

  • verfmowing

bufger

50

slide-66
SLIDE 66

heap overfmow: adjacent allocations

class V { char buffer[100]; public: virtual void ...; ... }; ... V *first = new V(...); V *second = new V(...); strcpy(first−>buffer, attacker_controlled);

the heap increasing addresses

second’s buffer second’s vtable first’s buffer first’s vtable result of

  • verfmowing

bufger

50

slide-67
SLIDE 67

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)

51

slide-68
SLIDE 68

diversion: implementing malloc/new

many ways to implement malloc/new we will talk about one common technique +

52

slide-69
SLIDE 69

heap object

struct AllocInfo { bool free; int size; AllocInfo *prev; AllocInfo *next; };

free space next prev size/free alloc’d object size/free free space next prev size/free free free space next prev size/free

53

slide-70
SLIDE 70

implementing free()

int free(void *object) { ... if (block_after−>free) { /* unlink from list */ new_block−>size += block_after−>size; block_after−>prev−>next = block_after−>next; block_after−>next−>prev = block_after−>prev; } ... }

arbitrary memory write

also other list management operations

54

slide-71
SLIDE 71

implementing free()

int free(void *object) { ... if (block_after−>free) { /* unlink from list */ new_block−>size += block_after−>size; block_after−>prev−>next = block_after−>next; block_after−>next−>prev = block_after−>prev; } ... }

arbitrary memory write

also other list management operations

54

slide-72
SLIDE 72

vulnerable code

char *buffer = malloc(100); ... strcpy(buffer, attacker_supplied); ... free(buffer); free(other_thing); ... free space next prev size/free alloc’d object size/free free space next prev size/free GOT entry: free GOT entry: malloc GOT entry: printf GOT entry: fopen

shellcode (or system()?)

size/free prev next

55

slide-73
SLIDE 73

vulnerable code

char *buffer = malloc(100); ... strcpy(buffer, attacker_supplied); ... free(buffer); free(other_thing); ... free space next prev size/free alloc’d object size/free free space next prev size/free GOT entry: free GOT entry: malloc GOT entry: printf GOT entry: fopen

shellcode (or system()?)

size/free prev next

55

slide-74
SLIDE 74

vulnerable code

char *buffer = malloc(100); ... strcpy(buffer, attacker_supplied); ... free(buffer); free(other_thing); ... free space next prev size/free alloc’d object size/free free space next prev size/free GOT entry: free GOT entry: malloc GOT entry: printf GOT entry: fopen

shellcode (or system()?)

size/free prev next

55

slide-75
SLIDE 75

beyond normal bufger overfmows

pretty much every memory error is a problem will look at exploiting:

  • fg-by-one bufger overfmows (!)

heap bufger overfmows double-frees use-after-free integer overfmows in size calculations

56

slide-76
SLIDE 76

double-frees

free(thing); free(thing); char *p = malloc(...); // p points to next/prev //

  • n list of avail.

// blocks strcpy(p, attacker_controlled); malloc(...); char *q = malloc(...); // q points to attacker− // chosen address strcpy(q, attacker_controlled2); ... free space next prev size alloc’d object size alloc’d object thing prev next size

malloc returns something still on free list because double-free made loop in linked list

57

slide-77
SLIDE 77

double-frees

free(thing); free(thing); char *p = malloc(...); // p points to next/prev //

  • n list of avail.

// blocks strcpy(p, attacker_controlled); malloc(...); char *q = malloc(...); // q points to attacker− // chosen address strcpy(q, attacker_controlled2); ... free space next prev size alloc’d object size alloc’d object thing/p prev next size

malloc returns something still on free list because double-free made loop in linked list

57

slide-78
SLIDE 78

double-frees

free(thing); free(thing); char *p = malloc(...); // p points to next/prev //

  • n list of avail.

// blocks strcpy(p, attacker_controlled); malloc(...); char *q = malloc(...); // q points to attacker− // chosen address strcpy(q, attacker_controlled2); ... free space next prev size alloc’d object size alloc’d object thing/p prev next size

malloc returns something still on free list because double-free made loop in linked list

57

slide-79
SLIDE 79

double-free expansion

// free/delete 1: double_freed−>next = first_free; first_free = chunk; // free/delete 2: double_freed−>next = first_free; first_free = chunk // malloc/new 1: result1 = first_free; first_free = first_free−>next; // + overwrite: strcpy(result1, ...); // malloc/new 2: first_free = first_free−>next; // malloc/new 3: result3 = first_free; strcpy(result3, ...);

next / double free’d object size fjrst_free (global) (original fjrst free) GOT entry: free first/second malloc third malloc

58

slide-80
SLIDE 80

double-free expansion

// free/delete 1: double_freed−>next = first_free; first_free = chunk; // free/delete 2: double_freed−>next = first_free; first_free = chunk // malloc/new 1: result1 = first_free; first_free = first_free−>next; // + overwrite: strcpy(result1, ...); // malloc/new 2: first_free = first_free−>next; // malloc/new 3: result3 = first_free; strcpy(result3, ...);

next / double free’d object size fjrst_free (global) (original fjrst free) GOT entry: free first/second malloc third malloc

58

slide-81
SLIDE 81

double-free expansion

// free/delete 1: double_freed−>next = first_free; first_free = chunk; // free/delete 2: double_freed−>next = first_free; first_free = chunk // malloc/new 1: result1 = first_free; first_free = first_free−>next; // + overwrite: strcpy(result1, ...); // malloc/new 2: first_free = first_free−>next; // malloc/new 3: result3 = first_free; strcpy(result3, ...);

next / double free’d object size fjrst_free (global) (original fjrst free) GOT entry: free first/second malloc third malloc

58

slide-82
SLIDE 82

double-free expansion

// free/delete 1: double_freed−>next = first_free; first_free = chunk; // free/delete 2: double_freed−>next = first_free; first_free = chunk // malloc/new 1: result1 = first_free; first_free = first_free−>next; // + overwrite: strcpy(result1, ...); // malloc/new 2: first_free = first_free−>next; // malloc/new 3: result3 = first_free; strcpy(result3, ...);

next / double free’d object size fjrst_free (global) (original fjrst free) GOT entry: free first/second malloc third malloc

58

slide-83
SLIDE 83

double-free expansion

// free/delete 1: double_freed−>next = first_free; first_free = chunk; // free/delete 2: double_freed−>next = first_free; first_free = chunk // malloc/new 1: result1 = first_free; first_free = first_free−>next; // + overwrite: strcpy(result1, ...); // malloc/new 2: first_free = first_free−>next; // malloc/new 3: result3 = first_free; strcpy(result3, ...);

next / double free’d object size fjrst_free (global) (original fjrst free) GOT entry: free first/second malloc third malloc

58

slide-84
SLIDE 84

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

59

slide-85
SLIDE 85

beyond normal bufger overfmows

pretty much every memory error is a problem will look at exploiting:

  • fg-by-one bufger overfmows (!)

heap bufger overfmows double-frees use-after-free integer overfmows in size calculations

60

slide-86
SLIDE 86

vulnerable code

class Foo { ... }; Foo *the_foo; the_foo = new Foo; ... delete the_foo; ... something_else = new Bar(...); the_foo−>something();

something_else likely where the_foo was

vtable ptr (Foo) data for Foo vtable ptr (Bar)?

  • ther data?

data for Bar

61

slide-87
SLIDE 87

vulnerable code

class Foo { ... }; Foo *the_foo; the_foo = new Foo; ... delete the_foo; ... something_else = new Bar(...); the_foo−>something();

something_else likely where the_foo was

vtable ptr (Foo) data for Foo vtable ptr (Bar)?

  • ther data?

data for Bar

61

slide-88
SLIDE 88

C++ inheritence: memory layout

vtable pointer

InputStream

vtable pointer

SeekableInputStream

vtable pointer file_pointer

FileInputStream

slot for get slot for get slot for seek slot for tell FileInputStream::get FileinputStream::seek FileInputStream::tell

62

slide-89
SLIDE 89

exploiting use after-free

trigger many “bogus” frees; then allocate many things of same size with “right” pattern

pointers to shellcode? pointers to pointers to system()?

  • bjects with something useful in VTable entry?

trigger use-after-free thing

63

slide-90
SLIDE 90

use-after-free easy cases

common problem for JavaScript implementations use-after-free’d object often some complex C++ object

example: representation of video stream

exploits can choose type of object that replaces

allocate that kind of object in JS

can often arrange to read/write vtable pointer

depends on layout of thing created easy examples: string, array of fmoating point numbers

64

slide-91
SLIDE 91

beyond normal bufger overfmows

pretty much every memory error is a problem will look at exploiting:

  • fg-by-one bufger overfmows (!)

heap bufger overfmows double-frees use-after-free integer overfmows in size calculations

65

slide-92
SLIDE 92

integer overfmow example

item *load_items(int len) { int total_size = len * sizeof(item); if (total_size >= LIMIT) { return NULL; } item *items = malloc(total_size); for (int i = 0; i < len; ++i) { int failed = read_item(&items[i]); if (failed) { free(items); return NULL; } } return items; }

len = 0x4000 0001 sizeof(item) = 0x10 total_size = 0x4 0000 0010

66

slide-93
SLIDE 93

integer overfmow example

item *load_items(int len) { int total_size = len * sizeof(item); if (total_size >= LIMIT) { return NULL; } item *items = malloc(total_size); for (int i = 0; i < len; ++i) { int failed = read_item(&items[i]); if (failed) { free(items); return NULL; } } return items; }

len = 0x4000 0001 sizeof(item) = 0x10 total_size = 0x4 0000 0010

66

slide-94
SLIDE 94

making this reliable

run program with malloc, free that output parameters knowledge of how malloc/etc. handles difgerent sized objects “heap spray”

32-bit systems — just have your shellcode or target address everywhere hope “random” address matches

global variables (fjxed addresses) — good place for shellcode

67

slide-95
SLIDE 95

control hijacking generally

usually: need to know/guess program addresses usually: need to insert executable code usually: need to overwrite code addresses next topic: countermeasures against these later topic: defeating those later later topic: secure programming languages

68

slide-96
SLIDE 96

fjrst mitigation: stack canaries

saw: stack canaries tries to stop:

  • verwriting code addresses

(as long it’s return addresses)

by assuming:

compile-in protection attacker can’t read ofg the stack attacker can’t “skip” parts of the stack

69

slide-97
SLIDE 97

second mitigation: address space randomization

problem for the stack smashing assignment tries to stop:

know/guess programming addresses

by assuming:

program doesn’t “leak” addresses relevant addresses can be changed (not hard-coded in progrma)

70

slide-98
SLIDE 98

next time

comparing mitigations

what do they assume the attacker can do? efgect on performance? recompilation? rewriting code?

71