Buffer Overflow
Contents
- Introduction
- Process Memory Organization
- Stack and Function Calls
- Buffer Overflow Implementations
- A Simple Buffer Overflow
- A Friendly Buffer Overflow
- A Less Friendly Buffer Overflow
- A More Realistic Buffer Overflow
- Buffer Overflow Types
- C-String Overflow
- Integer Overflow
- Format String Overflow
- Return to libc Overflow
- Buffer Overflow Defense
- Better Programming & Code Analysis
- Using hardware/OS mechanism
Introduction
Process Memory Organization
There’re three regions: program, heap, stack
Process memoryrefers to the memory space that is allocated to a specific process or program when it is executed on a computer. It includes all the data, instructions, and variables that are needed by the process to function properly.Heap segment: This is the memory region that is dynamically allocated during program execution to store data structures like arrays and linked lists. It grows in size as the program requests more memory and can be resized as needed.Stack segment: This region is used to store the program’s runtime stack, which is used to keep track of function calls and local variables. It typically grows downward in memory as more data is pushed onto the stack..bss: Contains uninitialized global and static variables. Memory is allocated by the OS at program startup and initialized to zero..text: Contains executable code of the program, such as arithmetic, logic, and data manipulation instructions. This section is typically read-only and not modified during execution..data: Contains initialized global and static variables allocated by the OS at program startup. Unlike “.bss”, the “.data” section contains initialized data, meaning it’s initialized to a predefined value before execution.
Stack and Function Calls
-
Stack is a continuous block of memory
-
Stack Pointer (
rsp) points to the top of stack -
The bottom of the stack is a fixed high memory,
0xffffffff
-
-
When function is called the stack contains
-
Function argument and local variables
-
Data required to recovery from the function call, which includes the return address of the calling statement
Example Stack Contents


-
Buffer Overflow Implementations
A Simple Buffer Overflow

strcopy()copies the contents of str into buffer, until a ‘\0’ is encountered in the string.- Since the size of memory pointed by str is larger than buffer, strcpy continues copying, overwriting
rbpandret. - As a result, the return address
retbecomes0x41414141
Segmentation Fault Case

A Friendly Buffer Overflow


-
First, we need to calculate the address of
ret.retis 4 bytes after the end of buffer 1, so address ofretisbuffer1 + 12. -
What will happen?
retnow points to the next instruction than it should be. Sox = 1is skipped.
A Less Friendly Buffer Overflow


-
A less friendly Buffer Overflow will modify the return address to a shellcode address, so that shell code will be executed.
-
Shell Code
-
Since the instructions are on the stack, they must be in assembler
-
To get shell code, you can write in C and compile. For instance:
Compile with
gcc -static -gand view usinggdborobjdump

-
Or you can go to website: exploit-db
-
-
Another Example


A More Realistic Buffer Overflow
- Realistically, program reads from an external source then copies to a buffer.
- The buffer overflow program is more difficult to write since we don’t know exactly where the buffer to overflow is, and cannot use an address of local variable to determin ret since we don’t know the source code.
- So we have to make a guess and provide an offset
Example👇 More Catch the Flag: http://pwnable.kr/play.php
Buffer Overflow Types
The examples above are all instances of C-String Buffer Overflow, but there are other types as well.
C-String Overflow
-
Overflow Layout

-
Real World Example

Integer Overflow
-
What is it?

-
OpenSSH Example

Format String Overflow
A format string overflow is a type of vulnerability that occurs when an attacker is able to provide input to a program that is later used as a format string argument in a call to a formatting function like “printf” or “sprintf” without proper input validation or bounds checking.
The issue arises when the attacker can supply a format string containing format specifiers like %s, %x, %n, etc. that the formatting function interprets as instructions to read from or write to memory locations outside the intended buffer or stack frame, leading to memory corruption and potentially allowing the attacker to execute arbitrary code or modify program data.
Example
printf(user_input);If the “user_input” variable contains a format string like “
%x%x%x”, the “printf” function will interpret it as an instruction to print the next three values on the stack as hexadecimal values. If the attacker can control the values on the stack, they can use this vulnerability to leak sensitive information or modify the program’s behavior.
To prevent format string vulnerabilities, input validation and bounds checking are necessary. Programmers should sanitize and validate any user-supplied input passed as format string arguments before using it in a formatting function. This can be done by limiting the number of format specifiers allowed, avoiding the use of user input as format strings, or using safer formatting functions such as “snprintf” that limit the amount of output produced.
Return to libc Overflow


-
Instead of putting large shell code in the buffer, the Overflow redirects the
rettosystem()function with parameter.- For instance, instead of putting the long
lsshell code inside buffer, we can redirect tosystem()function with parameterls.
- For instance, instead of putting the long
-
This type of overflow also made stack non-executable offer no protection, because there is no instruction on the stack, we just jump to another legitimate syscall.
Buffer Overflow Defense
Better Programming & Code Analysis
- Better programming practices (use type safe languages)
strcpy(),strcat(),sprintf()are not safe - Statically analyzing the source code
- Dynamically detecting overflow
Valgrind for memory debugging and leak protection
Fuzzing - provide all kinds of inputs
Using hardware/OS mechanism
-
Non-executable stack
Mark stack as non-executable, so shell code on stack will not work.
But it doesn’t prevent areturn to libcexploit -
Stack randomization
Randomly shifting the address of whole stack, but the relative address stays the same. So hackers can still using local variable relative address to locate
ret. -
Canaries
Run-Time check is a special values placed between the local and ret values. After function call, the integrity of canary values are checked.

But hacker can overwrite with exact canary content.






