What is Return-Oriented Programming?

Posted by Vetle Økland on Tue, Nov 14, 2017
In Exploit Development, Reverse Engineering
Tags exploit, return oriented programming, rop, malware

For a long time I’ve been casually wondering about how ROP really works and what it is. I understand buffer overflows and shellcode in stacks and heaps, but a simple explanation to ROP was apparently hard to find. I was reading about something else when it hit me how this concept works, but further reading was still a bit hazy to me.

While it is a powerful way to avoid Data Execution Prevention (when CPU will not execute code in heap and stack), it a really simple concept.

In simple terms, a buffer overflow on the stack introduces a return address and then some shellcode the return address should goes to. Data Execution Prevention (DEP) prevents the shellcode from being executable in the stack (and the heap), so that is a no-go in modern computing. When doing ROP, instead of introducing shellcode, you just introduce a whole bunch of return addresses pointing near the bottom of subroutines already established in the program.

Instead of creating shellcode, just find a whole bunch of subroutines that contain the instructions you want near the bottom of it. So if you want to execute this code:

mov eax, 0x4
add eax, 0x4
mov ebx, eax

Just find two or three subroutines ending with one or more of these instructions, then smash the stack with multiple pointers to those addresses in memory. The first one being something like:

mov eax, 0x4
ret

Then a second that might be

add eax, 0x4
mov ebx, eax
ret

And then you’ve got the ebx register stored with 0x8.


It is, of course, way easier to just introduce your own shellcode, but when it is not an option, this is still easy enough to pull off. ROP has been used in the past as a stepping stone to disable DEP and then go on to use shellcode, but with the introduction of hardware DEP I’m not sure this is as feasible anymore.