rop2win
Building a ROP chain for a ret2win binary.
Last updated
Building a ROP chain for a ret2win binary.
Last updated
All the challenges in this section are going to be 64-bit challenges. ROP in 32-bit is almost trivial because we pass parameters on the stack rather than the registers, meaning crafting payloads is super simple. In 64-bit, we need to find ways to load the registers with our desired parameters, which is much more difficult.
The challenge is very similar to win64. We need to be mindful that we are in 64-bit.
This challenge, along with all the others, are the 64-bit renditions from ROP emporium. They are by far the best resource for learning how to do ROP.
The primary functions we see in the binary are:
ret2win()
This function is straightforward. The string values are statically loaded, and we can easily reverse this function:
main()
This function makes a series of back-to-back puts()
calls and then calls read_in
. In 64-bit, these calls are super easy to interpret, given that you know the parameter register order.
pwnme()
Like the last two, we can pretty easily determine the C code for this function. The only one that's confusing is memset
, whose declaration is in the man
pages.
Based on what's loaded to the registers, we can tell the function call is memset(rbp-0x20, 0, 0x20)
:
Let's put the rest of the function together:
If you're struggling to put the C code together, that's okay! This is one of the hardest parts of binary exploitation. It comes with lots of practice! Keep practicing using gdb
to dissect binaries. Try making your own, then looking at them to reassemble the code you wrote.
Based on this code, we see a clear buffer overflow vulnerability. We are reading 0x38=56
bytes into the 0x20=32
byte buffer allocated.
Like win64, we need to track the following information:
What is the size of the buffer? In our case, it's 0x20
bytes to the base pointer, plus 0x8
bytes for the base pointer, totaling 0x28=40
bytes.
Where are we going? We need to overwrite the return pointer with the address of win()
, which is at 0x400756
.
Does our input cause the movaps
instruction to fail? Our payload is 48
bytes in total, which is divisible by 16
, meaning that we should be fine.
Let's write the exploit just like we wrote the win64 one:
Two notes here:
We will consistently read until the >
before sending our input because that's how ROP emporium formats their challenges.
We will distinguish between padding and payload (ROP chain) to illustrate the difference.
Most of our exploit files for this section will look the same. We will establish our process, then our critical functions and gadgets, build the padding and ROP chain and then send it to the process.
If we send this off, we'll get our flag!