Incident Response Services
Penetration Testing Services
IoT Security Services
Training & Certification
Managed Vulnerability Management
Managed Application Security
Managed Detection & Response
Find a Partner
Rapid7 Insight is your home for SecOps, equipping you with the visibility, analytics, and automation you need to unite your teams and amplify efficiency.
Insight Platform Overview Try Now
User Behavior Analytics & SIEM
Orchestration & Automation
Need a hand with your security program? From planning and strategy to full service support, our experts have you covered.
Need immediate help with a breach?
In today’s Whiteboard Wednesday, David Maloney, Sr. Security Researcher at Rapid7, will discuss the ROP exploit technique for buffer overflow vulnerabilities.
Watch this week’s Whiteboard Wednesday to learn more
Hello and welcome to this week's Whiteboard Wednesday. I'm David Maloney, Senior Security Researcher on the Metasploit team here at Rapid7. And today we are going to be continuing our ongoing series on exploit techniques for buffer overflows and the mitigations that help protect you against them.
So this week, we're going to be talking about ROP. Again, if you've spent any time in the security industry, you've probably heard this term thrown around but you might be a little confused as to what ROP actually is. So we're going to cover at a very high level today what ROP is and why it's important.
So ROP stands for Return Oriented Programming and this is a concept that was originally part of Linux exploitation in a technique known as return to libc. Essentially what it's about is using code that already exists in the program you're exploiting to perform certain key functions for you. Now the way we use ROP primarily is as a bypass for DEP, or data execution prevention, which we've talked about in one of the previous mitigation videos. What we do is we use return oriented programming to call Windows API functions to mark the stack as executable. So we discussed before how DEP prevents execution on the stack by not allowing non-executable memory to be treated as instructions. So what you do is you use ROP gadgets in order to call one of a couple different Windows functions, usually something like virtual protect and tell it to mark the stack as having execute permission. So then DEP is no longer in your way and you can execute your shell code here.
So essentially how this starts to work is that you have your shell code like normal. But where you get, where you replace either your save return pointer or your SEH record, whatever it happens to be that you're using to control execution, you're going to move to a ROP gadget. Now in the structured exception handler overwrite section we talked briefly about that pop pop ret instruction, which is actually a set of three instructions, that's actually a ROP gadget. It is a series of instructions that is concluded by a ret or return instruction. And what the return instruction always does is it returns back to the next, it returns to whatever the pointer next on the spec is.
So what we'll typically do is our first pointer will point to some kind of ROP gadget that will adjust the stack frame, which is pointed to by the register ESP, you don't have to worry too much about those specifics. But what it's basically gonna do is it's gonna move where we're writing stuff on the stack to down here, giving us some room to work. Then we'll have a return, and so when we return, after that first pointer we have to have another pointer to another ROP gadget that's going to do something.
Now don't worry too much about the specific set of instructions. This isn't a real ROP chain but essentially the flow is the same. You'll have a set of instructions that will always end with a return returning back to another pointer that will point to another ROP gadget. And what you're trying to do is actually down here, you are putting all of the arguments and then a pointer to the Windows functions you need to call on the stack down here in such a way that once you've finished your ROP chain, that final return will actually return to the function pointer for the Windows function you wanna call, causing it to send all of those arguments you set up on the stack to VirtualProtect or VirtualAlloc or a number of other methods which just tells it, "Hey, this section of the stack way up here where the rest of our shell code was, I need you to mark all of that executable now." And so when that happens all of a sudden that shell code that DEP would have prevented from running is now able to run like it's the early '90s again, essentially just making DEP a non-issue.
Now this used to be one of the really hard and challenging parts of exploit development. Fortunately there's a lot of tools out there, both inside Metasploit, also there is a tool for immunity debugger called mona.py that will help you build these ROP chains automatically. And so it's actually a much lower barrier to entry now for writing advanced exploits than it used to be.
So ROP basically completely invalidates DEP in scenarios where you can successfully build those ROP chains. It is still harder to write an exploit when you need to use ROP but it's still entirely possible thanks to ROP. And that's all we have for today. Check in with us next week and we'll see you then!
Know your weaknesses (and how to fix them): Let Rapid7 experts simulate a real-world attack on your organization.