#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ dfpReport 同步 pair 分析器 - 从 evidence/dfp_pair_sync.json 提取每个 wire 的 tag2 密文 (去掉 10B 魔数 + 9B 尾部字段) - 结合 plains 内存缓冲 (JSON 头 + 二进制尾) 计算 keystream - 验证输入布局假设: input = [JSON 554B][binary L-554B] """ import json, binascii, sys MAGIC = bytes.fromhex('571882cf664bb39401ee') TRAILER = bytes.fromhex('00400c0b8c980ca80c') EVID = 'evidence/dfp_pair_sync.json' def load_pairs(): d = json.load(open(EVID)) pairs = [] for i in range(0, len(d), 2): w, p = d[i], d[i+1] raw = binascii.unhexlify(w['hex']) idx = raw.find(b'\r\n\r\n') body = raw[idx+4:] mp = body.find(MAGIC) assert body.endswith(TRAILER), f"pair{i//2} trailer mismatch" tag2 = body[mp+10 : len(body)-len(TRAILER)] plains = [] for pl in p['plains']: if isinstance(pl, dict) and pl.get('hex'): plains.append({'addr': pl['addr'], 'buf': binascii.unhexlify(pl['hex'])}) pairs.append({'t': w['t'], 'tag2': tag2, 'plains': plains}) return pairs def find_json_end(buf): """locate the end of the 554B JSON string at buf head; return index after closing brace + boundaries of following non-zero region""" # JSON starts with '{' at offset 0. Find the matching close at known length 554 if buf[:1] != b'{': return None # standard JSON serialized 554B for this device json_bytes = buf[:554] assert json_bytes.startswith(b'{"appId":"5008"'), json_bytes[:40] return 554 def nonzero_ranges(buf, start): """return list of (start,end) runs of non-zero bytes in buf[start:]""" runs = [] in_run = False for i in range(start, len(buf)): if buf[i] != 0 and not in_run: s = i; in_run = True elif buf[i] == 0 and in_run: runs.append((s, i)); in_run = False if in_run: runs.append((s, len(buf))) return runs def main(): pairs = load_pairs() print(f"{len(pairs)} pairs loaded") for k, pr in enumerate(pairs): t2 = pr['tag2'] print(f"\n===== pair{k} t={pr['t']} tag2_len={len(t2)} (data={len(t2)}) =====") for pi, pl in enumerate(pr['plains']): buf = pl['buf'] je = find_json_end(buf) runs = nonzero_ranges(buf, 0) if je else [] # focus: runs after JSON end post = [r for r in runs if r[0] >= 554] print(f" plain{pi} addr={pl['addr']} buflen={len(buf)} json@0..{je if je else '?'}") # show a compact view: for each 256B block 0..8192 whether zero or nonzero blocks = [] for b in range(0, len(buf), 256): chunk = buf[b:b+256] nz = sum(1 for x in chunk if x != 0) blocks.append(f"{b//256}:{nz}") print(" nz/256B:", ' '.join(blocks)) # print runs summary first 6 for r in post[:6]: print(f" nonzero {r[0]}..{r[1]} (len {r[1]-r[0]}) head={buf[r[0]:r[0]+32].hex()}") if __name__ == '__main__': main()