FIT3173: Buffer Overflow and Memory Exploits
Dr. Jaigirdar
Department of Software Systems and Cybersecurity Faculty of Information Technology
Copyright By PowCoder代写 加微信 powcoder
Learning Outcomes of This Lecture
Understand the importance of buffer overflow attacks Describe and analyse how buffer overflow works Know how to prevent and mitigate buffer overflows
Understand other known memory exploits, i.e., format string vulnerabilities, integer overflow, read overflow
A buffer overflow is a bug that affects low-level code, typically in C and C++, with significant security implications
Normally, a program with this bug will simply crash
But an attacker can alter the situations that cause the program to do much worse
Steal private information
Corrupt valuable information
Run code of the attacker’s choice
Infamous Buffer Overflow
Why study it? Buffer overflow is still relevant today
C/C++ are popular
Buffer overflow shares common features with other bugs in
Buffer overflows occur with regularity •
How the attack works How to defend against it
Widely Adopted C/C++
https://spectrum.ieee.orgIstaticIinteractive-the-top-programming-languages-2019
Many embedded systems, e.g., industrial control systems, automobiles,… Known open-source libraries, e.g., OpenSSL, OpenCV,…
Critical Software in C/C++
• Many high-performance servers, e.g., Apache httpd, MySQL, redis,…
Most OS kernels and utilities, e.g., linux kernel, shell,…
Long History of Buffer Overflow • Morris worm 1988
• One of the first computer worms; $10-100M loss • Code Red worm 2001
• It attacked Microsoft’s IIS web server; 300K machines infected in 14h • SQL Slammer 2003
• It attacked Microsoft’s SQL Server and Desktop Engine database products; 75K machines infected in 10m
• Stagefright against Android phones 2015
• Allows an attacker to perform arbitrary operations on the victim’s device through remote code execution and privilege escalation
Statistics of Buffer Overflows
http://web.nvd.nist.gov/view/vuln/statistics
The Common Weakness Enumeration (CWETM) Top 25 Most Dangerous Software Errors
http://cwe.mitre.org/top25/archive/2020/2020_cwe_top25.html http://cwe.mitre.org/top25/archive/2021/2021_cwe_top25.html
Below is a brief listing of the weaknesses in the 2020 CWE Top 25, including the overall score of each.
Understand how buffer overflow works, and how to defend against it Require knowledge on
The compiler
• Thearchitecture
A whole-systems view
What we will study
Buffer overflow is defined as any access of a buffer outside of its allotted bounds
Terminology and Definition
Could be an over-read, or an over-write
• Could be during iteration “running of the end” or by direct access
Out-of-bounds access could be to addresses that precede or follow the buffer
High-level Description of An Example
Program allocates a buffer of length N for user input
Then it copies user input data without checking input length
If length(input) > N, excess input will overwrite memory addresses after the buffer With honest users, it causes a program crash
But, if carefully controlled, it can be used by the attacker to:
Overwrite critical program variables (Demo example 1)
Overwrite function return address to point to either desired existing program code (Demo example 2) or code injected by hacker (Demo example 3)
How functions are called
Buffer Overflow Exploits
Compilation into binary machine code
Exploits depend on how software programs run “under the hood”
Memory layout / stack frame structure
Details depend on programming language, CPU hardware, and OS
Our examples: C language (gcc compiler), Intel x86 CPU and Linux Ubuntu
Machine Code • General Intel assembly syntax:
• op. mnemonic
Memory Layout All programs are stored in memory
Low address: 0x00000000
High address: 0xffffffff
OS/CPU maps the virtual addresses (program view) to physical addresses
Text (code) segment: program code and fixed program constants
Low address: 0x00000000
Data segment: initialised global and static variables
Code Segment Data Segment BSS Segment Heap Segment Stack Segment
BSS (Block Started by Symbol) segment: uninitialised global and static variables
Heap segment: dynamic program data (e.g., malloc)
Memory Layout
context (calling function return address/stack frame) – can also contain code!
Stack segment: function local variables, arguments,
High address: 0xffffffff
How a program is compiled and executed?
lea ecx,[esp+0x4]
and esp,0xfffffff0
push DWORD PTR [ecx-0x4]
mov ebp,esp
sub esp,0x4
sub esp,0xc
push 0x80484c0
call 80482fa <_main+0x80482fa> add esp,0x10
mov eax,0x0
mov ecx,DWORD PTR [ebp-0x4] leave
lea esp,[ecx-0x4]
e: 83 ec 04
11: 83 ec 0c
14: 68 c0 84
19: e8 dc 82
1e: 83 c4 10
04 08 04 08
0x804840b
0xec 0x0c 0x68 0xc0 0x84 0x04 0xb7 0xfe 0xff 0xff 0x83 0xc4 0x00 0x00 0x00 0x00 0x8b 0x4d 0x8d 0x61 0xfc 0xc3 0x66 0x90
0x4c 0x24 0x04 0x83 0xe4 0xf0 0xff 0xfc 0x55 0x89 0xe5 0x51 0x83 0xec
Data segment: ? • BSS segment: ? • Stack: ?
Data segment: x • BSS segment: y • Stack: a, b, ptr
Heap: ptr[0], ptr[1]
Is a Container for data Bytes in memory
buf[6] = ‘o’;
Nothing Segmentation fault Custom Code Execution
char buf[6];
Consequence:
buf[6] = ‘o’;
For performance reasons, the OS might allocate multiple bytes
buf 0 1 2 3 4 5
Overflowing buf by a few bytes might not result in an error
Segmentation Fault
Custom Code Execution
Buffer overflow Consequence
If the index is large, it will eventually reach a memory zone not allocated to the program
The overflowing bytes have to redirect the execution flow to the customized code
The OS detects it and stops the program The overflow might also corrupt existing data
void foo(char *str) {
char buffer[12];
strcpy(buffer, str);
Stack foo()
Function Frame
arguments value of str return address
previous FP
Current FP
(Frame Pointer)
local value of buffer variables
stack grows
stack grows
void foo(char *str) {
char buffer[12];
strcpy(buffer, str);
main()’s FP
Foo()’s FP
int main() {
char *str = “test”;
Link between frames
} (Frame Pointer)
Current FP
Stack and Function Calls
%esp always points to the frontier of the stack
• Caller 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 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
• Returning:
7. Reset the previous stack frame 8. Jump back to return address
%ebp always points to the cell storing the old %ebp
Stack and Function Calls Stack frame stores each called function’s local variables/arguments (grows from high addresses to low addresses)
• Stack pointer (ESP register) points to the current top of stack
Low address: 0x00000000
Top of stack (esp)
• Push instruction inserts value on top of stack, decrements ESP
• Pop instruction removes a value from top of stack, increments ESP
previous frame pointer return address
Saved frame pointer (SFP)
Current frame pointer (ebp)
local vars
flag offset: [ebp-4]
test_function ret. addr a
test_function() stack frame
High address: 0xffffffff
%esp always points to the frontier of the stack
– Push instruction inserts value on top of stack, decrements
– Pop instruction removes a value from top of stack, increments %esp
Low address: 0x00000000
%ebp always points to the cell storing the old %ebp
• Caller function:
1. Pushargumentsontothestack(inreverse)
2. Pushthereturnaddress,i.e.,theaddressofthe instruction you want run after control returns to you
stack grows
3. Jump to the function’s address • Called function:
4. Pushtheoldframepointerontothestack(%ebp)
5. Set frame pointer (%ebp) to where the end of the stack is right now (%esp)
6. Pushlocalvariablesontothestack • Returning:
Top of stack (esp)
7. Resetthepreviousstackframe 8. Jumpbacktoreturnaddress
Frame for main
Stack and Function Calls
Highaddress:0xffffffff
Current framer pointer (ebp)
%esp always points to the frontier of the stack
– Push instruction inserts value on top of stack,
Low address: 0x00000000
decrements %esp
– Pop instruction removes a value from top of stack, increments %esp
%ebp always points to the cell storing the old %ebp
• Caller function:
1. Pushargumentsontothestack(inreverse)
2. Pushthereturnaddress,i.e.,theaddressofthe instruction you want run after control returns to you
3. Jump to the function’s address • Called function:
4. Pushtheoldframepointerontothestack(%ebp)
Top of stack (esp)
5. Set frame pointer (%ebp) to where the end of the stack is right now (%esp)
6. Pushlocalvariablesontothestack • Returning:
Frame for main
7. Resetthepreviousstackframe 8. Jumpbacktoreturnaddress
Current framer pointer (ebp)
Stack and Function Calls
Highaddress:0xffffffff
%esp always points to the frontier of the stack
– Push instruction inserts value on top of stack,
Low address: 0x00000000
decrements %esp
– Pop instruction removes a value from top of stack, increments %esp
%ebp always points to the cell storing the old %ebp
• Caller function:
1. Pushargumentsontothestack(inreverse)
2. Pushthereturnaddress,i.e.,theaddressofthe instruction you want run after control returns to you
3. Jump to the function’s address • Called function:
Top of stack (esp)
4. Pushtheoldframepointerontothestack(%ebp)
Frame for main
5. Set frame pointer (%ebp) to where the end of the stack is right now (%esp)
6. Pushlocalvariablesontothestack • Returning:
7. Resetthepreviousstackframe 8. Jumpbacktoreturnaddress
Current framer pointer (ebp)
Stack and Function Calls
Highaddress:0xffffffff
%esp always points to the frontier of the stack
– Push instruction inserts value on top of stack,
Low address: 0x00000000
decrements %esp
– Pop instruction removes a value from top of stack, increments %esp
%ebp always points to the cell storing the old %ebp
• Caller function:
1. Pushargumentsontothestack(inreverse)
2. Pushthereturnaddress,i.e.,theaddressofthe instruction you want run after control returns to you
Topofstack(esp)
3. Jumptothefunction’saddress • Called function:
returnaddress
test_functionret.addr 1(a)
Frame for main
4. Pushtheoldframepointerontothestack(%ebp)
5. Set frame pointer (%ebp) to where the end of the stack is right now (%esp)
6. Pushlocalvariablesontothestack • Returning:
7. Resetthepreviousstackframe 8. Jumpbacktoreturnaddress
Current framer pointer (ebp)
Stack and Function Calls
Highaddress:0xffffffff
%esp always points to the frontier of the stack
– Push instruction inserts value on top of stack,
Low address: 0x00000000
decrements %esp
– Pop instruction removes a value from top of stack, increments %esp
%ebp always points to the cell storing the old %ebp
• Caller function:
Top of stack (esp)
1. Pushargumentsontothestack(inreverse)
Saved frame pointer (SFP)
2. Pushthereturnaddress,i.e.,theaddressofthe instruction you want run after control returns to you
previous frame pointer
3. Jump to the function’s address • Called function:
return address
test_function ret. addr 1(a)
Frame for main
4. Pushtheoldframepointerontothestack(%ebp)
5. Set frame pointer (%ebp) to where the end of the stack is right now (%esp)
6. Pushlocalvariablesontothestack • Returning:
7. Resetthepreviousstackframe 8. Jumpbacktoreturnaddress
Current framer pointer (ebp)
Stack and Function Calls
Highaddress:0xffffffff
%esp always points to the frontier of the stack
– Push instruction inserts value on top of stack,
Low address: 0x00000000
decrements %esp
– Pop instruction removes a value from top of stack, increments %esp
%ebp always points to the cell storing the old %ebp
• Caller function:
Top of stack (esp)
1. Pushargumentsontothestack(inreverse)
Saved frame pointer (SFP)
2. Push the return address, i.e., the address of the instruction you want run after control returns to you
previous frame pointer
3. Jump to the function’s address • Called function:
return address
test_function ret. addr 1(a)
Frame for main
4. Pushtheoldframepointerontothestack(%ebp)
5. Set frame pointer (%ebp) to where the end of the stack is right now (%esp)
6. Pushlocalvariablesontothestack • Returning:
7. Resetthepreviousstackframe 8. :0xffffffff
Stack and Function Calls
Current framer pointer (ebp)
%esp always points to the frontier of the stack
– Push instruction inserts value on top of stack,
Low address: 0x00000000
Top of stack (esp)
decrements %esp
– Pop instruction removes a value from top of stack, increments %esp
Buffer (10 bytes)
%ebp always points to the cell storing the old %ebp
local vars
• Caller function:
Register stored values from caller function
1. Pushargumentsontothestack(inreverse)
Saved frame pointer (SFP)
2. Push the return address, i.e., the address of the instruction you want run after control returns to you
previous frame pointer
3. Jump to the function’s address • Called function:
return address
test_function ret. addr 1(a)
Frame for main
4. Pushtheoldframepointerontothestack(%ebp)
5. Set frame pointer (%ebp) to where the end of the stack is right now (%esp)
6. Pushlocalvariablesontothestack • Returning:
7. Resetthepreviousstackframe 8. :0xffffffff
Stack and Function Calls
Flag (4 bytes)
Current framer pointer (ebp)
%esp always points to the frontier of the stack
– Push instruction inserts value on top of stack,
Low address: 0x00000000
decrements %esp
– Pop instruction removes a value from top of stack, increments %esp
Buffer (10 bytes)
%ebp always points to the cell storing the old %ebp
local vars
• Caller function:
Register stored values from caller function
Top of stack (esp)
1. Pushargumentsontothestack(inreverse)
Saved frame pointer (SFP)
2. Push the return address, i.e., the address of the instruction you want run after control returns to you
previous frame pointer
3. Jump to the function’s address • Called function:
return address
test_function ret. addr 1(a)
Frame for main
4. Pushtheoldframepointerontothestack(%ebp)
5. Set frame pointer (%ebp) to where the end of the stack is right now (%esp)
6. Pushlocalvariablesontothestack • Returning:
7. Resetthepreviousstackframe 8. :0xffffffff
Stack and Function Calls
Flag (4 bytes)
Current framer pointer (ebp)
%esp always points to the frontier of the stack
– Push instruction inserts value on top of stack,
Low address: 0x00000000
decrements %esp
– Pop instruction removes a value from top of stack, increments %esp
Buffer (10 bytes)
%ebp always points to the cell storing the old %ebp
local vars
• Caller function:
Register stored values from caller function
1. Pushargumentsontothestack(inreverse)
Saved frame pointer (SFP)
2. Pushthereturnaddress,i.e.,theaddressofthe instruction you want run after control returns to you
previous frame pointer
3. Jump to the function’s address • Called function:
return address
test_function ret. addr 1(a)
Frame for main
4. Pushtheoldframepointerontothestack(%ebp)
5. Set frame pointer (%ebp) to where the end of the stack is right now (%esp)
6. Pushlocalvariablesontothestack • Returning:
7. Resetthepreviousstackframe 8. Jumpbacktoreturnaddress
Current framer pointer (ebp)
Stack and Function Calls
Highaddress:0xffffffff
Flag (4 bytes)
Top of stack (esp)
%esp always points to the frontier of the stack
– Push instruction inserts value on top of stack,
Low address: 0x00000000
decrements %esp
– Pop instruction removes a value from top of stack, increments %esp
Buffer (10 bytes)
%ebp always points to the cell storing the old %ebp
local vars
• Caller function:
Register stored values from caller function
1. Pushargumentsontothestack(inreverse)
Saved frame pointer (SFP)
2. Pushthereturnaddress,i.e.,theaddressofthe instruction you want run after control returns to you
previous frame pointer
3. Jump to the function’s address • Called function:
return address
test_function ret. addr 1(a)
Frame for main
Top of stack (esp)
4. Pushtheoldframepointerontothestack(%ebp)
5. Set frame pointer (%ebp) to where the end of the stack is right now (%esp)
6. Pushlocalvariablesontothestack • Returning:
7. Resetthepreviousstackframe 8. Jumpbacktoreturnaddress
Current framer pointer (ebp)
Stack and Function Calls
Highaddress:0xffffffff
Flag (4 bytes)
stack grows
void foo(char *str) {
char buffer[12];
strcpy(buffer, str);
value of str
return address
previous FP
int main() {
char *str = “test”;
buffer[11] ……
How to exploit the vulnerability?
buffer copy
} (Frame Pointer)
Current FP
stack grows
void foo(char *str) {
char buffer[12];
strcpy(buffer, str);
value of str foo()’s return address
int main() {
char *str = “This is definitely longer than 12”; foo(str);
stack previous FP
Current FP
(Frame Pointer) }
buffer[11] ……
How to exploit the vulnerability?
buffer copy
stack grows
Trigger the
execution of
malicious payloads
void foo(char *str) {
char buffer[12];
strcpy(buffer, str);
int main() {
char *str = “some text to
new address
overflow buf [new address]
some other text [malicious
buffer[11] ……
buffer copy
How to exploit the vulnerability?
Buffer Overflow: Example 1
Memory Contents
0xbffff7a0 0xbffff7a8 0xbffff7b0 0xbffff7b8
0xe5d77fd4 0x3b63856e 0xe37da46c 0xfac49c84 0x00000000 0xbffff7c0 0xa0003300 0xb0005300
password_buffer auth_flag
Buffer Overflow: Example 1
Memory Contents
0xbffff7a0 0xbffff7a8 0xbffff7b0 0xbffff7b8
0x44434241 0x48474645 0x4c4b4a49 0x504f4e4d 0x00000051 0xbffff7c0 0xa0003300 0xb0005300
password_buffer auth_flag
Memory contents after strcpy of password “ABCDEFGHIJKLMNOPQ” from user (attacker) input
Buffer Overflow: Example 1
Memory Contents
0xbffff7a0 0xbffff7a8 0xbffff7b0 0xbffff7b8
0x44434241 0x48474645 0x4c4b4a49 0x504f4e4d 0x00000051 0xbffff7c0 0xa0003300 0xb0005300
password_buffer auth_flag
allocated for passwords up to 16 chars (bytes): longer passwords overflow into auth_flag
overflow 1 byte!
Modify a secret key to be one known to the attacker, to be able to decrypt future intercepted messages
Modify interpreted strings used as part of commands, e.g., to facilitate SQL injection
Corrupting data
Modify state variables to bypass authorisation check (our example)
Attackers can overflow data:
Buffer Overflow: Example 2
Memory Contents
0xbffff7a0 0
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com