0% found this document useful (0 votes)
63 views86 pages

BOF en

The document discusses buffer overflow vulnerabilities. It provides background on stack structure and function calling conventions. When a program receives input without bounds checking, a buffer overflow can overwrite variables and control execution flow. Specifically, a stack overflow occurs when user input exceeds the allocated buffer size on the stack, potentially overwriting return addresses and allowing arbitrary code execution.

Uploaded by

yc
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
63 views86 pages

BOF en

The document discusses buffer overflow vulnerabilities. It provides background on stack structure and function calling conventions. When a program receives input without bounds checking, a buffer overflow can overwrite variables and control execution flow. Specifically, a stack overflow occurs when user input exceeds the allocated buffer size on the stack, potentially overwriting return addresses and allowing arbitrary code execution.

Uploaded by

yc
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 86

Buffer Overflow

nae @ NCTUCSC & BambooFox

1
Preface
• Environment

• gcc-4.8

• Glibc - 2.24

• Kernel - 4.8.0-59

• 64-bit OS

• The following content will be based on 32-bit for better


explanation and understanding.

2
Outline
• Background Knowledge

• Stack Frame

• Calling Convention

• Buffer Overflow

• Exploit

• Shellcode

• Return to text

• Return to libc

• Bypass stack guard

3
What’s stack?
• OS kernel maps the program to the memory Low addr

• text text

• program code
data

• data
heap
• program data

• heap

• dynamic memory space

• stack
stack
• local variable, arguments, base pointer, return address
High addr
4
Stack Frame
• Stack: LIFO (Last In First Out)

PUSH Low Address POP

Last Last

Second Second
Stack growth

High Address
First First

5
Function Call & Stack

1. Call Function

2. Back to main to
continue execution

6
Function Call & Stack
• After executing a function, the program needs to go back
to the next instruction which is right after the function call
and it will use stack to store the address of that instruction.

Jump to 0x0804840b to execute Func


Back to here to continue

7
Function Call & Stack
Stack
Low
• Caller Part

• ESP: Stack Pointer

• void Func(int a, int b)


growth
• …

push b

push a

call Func
ESP High

8
Function Call & Stack
Stack
Low
• Caller Part

• ESP: Stack Pointer

• void Func(int a, int b)


growth
• …

push b

push a
ESP
call Func
b
High

9
Function Call & Stack
Stack
Low
• Caller Part

• ESP: Stack Pointer

• void Func(int a, int b)


growth
• …

push b
ESP
push a a

call Func
b
High

10
Function Call & Stack
Stack
Low
• Caller Part

• Return Address: address of the


instruction next to function call

• void Func(int a, int b)


growth

• …
push b
ESP
Return Address

push a a

call Func
b
High

11
Function Call & Stack
Stack
Low
• Callee Part

• At this moment EBP records the


address of main stack frame

• void Func(int a, int b)



ESP growth
char buf[12]; Previous ebp

push ebp Func Stack Frame Return Address


=======
mov ebp, esp Main Stack Frame a

sub esp, 0xc


b
High

12
Function Call & Stack
Stack
Low
• Callee Part

• At this moment EBP records the


address of Func stack frame

• void Func(int a, int b)



EBP = ESP growth
char buf[12]; Previous ebp

push ebp Func Stack Frame Return Address


=======
mov ebp, esp Main Stack Frame a

sub esp, 0xc


b
High

13
Function Call & Stack
Stack
Low
• Callee Part
ESP
buf[0]~[3]
• void Func(int a, int b)

char buf[12]; buffer buf[4]~[7]

buf[8]~[11]
EBP growth
Previous ebp

push ebp Return Address

mov ebp, esp a

sub esp, 0xc


b
High

14
Function Call & Stack
Stack
Low
• void Func(int a, int b)

char buf[12]; EBP - 0xc
buf[0]~[3]
EBP - 0x8
buffer buf[4]~[7]
EBP - 0x4
buf[8]~[11]
EBP growth
Previous ebp
EBP + 0x4
push ebp
Return Address
mov ebp, esp EBP + 0x8
a
sub esp, 0xc EBP + 0xc
b
… High

15
Buffer Overflow
• If the program doesn’t check input size, then it would be
possible for the user to enter input that is larger than buffer
size. Once that happens, the overflow part will override
other variables and may effect the behavior of
program.(e.g., variable value, control flow)

16
Buffer Overflow
• Unsafe Function

• gets -> fgets

• scanf -> never use scanf(“%s”)

• strcpy -> strncpy

• …

• Buffer Overflow can be classified according to memory space

• stack overflow

• heap overflow

17
Stack Overflow
Stack
Low
• void Func(int a, int b)

char buf[12];
 ESP
gets(buf); buf[0]~[3]

buffer buf[4]~[7]

buf[8]~[11]
EBP growth
Previous ebp

Return Address

b
High

18
Stack Overflow
Stack
Low
• aaaaaaaaaaaa(a * 12)
ESP
aaaa

buffer aaaa

aaaa
EBP growth
Previous ebp

Return Address

b
High

19
Stack Overflow
Stack
aaaaaaaaaa Low
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa aaaa
aaaaaaaaaa
aaaaaaaaaa buffer aaaa
aaaaaaaaaa
aaaaaaaaaa aaaa
aaaaaaaaaa growth
aaaaaaaaaa aaaa
aaaaaaaaaa
aaaaaaaaaa aaaa
aaaaaaaaaa
aaaaaaaaaa
aaaa
aaaaaaaaaa
aaaaaaaaaa
aaaa
High

20
Stack Overflow

https://www.linkedin.com/pulse/buffer-overflow-exploits-protection-mechanisms-roman-
postanciuc
21
Stack Overflow
Stack
Low
• aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
(a*100)
ESP = EBP growth
aaaa(pre ebp)

aaaa(ret addr)
mov esp, ebp
aaaa
pop ebp
aaaa
ret High

22
Stack Overflow
Stack
Low
• aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
(a*100)
growth

… ESP
aaaa(ret addr)
mov esp, ebp
aaaa
pop ebp ; ebp == 0x61616161
aaaa
ret High

23
Stack Overflow
Stack
Low
• aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
(a*100)
growth

mov esp, ebp ESP


aaaa
pop ebp ; ebp == 0x61616161
aaaa
ret (pop eip) ; eip == 0x61616161 High

24
Stack Overflow
• Program will try to get instruction from 0x61616161 which
is an invalid address.

25
Stack Overflow
• Calculate the offset

26
Stack Overflow
Stack
Low
• Calculate the offset
EBP - 0xc
aaaa
• Where is dddd & eeee
EBP - 0x8
buffer bbbb
• stack alignment EBP - 0x4
cccc
EBP growth
ffff
EBP + 0x4
gggg
EBP + 0x8
hhhh
EBP + 0xc
iiii
High

27
Stack Overflow
Stack
Low
• How to calculate the
offset EBP - 0xc
aaaa
EBP - 0x8
• gdb buffer bbbb
EBP - 0x4
• cyclic in pwntools
EBP
cccc
growth
ffff
EBP + 0x4
gggg
EBP + 0x8
hhhh
EBP + 0xc
iiii
High

28
Stack Overflow
Stack
Low
• Total bytes needed to
pad from buf to return EBP - 0xc
address aaaa
EBP - 0x8
buffer bbbb
• 12 (buf) EBP - 0x4
cccc
EBP growth
• 8 (alignment) ffff
EBP + 0x4
• 4 (ebp)
EBP + 0x8
gggg

hhhh
• 12 + 8 + 4 = 24 bytes EBP + 0xc
iiii
High

29
Exploit
• Shellcode

• Return to text

• Return to libc

• Bypass stack guard

30
Exploit
• Shellcode

• Code written in machine language (can be execute


directly)

• Execution on input data

• Example

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80

31
Exploit
• Shellcode

• Converting the shellcode to assembly will look like this.

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80

execve("/bin/sh", NULL, NULL);

32
Exploit
Stack
Low
• Shellcode
ESP
aaaa
• Write shellcode into
any buffer. buffer aaaa

• Use buffer overflow to


EBP
aaaa
growth
overwrite the return aaaa
address, then it will
return to the shellcode \xc0\x9f\x04\x08
and execute.
a
0x08049fc0 shellcode
b
High

33
Protection
• DEP (Data Execution Prevention)

• ASLR (Address Space Layout Randomization)

• Stack Guard (Stack Canary)

• RELRO (Relocation Read Only)

• PIE (Position Independent Executable)

34
Protection
• DEP (Data Execution Prevention)

• Shellcode on data buffer can not be executed.

• ❌ stack

• ❌ heap

• ❌ .data

• ❌ .bss

35
Protection
• DEP (Data Execution Prevention)

• DEP On / Off

• gcc -z execstack

• execstack --set-execstack

• execstack --clear-execstack

• Check Program Header - GNU_STACK

• readelf --program-headers ${binary}

36
Protection
• ASLR (Address Space Layout Randomization)

• System dependent

• Linux - cat /proc/sys/kernel/randomize_va_space

• Default is 2

• 0 - Turn off ASLR

• 1 - stack, shared library, mmap()

• 2 - All the settings from mode 1 with the start of brk() area

37
Protection
• Stack Guard (Stack Canary)

• A random value will be pushed into stack after return


address and ebp are pushed.

• Check the canary before function returns.

38
Protection
• Stack Guard (Stack Canary)

• On / Off

• gcc -fstack-protector / gcc -fno-stack-protector

• Check function symbol

• readelf -s ${binary} | grep __stack_chk_fail

39
Protection
• Stack Guard (Stack Canary)

40
Protection
• Stack Guard (Stack Canary)

http://www.troll.me/2011/12/16/you-shall-not-pass-gandalf/you-shall-not-pass-16/
41
Protection
• Stack Guard (Stack Canary)

42
Protection
• RELRO (Relocation Read Only)

• Disable

• .got / .got.plt are writable

• Partial

• .got.plt is writable

• Full

• .got / .got.plt are read-only

• Every library function used in program is resolved during the loading


time.

43
Protection
• RELRO (Relocation Read Only)

• Default is Partial

• How to open full mode / disable mode

• gcc -Wl,-z,relro,-z,now / gcc -Wl,-z,norelro

• Check dynamic tag

• DT_BIND_NOW - Full

• GNU_RELRO - Partial

44
Protection
• PIE (Position Independent Executable)

• Default is off. (before GCC 6)

• Text and data section will be affected by ASLR. Thus,


exploit would be more difficult when PIE is on.

45
Protection
• PIE (Position Independent Executable)

• On / Off

• gcc -fPIC -pie / gcc -no-pie

• Check ELF header

• DYN (shared object file)

readelf -h ${binary} | grep Type

46
Protection
• Check protection

• checksec in pwntools

47
Exploit
• Shellcode

• Return to text

• Return to libc

• Bypass stack guard

48
Exploit
• Return to text

• Use the code of program (Located at .text section,


definitely executable)

• Without PIE, the address of code is fixed.

49
Exploit
• Return to text

• Demo

50
Exploit
Stack
Low
aaaa

aaaa
buffer
….

aaaa
growth
aaaa(ebp)

0x804846d(ret addr)

aaaa

aaaa
High

51
Exploit
• Return to text

• Endianness

https://upload.wikimedia.org/wikipedia/en/7/77/Big-little_endian.png
52
Exploit
• Return to text

• Endianness

• x86 architecture use little-endian.

High Low

Low High
53
Exploit
• Return to text

• In most case, we can not finish our exploit just with the
code of program.

• Return to libc + ROP

54
Exploit
• Shellcode

• Return to text

• Return to libc

• Linking

• Lazy Binding

• Bypass stack guard

55
Static Linking Dynamic

hello.c hello.c

Preprocess Preprocess

Compilation Compilation

Assembly Assembly

hello.o libc.a hello.o

Linking Linking

56
Linking
• Linking

• Static Linking

• Put machine code of all library functions in ELF when


linking.

• Dynamic Linking

• Mark library function with a symbol of dynamic linking

• Shared object will be loaded into memory with ELF.

57
Linking
• Dynamic Linking

58
Lazy Binding
• Some library functions may not be called during the
lifetime of a running program.

here

59
Lazy Binding
• The ELF with dynamic linking uses lazy binding. That
means the program will not resolve the real function
address until the very first call of that function.

60
Lazy Binding
• ELF uses PLT (Procedure Linkage Table) to implement
lazy binding.

<Foo@plt>:
0x400450: jmp Foo@got <Foo@got>: 0x400456
0x400456: push n
0x40045b: push module ID
0x400461: jmp _dl_runtime_resolve

61
Lazy Binding
<Foo@plt>:
0x400450: jmp Foo@got <Foo@got>: 0x400456
0x400456: push n
0x40045b: push module ID
0x400461: jmp _dl_runtime_resolve

62
Lazy Binding
<Foo@plt>:
0x400450: jmp Foo@got <Foo@got>: 0x400456
0x400456: push n
0x40045b: push module ID
0x400461: jmp _dl_runtime_resolve

63
Lazy Binding
<Foo@plt>:
0x400450: jmp Foo@got <Foo@got>: 0x400456
0x400456: push n
0x40045b: push module ID
0x400461: jmp _dl_runtime_resolve

64
Lazy Binding
<Foo@plt>:
0x400450: jmp Foo@got <Foo@got>: 0x400456
0x400456: push n
0x40045b: push module ID
0x400461: jmp _dl_runtime_resolve

65
Lazy Binding
<Foo@plt>:
0x400450: jmp Foo@got <Foo@got>: 0x7ffff7a66666
0x400456: push n
0x40045b: push module ID
0x400461: jmp _dl_runtime_resolve

0x7ffff7a66666 <Foo>: …

66
Lazy Binding
<Foo@plt>:
0x400450: jmp Foo@got <Foo@got>: 0x7ffff7a66666
0x400456: push n
0x40045b: push module ID
0x400461: jmp _dl_runtime_resolve

0x7ffff7a66666 <Foo>: …

67
Lazy Binding
• n <Foo@plt>:
0x400450: jmp Foo@got
• index of Foo in .rel.plt 0x400456: push n
0x40045b: push module ID
• module ID
0x400461: jmp _dl_runtime_resolve

• name of library

68
Lazy Binding
• Reuse code
<PLT0>:
0x400440: push module ID
0x400446: jmp _dl_runtime_resolve

<Foo@plt>:
0x400450: jmp Foo@got
0x400456: push n
0x40045b: jmp PLT0

69
Lazy Binding
• See Angelboy - Execution p.17 for more details.

70
Exploit
• Return to libc

• In addition to the code in binary, we can use code in


shared library.

• system

• execve

• …

71
Exploit
• Return to libc

• The base address of libc will be random each time the


program executes due to ASLR. We need to leak the
information we need.

• Once we get the address of somewhere in libc, we can


have the base address by calculating the offset.

• Then, we can use any function in libc with function offset.

• In the same libc, each function offset is fixed.

72
Exploit
• Return to libc

• Find libc address

• GOT

• stack

• e.g., return address of main

• heap

• e.g., main_arena

73
Exploit
• Return to libc

• Find library function offset

readelf -s /path/of/libc | grep ${function_name}

74
Exploit
• Return to libc

• After getting the libc base address

• Forge a function call on stack

• GOT hijack

• …

75
Exploit
Stack
Low
• Return to libc

aaaa
• Forge a function call on stack
buffer aaaa
• Constraints
aaaa
growth
• overflow aaaa
ESP
• Arbitrary write system (ret addr)

fake return address


Fake Frame
address of “/bin/sh”
High

76
Exploit
• Return to libc
<gets@plt>:

• GOT hijack 0x400450: jmp gets@got


0x400456: push n

• Constraints 0x40045b: jmp PLT0

• Arbitrary write
<gets@got>: 0x7ffff7a6dead
• gets(buf) -> system(buf)

0x7ffff7a6dead <system>: …

77
Exploit
• Shellcode

• Return to text

• Return to libc

• Linking

• Lazy Binding

• Bypass stack guard

78
Exploit
• Bypass stack guard

• leak canary

• GOT hijack

• …

79
Exploit
• Bypass stack guard

• leak canary

• Some function doesn’t put null byte at the end of buffer after
getting the user’s input. We can take advantage of this to
leak canary. Of course, stack or libc may be leaked, too.

• read()

• strcpy()

• strncpy()

80
Exploit
Stack
ESP Low
• Bypass stack guard

• leak canary buffer

• The end of canary must be


null byte. 0xdead1200 (canary)
growth
ebp

return address

arg1

arg2
High

81
Exploit
Stack
ESP Low
• Bypass stack guard aaaa

aaaa
• leak canary buffer

aaaa
• If there is a function like
printf("%s", buf), it will keep 0xdead1261 (canary)
growth
outputing data until ebp
reaching a null byte.
return address

• a*12 + 0x61 + 0x12 + 0xad


arg1
+ 0xde + …
arg2
High

82
Exploit
• Bypass stack guard

• GOT hijack

• Constraints

• Write arbitrarily

• Partial / No RELRO

83
Exploit
• Bypass stack guard

• GOT hijack (cont.)

• Overwrite the GOT entry of __stack_chk_fail. According to different data we


write, we have different ways to exploit

• NOP

• Overflow directly, then do ROP

• one_gadget

• system

• Forge a function call (no need of return address)

• …

84
Reference
• http://l4ys.tw/ROP_bamboofox.pdf

• AngelBoy

• 程式設計師的⾃自我修養

• https://goo.gl/wKFGfn

• https://en.wikipedia.org/wiki/
Executable_space_protection#Windows

• https://en.wikipedia.org/wiki/
Address_space_layout_randomization

85
Contact
• Mail: [email protected]

86

You might also like