ROP Emporium Ret2CSU Writeup
Last ROP Emporium callenge - Ret2CSU! This challenge requires a usage of something called Universal Gadget, that will allow us to use three parameters to functions calls, when we do not have any useful gadgets available to us.
Our goal is to call the ret2win
function with rdx
filled with 0xdeadcafebabebeef
. As mentioned before, the main challenge here is having no gadgets allowing us to directly control rdx
.
Looking at the disassembly, this challenge is pretty much the same as earlier challenges. We need to overflow the buffer in pwnme
, return to ret2win
BUT change rdx
first. Let’s hunt for gadgets:
I tried searching for more rdx-related gadgets but could not find any. After struggling with this for some time, I discovered something I was unfamiliar with - Universal gadgets.
__libc_csu_init functions provides a few nice gadgets to load data into certain critical registers. Most importantly EDI, RSI and RDX.
That’s perfect! Let’s get these gadgets from the disassembly of the file:
This allows us to move r15 into rdx
- But, then there’s a call to [r12+rbx*8]
and a cmp
instruction right after. We’re going to need to use the second section of gadgets shown above to control r12
and rbx
, so these instructions won’t get in our way.
Here’s another useful quote from the article linked to above:
To effectively use mov rdx,r13 , we have to ensure that
call QWORD PTR [r12+rbx*8]
doesn’t SIGSEGV,cmp rbx,rbp
equals and most importantly value ofRDX
is not altered.
Also noted in the article is that it’s possible to use pointers for the _init
function, located at &_DYNAMIC
. That’s just what we need for r12
, as we’ll zero rbx
- call [_init+0*8]
.
pwndbg> x/10gx &_DYNAMIC
0x600e20: 0x0000000000000001 0x0000000000000001
0x600e30: 0x000000000000000c 0x0000000000400560
0x600e40: 0x000000000000000d 0x00000000004008b4
0x600e50: 0x0000000000000019 0x0000000000600e10
0x600e60: 0x000000000000001b 0x0000000000000008
0x600e48
contains an address to 0x00000000004008b4
:
pwndbg> x/4i 0x00000000004008b4
0x4008b4 : sub rsp,0x8
0x4008b8 : add rsp,0x8
0x4008bc : ret
Remember that after the call instruction, the program will again pop all registers until reaching the ret instruction. Also, we have add rsp, 0x8
meaning we need another dummy in the stack. Also, rbp
and rbx
must not be equal (because of the cmp
instruction)!
Summing Up
Here’s the plan:
- Call first gadget at
0x0040089a
. - Pop all desired values.
- Register R12 = pointer to
__init
address. - Register R15 =
0xdeadcafebabebeef
. - Register
RBX = 0x0
whileRBP = 0x01
. - Use second gadget at address 0x400880 that will put the values at correct registers.
- Place the address of ret2win function in the stack.