Files
live-hub-py/tools/dfp_rc4.py
T

84 lines
3.1 KiB
Python

#!/usr/bin/env python3
"""dfpReport 编解码器 — R37 攻坚定论 (2026-08-29)
算法 (R35-R37 三轮活体捕获 + 12/12 历史密文解密验证):
明文 JSON -> gzip (zlib deflate, gzip wrapper, 头 1f8b08 00 00000000 02 03)
-> C = RC4(key) keystream XOR gzip (逐字节, 长度保持, 标准 KSA/PRGA 无 drop)
-> wire body = 密文整段 (前 10B 即所谓 magic 571882cf664bb39401ee = keystream XOR gzip 头,
不是魔数! 密钥同则 magic 同)
-> 尾部 10B 为 gzip 流之后的附加段 (decompressobj unused_data)
密钥 = 32 字符 hex ASCII 串 (如 865a4924a40897ac1fcfe6b4c2abc798), 每注册轮换.
捕获点: libhydeviceid.so!0x60e6c onEnter x1 = 密钥串 (tools/frida/hook_hy.js).
XXTEA/静态密钥 f15e... 与 dfpReport 无关 (那是 hdid 子系统) — 45 函数零调用之谜即此.
"""
from __future__ import annotations
import sys, zlib
def rc4_keystream(key: bytes, n: int) -> bytes:
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % len(key)]) & 0xFF
S[i], S[j] = S[j], S[i]
out = bytearray()
i = j = 0
for _ in range(n):
i = (i + 1) & 0xFF
j = (j + S[i]) & 0xFF
S[i], S[j] = S[j], S[i]
out.append(S[(S[i] + S[j]) & 0xFF])
return bytes(out)
def decrypt(body: bytes, key: bytes) -> bytes:
"""body = wire body (magic 10B + cipher) -> 指纹 JSON 明文."""
ks = rc4_keystream(key, len(body))
plain = bytes(a ^ b for a, b in zip(body, ks))
d = zlib.decompressobj(31) # gzip
json_bytes = d.decompress(plain, 1 << 20)
return json_bytes
def encrypt(json_bytes: bytes, key: bytes) -> bytes:
"""指纹 JSON -> wire body. 尾部 10B 附加段按全 0 处理 (服务端解 gzip 忽略)."""
gz = gzip_wrap(json_bytes)
ks = rc4_keystream(key, len(gz) + 10)
return bytes(a ^ b for a, b in zip(gz + b"\x00" * 10, ks))
def gzip_wrap(json_bytes: bytes) -> bytes:
co = zlib.compressobj(9, zlib.DEFLATED, 31) # gzip wrapper
gz = co.compress(json_bytes) + co.flush()
# 对齐 turing 原生 gzip 头: OS 字节 = 0x03 (Unix), Python 写 0x13
return gz[:9] + b"\x03" + gz[10:]
def _selftest():
MAGIC = bytes.fromhex("571882cf664bb39401ee")
KEY = b"865a4924a40897ac1fcfe6b4c2abc798"
body = open("evidence/dfp_live/dfp_body_4303.bin", "rb").read()
i = body.find(MAGIC)
wire = body[i:]
js = decrypt(wire, KEY)
assert js.startswith(b'{"Athena"'), js[:40]
print(f"decrypt OK: {len(js)}B JSON")
gz = gzip_wrap(js)
re_enc = encrypt(js, KEY)
n = len(gz)
print(f"re-encrypt: gzip {n}B + 10B tail vs wire {len(wire)}B, "
f"cipher part {'IDENTICAL' if re_enc[:n] == wire[:n] else 'DIFFERS'} "
f"(magic10 {'==' if re_enc[:10] == wire[:10] else '!='})")
if __name__ == "__main__":
if len(sys.argv) >= 3 and sys.argv[1] == "dec":
key = sys.argv[3].encode()
body = open(sys.argv[2], "rb").read()
MAGIC = bytes.fromhex("571882cf664bb39401ee")
i = body.find(MAGIC)
sys.stdout.buffer.write(decrypt(body[i:], key))
else:
_selftest()