Skip to content

Note 98 · panthor M2l:双变体 diff 密码攻击——FS 代码与常量指纹 ​

日期:2026-09-06 · 战役七第十七篇 · 上一节:note 97(常量不在内存)

0. 摘要 ​

绕开反汇编器的已知明文攻击:glestriangle 红/蓝/绿/白四变体各跑一遍, GPUPOOL 仪器整窗 dump 批池(SPD_2±0x8000 映射页 hex),diff 出 常量编码的完整指纹。核心发现三条:

  1. FS 代码就在批池窗内(va 0x7fffffffc000+0x80 起 32B),无需 再考古 SRT 载体链——扫描即得。
  2. 常量差分只在两条指令字(+0x80 的第 3/4 槽),且疑似 8 位 half 立即数(0xC0≈1.0? 0xDB? 0x00=0.0?)+ FAU 小常量索引混合 编码(0x13c/0x03c 差分位)。
  3. 编译器按颜色换指令序列:green 变体的第 3 槽从 6910 形态换成 6891 形态——常量提取器必须识别多条序列,"固定位域提取"不成立。

1. 四变体明文表(本战役最珍贵的密码学资产) ​

输出
       指令槽 A(+0x80 w3)      指令槽 B(+0x80 w4)
red    6910c000_003c00c0       4891c100_000000db     (1,0,0,1)
blue   6910c13c_003c00c0       4891c000_000000c0     (0,0,1,1)
green  6891c000_000000db       4891c100_000000db     (0,1,0,1)  ← 序列不同!
white  6910c03c_003c00c0       4891c100_00000000     (1,1,1,1)

初步破译线索(待 ISA 正解):

  • A 槽 low 三变体恒 003c00c0——0x3c00=fp16 1.0(字节序存疑),0xC0 疑似 8 位 half 立即数编码的 1.0;
  • A 槽 high 低 12 位随 R/B 变(red=000/blue=13c/white=03c);
  • B 槽 low:{red,green}=0xdb、blue=0xc0、white=0x00——red 与 green 同码 ⇒ B 槽不区分 R/G(区分信息在换了序列的 A 槽);
  • B 槽 high 的 bit8(0x100):blue 独有清零。

2. 方法论沉淀:变体 diff 法 ​

当目标值烤进代码而代码可重复生成时(本例:改 FS 色 → 重编译 → 同布局批池),"跑 N 个已知明文变体 + 内存 diff"能把编码位段全暴露, 代价只是 N 次测试运行。比反汇编器搭建便宜一个数量级。要点:

  • dump 用数据行比对(剥 PA 前缀——物理地址每次跑都变);
  • 同 VA 页按出现序分组(第 i 组 = 第 i 次运行的快照);
  • 注意编译器可能换序列(本例 green),diff 前先对齐指令形态。

3. M2l 剩余施工(下一会话,弹药全在) ​

  1. 8 位 half 立即数表 + 指令位域正解:/tmp/mesa valhall/ISA.xml (重启会清,重克隆命令 note 97 §3)——目标只解 2 条指令 (6910/6891/4891 形态)的源编码位段。
  2. 提取器:RUN_IDVS 时扫批池找 FS 代码特征(四形态指纹)→ 解 RGBA → pending_fs_color。
  3. 执行:RUN_FRAGMENT 时以 FS 语义铺 FBD(顺序:try_blit → FS 色 → clear)。
  4. 验收:红/蓝/绿/白四变体全 PASS(色值来自 guest 指令流 = note 76 证据门的"真 shader 语义")。

4. 资产 ​

  • GPUPOOL=1:批池整窗 hex dump 仪器(POOLPAGE 分页)
  • /tmp/gt_{blue,green,white}_src.py 变体生成脚本(源头 sim/glestriangle.py 单行替换)
  • 四变体指纹表(§1,防重启丢失已录入本文)

5. 八变体主表(同日补:halfred/cyan/magenta/black 四变体追加) ​

输出
variant          A 槽                  B 槽
red(1,0,0)       6910c000_003c00c0     4891c100_000000db
blue(0,0,1)      6910c13c_003c00c0     4891c000_000000c0
green(0,1,0)     6891c000_000000db     4891c100_000000db
white(1,1,1)     6910c03c_003c00c0     4891c100_00000000
halfred(.5,0,0)  6910c000_003800c0     4891c100_000000db
cyan(0,1,1)      6910c13c_003c00c0     4891c000_000000db
magenta(1,0,1)   6910c000_003c00c0     4910c13c_003c00c0
black(0,0,0)     6891c000_000000c0     4891c100_000000db

追加发现:

  1. BE-half 假设成立一半:halfred 的 A 槽 low 高半字 0x003c→0x0038 恰是 fp16 1.0(0x3C00)→0.5(0x3800) 的字节交换——A 槽 low bits[31:16] 承载一个 half 通道值,但通道→槽位映射不固定(编译器换分配: blue 的 A 槽 half=1.0 装的是 B 通道)。
  2. 指令模板统一:magenta 的 B 槽(4910c13c_003c00c0)与 blue 的 A 槽(6910c13c_003c00c0)同码仅高字节异——高字节=主操作码+目标 寄存器,low=源编码(half+LUT 修饰)。0x13c/0x03c/0x000 差分位与 ISA.xml 32 条 LUT 表(idx16=1.0、idx21=0.0、idx27=half 1.0…) 对上了方向但精确位段未定。
  3. B 槽 low 的 8 位(0xdb/0xc0/0x00)疑为 8 位 half 立即数表索引, 三态与通道组合的关系未闭合。
  4. PAN_MESA_DEBUG=shaders 也是空(Ubuntu mesa 连编译器 dump 都 裁了)——guest 侧拿汇编文本的路彻底断,精确解码只能 host 侧 disassembler 编译或 ISA.xml 编码考古。

6. 下一轮弹药清单 ​

  • 八变体表(§5)+ LUT 表(ISA.xml 头 32 条)= 解码约束集
  • /tmp/mesa 重克隆(note 97 §3)后看 bifrost/disassembler 的 decode 表(.py 生成器 gen_pack/valhall 编码常量在 compiler/bifrost/valhall/*.py)

由 rk-forge pdf/2026-06-23-1120-192-gd5045ae 构建