diff --git a/decrypt_rootfs.py b/decrypt_rootfs.py index e60c0a9..1571c2a 100644 --- a/decrypt_rootfs.py +++ b/decrypt_rootfs.py @@ -1,3 +1,4 @@ +import sys from miasm.core.locationdb import LocationDB from miasm.analysis.binary import Container from miasm.analysis.machine import Machine @@ -32,9 +33,9 @@ class crypto_ctx(ctypes.Structure): _fields_ = [ ("padding", ctypes.c_uint8 * 174), ("null", ctypes.c_uint8), + ("rootfs_hash", ctypes.c_uint8 * 32), ("u", crypto_ctx_ctr_u), ("aes_key", ctypes.c_uint8 * 32), - ("rootfs_hash", ctypes.c_uint8 * 32), ] @@ -45,6 +46,46 @@ def print_logo(): print("https://randorisec.fr\n\n\n".center(max_width)) +def resolve_register(expr): + if expr.is_id(): + return expr.name + + if expr.is_slice() and expr.arg.is_id(): + base = expr.arg.name.upper() + start = expr.start + stop = expr.stop + size = stop - start + + reg_aliases = { + # format: (base, start, size): alias + ("RAX", 0, 8): "AL", + ("RAX", 0, 16): "AX", + ("RAX", 0, 32): "EAX", + ("RAX", 0, 64): "RAX", + + ("RBX", 0, 8): "BL", + ("RBX", 0, 16): "BX", + ("RBX", 0, 32): "EBX", + ("RBX", 0, 64): "RBX", + + ("RDX", 0, 8): "DL", + ("RDX", 0, 16): "DX", + ("RDX", 0, 32): "EDX", + ("RDX", 0, 64): "RDX", + + ("RCX", 0, 8): "CL", + ("RCX", 0, 16): "CX", + ("RCX", 0, 32): "ECX", + ("RCX", 0, 64): "RCX", + + # Extend as needed + } + + return reg_aliases.get((base, start, size), f"{base}[{start}:{stop}]") + + return None + + def locate_fgt_verify_initrd(file_flatkc): output = subprocess.check_output( f""" @@ -96,6 +137,47 @@ def derivate_chacha20_params(seed): return key, iv +def extract_chacha20_params(reg1, reg2): + machine = Machine(container.arch) + mdis = machine.dis_engine(container.bin_stream, loc_db=loc_db) + asmcfg = mdis.dis_multiblock(fgt_verify_initrd_addr) + all_srcs = [] + for block in asmcfg.blocks: + if "sha256_update" not in block.to_string(): + continue + + reg1_val, reg2_val = 0, 0 + for instr in block.lines: + if instr.name == "MOV": + dst, src = instr.get_args_expr() + + if (resolve_register(dst) == reg1) and src.is_int(): + reg1_val = src.arg + + if (resolve_register(dst) == reg2) and src.is_int(): + reg2_val = src.arg + + all_srcs.append((reg1_val, reg2_val)) + if (len(all_srcs)) == 4: + break + + if (len(all_srcs)) != 4: + # Failed to find all components + return None, None + + sha = sha256() + sha.update(container.executable.get_virt().get(all_srcs[0][0], all_srcs[0][0] + all_srcs[0][1])) + sha.update(container.executable.get_virt().get(all_srcs[1][0], all_srcs[1][0] + all_srcs[1][1])) + key = sha.digest() + + sha = sha256() + sha.update(container.executable.get_virt().get(all_srcs[2][0], all_srcs[2][0] + all_srcs[2][1])) + sha.update(container.executable.get_virt().get(all_srcs[3][0], all_srcs[3][0] + all_srcs[3][1])) + iv = sha.digest()[:16] + + return key, iv + + def decrypt_rsapubkey(rsapubkey_data, key, iv): chacha = ChaCha20.new(key=key, nonce=iv[4:]) counter = int.from_bytes(iv[:4], "little") @@ -113,6 +195,9 @@ def decrypt_rootfs_sig(rootfs_sig, decoded_key): num_bytes = (res.bit_length() + 7) // 8 assert num_bytes == 255, "signature broken" + + logging.debug(f"sig: {binascii.hexlify(res.to_bytes(num_bytes, "big")).upper()}") + sig_struct = crypto_ctx() ctypes.memmove(ctypes.byref(sig_struct), res.to_bytes(num_bytes, "big"), num_bytes) return sig_struct @@ -178,9 +263,9 @@ def decrypt_rootfs(file_rootfs_dec, rootfs_enc): fgt_verify_initrd_addr = locate_fgt_verify_initrd(options.flatkc) loc_db = LocationDB() container = Container.from_stream(open(options.flatkc, "rb"), loc_db) - seed_addr = get_seed() - seed_data = container.executable.get_virt().get(seed_addr, seed_addr + 32) - logging.debug(f"SEED: {binascii.hexlify(seed_data).upper()}") + # seed_addr = get_seed() + # seed_data = container.executable.get_virt().get(seed_addr, seed_addr + 32) + # logging.debug(f"SEED: {binascii.hexlify(seed_data).upper()}") rsapubkey_addr = get_rsapubkey_addr() rsapubkey_data = container.executable.get_virt().get( @@ -188,7 +273,15 @@ def decrypt_rootfs(file_rootfs_dec, rootfs_enc): ) logging.debug(f"RSAPUBKEY: {binascii.hexlify(rsapubkey_data).upper()}") - key, iv = derivate_chacha20_params(seed_data) + # key, iv = derivate_chacha20_params(seed_data) + key, iv = extract_chacha20_params("RSI", "EDX") + if key == None or iv == None: + logging.error("Failed to extract key or iv") + sys.exit(1) + + logging.debug(f"key: {binascii.hexlify(key).upper()}") + logging.debug(f"iv: {binascii.hexlify(iv).upper()}") + decoded_key, _ = decoder.decode( decrypt_rsapubkey(rsapubkey_data, key, iv), asn1Spec=rfc3279.RSAPublicKey() )