Don't like this style? Click here to change it! blue.css
So the conversation in the last class got me thinking about the wide-open nature of hacking in a ROP context. That context is:
In class I used the analogy of learning to make meals given a supermarket. You now have a TON of freedom compared to having parents prepare your meals.
I was asked the question, what are the basics of ROP. The truth is that the basics are maybe too abstract to help, but here goes an attempt:
ret
instruction is executedsystem("/bin/sh")
That's maybe not that helpful to a young practitioner.
In my feeding yourself analogy that's like saying, all meals involve eating food.
You need to know how to make a meal for yourself, and the truth is there are a LOT of ways to do that. We have whole cooking networks and reality shows and recipe books and subcultures of etiquitte. None of which are prerequisites to you eating.
So now the question is, how do I guide you through some interesting ways to use this skill?
system
(alternatively syscall
)Let's tackle these one at a time
We know that there are essentially 3 (soon to be 4) valuable memory segments that are randomized every time a program executes:
Our analogy for these has been a fleet of battleship pieces. If you can identify any address in any of the ships you can do some simple addition/subtraction to find anything else in that segment.
This segment can be unrandomized by the -no-pie flag.
This segment contains:
printf("hi");
)The stack sets up a "stack frame" for each function called which has room for:
These frames are setup recursively so they can make a clean frame in the middle of a function call and restore the previous stack frame after a ret.
We've talked endlessly about it, but worth noting: there are always interesting little treasures (e.g. identifyable addresses from one of these key segments) to be found on the stack, so if you can scan the stack then that's good.
Inside of the glibc segments are almost anything you could ever want. I call them multiple segments because there is so much stuff that it's typically 4+ segments in a row some with R-X and some with RW-
Here are some key targets in glibc:
OK so one of the things we need to assess is UNDER WHAT CONDITIONS can you undo randomization?
When we get to the heap we'll show more sophisticated ways to generate leaks that don't feel as toy-like.
So if you're in the wilderness you need to find a copy of "/bin/sh" somewhere
You can either write it to an address you can predict or find it in the binary or leak a glibc address.
But even given the address where "/bin/sh" lives how do you get it INTO the call of system
?
"PADDINGHERE"+p32(systemaddr)+"JUNK"+p32(BINSHADDR)
call system
you don't need the "JUNK" four-byte offset (this offset is because "call" pushes a return address onto the stack which you have to emulate when JMPing rather than CALLing)pop rdi; ret;
ROPgadget --binary nameofbinary
and looking for the right gadget.ret
You can find these all over the place for what it's worthI'd like to highlight my auto-pwn ROP chain presuming NO PIE and partial RELRO.
This is a sophisticated ROP chain that is doing the following:
Here's the 64-bit version:
Here's the 32-bit version of the same concept:
So my favorite recipe is system("/bin/sh") so I'm hunting for any method I can to do that.
But sometimes the challenge forces you to do unusual tricks so this section might be "alternatives" to the standard system("/bin/sh") strat.
one_gadget
is a cool utility that finds a single address in a glibc that pops a shell for you. Typically these have some constraints like r9 is null or rsp+27 is 0 or something weird like that.syscall
gadget? We'll do this Friday where a syscall gadget can be used to invoke any kernel level process, the most common are execve and read/writeWith the supermarket strategy this section is sort of a world cuisine tour, there are MANY WAYS to win and you can expand your horizons with more practice, CTFing, experimenting with new methods.
You don't have to master them all, but the more you know the better you get.