#!/usr/bin/env python3 """ Brute-force search for the AES root key in libwvdrmengine.so that decrypts the ay64.dat keybox. """ from Crypto.Cipher import AES import struct CDM_LIB = "libwvdrmengine.so" KEYBOX = "L3/ay64.dat" keybox = open(KEYBOX, "rb").read() # 128 bytes cdm = open(CDM_LIB, "rb").read() # The decrypted keybox plaintext should look like structured data. # Known Widevine keybox magic signatures to check for. MAGIC_PATTERNS = [ b"KBPI", b"KEYB", b"kbpi", b"\x01\x00\x00\x00", b"\x00\x00\x00\x01", ] # Also check if decrypted bytes look like a DER-encoded structure def looks_like_der(data): return data[0] == 0x30 and data[1] in (0x81, 0x82) def looks_like_rsa_key(data): # SEQUENCE { INTEGER 0, INTEGER (modulus)... } return data[:4] == b"\x30\x82" or data[:2] == b"\x30\x81" hits = [] step = 1 # slide byte by byte print(f"Scanning {len(cdm):,} bytes of libwvdrmengine.so for AES root key...") print(f"Keybox first block: {keybox[:16].hex()}") print() for i in range(0, len(cdm) - 16, step): candidate_key = cdm[i:i+16] # Skip keys that are all zeros, all same byte, or look like code if len(set(candidate_key)) < 4: continue try: # Try ECB first (no IV needed) cipher = AES.new(candidate_key, AES.MODE_ECB) decrypted = cipher.decrypt(keybox) for magic in MAGIC_PATTERNS: if decrypted.startswith(magic): print(f"[!] MAGIC HIT at offset {i:#010x}: key={candidate_key.hex()}") print(f" Decrypted: {decrypted.hex()}") hits.append(("ECB", i, candidate_key, decrypted)) if looks_like_der(decrypted): print(f"[!] DER HIT (ECB) at offset {i:#010x}: key={candidate_key.hex()}") hits.append(("ECB-DER", i, candidate_key, decrypted)) # Try CBC with first block as IV iv = keybox[:16] cipher2 = AES.new(candidate_key, AES.MODE_CBC, iv) dec2 = cipher2.decrypt(keybox[16:]) for magic in MAGIC_PATTERNS: if dec2.startswith(magic): print(f"[!] CBC MAGIC HIT at offset {i:#010x}: key={candidate_key.hex()}") hits.append(("CBC", i, candidate_key, dec2)) if looks_like_der(dec2): print(f"[!] DER HIT (CBC) at offset {i:#010x}: key={candidate_key.hex()}") hits.append(("CBC-DER", i, candidate_key, dec2)) except Exception: pass if i % 500000 == 0: print(f" Progress: {i:,}/{len(cdm):,} ({100*i/len(cdm):.1f}%)") if hits: print(f"\nFound {len(hits)} candidate(s)!") else: print("\nNo direct AES magic hits found.") print("The root key may be derived at runtime (not stored as a raw 16-byte value).")