Return Oriented Programming
“These courses expects a high standard of professionalism from its students with regard to how security testing is conducted. We expect all students to act in good faith at all times […]”
TL;DR Don’t be mean
Friday 2nd July (This week)
3 questions, 2 hours
10am - 6pm
[WebCMS] -> [Course Work] -> [Major Project]
Key Dates
Project Groups

ret instruction which already exist as executable code within each binary or library. These gadgets may be used for binary exploitation and to subvert vulnerable executables.When the addresses of many ROP Gadgets are written into a buffer we have formed a ROP Chain. If an attacker can move the stack pointer into this ROP Chain then control can be completely transferred to the attacker.
Most executables contain enough gadgets to write a turing-complete ROP Chain. For those that don’t, one can always use dynamic libraries contained in the same address-space (such as libc) once we know their addresses.
The beauty of using ROP Gadgets is that no new executable code needs to be written anywhere - an attacker may achieve their objective using only the code that already exists in the program. Source: github.com/Ben-Lichtman/ropr
Hi confused! I’m a diagram
0xFFFF +-----------+
| |
| |
| |
| |
| |
| |
|== RET ==|
| | \
| | |
| | | Current function
Start of ----> | | |
buffer | | /
0x0000 +-----------+
Ultimately we want to use gadgets that form some desired shellcode e.g. call to /bin/sh
execve("/bin/sh", NULL, NULL)
eax = 0xb (execve syscall) # mov eax, 0xb
ebx = bin_sh_address # ...
ecx = 0 # xor ecx, ecx
edx = 0 # xor edx, edx
syscall # int 0x80
inc ...mov ...add ...sub ...pop ...popYour ROP exploit doesn’t need to comprised of just addresses. We can pass values (NB: encoded correctly) and pop them off!
i.e. Set EAX to 13
gdgt{mov eax, 13}gdgt{xor eax, eax} + gdgt{inc eax} …gdgt{pop eax} + p32(0xd)
pop ...+ value
... |
payload += gdgt{pop ebx; ret;} |
payload += p32(0xAABBCCDD) | payload += ...
... | ...
# ebx = 0xAABBCCDD | #
push espIf you need to get the address of the stack position… find a gadget that pushes esp, and pops it
push esp; pop ...
Note: Generally both of these instructions need to be in the same gadget
We can also add addresses in our ROP chain.
i.e found a call to
system? Use that!
payload += p32(0x804aabb) # some system() function address
payload += p32(addr_to_binsh)
0xFFFF +-----------------+
| | # esp+4 ^ when popped
| addr_to_binsh | # esp
| 0x804aabb | # esp-4 v when pushed
| ^-------- buffer start
0x0000 +-----------------+
What if a program doesn’t have enough gadgets?
A:
Find a better program
Use gadgets in dependent libraries
A: Uninstall, give up, cry, sleep
libc provides functions used by most programs!
i.e basically literally any C function
puts, printf, gets, etc…
libc versionYou can set the base address of an ELF in pwntools!
<ELF>.address = base_address
libc = ELF("libc_version.so")
libc.address = printf_leak - l.symbols['printf']
...
payload += p32(l.symbols['system']) # Offset adjusted!
Note: Also works for the program base
Note
Don’t forget about ASLR / PIE
roproproproproproproprop