强大的 Unidbg Trace 可视化分析工具
- 反向追踪:追踪寄存器值的来源
- 前向污点分析:追踪数据的传播路径
- 增强污点分析 🆕:字节级内存追踪 + 污点标签系统 + 汇合点检测
- 候选选择:精确定位多次执行中的目标事件
- 实时联动:寄存器面板与追踪结果同步更新
- 增强代码面板 🆕:行号显示 + 内联寄存器值 + 操作类型图标(📥加载 📤存储 ⚡逻辑 ➕算术等)
- 智能寄存器分析 🆕:自动识别用途(📍指针 📏索引 🔑密钥)和趋势(↗递增 →常量 ↕变化)
- 三联动视图:函数列表 / 代码窗口 / 寄存器窗口
- 内存写入对比:字节级差异高亮显示
- 智能跳转:代码、函数、地址一键定位
- 语法高亮:助记符、寄存器、立即数彩色标注
- 后台处理:解析、追踪等耗时操作不阻塞界面
- 快捷操作:右键菜单、双击跳转、快捷键支持
- 寄存器复原:点击代码行自动复原该时刻的寄存器状态
- 字体调节:Ctrl+= / Ctrl+- 调整代码字体大小
# 克隆仓库
git clone https://github.com/yourusername/UnidbgTraceViewer.git
cd UnidbgTraceViewer
# 安装依赖
pip install -r requirements.txt
# 或使用 pip 安装
pip install -e .# 直接启动(会弹出文件选择对话框)
python3 -m trace_viewer.app
# 或指定trace文件
python3 -m trace_viewer.app /path/to/trace.txt
# 安装后可使用命令
trace-viewer
trace-viewer /path/to/trace.txt场景:追踪某个寄存器值的来源
步骤:
-
在代码区找到目标指令
例如:0x12025890: strb r1, [r0] -
右键点击该行,选择"反向追踪寄存器值来源..."
-
在弹出的对话框中输入:
- 寄存器名:
r1 - 执行前的值:
0x8(十六进制)
- 寄存器名:
-
查看候选窗口:
行号 时间戳 PC 指令 寄存器读取 37556 [242] 0x12025890 strb r1, [r0] r0=0xe4fff2b1 r1=0x8 49298 [433] 0x12025890 strb r1, [r0] r0=0xe4fff1a8 r1=0x8 1162698 [628] 0x12025890 strb r1, [r0] r0=0x122802a6 r1=0x8 1216188 [297] 0x12025890 strb r1, [r0] r0=0x122802a1 r1=0x8 -
选择目标候选:
- 点击不同候选时,寄存器面板会实时更新
- 根据
r0等其他寄存器的值确认正确的执行 - 双击或点击"确定"开始追踪
-
查看追踪结果:
- 值流面板显示完整的追踪链路
- 双击任意行跳转到该指令
场景:追踪数据如何传播
步骤:
-
在值流面板输入源污点:
寄存器:r0,r1 或内存:0x8000 -
点击"污点前向分析"
-
查看分析结果:
- 传播次数统计
- 目标命中情况
- 详细的传播路径
-
双击结果跳转到具体指令
为什么需要候选选择?
在循环或重复执行的代码中,同一条指令可能执行多次,但每次的寄存器值不同:
# 同一个 PC,但执行了 4 次,r1 都是 0x8,但 r0 不同
行 37556: r0=0xe4fff2b1 r1=0x8 ← 可能是你要找的
行 49298: r0=0xe4fff1a8 r1=0x8
行 1162698: r0=0x122802a6 r1=0x8
行 1216188: r0=0x122802a1 r1=0x8
如何快速识别?
- ✅ 看行号:唯一标识
- ✅ 看时间戳:判断执行顺序
- ✅ 看其他寄存器:通过
r0等寄存器的值区分 - ✅ 实时联动:点击候选时,寄存器面板会显示该时刻的所有寄存器
from trace_viewer.trace_parser import TraceParser
# 解析 trace 文件
parser = TraceParser()
parser.parse_file("trace.txt")
# 访问事件
print(f"总事件数: {len(parser.events)}")
ev = parser.events[0]
print(f"PC: 0x{ev.pc:08x}, 指令: {ev.asm}")
print(f"读取寄存器: {ev.reads}")
print(f"写入寄存器: {ev.writes}")# 查找特定寄存器值的所有出现
candidates = parser.find_value_candidates('r1', 0x8)
print(f"找到 {len(candidates)} 个 r1=0x8 的事件")
# 反向追踪
hits = parser.taint_backward(
start_idx=37556,
target_reg='r1',
same_call_only=False
)
print(f"反向追踪找到 {len(hits)} 个相关事件")# 基础污点分析
hits = parser.taint_forward(
start_idx=0,
source_regs=['r0', 'r1'],
enable_memory_taint=True
)
# 高级污点分析(带统计)
result = parser.advanced_taint_analysis(
start_idx=0,
source_regs=['r0'],
target_regs=['r5'],
enable_memory_taint=True
)
print(f"传播次数: {result['statistics']['register_propagations']}")
print(f"到达目标: {result['target_reached']}")- 在代码区选择两行
- 右键选择"对比内存写入"
- 查看字节级差异高亮
- 在代码区选择多行
- 右键选择"导出所选代码为伪C"
- 获得可复现的 C 代码片段
- 点击任意代码行
- 寄存器面板自动显示该时刻的寄存器状态
- 使用 LRU 缓存优化性能
- Python ≥ 3.8
- PyQt6 ≥ 6.4.0
- 支持平台:Windows / macOS / Linux
- ✅ 支持超大 trace 文件(百万级事件)
- ✅ 后台线程处理,界面始终流畅
- ✅ 位图优化,内存占用减少 96%
- ✅ LRU 缓存,寄存器复原快速响应
A: 因为代码面板只显示汇编指令,看不到每次执行的寄存器值。手动输入可以确保追踪的准确性。
A: 因为同一条指令可能在循环中执行多次。通过行号、时间戳和其他寄存器值来区分。
A: 点击不同候选时,主窗口的寄存器面板会实时更新,帮助你确认是否是目标执行。
A:
- 反向追踪:从某个值开始,往前找它是怎么来的
- 前向分析:从某个值开始,往后看它传播到哪里去了
- ⬆️ 升级到 PyQt6(更好的 emoji 支持)
- ✨ 增强代码面板:行号、内联寄存器值、操作类型图标、鼠标悬停提示
- ✨ 智能寄存器分析:自动识别用途(指针/索引/密钥)和趋势(递增/常量/变化)
- 🎨 代码优化:import 统一放到文件顶部
- 📖 文档整合:从8个md整合到3个核心文档
- ✨ 右键追踪改为输入对话框,支持手动指定寄存器和值
- ✨ 候选窗口显示所有寄存器值,支持实时联动
- 🐛 修复值匹配逻辑,精确查找 PC+寄存器+值
- 🎨 移除冗余的"调用#"列,界面更简洁
- ✨ 新增扩展 ARM32 指令支持
- 🚀 位图优化,内存占用减少 96%
- ✅ 指令覆盖率达到 98%+
欢迎提交 Issue 和 Pull Request!
MIT License
- Unidbg - Android/iOS 模拟器框架
Made with ❤️ for reverse engineering
