DRMLab Project
This commit is contained in:
parent
4a0f3c9275
commit
7ba5bce8a9
56
tools/decrypt.py
Normal file
56
tools/decrypt.py
Normal file
@ -0,0 +1,56 @@
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import pad
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
def decrypt_file(input_file, key_hex):
|
||||
try:
|
||||
key = bytes.fromhex(key_hex)
|
||||
except ValueError:
|
||||
print("[-] Invalid AES key")
|
||||
return
|
||||
|
||||
with open(input_file, "rb") as f:
|
||||
encrypted_data = f.read()
|
||||
|
||||
cipher = AES.new(key, AES.MODE_ECB)
|
||||
dec_data = cipher.decrypt(pad(encrypted_data, 16))
|
||||
|
||||
if b"INNER_MSTAR" not in dec_data:
|
||||
print("[-] AES key not working")
|
||||
return
|
||||
|
||||
payload = None
|
||||
for offset in (64, 96):
|
||||
candidate = dec_data[offset:]
|
||||
if b"CHAI" in candidate or b"kbox" in candidate:
|
||||
payload = candidate
|
||||
break
|
||||
|
||||
if payload is None:
|
||||
payload = dec_data[64:]
|
||||
|
||||
if b"CHAI" in payload:
|
||||
out_data = payload
|
||||
elif b"kbox" in payload:
|
||||
out_data = payload[:128]
|
||||
else:
|
||||
out_data = payload[:32]
|
||||
|
||||
base, _ = os.path.splitext(input_file)
|
||||
out_file = f"{base}_encrypted.dat"
|
||||
|
||||
with open(out_file, "wb") as f:
|
||||
f.write(out_data)
|
||||
|
||||
print(f"[+] Saved {out_file}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print(f"Usage: python3 {sys.argv[0]} <file.dat>")
|
||||
sys.exit(1)
|
||||
|
||||
aes_key = input("AES key (hex): ").strip()
|
||||
decrypt_file(sys.argv[1], aes_key)
|
||||
269
tools/dump_buildprop.py
Normal file
269
tools/dump_buildprop.py
Normal file
@ -0,0 +1,269 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse, os, re, sys
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
RE_BLOCK = re.compile(
|
||||
br'(?mi)^(#\s*begin[^\n]*build\s+properties[^\n]*\n)(.*?)(^#\s*end[^\n]*build\s+properties[^\n]*$)',
|
||||
re.DOTALL,
|
||||
)
|
||||
|
||||
BASE_CANONICAL: List[Tuple[str, bool]] = [
|
||||
("# begin build properties", True),
|
||||
("# autogenerated by buildinfo.sh", True),
|
||||
("ro.build.id", False),
|
||||
("ro.build.display.id", False),
|
||||
("ro.build.version.incremental", False),
|
||||
("ro.build.version.sdk", False),
|
||||
("ro.build.version.preview_sdk", False),
|
||||
("ro.build.version.codename", False),
|
||||
("ro.build.version.all_codenames", False),
|
||||
("ro.build.version.release", False),
|
||||
("ro.build.version.security_patch", False),
|
||||
("ro.build.version.base_os", False),
|
||||
("ro.build.date", False),
|
||||
("ro.build.date.utc", False),
|
||||
("ro.build.type", False),
|
||||
("ro.build.user", False),
|
||||
("ro.build.host", False),
|
||||
("ro.build.tags", False),
|
||||
("ro.build.flavor", False),
|
||||
("ro.build.system_root_image", False),
|
||||
("ro.build.ab_update", False),
|
||||
("ro.product.model", False),
|
||||
("ro.product.brand", False),
|
||||
("ro.product.name", False),
|
||||
("ro.product.device", False),
|
||||
("ro.product.board", False),
|
||||
("# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,", True),
|
||||
("# use ro.product.cpu.abilist instead.", True),
|
||||
("ro.product.cpu.abi", False),
|
||||
("ro.product.cpu.abi2", False),
|
||||
("ro.product.cpu.abilist", False),
|
||||
("ro.product.cpu.abilist32", False),
|
||||
("ro.product.cpu.abilist64", False),
|
||||
("ro.product.manufacturer", False),
|
||||
("ro.product.locale", False),
|
||||
("ro.wifi.channels", False),
|
||||
("ro.board.platform", False),
|
||||
("# ro.build.product is obsolete; use ro.product.device", True),
|
||||
("ro.build.product", False),
|
||||
("# Do not try to parse description, fingerprint, or thumbprint", True),
|
||||
("ro.build.description", False),
|
||||
("ro.build.fingerprint", False),
|
||||
("ro.build.thumbprint", False),
|
||||
("ro.build.characteristics", False),
|
||||
("# end build properties", True),
|
||||
]
|
||||
|
||||
GENERIC_TOKENS = {"", "unknown", "generic", "aosp", "android", "android_device"}
|
||||
|
||||
def is_generic(v: str) -> bool:
|
||||
s = (v or "").strip().lower()
|
||||
return s in GENERIC_TOKENS or s.startswith("generic-") or s == "test-keys"
|
||||
|
||||
def parse_props(text: str) -> Dict[str, str]:
|
||||
d: Dict[str, str] = {}
|
||||
for raw in text.splitlines():
|
||||
line = raw.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
k, v = line.split("=", 1)
|
||||
d[k.strip()] = v.strip()
|
||||
return d
|
||||
|
||||
def block_kind(header: str, body: str) -> str:
|
||||
h = (header + body).lower()
|
||||
return "common" if "common build properties" in h or "buildinfo_common.sh" in h else "base"
|
||||
|
||||
def find_blocks(data: bytes):
|
||||
blocks = []
|
||||
for m in RE_BLOCK.finditer(data):
|
||||
header = m.group(1).decode(errors="ignore")
|
||||
body = m.group(2).decode(errors="ignore")
|
||||
footer = m.group(3).decode(errors="ignore")
|
||||
text = (header + body + footer).replace("\r\n","\n")
|
||||
props = parse_props(text)
|
||||
blocks.append({"text": text, "props": props, "kind": block_kind(header, body)})
|
||||
return blocks
|
||||
|
||||
SOC_VENDOR_PATTERNS = {
|
||||
"mstar": ["mstar", "cv6a", "msd6a", "mst", "cva"],
|
||||
"mediatek":["mediatek", "mtk", "mt5", "mt6", "mt8"],
|
||||
"amlogic": ["amlogic", "s905", "s912", "s922", "a113", "g12"],
|
||||
"qualcomm":["qcom", "qualcomm", "msm", "sdm", "sm"],
|
||||
"hisilicon":["hisilicon", "kirin", "hi37", "hi38", "hi35"],
|
||||
"rockchip":["rockchip", "rk3", "rk33", "rk35", "px3", "px5"],
|
||||
}
|
||||
|
||||
def detect_soc_vendor(props: Dict[str,str]) -> str:
|
||||
hay = " ".join([
|
||||
props.get("ro.board.platform",""),
|
||||
props.get("ro.hardware",""),
|
||||
props.get("ro.soc.manufacturer",""),
|
||||
props.get("ro.soc.model",""),
|
||||
props.get("ro.product.board",""),
|
||||
]).lower()
|
||||
for vendor, pats in SOC_VENDOR_PATTERNS.items():
|
||||
if any(p in hay for p in pats):
|
||||
return vendor.capitalize()
|
||||
return props.get("ro.soc.manufacturer","").strip()
|
||||
|
||||
FINGERPRINT_KEYS = [
|
||||
"ro.build.fingerprint",
|
||||
"ro.system.build.fingerprint",
|
||||
"ro.product.build.fingerprint",
|
||||
"ro.vendor.build.fingerprint",
|
||||
"ro.odm.build.fingerprint",
|
||||
"ro.oem.build.fingerprint",
|
||||
"ro.bootimage.build.fingerprint",
|
||||
]
|
||||
|
||||
def first_non_generic(*vals: str) -> str:
|
||||
for v in vals:
|
||||
if v and not is_generic(v):
|
||||
return v
|
||||
return vals[0] if vals else ""
|
||||
|
||||
def derive_company_from_fp(fp: str) -> str:
|
||||
if not fp or "/" not in fp:
|
||||
return ""
|
||||
head = fp.split("/", 1)[0].strip()
|
||||
return head[:1].upper() + head[1:] if head else ""
|
||||
|
||||
def detect_form_factor(all_props: Dict[str,str]) -> str:
|
||||
text = " ".join([
|
||||
all_props.get("ro.build.characteristics",""),
|
||||
all_props.get("ro.build.flavor",""),
|
||||
all_props.get("ro.build.fingerprint",""),
|
||||
all_props.get("ro.product.model",""),
|
||||
all_props.get("ro.product.name",""),
|
||||
all_props.get("ro.product.device",""),
|
||||
all_props.get("ro.product.system.model",""),
|
||||
all_props.get("ro.product.system.name",""),
|
||||
]).lower()
|
||||
if any(t in text for t in [" tv", "/tv", "mitv", "atv", "dvb", "android-tv", "google/atv"]):
|
||||
return "tv"
|
||||
if "tablet" in text or "pad" in text or "tab" in text:
|
||||
return "tablet"
|
||||
if "watch" in text or "wear" in text:
|
||||
return "watch"
|
||||
if "automotive" in text or "car" in text or "ivi" in text:
|
||||
return "automotive"
|
||||
return ""
|
||||
|
||||
def compose_props(base: Dict[str,str], commons: Dict[str,str], prefer_soc: bool,
|
||||
prefer_board_device: bool, force_ff: str|None) -> Dict[str,str]:
|
||||
merged = dict(commons)
|
||||
merged.update(base)
|
||||
out = dict(base)
|
||||
|
||||
fp = base.get("ro.build.fingerprint","")
|
||||
if not fp or is_generic(fp) or "/" not in fp:
|
||||
out["ro.build.fingerprint"] = first_non_generic(*(commons.get(k,"") for k in FINGERPRINT_KEYS[1:])) or fp
|
||||
|
||||
for tail in ["brand","manufacturer","model","device","name","board"]:
|
||||
dst = f"ro.product.{tail}"
|
||||
cur = base.get(dst, "")
|
||||
cand = first_non_generic(
|
||||
commons.get(f"ro.product.system.{tail}",""),
|
||||
commons.get(f"ro.product.product.{tail}",""),
|
||||
commons.get(f"ro.product.vendor.{tail}",""),
|
||||
commons.get(f"ro.product.odm.{tail}",""),
|
||||
commons.get(f"ro.product.oem.{tail}",""),
|
||||
merged.get(dst,""),
|
||||
cur,
|
||||
)
|
||||
out[dst] = cand or cur
|
||||
|
||||
if prefer_board_device:
|
||||
dev = out.get("ro.product.device","")
|
||||
if is_generic(dev) or dev in {"croods","android"}:
|
||||
repl = first_non_generic(
|
||||
merged.get("ro.product.board",""),
|
||||
merged.get("ro.soc.model",""),
|
||||
merged.get("ro.hardware",""),
|
||||
dev,
|
||||
)
|
||||
out["ro.product.device"] = repl or dev
|
||||
|
||||
fp_final = out.get("ro.build.fingerprint","")
|
||||
fp_brand = derive_company_from_fp(fp_final)
|
||||
soc_vendor = detect_soc_vendor(merged)
|
||||
if prefer_soc and soc_vendor:
|
||||
out["ro.product.brand"] = soc_vendor
|
||||
out["ro.product.manufacturer"] = soc_vendor
|
||||
else:
|
||||
if is_generic(out.get("ro.product.brand","")) and fp_brand:
|
||||
out["ro.product.brand"] = fp_brand
|
||||
if is_generic(out.get("ro.product.manufacturer","")) and fp_brand:
|
||||
out["ro.product.manufacturer"] = fp_brand
|
||||
|
||||
if is_generic(out.get("ro.product.board","")):
|
||||
out["ro.product.board"] = first_non_generic(
|
||||
merged.get("ro.product.board",""),
|
||||
merged.get("ro.soc.model",""),
|
||||
merged.get("ro.board.platform",""),
|
||||
out.get("ro.product.device",""),
|
||||
)
|
||||
if not out.get("ro.board.platform",""):
|
||||
out["ro.board.platform"] = first_non_generic(
|
||||
merged.get("ro.board.platform",""),
|
||||
merged.get("ro.hardware",""),
|
||||
merged.get("ro.soc.model",""),
|
||||
)
|
||||
|
||||
if force_ff:
|
||||
out["ro.build.characteristics"] = force_ff
|
||||
else:
|
||||
cur_ff = out.get("ro.build.characteristics","").strip().lower()
|
||||
if cur_ff in {"", "default", "nosdcard"}:
|
||||
auto = detect_form_factor({**merged, **out})
|
||||
if auto:
|
||||
out["ro.build.characteristics"] = auto
|
||||
|
||||
return out
|
||||
|
||||
def render_canonical(props: Dict[str,str]) -> str:
|
||||
lines: List[str] = []
|
||||
for token, is_comment in BASE_CANONICAL:
|
||||
lines.append(token if is_comment else f"{token}={props.get(token,'')}")
|
||||
return "\n".join(lines).strip() + "\n"
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Compose canonical build.prop (fills brand/device/fingerprint/form-factor).")
|
||||
ap.add_argument("file")
|
||||
ap.add_argument("--outdir", default="out")
|
||||
ap.add_argument("--prefer-soc", action="store_true")
|
||||
ap.add_argument("--prefer-board-device", action="store_true")
|
||||
ap.add_argument("--form-factor", choices=["auto","tv","tablet","phone","watch","automotive"], default="auto")
|
||||
args = ap.parse_args()
|
||||
|
||||
with open(args.file, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
blocks = find_blocks(data)
|
||||
if not blocks:
|
||||
print("No build properties blocks found.")
|
||||
sys.exit(1)
|
||||
|
||||
base = next((b for b in blocks if b["kind"]=="base"), blocks[0])
|
||||
commons: Dict[str,str] = {}
|
||||
for b in blocks:
|
||||
if b["kind"] == "common":
|
||||
commons.update(b["props"])
|
||||
|
||||
force_ff = None if args.form_factor == "auto" else args.form_factor
|
||||
composed = compose_props(base["props"], commons, args.prefer_soc, args.prefer_board_device, force_ff)
|
||||
txt = render_canonical(composed)
|
||||
|
||||
os.makedirs(args.outdir, exist_ok=True)
|
||||
outp = os.path.join(args.outdir, "best_build_composed.prop")
|
||||
with open(outp, "w", encoding="utf-8") as fo:
|
||||
fo.write(txt)
|
||||
|
||||
print("Done:", outp)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user