ROP
Return Oriented Programming: Execute code already present in the program.
Each snippet is composed of some instructions + RET.
RET pops
RIP
from the stack.
Program flow is controlled by values in the stack.
The attacker puts values in a stack pointing to gadgets.
When a gadget ends, the code jumps to the next gadget.
Any program can be constructed as long as there are gadgets available.
When Good Instructions Go Bad: Generalizing Return-Oriented Programming to RISC [1] - Buchanan, E.; Roemer, R.; Shacham, H.; Savage, S.
Return-Oriented Programming: Exploits Without Code Injection [2] - Shacham, Hovav; Buchanan, Erik; Roemer, Ryan; Savage, Stefan.
ROP Attacks: Chain gadgets to execute malicious code.
A gadget is a suite of instructions that end by the branch instruction ret (Intel) or the equivalent on ARM.
Intel examples:
pop eax ; ret xor ebx, ebx ; ret
ARM examples:
pop {r4, pc} str r1, [r0] ; bx lr
Objective: Use gadgets instead of classical shellcodes.
Because x86 instructions aren't aligned, a gadget can contain another gadget.
Doesn't work on RISC architectures like ARM, MIPS, SPARC...
Using ROP, the stack is subverted to create a jump sequence. It contains:
Values to be loaded;
Addresses to other gadgets;
May also contain arguments to functions called.
Gadgets are present in program code and loaded libraries.
Each function available provides one gadget;
Plus misaligned access.
Why?
It can bypass several security mechanisms.
Practical Example: return_to_libc.c (x86_64)
Payload strategy:
All addresses are 8 bytes;
Buffer: padding with 16 bytes (buffer + RBP);
Gadget address: ?? ->
rop --search “pop rdi; ret”
pop RDI: load command address into RDI;
ret: load system address into RIP;
Command address: ?? ->
grep /bin/sh
Approaches: Find a string already in RAM (better); add the payload after the system address (if required);
System address: ?? ->
print system
Last updated