ROP32 — PicoCTF2019

Nguyễn Tín
6 min readApr 23, 2020

It’s been a long time since my last writeup, now i came back with this exciting challenge. I knew that there’s a lot of writeup about this challenge on the internet but this one I only based my own limited knowledge.

so let’s jump in!!!


Can you exploit the following program to get a flag? You can find the program in /problems/rop32_1_c4f09c419e5910665553c0237de93dcf on the shell server. Source.


This is a classic ROP to get a shell


### Gathering

The name and the hint itself pretty clear about what we’re going to do. If you don’t know what is ROP, then I suggest you should research it more about it andread this writeup.

From the source, we’ll see the gets function that’s lead to the Buffer Overflow (abbr BOF )vulnerability. But if we checksec it,

that’s the NX bit is on, so there is no way we can put our shellcode to the stack and let it execute itself. We need to use ROP technique to bypass NX bit.

So what’s ROP? Basically it use the present codes inside the binary, which we call gadgets, and we chain it into a ROP chain.

now let’s find our offset first

our offset is 0x1c (or 28 if you prefer decimal)

now because we’re all new to ROP (I presume that you readers and myself), we need to ROP our way some how to execute this syscall

execve(‘/bin/sh’, [‘/bin/sh’], NULL)

according to the syscall table above, we need

  • eax == 0xb (11 in dec)
  • ebx == address in the memory of the string ‘/bin/sh’
  • ecx == a pointer point to the address of ‘/bin/sh’
  • edx == NULL (\x00)

as you may know parameters are passed to syscall via the registers. You can see that each of the regs represent an argument in the execve function, and of course the eax is the exception one, because you can determine which syscall should the machine use.

alright now let’s jump into the next step


first i use ROPgadget to find our gadgets and dump it into a file.

let’s test this one and see

0x080a8e36 : pop eax ; ret

hmm, weird. Do you notice that my gadgets is 0x080a8e36 not 0x08008e36?

i’m strolling around the internet and then found this.

because in our gadget it has a special byte which is 0x0a if you decipher that hex value it means the newline character (AKA \n). When the machine meet that byte it simply nulled it. that’s why our gadget didn’t work.

let’s find the suitable gadget without the badbyte

0x08056334 : pop eax ; pop edx ; pop ebx ; ret

alright let’s sum up what we should do

  • first we found all the suitable gadgets to trigger the syscall
  • I myself need to specify a clear way to solve this challenge xD

here are the basic step that i found suggest

  • Step 1 — Write-what-where gadgets
  • Step 2 — Init syscall number gadgets
  • Step 3 — Init syscall arguments gadgets
  • Step 4 — Syscall gadget
  • Step 5 — Build the ROP chain

the first step is simple, you need to write your string to a writable memory (such ass .bss section)

the second step is to find the gadget that can allow you to modify the value of eax

the third step is to find gadgets that can allow you to modify the ebx, ecx, edx regs

the fourth step is to find the gadget that initiate the syscall (which is int 0x80)

the fifth step was the obvious captain !!!

now for the first step i’m using the .data section

  • i’m using the following gadgets to write it:

0x8056e65 mov dword ptr [edx], eax ; ret
0x806ee6b pop edx ; ret
0x8056334 pop eax ; pop edx ; pop ebx ; ret

for the 2nd step

0x8056420 xor eax, eax ; ret
0x807c2fa inc eax ; ret

for the 3nd step

0x80481c9 pop ebx ; ret
0x806ee92 pop ecx ; pop ebx ; ret
0x806ee6b pop edx ; ret

the final one

0x8049563 int 0x80

now let’s stroll through our gadgets. The first step was pretty interesting one, you saw that i’m using the mov [reg1] reg2 instruction. Because that’s the only way (i think) we can write a value to a specific address. So our first step’s gonna be

nice, now we can write it with the gadget mov [reg1] reg2

Great! Now that we’re wrote ‘/bin’ to the 0x080da060 now we need to increase our address to 4 more bytes to write our next string ‘/bin//sh’ (because we need to fill up 4 bytes and when the machine saw 2 forward slashes, it ignore one)

Cool right? now before we move to the next step we just need to make sure like 4 bytes more with null byte because we need our ecx, edx == NULL

we just need to null it with the mov [reg1] reg2 instruction

phew, finally done step one!!!

now we go to step two (i mean step 3 because step 2 it’s kinda easy we just using it for 11 times)

3rd and 4th step

now we just need to ssh to the sever and take our flag

enjoy hacking !!!