Created
May 2, 2018 13:21
-
-
Save SadPaladin/3ec7971468ec2c4532633131bfaf1bc2 to your computer and use it in GitHub Desktop.
A script to decrypt uboot/kernel/mcu update images used by Allwinner T8-based car radio headunits
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 python3 | |
import hashlib | |
import sys | |
import tqdm # Used to report progress during decryption | |
if len(sys.argv) not in (2,3): | |
print("Usage: dcupdate.py enciphered_file [deciphered_file]") | |
print("Deciphers images used by Allwinner T8-based car radio headunits") | |
sys.exit(0) | |
print("Deciphering update '{}'".format(sys.argv[1])) | |
# Extracted from UBoot Firmware | |
unkA = bytes([0xC1, 0x81, 0x56, 0xC2, 0x44, 0xBD, 0x11, 0xE1, 0x94, 0x38, 0x00, 0x0C, 0x29, 0xBA, 0x27, 0xC0]) | |
unkB = bytes([0x81, 0x6B, 0xAE, 0x89, 0x3F, 0x95, 0xE6, 0xDB, 0x96, 0xA3, 0xB9, 0x90, 0x57, 0x17, 0x29, 0xAF]) | |
unk_xored = bytes([a ^ b for a,b in zip(unkA, unkB)]) | |
print("Magic bytes:") | |
print(" A = {}".format(unkA.hex())) | |
print(" B = {}".format(unkB.hex())) | |
print(" A ^ B = {}".format(unk_xored.hex())) | |
def obfuscate_block(key_block, in_block): | |
inner_digest = hashlib.md5(key_block + in_block + unk_xored).digest() | |
outer_digest = hashlib.md5(inner_digest + unkB).digest() | |
return outer_digest | |
fn = sys.argv[1] | |
try: | |
with open(fn, 'rb') as f: | |
buffer = f.read() | |
key_block = buffer[-0x20:-0x10] | |
print("Key Block: {}".format(key_block.hex())) | |
# Verify checksum | |
file_md5 = hashlib.md5(buffer[:-0x10]).digest() | |
obfuscated_md5 = obfuscate_block(key_block, file_md5) | |
exp_obfuscated_md5 = buffer[-0x10:] | |
print("Obfuscated Checksum: {}".format(obfuscated_md5.hex())) | |
print("Expected Checksum: {}".format(exp_obfuscated_md5.hex())) | |
assert obfuscated_md5 == exp_obfuscated_md5, "Checksums do not match" | |
if len(sys.argv) == 2: | |
print("Checksums match! No output file specified, exiting...") | |
sys.exit(0) | |
# Dump deciphered file | |
print("Deciphering file...") | |
out_fn = sys.argv[2] | |
xor_block = bytes([0] * 16) | |
with open(out_fn, 'wb') as fout: | |
for i in tqdm.trange(0, len(buffer) - 0x20, 0x10): | |
xor_block = obfuscate_block(key_block, xor_block) | |
block = buffer[i:i+min(0x10, len(buffer) - 0x20)] | |
dec_block = bytes([a ^ b for a,b in zip(block, xor_block)]) | |
fout.write(dec_block) | |
except IOError as e: | |
print("I/O Error ({0}): {1}".format(e.errno, e.strerror)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment