Buffer Software Security overflows and other memory safety - - PowerPoint PPT Presentation

buffer
SMART_READER_LITE
LIVE PREVIEW

Buffer Software Security overflows and other memory safety - - PowerPoint PPT Presentation

Last time We continued By launching our 1st section: Buffer Software Security overflows and other memory safety vulnerabilities Buffer overflow fundamentals This time We will finish up By looking at Buffer Overflow overflows


slide-1
SLIDE 1

Last time

  • Buffer overflow fundamentals

Buffer

  • verflows

By launching

and other memory safety vulnerabilities

We continued

Software

Security

  • ur 1st section:
slide-2
SLIDE 2

This time

  • Finish overflow attacks & other vulnerabilities
  • Overflow defenses
  • Everything you’ve always wanted to know about

gdb but were too afraid to ask

Buffer

  • verflows

We will finish up

and other memory safety vulnerabilities

By looking at

Overflow

Defenses

slide-3
SLIDE 3

First, a recap (args)

#include <stdio.h> void func(char *arg1, int arg2, int arg3) { printf(“arg1 is at %p\n”, &arg1); printf(“arg2 is at %p\n”, &arg2); printf(“arg3 is at %p\n”, &arg3); } int main() { func(“Hello”, 10, -3); return 0; }

slide-4
SLIDE 4

First, a recap (args)

#include <stdio.h> void func(char *arg1, int arg2, int arg3) { printf(“arg1 is at %p\n”, &arg1); printf(“arg2 is at %p\n”, &arg2); printf(“arg3 is at %p\n”, &arg3); } int main() { func(“Hello”, 10, -3); return 0; }

&arg1 < &arg2 < &arg3? &arg1 > &arg2 > &arg3?

What will happen?

slide-5
SLIDE 5

First, a recap (locals)

#include <stdio.h> void func() { char loc1[4]; int loc2; int loc3; printf(“loc1 is at %p\n”, &loc1); printf(“loc2 is at %p\n”, &loc2); printf(“loc3 is at %p\n”, &loc3); } int main() { func(); return 0; }

slide-6
SLIDE 6

First, a recap (locals)

#include <stdio.h> void func() { char loc1[4]; int loc2; int loc3; printf(“loc1 is at %p\n”, &loc1); printf(“loc2 is at %p\n”, &loc2); printf(“loc3 is at %p\n”, &loc3); } int main() { func(); return 0; }

&loc1 < &loc2 < &loc3? &loc1 > &loc2 > &loc3?

What will happen?

slide-7
SLIDE 7

Stack and functions: Summary

~0x0 0x0

caller’s data

%ebp

code

%eip

slide-8
SLIDE 8

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

~0x0 0x0

caller’s data

%ebp

code

%eip

slide-9
SLIDE 9

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

~0x0 0x0

caller’s data arg2

%ebp

code

%eip

slide-10
SLIDE 10

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

~0x0 0x0

caller’s data arg2 arg1

%ebp

code

%eip

slide-11
SLIDE 11

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

~0x0 0x0

caller’s data arg2 arg1

%eip+…

%ebp

code

%eip

slide-12
SLIDE 12

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

~0x0 0x0

caller’s data arg2 arg1

%eip+…

%ebp

code

%eip

slide-13
SLIDE 13

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

~0x0 0x0

caller’s data arg2 arg1

%eip+…

%ebp

code

%eip

slide-14
SLIDE 14

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

Called function:

4.Push the old frame pointer onto the stack: %ebp 5.Set frame pointer %ebp to where the end of the stack is right now: %esp 6.Push local variables onto the stack; access them as offsets from %ebp

~0x0 0x0

caller’s data arg2 arg1

%eip+…

%ebp

code

%eip

slide-15
SLIDE 15

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

Called function:

4.Push the old frame pointer onto the stack: %ebp 5.Set frame pointer %ebp to where the end of the stack is right now: %esp 6.Push local variables onto the stack; access them as offsets from %ebp

~0x0 0x0

caller’s data arg2 arg1

%ebp

%eip+…

%ebp

code

%eip

slide-16
SLIDE 16

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

Called function:

4.Push the old frame pointer onto the stack: %ebp 5.Set frame pointer %ebp to where the end of the stack is right now: %esp 6.Push local variables onto the stack; access them as offsets from %ebp

~0x0 0x0

caller’s data arg2 arg1

%ebp

%eip+…

%ebp

code

%eip

slide-17
SLIDE 17

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

Called function:

4.Push the old frame pointer onto the stack: %ebp 5.Set frame pointer %ebp to where the end of the stack is right now: %esp 6.Push local variables onto the stack; access them as offsets from %ebp

~0x0 0x0

caller’s data arg2 arg1

%ebp

%eip+…

%ebp

code

%eip

slide-18
SLIDE 18

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

Called function:

4.Push the old frame pointer onto the stack: %ebp 5.Set frame pointer %ebp to where the end of the stack is right now: %esp 6.Push local variables onto the stack; access them as offsets from %ebp

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1

%eip+…

%ebp

code

%eip

slide-19
SLIDE 19

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

Called function:

4.Push the old frame pointer onto the stack: %ebp 5.Set frame pointer %ebp to where the end of the stack is right now: %esp 6.Push local variables onto the stack; access them as offsets from %ebp

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1 loc2

%eip+…

%ebp

code

%eip

slide-20
SLIDE 20

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

Called function:

4.Push the old frame pointer onto the stack: %ebp 5.Set frame pointer %ebp to where the end of the stack is right now: %esp 6.Push local variables onto the stack; access them as offsets from %ebp

Returning function:

7.Reset the previous stack frame: %ebp = (%ebp) 8.Jump back to return address: %eip = 4(%ebp)

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1 loc2

%eip+…

%ebp

code

%eip

slide-21
SLIDE 21

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

Called function:

4.Push the old frame pointer onto the stack: %ebp 5.Set frame pointer %ebp to where the end of the stack is right now: %esp 6.Push local variables onto the stack; access them as offsets from %ebp

Returning function:

7.Reset the previous stack frame: %ebp = (%ebp) 8.Jump back to return address: %eip = 4(%ebp)

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1 loc2

%eip+…

%ebp

code

%eip

slide-22
SLIDE 22

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

Called function:

4.Push the old frame pointer onto the stack: %ebp 5.Set frame pointer %ebp to where the end of the stack is right now: %esp 6.Push local variables onto the stack; access them as offsets from %ebp

Returning function:

7.Reset the previous stack frame: %ebp = (%ebp) 8.Jump back to return address: %eip = 4(%ebp)

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1 loc2

%eip+…

%ebp

code

%eip

slide-23
SLIDE 23

gdb tutorial

slide-24
SLIDE 24

Your new best friends

i f i r x/<n> <addr> b <function>
 s Set a breakpoint at <function>
 step through execution (into calls) Examine <n> bytes of memory
 starting at address <addr> Show info about registers
 (%eip, %ebp, %esp, etc.) Show info about the current frame
 (prev. frame, locals/args, %ebp/%eip)

slide-25
SLIDE 25

Buffer overflow

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1 loc2

%eip+…

code

char loc1[4];

slide-26
SLIDE 26

Buffer overflow

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1 loc2

%eip+…

code

gets(loc1);
 strcpy(loc1, <user input>); memcpy(loc1, <user input>); etc. char loc1[4];

slide-27
SLIDE 27

Buffer overflow

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1 loc2

%eip+…

code

Input writes from low to high addresses

gets(loc1);
 strcpy(loc1, <user input>); memcpy(loc1, <user input>); etc. char loc1[4];

slide-28
SLIDE 28

Buffer overflow

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1 loc2

%eip+…

code

Input writes from low to high addresses

gets(loc1);
 strcpy(loc1, <user input>); memcpy(loc1, <user input>); etc. char loc1[4];

slide-29
SLIDE 29

Buffer overflow

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1 loc2

%eip+…

code

Input writes from low to high addresses

gets(loc1);
 strcpy(loc1, <user input>); memcpy(loc1, <user input>); etc. char loc1[4]; Can over-write other data (“AuthMe!”)

slide-30
SLIDE 30

Buffer overflow

~0x0 0x0

caller’s data arg2 arg1

%ebp

loc1 loc2

%eip+…

code

Input writes from low to high addresses

gets(loc1);
 strcpy(loc1, <user input>); memcpy(loc1, <user input>); etc. char loc1[4]; Can over-write other data (“AuthMe!”) Can over-write the program’s control flow (%eip)

slide-31
SLIDE 31

Code injection

slide-32
SLIDE 32

High-level idea

void func(char *arg1) { char buffer[4]; sprintf(buffer, arg1); ... }

&arg1 %eip

%ebp

00 00 00 00

buffer ...

slide-33
SLIDE 33

High-level idea

void func(char *arg1) { char buffer[4]; sprintf(buffer, arg1); ... }

&arg1 %eip

%ebp

00 00 00 00

buffer

(1) Load my own code into memory

Haxx0r c0d3

...

slide-34
SLIDE 34

High-level idea

void func(char *arg1) { char buffer[4]; sprintf(buffer, arg1); ... }

&arg1 %eip

%ebp

00 00 00 00

buffer

(1) Load my own code into memory

Haxx0r c0d3

Text

%eip (2) Somehow get %eip to point to it

...

slide-35
SLIDE 35

High-level idea

void func(char *arg1) { char buffer[4]; sprintf(buffer, arg1); ... }

&arg1 %eip

%ebp

00 00 00 00

buffer

(1) Load my own code into memory

Haxx0r c0d3

Text

%eip (2) Somehow get %eip to point to it

...

slide-36
SLIDE 36

High-level idea

void func(char *arg1) { char buffer[4]; sprintf(buffer, arg1); ... }

&arg1 %eip

%ebp

00 00 00 00

buffer

(1) Load my own code into memory

Haxx0r c0d3

Text

%eip (2) Somehow get %eip to point to it

...

slide-37
SLIDE 37

This is nontrivial

  • Pulling off this attack requires getting a few things

really right (and some things sorta right)

  • Think about what is tricky about the attack
  • The key to defending it will be to make the hard parts

really hard

slide-38
SLIDE 38

Challenge 1

  • It must be the machine code instructions (i.e.,

already compiled and ready to run)

  • We have to be careful in how we construct it:
  • It can’t contain any all-zero bytes
  • Otherwise, sprintf / gets / scanf / … will stop copying
  • How could you write assembly to never contain a full zero

byte?

  • It can’t make use of the loader (we’re injecting)
  • It can’t use the stack (we’re going to smash it)

Loading code into memory

slide-39
SLIDE 39

What kind of code would we want to run?

  • Goal: full-purpose shell
  • The code to launch a shell is called “shell code”
  • It is nontrivial to it in a way that works as injected

code

  • No zeroes, can’t use the stack, no loader dependence
  • There are many out there
  • And competitions to see who can write the smallest
  • Goal: privilege escalation
  • Ideally, they go from guest (or non-user) to root
slide-40
SLIDE 40

Shellcode

#include <stdio.h> int main( ) { char *name[2]; name[0] = “/bin/sh”; name[1] = NULL; execve(name[0], name, NULL); }

slide-41
SLIDE 41

Shellcode

#include <stdio.h> int main( ) { char *name[2]; name[0] = “/bin/sh”; name[1] = NULL; execve(name[0], name, NULL); } xorl %eax, %eax pushl %eax pushl $0x68732f2f pushl $0x6e69622f movl %esp,%ebx pushl %eax ...

Assembly

slide-42
SLIDE 42

Shellcode

#include <stdio.h> int main( ) { char *name[2]; name[0] = “/bin/sh”; name[1] = NULL; execve(name[0], name, NULL); } xorl %eax, %eax pushl %eax pushl $0x68732f2f pushl $0x6e69622f movl %esp,%ebx pushl %eax ...

Assembly

slide-43
SLIDE 43

Shellcode

#include <stdio.h> int main( ) { char *name[2]; name[0] = “/bin/sh”; name[1] = NULL; execve(name[0], name, NULL); } xorl %eax, %eax pushl %eax pushl $0x68732f2f pushl $0x6e69622f movl %esp,%ebx pushl %eax ...

Assembly

“\x31\xc0” “\x50” “\x68””//sh” “\x68””/bin” “\x89\xe3” “\x50” ...

Machine code

slide-44
SLIDE 44

Shellcode

#include <stdio.h> int main( ) { char *name[2]; name[0] = “/bin/sh”; name[1] = NULL; execve(name[0], name, NULL); } xorl %eax, %eax pushl %eax pushl $0x68732f2f pushl $0x6e69622f movl %esp,%ebx pushl %eax ...

Assembly

“\x31\xc0” “\x50” “\x68””//sh” “\x68””/bin” “\x89\xe3” “\x50” ...

Machine code (Part of) your input

slide-45
SLIDE 45

Privilege escalation

  • Permissions later, but for now…
  • Recall that each file has:
  • Permissions: read / write / execute
  • For each of: owner / group / everyone else
  • Consider a service like passwd
  • Owned by root (and needs to do root-y things)
  • But you want any user to be able to run it
slide-46
SLIDE 46

Effective userid

  • Userid = the user who ran the process
  • Effective userid = what is used to determine what

access the process has

  • Consider passwd: root owns it, but users can run it
  • getuid() will return you (real userid)
  • seteuid(0) to set the effective userid to root
  • It’s allowed to because root is the owner
  • What is the potential attack?
slide-47
SLIDE 47

Effective userid

  • Userid = the user who ran the process
  • Effective userid = what is used to determine what

access the process has

  • Consider passwd: root owns it, but users can run it
  • getuid() will return you (real userid)
  • seteuid(0) to set the effective userid to root
  • It’s allowed to because root is the owner
  • What is the potential attack?

If you can get a root-owned process to run
 setuid(0)/seteuid(0), then you get root permissions

slide-48
SLIDE 48

Challenge 2

  • All we can do is write to memory from buffer onward
  • With this alone we want to get it to jump to our code
  • We have to use whatever code is already running

Thoughts?

&arg1 %eip

%ebp

00 00 00 00

buffer ...

Getting our injected code to run

slide-49
SLIDE 49

Challenge 2

  • All we can do is write to memory from buffer onward
  • With this alone we want to get it to jump to our code
  • We have to use whatever code is already running

Thoughts?

&arg1 %eip

%ebp

00 00 00 00

buffer ...

Getting our injected code to run

slide-50
SLIDE 50

Challenge 2

  • All we can do is write to memory from buffer onward
  • With this alone we want to get it to jump to our code
  • We have to use whatever code is already running

Thoughts?

&arg1 %eip

%ebp

00 00 00 00

buffer ...

\x0f \x3c \x2f ...

Getting our injected code to run

slide-51
SLIDE 51

Challenge 2

  • All we can do is write to memory from buffer onward
  • With this alone we want to get it to jump to our code
  • We have to use whatever code is already running

Thoughts?

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

\x0f \x3c \x2f ...

Getting our injected code to run

slide-52
SLIDE 52

Challenge 2

  • All we can do is write to memory from buffer onward
  • With this alone we want to get it to jump to our code
  • We have to use whatever code is already running

Thoughts?

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

\x0f \x3c \x2f ...

Getting our injected code to run

slide-53
SLIDE 53

Challenge 2

  • All we can do is write to memory from buffer onward
  • With this alone we want to get it to jump to our code
  • We have to use whatever code is already running

Thoughts?

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

\x0f \x3c \x2f ...

Getting our injected code to run

slide-54
SLIDE 54

Stack and functions: Summary

Calling function:

1.Push arguments onto the stack (in reverse) 2.Push the return address, i.e., the address of the instruction you want run after control returns to you: %eip+something 3.Jump to the function’s address

Called function:

4.Push the old frame pointer onto the stack: %ebp 5.Set frame pointer %ebp to where the end of the stack is right now: %esp 6.Push local variables onto the stack; access them as offsets from %ebp

Returning function:

7.Reset the previous stack frame: %ebp = (%ebp) 8.Jump back to return address: %eip = 4(%ebp)

slide-55
SLIDE 55

Hijacking the saved %eip

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

%ebp

\x0f \x3c \x2f ...

slide-56
SLIDE 56

Hijacking the saved %eip

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

0xbff

%ebp

\x0f \x3c \x2f ...

slide-57
SLIDE 57

Hijacking the saved %eip

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

0xbff

%ebp

\x0f \x3c \x2f ...

slide-58
SLIDE 58

Hijacking the saved %eip

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

0xbff

But how do we know the address? %ebp

\x0f \x3c \x2f ...

slide-59
SLIDE 59

Hijacking the saved %eip

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

0xbff

%ebp

What if we are wrong?

\x0f \x3c \x2f ...

slide-60
SLIDE 60

Hijacking the saved %eip

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

0xbff

%ebp

What if we are wrong?

0xbdf

\x0f \x3c \x2f ...

slide-61
SLIDE 61

Hijacking the saved %eip

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

0xbff

%ebp

What if we are wrong?

0xbdf

\x0f \x3c \x2f ...

slide-62
SLIDE 62

Hijacking the saved %eip

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

0xbff

%ebp

What if we are wrong?

0xbdf

This is most likely data, so the CPU will panic (Invalid Instruction)

\x0f \x3c \x2f ...

slide-63
SLIDE 63

Challenge 3

Finding the return address

slide-64
SLIDE 64

Challenge 3

  • If we don’t have access to the code, we don’t know

how far the buffer is from the saved %ebp Finding the return address

slide-65
SLIDE 65

Challenge 3

  • If we don’t have access to the code, we don’t know

how far the buffer is from the saved %ebp

  • One approach: just try a lot of different values!

Finding the return address

slide-66
SLIDE 66

Challenge 3

  • If we don’t have access to the code, we don’t know

how far the buffer is from the saved %ebp

  • One approach: just try a lot of different values!
  • Worst case scenario: it’s a 32 (or 64) bit memory

space, which means 232 (264) possible answers Finding the return address

slide-67
SLIDE 67

Challenge 3

  • If we don’t have access to the code, we don’t know

how far the buffer is from the saved %ebp

  • One approach: just try a lot of different values!
  • Worst case scenario: it’s a 32 (or 64) bit memory

space, which means 232 (264) possible answers

  • But without address randomization:
  • The stack always starts from the same, fixed address
  • The stack will grow, but usually it doesn’t grow very

deeply (unless the code is heavily recursive)

Finding the return address

slide-68
SLIDE 68

Improving our chances: nop sleds

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

0xbff

%ebp

0xbdf

nop is a single-byte instruction (just moves to the next instruction)

\x0f \x3c \x2f ...

slide-69
SLIDE 69

Improving our chances: nop sleds

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

0xbff

%ebp

0xbdf

nop nop nop …

nop is a single-byte instruction (just moves to the next instruction)

\x0f \x3c \x2f ...

slide-70
SLIDE 70

Improving our chances: nop sleds

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbff

0xbff

%ebp

0xbdf

nop nop nop …

nop is a single-byte instruction (just moves to the next instruction) Jumping anywhere here will work

\x0f \x3c \x2f ...

slide-71
SLIDE 71

Improving our chances: nop sleds

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

... 0xbff

%ebp

0xbdf

nop nop nop …

nop is a single-byte instruction (just moves to the next instruction) Jumping anywhere here will work

\x0f \x3c \x2f ...

slide-72
SLIDE 72

Improving our chances: nop sleds

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

... 0xbff

%ebp

0xbdf

nop nop nop …

nop is a single-byte instruction (just moves to the next instruction) Now we improve our chances


  • f guessing by a factor of #nops

Jumping anywhere here will work

\x0f \x3c \x2f ...

slide-73
SLIDE 73

Putting it all together

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

slide-74
SLIDE 74

Putting it all together

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

padding

slide-75
SLIDE 75

Putting it all together

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

padding But it has to be something;
 we have to start writing wherever
 the input to gets/etc. begins.

slide-76
SLIDE 76

Putting it all together

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbdf

good
 guess padding But it has to be something;
 we have to start writing wherever
 the input to gets/etc. begins.

slide-77
SLIDE 77

Putting it all together

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

nop nop nop …

nop sled

0xbdf

good
 guess padding But it has to be something;
 we have to start writing wherever
 the input to gets/etc. begins.

slide-78
SLIDE 78

Putting it all together

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

nop nop nop …

nop sled

0xbdf

good
 guess padding

\x0f \x3c \x2f ...

malicious code But it has to be something;
 we have to start writing wherever
 the input to gets/etc. begins.

slide-79
SLIDE 79

Putting it all together

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

nop nop nop …

nop sled

0xbdf

good
 guess padding

\x0f \x3c \x2f ...

malicious code But it has to be something;
 we have to start writing wherever
 the input to gets/etc. begins.

slide-80
SLIDE 80

Putting it all together

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

nop nop nop …

nop sled

0xbdf

good
 guess padding

\x0f \x3c \x2f ...

malicious code But it has to be something;
 we have to start writing wherever
 the input to gets/etc. begins.

slide-81
SLIDE 81

Project one will be posted by tomorrow morning

Due 2 weeks later (11:59pm Wednesday Feb 18)

slide-82
SLIDE 82

Defenses

slide-83
SLIDE 83

Recall our challenges

  • Putting code into the memory (no zeroes)
  • Getting %eip to point to our code (dist buff to stored eip)
  • Finding the return address (guess the raw addr)

How can we make these even more difficult?

slide-84
SLIDE 84

Detecting overflows with canaries

00 00 00 00

buffer

Text

%eip

...

&arg1 %eip

%ebp

slide-85
SLIDE 85

Detecting overflows with canaries

00 00 00 00

buffer

Text

%eip

...

&arg1 %eip

%ebp

slide-86
SLIDE 86

Detecting overflows with canaries

00 00 00 00

buffer

Text

%eip

...

&arg1 %eip

%ebp

… 02 8d e2 10

canary

slide-87
SLIDE 87

Detecting overflows with canaries

00 00 00 00

buffer

Text

%eip

...

&arg1 %eip

%ebp

… 02 8d e2 10

canary

nop nop nop …

0xbdf

\x0f \x3c \x2f ...

slide-88
SLIDE 88

Detecting overflows with canaries

00 00 00 00

buffer

Text

%eip

...

&arg1 %eip

%ebp

… 02 8d e2 10

canary

nop nop nop …

0xbdf

\x0f \x3c \x2f ...

slide-89
SLIDE 89

Detecting overflows with canaries

00 00 00 00

buffer

Text

%eip

...

&arg1 %eip

%ebp

… 02 8d e2 10

canary

nop nop nop …

0xbdf

\x0f \x3c \x2f ...

Not the expected value: abort

slide-90
SLIDE 90

Detecting overflows with canaries

00 00 00 00

buffer

Text

%eip

...

&arg1 %eip

%ebp

… 02 8d e2 10

canary

nop nop nop …

0xbdf

\x0f \x3c \x2f ...

Not the expected value: abort What value should the canary have?

slide-91
SLIDE 91

Canary values

  • 1. Terminator canaries (CR, LF, NULL, -1)
  • Leverages the fact that scanf etc. don’t allow these
  • 2. Random canaries
  • Write a new random value @ each process start
  • Save the real value somewhere in memory
  • Must write-protect the stored value
  • 3. Random XOR canaries
  • Same as random canaries
  • But store canary XOR some control info, instead

From StackGuard [Wagle & Cowan]

slide-92
SLIDE 92

Recall our challenges

  • Putting code into the memory (no zeroes)
  • Option: Make this detectable with canaries

  • Getting %eip to point to our code(dist buff to stored eip)
  • Finding the return address (guess the raw addr)

How can we make these even more difficult?

slide-93
SLIDE 93

Return-to-libc

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

nop nop nop …

nop sled

0xbdf

good
 guess padding

\x0f \x3c \x2f ...

malicious code libc

slide-94
SLIDE 94

Return-to-libc

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

nop nop nop …

nop sled

0xbdf

good
 guess padding libc

slide-95
SLIDE 95

Return-to-libc

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

0xbdf

good
 guess padding libc

slide-96
SLIDE 96

Return-to-libc

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

padding libc

slide-97
SLIDE 97

Return-to-libc

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

padding libc

exec()

... ...

printf()

...

“/bin/sh”

libc

slide-98
SLIDE 98

Return-to-libc

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

padding

0x17f

known
 location libc

exec()

... ...

printf()

...

“/bin/sh”

libc

slide-99
SLIDE 99

Return-to-libc

&arg1 %eip

%ebp

00 00 00 00

buffer

Text

%eip

...

padding

0x17f

known
 location

0x20d

libc

exec()

... ...

printf()

...

“/bin/sh”

libc

slide-100
SLIDE 100

Recall our challenges

  • Putting code into the memory (no zeroes)
  • Option: Make this detectable with canaries

  • Getting %eip to point to our code (dist buff to stored eip)
  • Non-executable stack doesn’t work so well
  • Finding the return address (guess the raw addr)

How can we make these even more difficult?

slide-101
SLIDE 101

Address Space Layout Randomization (ASLR)

  • Basic idea: change the layout of the stack
  • Slow to adopt
  • Linux in 2005
  • Vista in 2007 (off by default for compatibility with
  • lder software
  • OS X in 2007 (for system libraries), 2011 for all apps
  • iOS 4.3 (2011)
  • Android 4.0
  • FreeBSD: no

How would you overcome this as an attacker?

slide-102
SLIDE 102

Overflow defenses summary

  • Putting code into the memory (no zeroes)
  • Option: Make this detectable with canaries

  • Getting %eip to point to our code (dist buff to stored eip)
  • Non-executable stack doesn’t work so well

  • Finding the return address (guess the raw addr)
  • Address Space Layout Randomization

  • Good coding practices
slide-103
SLIDE 103

Next time

Required reading:

“StackGuard: Simple Stack Smash Protection for GCC” Optional reading: “Basic Integer Overflows” “Exploiting Format String Vulnerabilities”

Secure


Code

Writing & testing for

Continuing with

Software

Security

http://nob.cs.ucdavis.edu/bishop/secprog/robust.html