Files
MASForensic/DESIGN.md
BattleTag 81ade8f7ac feat(refit): complete S1-S6 — case abstraction, grounding, log-odds, plugins, coref, multi-source
Consolidates the long-running refit work (DESIGN.md as authoritative spec)
into a single baseline commit. Six stages landed together:

  S1  Case + EvidenceSource abstraction; tools parameterised by source_id
      (case.py, main.py multi-source bootstrap, .bin extension support)
  S2  Grounding gateway in add_phenomenon: verified_facts cite real
      ToolInvocation ids; substring / normalised match enforced; agent +
      task scope checked. Phenomenon.description split into verified_facts
      (grounded) + interpretation (free text). [invocation: inv-xxx]
      prefix on every wrapped tool result so the LLM can cite.
  S3  Confidence as additive log-odds: edge_type → log10(LR) calibration
      table; commutative updates; supported / refuted thresholds derived
      from log_odds; hypothesis × evidence matrix view.
  S4  iOS plugin: unzip_archive + parse_plist / sqlite_tables /
      sqlite_query / parse_ios_keychain / read_idevice_info;
      IOSArtifactAgent; SOURCE_TYPE_AGENTS routing.
  S5  Cross-source entity resolution: typed identifiers on Entity,
      observe_identity gateway, auto coref hypothesis with shared /
      conflicting strong/weak LR edges, reversible same_as edges,
      actor_clusters() view.
  S6  Android partition probe + AndroidArtifactAgent; MediaAgent with
      OCR fallback; orchestrator Phase 1 iterates every analysable
      source; platform-aware get_triage_agent_type; ReportAgent renders
      actor clusters + per-source breakdown.

142 unit tests / 1 skipped — full coverage of the new gateway, log-odds
math, coref hypothesis fall-out, and orchestrator multi-source dispatch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 02:12:10 -10:00

18 KiB
Raw Blame History

MASForensics 系统改造设计

目标:把当前「单台 Windows 磁盘取证」系统改造为能处理多设备、多行为人、 异构证据、需跨源关联的复杂取证系统。本文是唯一的权威设计文档 (已合并早先的 REFIT_PLAN.md / RESEARCH_DESIGN.md 两份草稿)。

触发本次改造的实际案件2025 美亚杯资格赛 Individual —— 5 份证据 1 USB E01、1 安卓整盘 blk0_sda.bin、3 份 iOS 提取、1 组交易截图), 跨 LEUNG YL / CHAN MH / FUNG CC 至少 3 人。


1. 设计原则(贯穿全文的不变式)

  1. LLM 提议,代码裁决。LLM 负责语言/分类/感知;它不持有案件状态、 不产出数值、不写入未经核验的事实。所有「真相」在符号层。
  2. 每条记录的事实都可从一次工具调用重新推导。结论可被独立复核。
  3. 推理核心与设备类型无关。设备特定逻辑全部位于「能力插件」中; 支持一种新设备 = 写插件,绝不改核心。
  4. 看似不可逆的操作(如实体归并)实为可逆、带证据的论断,可被推翻。

这四条不是口号——下文每个设计决策都对应其中一条。


2. 现状问题诊断

# 问题 位置 后果
P1 单镜像假设深植:工具是闭包绑死 image_path,图是单源,主程序只选一个镜像 tool_registry.py:148 register_all_toolsmain.py:91-153 无法摄取多份证据,无法跨设备关联
P2 反幻觉只写在提示词里 base_agent.py system prompt LLM 一旦不听话,错误事实进入案件记录且事后无法识别
P3 置信度公式无统计含义且有序依赖缺陷delta=weight*(1-conf)(正)/weight*conf(负),正负边混合时更新结果与边的到达顺序有关 evidence_graph.py:26-33 置信度不可校准、不可辩护
P4 工件分类是 Windows 专属:靠 hive 名 / .pf / mirc 关键词 tool_registry.py:80-107 _auto_categorize iOS/安卓工件全部落入 other
P5 案件信息硬编码 cfreds_hacking_case config.yaml:35-50 换案即需改代码
P6 镜像发现靠扩展名 glob.bin 不在列表 main.py:28 _IMAGE_GLOBS blk0_sda.bin 不被发现
P7 Phenomenon 无来源标注 evidence_graph.py:85 Phenomenon 不知道某发现出自哪台设备,跨源关联无锚点

改造同时解决「接入新证据」与「修掉 P1-P7 这些固有缺陷」。


3. 目标架构

case.yaml ──► Case ──► N × EvidenceSource
                         ├ id / type / owner / path
                         └ access_mode: image | tree
                                 │
                  ┌──────────────┴───────────────┐
            image-backed                     tree-backed
          (TSK, inode 寻址)              (路径寻址:已挂载/已解包)
                  │                              │
                  └────────────┬─────────────────┘
                               ▼
        SourceRegistry  ── source_id → SourceHandle解析 path/offset/mode
                               │
        ToolRegistry    ── 工具按 access_mode 注册,调用时绑定 source_id
                               │
        ┌──────────────────────┼───────────────────────┐
        ▼                      ▼                       ▼
  Knowledge-Source         Graph Write Gateway      ToolInvocationLog
  Agents (LLM)        ──►  (唯一写入口,强制      (每次工具调用留痕:
  只能经网关写图           前置条件 = grounding     args / 输出 / sha256
        │                      │
        └──────────────────────┴──► Grounded Evidence Graph (GEG)
                                     Phenomenon / Hypothesis / Entity
                                     置信度 = 对数几率累加

保留现有的五阶段流水线、断连恢复、运行归档、工具结果缓存、 AgentFactory 动态组合——这些设计是好的,不重写,只适配。


4. 核心设计

4.1 证据源抽象(解决 P1/P5/P6/P7地基

新增 case.py

  • EvidenceSource 数据类:idlabeltypeowner(关联人)、 pathaccess_modemeta(类型特定,如分区 offset / 解包后根目录)。
  • Case:持有 list[EvidenceSource] + 案件元数据,从 case.yaml 加载。
  • access_mode 是关键设计区分
    • image:块设备/磁盘镜像,用 TSK 按 inode 寻址USB E01、安卓 blk0_sda 各分区)。
    • tree已挂载文件系统或已解包目录按路径寻址iOS 提取解压后、归档展开后)。
    • 工具按 access_mode 分族注册(见 4.2)。一份证据可经「准备」从 image 变为 tree (如分区 mount、zip 解包)。

main.pyselect_image_interactive:91-153改为加载/构造 Case _IMAGE_GLOBS 改为类型探测(mmls 试探 + 文件头嗅探),不再靠扩展名。 config.yaml 删除 cfreds_hacking_case,案件信息移入 case.yaml

4.2 工具注册按源参数化(解决 P1

现状:register_all_tools(image_path, offset, ...) 把单一镜像闭包进每个工具 tool_registry.py:159+)。改造:

  • 工具执行器签名增加 source_id;执行时经 SourceRegistry 解析出真实 path/offset/mode。
  • TOOL_CATALOGaccess_mode 标注工具适用性agent 拿到的工具集由其 负责的源类型决定。
  • 「当前源」上下文:编排器为 agent 设置 current source类比现有 graph._current_agent工具默认作用于它——LLM 不必每次传 source_id (减少出错)。跨源工具(时间线合并、实体查询)显式跨源。
  • 缓存键 _cache_keytool_registry.py:41)纳入 source_id,防止跨源串味。

4.3 图写入网关(解决 P2落实原则 1

现状agent 通过 add_phenomenon 等工具直接写图,约束只在 prompt。改造

  • 所有图变更(add_phenomenon / add_hypothesis / link / observe_identity …) 收敛到一个写入网关。网关在代码层强制前置条件。
  • 现有 prompt 里的「反幻觉规则」下沉为网关的硬校验。LLM agent 的四阶段工作流 INVESTIGATE→RECORD→LINK→ANSWER不变——变的是 RECORD 这一步底下的网关变严。
  • base_agent.pymandatory_record_tools 机制保留(它保证 agent 真的记录了东西)。

4.4 证据落地约束 Grounding解决 P2落实原则 2

这是系统可靠性的核心机制。

ToolInvocationLog:每次工具调用留痕一条记录 {invocation_id, source_id, tool, args, output, output_sha256, agent, ts}。 现有结果缓存(tool_registry.py:29)已存确定性输出,扩展为完整留痕即可。

Phenomenon 一分为二——把「事实」和「解读」分开:

  • verified_facts: list[{type, value, invocation_id}] type ∈ {path, timestamp, inode, hash, identifier, count, ...}
  • interpretation: 自由文本agent 的分析叙述。

add_phenomenon 网关前置条件

  1. 每个 fact 必须引用一次本 agent 本任务内真实发生过的 invocation_id
  2. 代码校验 fact.value 命中该次调用的输出:
    • 文本输出 → 逐字 substring 匹配;
    • 结构化/二进制工具输出 → 与解析后的字段匹配。
  3. 任一 fact 不通过 → 整条拒绝写入,返回失败的 factagent 须修正重试。
  4. 通过 → 写入;verified_facts 每条带 invocation_id(可重跑复核), interpretation 标记为「未核验分析」。

效果:在系统里「记录一条工具输出未支撑的路径/时间戳/哈希/标识符」 结构性地不可能。LLM 仍可能写错 interpretation,但报告会把 verified facts带重跑指令的引证与 interpretation明确标注的分析 分开渲染,人类调查员一眼可辨。这是诚实划定边界的可靠性保证。

现有 _make_auto_recordtool_registry.py:126)把工具输出直接转 phenomenon—— 那是「平凡落地」的特例(描述即输出),新设计是它的一般化与形式化。

4.5 假设置信度:似然比 / 对数几率(解决 P3

evidence_graph.py:26_DEFAULT_EDGE_WEIGHTS 从「拍脑袋的 delta」 换成基于**似然比LR**的对数几率累加:

  • 每条 Phenomenon → Hypothesis 边代表一个似然比。LLM 仍只做离散分类 (这条证据对这条假设是 direct_evidence / supports / weakens / contradicts …), 数值 log₁₀(LR) 由标定表查得——LLM 绝不吐数字延续现有「LLM 选类型、 代码算数值」哲学并赋予统计基础)。

  • 置信度更新:

    L_post = L_prior + Σ log₁₀(LR_i)        # 对数几率,可交换 → 无序依赖
    confidence = 1 / (1 + 10^(L_post))
    
  • 边类型 → log₁₀(LR) 标定表(初值,后续可由标注案例校准):

    边类型 log₁₀LR
    direct_evidence +2.0
    supports / consequence_observed +1.0
    prerequisite_met +0.5
    weakens 0.5
    contradicts 2.0
  • 阈值不变≥0.8 supported / ≤0.2 refuted只是改由 L_post 推出。

  • prior_prob 成为可配置量(默认 0.5 → L_prior=0)。

  • 简化假设说明:多条边按独立处理(朴素贝叶斯)。同类证据反复出现并非 完全独立——加一个旋钮:同 (hypothesis, edge_type) 的边数封顶或衰减,避免 「同一发现被多 agent 重复入图」虚高置信度(现有 Jaccard 去重已部分缓解)。

附带产出一个 假设 × 证据矩阵视图,供报告与线索选择使用。

4.6 跨源实体解析(解决「复杂场景」的关联难题,落实原则 4

复杂取证的核心难题iPhone keychain 里的 Apple ID、安卓短信库里的号码、 USB 文件作者、交易截图里的钱包地址——哪些指向同一行为人?

关键设计:「身份共指」本身就是一条假设——于是实体解析不是独立子系统, 而是 4.5 假设机制的复用:

  • agent 观察到标识符即经网关 observe_identity,记一条类型化的标识符 强标识符IMEI / 钱包地址 / email / 电话号;弱标识符:昵称 / 显示名), 挂到暂定 Entity
  • 「Entity A ≡ Entity B」登记为一条 Hypothesis;共享强标识符 = 强 +LR 边, 共享弱标识符 = 弱 +LR 边,冲突的强标识符 = 强 LR 边——用 4.5 同一套计算打分。
  • 不做破坏性归并:跨阈值时在两个 Entity 间加一条 same_as 边(由该 coref 假设背书)。查询时把 same_as 连通分量视作同一行为人。完全可逆、可审计、 可被后续 contradicts 证据推翻(落实原则 4
  • Blocking:只在「至少共享一个标识符或名称高相似」的实体对间建 coref 假设, 避免 O(n²)。

跨设备时间线、「谁在何时做了什么」由 same_as 连通后的实体图自然涌现。

4.7 能力插件层(接入 5 类证据)

每类证据 = 一个 (摄取 handler, 工具集, 知识源 agent) 三元组。推理核心不动。

插件 摄取 新工具 知识源 agent
iOS 提取 unzip 解包为 tree parse_plist(含二进制 plist)、sqlite_tables/sqlite_query(sms.db、WhatsApp ChatStorage.sqlite、通讯录)、parse_ios_keychainread_idevice_info iOSArtifactAgent
安卓整盘 mmls 分区→各分区 image 源;可 mount 为 tree 复用 TSKext4/F2FS 读取;fsstat 探明加密 复用 filesystem + AndroidArtifactAgent
磁盘镜像(E01) 已支持TSK 含 ewf 现有 TSK 工具链 现有 filesystem/registry
归档 unzip_archive 通用解包 —— ——
媒体/截图 —— ocr_imagetesseract注意 DeepSeek 无视觉能力,必须走 OCR MediaAgent

安卓风险blk0_sdauserdata 分区大概率 FBE 加密。先 fsstat 各分区 探明未加密→TSK 直接用;加密且无密钥→只能分析 EFS/PARAM/system 等非加密区。

tool_registry.py:80_auto_categorize 改为可扩展:分类由源插件提供自己的 工件分类表,而非全局 Windows 关键词表(解决 P4

4.8 Agent 体系重组

现有 7 个 agent 按 Windows 工件命名registry、communication=邮件/IRC、 network=浏览器/PCAP。改为按调查职能组织,并增加平台特定 agent

  • agent_factory.py_AGENT_CLASSES:34-40扩充新增 ios_artifactandroid_artifactfinancial(钱包/交易)、media
  • communication 泛化:邮件 + IM + 短信,跨平台。
  • 新增 源类型 → 适任 agent 映射,供 Phase 1 逐源派 triage agent。
  • create_specialized_agent:69的动态组合机制保留——它本就是应对能力缺口的 正确手段,只是工具目录变大后选择空间更丰富。

4.9 编排器多源流水线

阶段 改造
Phase 1 「单镜像初勘」→ 逐源并行 triage,每源派类型适配的 agent
Phase 2 假设跨源生成;身份共指假设在此首次登记
Phase 3 leads 派发到源感知 agent假设×证据矩阵实时更新
Phase 4 跨源时间线合并,按源做时区归一iOS UTC vs 安卓本地时间)
Phase 5 一案一份综合报告:含假设结论、实体关联图、每条结论的 provenance 引证

断连恢复、运行归档逻辑保留,graph_state.json 增量纳入新字段。


5. 数据模型变更汇总

节点/结构 变更
EvidenceSource 新增一等节点(src-*
ToolInvocation 新增留痕记录(inv-*),随 graph 持久化
Phenomenon + source_iddescription 拆为 verified_facts[] + interpretation;澄清/移除语义含混的 confidence(默认 1.0),观测的可靠性由 grounding 表达
Hypothesis + prior_problog_odds(累加量);confidence 改为派生值
Entity + 类型化标识符集合;通过 same_as 边跨源连通
Phenomenon→Hypothesis 边 携带 edge_type,映射到 log₁₀(LR)(替换 _DEFAULT_EDGE_WEIGHTS
Entity→Entity 边 新增 same_as(由 coref 假设背书,可逆)

evidence_graph.pyVALID_EDGE_TYPES、序列化/反序列化、Jaccard 去重相应适配。


6. 组件改动清单

文件 改动
case.py 新建Case / EvidenceSource / SourceRegistry
main.py 选源逻辑改为加载 Case;类型探测替代扩展名 glob
tool_registry.py 工具按 source_id 参数化;缓存键含 source_auto_categorize 改可扩展;ToolInvocationLog
evidence_graph.py 数据模型变更(第 5 节LR/对数几率置信度;写入网关 + grounding 校验
base_agent.py RECORD 走网关;add_phenomenon 改为 verified_facts+interpretation 接口
agent_factory.py _AGENT_CLASSES 扩充源类型→agent 映射
orchestrator.py Phase 1 逐源Phase 4 跨源时区归一Phase 5 综合报告
agents/ 新增 ios_artifact.py / android_artifact.py / financial.py / media.pycommunication.py 泛化
tools/ 新增 mobile_ios.pyplist/sqlite/keychainmedia.pyOCRarchive.py(解包)
config.yaml / case.yaml 删除 cfreds_hacking_case;新建 case.yaml 证据清单

7. 构建顺序(按依赖排序)

阶段 内容 依赖 价值
S1 4.1 证据源抽象 + 4.2 工具参数化 + 修 P6 —— 地基;先只在 USB E01 上跑通验证不破坏现有逻辑
S2 4.3 写入网关 + 4.4 grounding + ToolInvocationLog S1 可靠性核心;可量化「零幻觉录入」
S3 4.5 LR/对数几率置信度 独立(可与 S2 并行) 修 P3置信度可辩护
S4 4.7 iOS 插件 + 4.8 agent 重组 S1 覆盖率 1/5 → 4/5
S5 4.6 跨源实体解析 S1+S3 跨设备关联,复杂场景能力成型
S6 4.7 安卓 + 媒体插件 + 4.9 编排器适配 S1+S4 全 5 份证据接入

S1+S2+S3 是「把系统改对」S4-S6 是「把能力铺全」。建议严格按序—— S1 不稳,后面全是空中楼阁。


8. 设计取舍与未决问题

  1. grounding 对自由文本的边界:只硬核验 verified_facts 里的结构化原子, interpretation 不做逐字核验(诚实划界)。可加一个二级 lint扫描 interpretation 中形似路径/时间戳/哈希但未被任何引用调用覆盖的串并告警。
  2. LR 标定表初值人定:先用第 4.5 节的初值跑通;「从标注案例学习 LR」是后续工作。
  3. 安卓 userdata 加密:能否取得解密密钥决定 4.7 安卓插件的证据深度——需尽早探明。
  4. 实体解析的破坏性 vs 可逆:本设计选可逆的 same_as而非破坏性归并—— 牺牲一点查询效率换取完全可审计可回滚,符合原则 4。
  5. 报告粒度:定为「一案一份综合报告」,内嵌每证据小节 + 跨源关联, 而非每证据独立成篇。