# MV Adimeht FISH VM 结构笔记
本文档记录了 mv_adimeht analyzer 所使用的 FISH VM 的抽象模型。
不在此文档中写入每个 trace 的实际值,如 address、offset、opcode 值和 row ID。
这些值保存在 docs/mv_adimeht/trace_notes/ 下的每个 trace 笔记中。
范围
本笔记描述了当前 analyzer 代码和分析过程中推断出的 working model。
这不是 Themida FISH VM 的完整规范。如果在多个 sample 中反复确认导致 VM 结构模型本身发生改变,则更新本文档。
相关实现文件:
当前主分析 trace:
整体模型
FISH VM 的执行被视为在 host x86 trace 中进入 VM scope,操作 VBR-relative state block,fetch VM bytecode,决定 virtual handler,然后 dispatch 到实现单个 virtual instruction 或其一部分的 host instruction 的流程。
Analyzer 不会试图一次性从 raw host code 中直接恢复 VM semantics。
而是通过以下 VM-specific storage class 来追踪 data provenance。
Virtual Bus slot: VB_...
VM bytecode fetch: VMBLOB_...
virtual handler table entry: VCH_...
Virtual Micro OPcode slot: VMOP_...
virtual program counter slot: VPC_...
virtual handler table pointer slot: VHTP_...
术语
VBR: Virtual Base Register。被视为 VM 内部 state 和 Virtual Bus slot 访问基准的 base register/base value。
VB: Virtual Bus。VB_0x... label 表示通过 VBR + offset 访问的 Virtual Bus slot。
VMOP: Virtual Micro OPcode。VMOP_0x... label 表示在 dispatch cycle 中存储解码后的 micro opcode byte 的 Virtual Bus slot。
VM Scope
当前模型将 host EBP 的值视为 VM base register carrier。将整个 trace 中最常出现的 EBP 值检测为 VBR。
过去的 lightweight 模型只查看每行的 EBP 是否与检测到的 VBR 相同来判断是否在 VM 内部。当前的 LightFISH 仅将此值作为结构证据之一。收集 VBR-relative access、VHTP-range access、稳定的 EBP == VBR row 来寻找实际观察到 VM 结构的区间,并包含其前后的 context-save prologue 和 restore epilogue,从而创建 vm_intervals。
具体来说,entry 侧优先查找第一个结构证据之前的 pushfd/pushf stack write,exit 侧优先查找最后一个结构证据之后 popfd/popf restore 之后的 ret。这个 full interval 用于 [VM] comment 和 UI 显示,provenance 追踪使用从第一个结构证据开始的 vm_tracking_intervals。这样可以在将像 black 系列那样 EBP 暂时变为非 VBR 值的 VM 进入/退出区间标记为 VM scope 的同时,避免将 host register 保存 stub 过度 seed 到 VM data-flow 中。
VBR And VB Slots
VBR 是 Virtual Base Register。在当前 trace 模型中,它被追踪为 VM 内部 state 和 Virtual Bus 访问的基准 base value。effective address 为 VBR + offset 形式的 memory access 被建模为 Virtual Bus slot。
text
VBR + offset -> VB_0x{offset}一些 VB_... slot 在 detection 之后会获得更具体的 label。
VPC_0x...: virtual program counter slot
VHTP_0x...: virtual handler table pointer slot
VMOP_0x...: Virtual Micro OPcode slot
一般的 VB_... slot 可以是 Virtual Bus 上的 virtual register、temporary VM state、dispatch state、handler-local value 等。仅凭抽象 label 不能确定准确的 semantics,只具有作为基于 VBR 的 offset 访问的 Virtual Bus slot 的含义。
VPC
VPC 被视为被重复读取后像 VM bytecode fetch address 一样被反向引用的 VBR-relative slot。
当前的 detection heuristic:
收集 VBR-relative slot 的 read/write。
针对每个 slot,计算 read value 在短暂的 lookahead 内再次被用作 memory address 的比例。
选择 pointer-dereference behavior 最强的 slot。
执行过程中的 VPC write 被标注(annotate)为 virtual program counter 的移动。arithmetic write 尽可能解释为相对于前一个 VPC 值或当前 VPC base 的 stride。
VPC provenance 的基本策略是保留 VPC_... 本身。即使使用了像 ADD [VPC], offset 这样由 bytecode 派生的 stride,该 stride 也仅在该 fetch row 上被标注为 vpc stride,而不视为在更新后的 VPC 值中继续存活的 provenance。因为 Program counter 更接近于表示下一个 fetch 位置的 cursor,如果持续 carry 过去的 offset source,会使后续的 fetch 和 VB offset annotation 被过度污染。
VMBLOB
如果 Memory read 使用了 VPC-derived address,则将访问的 concrete address 标记为 VM bytecode fetch。
text
VPC-derived read -> VMBLOB_0x{fetch_addr}VMBLOB_... label 是 provenance marker。它是用于追踪哪个 bytecode byte 或 field 对后续的 VM state、handler index 计算、VPC 移动、VMOP assignment、branch decision 做出了贡献的名称。
Fetch row 可以带有反向 annotation。
fetch
vmop
vpc stride
vb offset
vhtp index
vtable offset
Fetch annotation 会一直保留,直到通过 VCH table entry load 确认 handler selection。VPC arithmetic update 可以在同一个 virtual instruction decode 流程中发生,因此不能仅仅因为 VPC 移动了就关闭 fetch row mapping。如果确认了 VCH load,就关闭相应的 fetch row mapping;如果之后再次 fetch 同一个 concrete bytecode address,则重新记录为新的 dynamic fetch row。
VHTP And VCH
VHTP 被视为与观察到的 VPC 值分离的 stable VBR-relative slot。在当前 sample 中,它被用作 handler-related indexing 的基准值,与其说是固定的 code-section 本身,不如说被解释为计算下一个 handler/dispatch 位置的 virtual PC 系列状态值。
如果在 VHTP-derived address 上发生 read,则建模为 virtual handler table access。
text
VHTP + index * entry_size -> VCH_0x{index}VCH_... label 追踪由 VM bytecode-derived value 选择的 handler。如果 JMP 或 CALL 使用了携带 VCH_... label 的值,analyzer 会将那一行标注(annotate)为 handler transfer。
特殊 label VTABLE 可以在 VHTP-derived index 被解释为 root table position 而不是 concrete handler entry 时使用。
VMOP
VMOP 是 Virtual Micro OPcode slot。被视为在 Dispatch cycle 中存储解码后的 micro opcode byte 的 VBR-relative slot。
当前的 detection heuristic:
如果 VM bytecode-derived value 被 write 到 VMOP,可以在对该值做出贡献的 fetch row 上标注(annotate) opcode byte。之后利用该 slot 的 read 和 comparison 来检测 dispatch decode point。
Dispatch And Decode
当前模型将许多 dispatch decision 视为 comparison 之后跟随 conditional branch 的形式。
Full mode 会更精确地追踪以下信息。Light mode 也可以标注(annotate) VMOP slot、VMOP write、简单的 VMOP-derived decode decision。
对当前 VMOP 做出贡献的 bytecode fetch
flag-setting instruction 执行时点存在的 symbolic variable
随后的 conditional branch 是否对应于 VMOP decode match
如果 Branch condition 意味着 equality match,analyzer 可以输出针对当前 VMOP value 的 decode annotation。
非 VMOP branch decision 如果 comparison 源自正在追踪的 VB_... 或 VMBLOB_... 值,也可以标注(annotate)。
Symbolic And Lightweight Modes
Full mode 即 TraceAdimehtFISH,通过 TraceContext 和 TraceTaint 使用 z3-backed symbolic expression。它可以表达 mixed provenance 并恢复更详细的关系,但成本更高。
Lightweight mode 即 TraceAdimehtLightFISH,将 provenance 作为 label set 来追踪。它是用于快速重复执行和 UI-friendly tracing 的 mode。主要结构概念与 full mode 相同,但不保留 full symbolic expression。
两种 mode 至少必须在以下大的结构上保持一致。
如果两种 mode 产生不同结果,首先将 sample-specific evidence 记录到 trace 笔记中。在多个 sample 中反复确认模式之前,不改变此抽象模型。
Analysis Flow
Analyzer 目前大致按以下顺序运行。
从 Host EBP 的 dominant value 中检测 VBR。
检测 VPC、VHTP、full mode 的 VMOP 等 special VBR-relative slot。VPC 默认使用 20-row lookahead 查找,像 black 那样延迟 fetch 很大的情况,使用 1000-row lookahead fallback。
利用 VBR/VHTP/VB 访问和 prologue/epilogue 检测 VM interval。
解析每个 host instruction 和 operand。
判断当前 row 是否在 VM scope 内部。
将 VBR-relative slot access 注册为 VB_... 或 special slot。
将 VPC-derived memory read 注册为 VMBLOB_... fetch。
在 black 系列中,如果像 push [VMBLOB] 这样 fetch payload 先被存储到 host stack,则注册为 STACK_0x... temporary carrier,并在之后的 stack read/pop 中再次传播到 register 或 VB slot。
追踪 Fetch 的 bytecode data 传播到 VM slot、VPC movement、VMOP、VHTP indexing、handler transfer 的流程。
在 Trace row 上标注(annotate) symbolic disassembly 和 internal VM event。
保存要显示在 UI table 上的 row snapshot。
每个 Trace 的实际值
以下值不保存在此抽象笔记中,而是保存在每个 trace 的文件中。
检测到的 VBR
VPC、VHTP、VMOP offset 和 concrete address
VHTP concrete value
确认了含义的主要 VB_... slot
重要的 VMBLOB_... fetch address 和 row ID
handler index 和观察到的 transfer row
decoded VMOP value 和 row ID
仅在特定 sample 中成立的 assumption
添加新的 sample note 时,使用 docs/mv_adimeht/trace_notes/TEMPLATE.md。