Address space layout
General Memory Layout
- Heap
- Dynamically allocated as needed
malloc(), calloc(), new, ...
- Statically allocated Data
- Read/Write : global variables (Static Data)
- Read-only : string literals (Literals)
- Code / Instructions
- Executable machine instructions
- Read-only
![](https://velog.velcdn.com/images/s_sub/post/690a37c0-9795-4789-be69-46bee39b8b44/image.png)
x86-64 Linux Memory Layout
- Heap
- Dynamically allocated as needed
malloc(), calloc(), new, ...
- Statically allocated Data
- Read/Write : global variables (Static Data)
- Read-only : string literals (Literals)
- Code / Instructions
- Executable machine instructions
- Read-only
![](https://velog.velcdn.com/images/s_sub/post/e4963473-0a24-42ea-8575-b081332b729d/image.png)
Memory Allocation Example
![](https://velog.velcdn.com/images/s_sub/post/9a51f956-6ab4-4f49-b57a-e90c2547cee1/image.png)
What is a Buffer?
- A buffer is an array used to temporarily store data
- Buffers can also store user input
x86-64/Linux Stack Frame
- Caller's Stack Frame
- Arguments (if more than 6 args) for this call
- Current / Callee Stack Frame
- Return address (pushed by
call
instruction)
- Old frame pointer (optional)
- Caller-saved pushed before setting up arguments for a function call
- Callee-saved pushed before using long-term registers
- Local variables (if can't be kept in registers)
- "Argument build" area
(need to call a function with >6 arguments? Put them here)
![](https://velog.velcdn.com/images/s_sub/post/0aa5050d-6b81-4dd4-afe4-0d56271d0198/image.png)
Overflowing buffers and injecting code
Buffer Overflow in a Nutshell
- C does NOT check array bounds
- Many Unix/Linux/C functions don't check argument sizes
- Allows overflowing (writing past the end) of buffers (arrays)
- "Buffur Overflow" : Writing past the end of an array
example
- Stack grows down towards lower addresses
- Buffer grows up towards higher addresses
- If we write past the end of the array,
we overwrite data on the stack
![](https://velog.velcdn.com/images/s_sub/post/5c34ca4f-847b-4c33-abfc-f7abdb610704/image.png)
![](https://velog.velcdn.com/images/s_sub/post/814d21cd-709d-4dcf-bf9f-2db5d37fb2a8/image.png)
- Buffer overflows on the stack can overwrite "interesting" data
- Attackers just choose the right inputs
- Simplest form ("stack smashing")
- Unchecked length on string input into bounded array causes overwriting of stack data
- Try to change the return address of the current procedure
- Why is this a big deal?
- It was the #1 technical cause of security vulnerablities
String Library Code
- gets()
![](https://velog.velcdn.com/images/s_sub/post/a6837f15-732c-4e51-a1d7-84ea9148b9b3/image.png)
- No way to specify limit on number of characters to read
- Similar problems with other Unix functions :
- strcpy, scanf, fscanf, sscanf with %s specifier
Vulnerable Buffer Code
Malicious Use of Buffer Overflow
: Code Injection Attacks
![](https://velog.velcdn.com/images/s_sub/post/c9c50092-8312-48b5-98e8-9a2a3aea4126/image.png)
- Input string contains byte representation of executable code
- Overwrite return address A with address of buffer B
- When
bar()
executes ret, will jump to exploit code
Defense against buffer overflows
System-Level Protections
![](https://velog.velcdn.com/images/s_sub/post/405df8a1-b3ba-4512-9d80-523865642198/image.png)
- non-executable code segments
- Works well, but can't always use it
- Many embedded devices do not have this protection
- Some exploits still work!
- return-oriented programming
- return to libc attack
- JIT-spray attack
Avoid Overflow Vulnerablities in Code
![](https://velog.velcdn.com/images/s_sub/post/75d92dbb-2700-4fce-9910-b841c0ccc323/image.png)
- Use library routines that limits string lengths
fgets
instead gets
(2nd argument to fgets
sets limit)
strncpy
instead strcpy
- Don't use
scanf
with %s conversation specification
- Use
fgets
to read the string
- Use %ns where n is a suitable integer
- Don't use C.
Use a language that does array index bounds check
- Buffer overflow is impossible in Java
- Rust language was designed with security in mind
Stack Canaries
- Basic Idea : place special value('canary') on stack just beyond the buffer
- Secret value that is randomized before main()
- Placed between buffer and return address
- Check for corruption before exiting function
- GCC implementation
-fstack -protector
![](https://velog.velcdn.com/images/s_sub/post/aacd1a7b-4eb6-422f-b7f0-1c6d9b792180/image.png)
Disassembled
![](https://velog.velcdn.com/images/s_sub/post/647c5856-3f95-42d4-9b42-e167697c21f3/image.png)
setting up canary
![](https://velog.velcdn.com/images/s_sub/post/c2c2dd45-44d2-4f59-9def-f0a052f02895/image.png)
checking canary
![](https://velog.velcdn.com/images/s_sub/post/edbefb9f-8134-4a5e-956a-25b76c37851b/image.png)