- 开发工具
- 逆向工程
- 嵌入式
【免费下载链接】SavvyCAN
QT based cross platform canbus tool
SavvyCAN 的 File Comparison(文件对比)窗口是一个面向逆向工程场景的 CAN 日志差分工具:它把一批"参考文件"(reference files)的所有报文汇入同一个"帧桶",再与一个"关注文件"(file of interest)逐 ID 对比,找出只在某一边出现的 ID、只在某一边置位的 bit,以及只在某一边出现的数据值与 DBC 信号取值。本文基于仓库中的官方文档 help/filecomparison.md 与源码 re/filecomparatorwindow.cpp 编写,读完你将掌握该窗口的完整操作流程、差异列表三层结构的读法,以及如何用它从海量 CAN 流量中定位顽固的未知信号。
文件对比窗口的用途:用"背景噪音"反衬出目标信号
文件对比窗口的核心思想是把日志分成两侧做差分:
- Side 1(关注文件,File of interest):只有一个文件,是你要重点研究的那个捕获。
- Side 2(参考文件,Reference frames):可以加载任意多个文件,程序不会逐个文件分别列出,而是把所有这些文件里的报文全部倾倒进同一个"帧桶"(bucket)里,合成一个统一的参考集合。
因此你可以一次性加载一批文件,然后与唯一的那一个"关注文件"做对比。对比要回答的问题非常具体:
- 有没有只在某一侧出现的 ID?
- 对于两侧都出现的 ID,有没有只在某一侧被置位的 bit?
- 对于两侧都出现的 ID,有没有只在某一侧出现过的数据值或信号值?
这套机制最经典的实战用法,是制造"背景噪音"来反衬出你苦苦寻找的那个信号。文档给出的示例是寻找换挡信号(gear shift signal):
- 长时间怠速行驶、让车辆长时间空转,捕获一大批"背景"流量——但绝不做你要找的那个动作(不换挡)。
- 再进行第二次捕获,期间做几次你要找的动作(换挡几次)。
- 把第二次捕获作为"关注文件",把第一次的大批量背景捕获作为"参考文件",运行对比。
- 两边的差异里,就应该藏着那个你始终找不到的换挡信号。
这样得到的候选列表远比"大海捞针"式地逐帧翻日志要窄得多。凡是你能"先抓一段不含目标行为的基线、再抓一段含目标行为的捕获"的场景,都可以套用这个方法——例如定位车门开启、踩刹车、切灯等任何只在特定时刻出现的信号。
界面布局与两侧文件的操作
窗口由 ui/filecomparatorwindow.ui 定义,整体分为上下两部分。
上方:两侧文件选择区
上方是两个并排的区域,中间用一条竖直分隔线隔开:
- Side 1:显示 "Single file to compare to side 2:",下方有一个显示已加载关注文件名的标签(
lblFirstFile)和Load New File按钮(btnInterestedFile)。点击后通过FrameFileIO::loadFrameFile()弹出文件选择对话框,选中的文件名会显示在标签上(见 re/filecomparatorwindow.cpp)。 - Side 2:显示 "One or more files to compare with the single file on side 1:",包含Load A File按钮(
btnLoadRefFile)、Clear Frames按钮(btnClear)和显示 "Loaded frames: N" 的帧计数标签(lblRefFrames)。每点一次Load A File就向参考帧桶追加一个文件,帧计数随之累加;Clear Frames会把参考帧桶清空、同时清空结果树(见 re/filecomparatorwindow.cpp)。
文件加载复用 SavvyCAN 全局的FrameFileIO框架,它具备自动探测格式的能力:程序会通过一系列isXxxFile()预扫描函数判断文件类型,再调用对应的loadXxxFile()加载,支持的格式包括 CRTD、原生/通用 CSV、Log、Microchip、Trace、IXXAT、CANdo、Vehicle Spy、canDump、Lawicel、PCAN、Kvaser、CANalyzer ASC/BLF、CARBUS Analyzer、CANHacker、Cabana、CANopen、Tesla AP、CLX000、CANserver、Wireshark 等(完整清单见 framefileio.h)。也就是说,你手头的各种格式 CAN 日志基本都能直接拖进来对比,无需预先转换。
下方:结果树与导出按钮
下方是一棵结果树(treeDetails,单列显示)、一个Show only data unique to Side 1复选框(ckUniqueToInterested)和一个Save Details to File按钮(btnSaveDetails)。
- 勾选 "Show only data unique to Side 1" 后,结果树只显示关注文件独有的信息:仅关注文件出现的 ID、仅在关注文件侧置位的 bit、仅在关注文件侧出现的值。参考文件独有的一切都会被隐藏。从源码看,
uniqueInterested为真时会跳过 "IDs found only in Side 2" 顶层节点、参考侧 bit 子树和参考侧值子树(见 re/filecomparatorwindow.cpp 与 #L380-L436),适合你只想快速确认"目标行为带来了什么新东西"时使用。 - Save Details to File会弹出保存对话框,把结果树按层级缩进导出为 UTF-8 文本文件;若文件名不带扩展名会自动补
.txt(见 re/filecomparatorwindow.cpp)。
另外两点体验细节:窗口支持 F1 键随时呼出本文档对应的帮助页(见 re/filecomparatorwindow.cpp);在"偏好设置"中勾选恢复窗口位置后,窗口尺寸与位置会按FileComparator/WindowSize、FileComparator/WindowPos键保存并在下次打开时恢复(见 re/filecomparatorwindow.cpp)。
差异列表的三层树结构
计算完成后,结果树会呈现三个顶层节点(当勾选 "Show only data unique to Side 1" 时第二个节点被隐藏),对应三种差异类别。
1. IDs found only in (仅在关注文件中出现的 ID)
子节点是每一个只在关注文件里出现、而在所有参考文件中从未出现的 ID。这是"目标行为"最直接的候选区——例如换挡测试捕获里出现的某个 ID,怠速背景流量里根本没有它。
2. IDs found only in reference frames(仅在参考帧中出现的 ID)
按文档的提示,"理论上这个列表应该相当小"——列出的是那些在关注文件里从未见过的 ID。如果这个列表异常庞大,通常意味着两次捕获的工况差异过大(比如参考文件里包含了另一个总线或另一套功能模块的流量),需要审视捕获方案。由于它的目的是提醒你"参考侧还有这些没对上号的 ID",在只看关注文件独有内容时会被隐藏。
3. IDs found only on both sides(两侧都出现的 ID)
这是最有信息量的区域:两侧共同出现的每个 ID 是一个子节点(节点文本为十六进制 ID,若当前加载了 DBC 且能匹配到消息,还会附上(消息名)),每个 ID 节点下再按三类差异展开:
- Bits set only in / Bits set only in Side 2:按 bit 粒度列出只在某一侧被置位过的位。源码中对每个帧把 8 个数据字节按
bit = 字节值 << (8 * 字节下标)的方式逐字节累积到一个 64 位bitmap上(见 re/filecomparatorwindow.cpp),最终得到"该 ID 在两侧各自所有帧中出现过的所有 bit 的并集",然后逐位做(interestedBits & 1) ^ (referenceBits & 1)式异或,把只在单侧置位的 bit 找出来(见 #L388-L408)。bit 节点的文本形如7 (0:7),即"第 7 位(字节 0 的第 7 位)",方便你直接换算到数据字节的哪个位。注意:这是"曾出现过的位的并集"比较,而非逐帧位翻转比较,所以它回答的是"这个 bit 在两侧是否都出现过",而不是"两侧的 bit 状态是否不同"。 - Byte N → Values found only in / Values found only in Side 2:按字节(0~7)分组,列出该字节上只在某一侧出现过的取值。源码为每个 ID 维护
values[8][256]统计矩阵,values[字节][取值]记录该字节取到某个 0x00~0xFF 值的次数(见 re/filecomparatorwindow.cpp);比较时只要一侧出现次数 >0 而另一侧为 0,就判定为该侧独有值(见 #L424-L437)。如果一个数据字节在关注文件里出现过参考文件没有的值,它就很可能是承载目标信号的字节,而这个新值就是候选信号值。 - Signal <信号名> → Values found only in / Values found only in Side 2:如果两侧 ID 对应的 DBC 消息里存在信号,并且信号能解析出文本值,程序会把每个信号出现过的文本值收集到
signalInstances哈希表中(见 re/filecomparatorwindow.cpp),再对比两侧,列出只在某一侧出现过的信号值。这是把差分能力从"原始字节"提升到"语义信号"的关键一层——你不仅能知道哪个字节变了,还能直接看到某个 DBC 信号在目标行为发生时出现了哪些新取值,这些取值很可能就是你要找的未知信号。
底层原理:两遍扫描 + 三类统计量
从源码可以清晰看到对比算法的整体流程(re/filecomparatorwindow.cpp):
- 数据准备阶段:分别遍历关注帧(
interestedFrames)和参考帧(referenceFrames)两个QVector<CANFrame>,对每个 ID 构建一个FrameData(见 re/filecomparatorwindow.h):bitmap:64 位位图,标记该 ID 所有帧中哪些 bit 曾被置位(最多覆盖 8 字节);values[8][256]:每个字节上各取值的出现次数;signalInstances:每个 DBC 信号出现过的文本值集合。 DBC 消息查找通过DBCHandler::getReference()获取的全局 DBC 处理器完成,信号解析复用DBC_SIGNAL::processAsText(),因此只有当前已加载并匹配的 DBC 才会产生信号层对比。
- 逐 ID 归类:遍历关注文件的所有 ID,凡在参考集合中不存在的归入顶层节点 1;存在的则进入节点 3,并用上面的三类统计量生成 bit、字节取值、信号取值三个维度的差异子节点。
- 反向补全:遍历参考文件的所有 ID,把关注文件中没出现过的归入顶层节点 2。
- 交互反馈:由于日志可能很大,计算期间会显示一个无进度条的模态"Calculating differences"对话框,并在处理中周期性调用
qApp->processEvents()保持界面响应(见 re/filecomparatorwindow.cpp)。
结果树默认不自动展开;若在偏好设置中勾选了 "Auto-expand"(对应设置键InfoCompare/AutoExpand,见 mainsettingsdialog.cpp),计算完成后会自动expandAll()展开全部节点(见 re/filecomparatorwindow.cpp)。
实战操作流程:完整步骤
结合文档与源码,一次完整的对比操作如下:
- 从主窗口菜单栏RE Tools → File Comparison打开文件对比窗口(对应动作
actionFile_Comparison,见 ui/mainwindow.ui 与 mainwindow.cpp)。 - 点击Load New File,选择包含目标行为的"关注文件"(如换挡测试捕获)。
- 点击Load A File一次或多次,把不含目标行为的"背景"日志(如怠速捕获)全部加入参考帧桶;窗口会实时显示 "Loaded frames: N"。每加载完一个文件,只要两侧都有帧,程序就会自动重新计算差异。
- 阅读结果树的三层节点:先看"仅在关注文件中出现的 ID",再看两侧共有 ID 下的 bit / 字节取值 / 信号取值差异,圈定候选信号。
- 若只想关注关注文件的新增内容,勾选Show only data unique to Side 1重新聚焦。
- 点击Save Details to File把完整差异树导出为文本,便于存档或在其他工具中继续分析。
- 如需换一组背景,点击Clear Frames清空参考帧桶重新开始。
操作提示:对比前建议先通过 DBC 管理器加载与总线匹配的 DBC 文件,否则两侧共有 ID 下将只有 bit 和字节取值两层,缺少信号层差异,信息量会明显下降。
与其他 RE 工具的协同定位
文件对比窗口定位出"嫌疑 ID/bit/值"之后,可以继续用 SavvyCAN 的其他逆向工具接力验证:用 Flow View 观察嫌疑 ID 在时间轴上的出现规律,用 Frame Data Analysis 查看该 ID 的统计细节,用 Graph 工具把嫌疑信号画成曲线确认它是否随目标行为变化,用 DBC Editor 把新信号定义进 DBC 后再次回到文件对比窗口验证信号层差异。这样"日志差分圈定候选 → 信号级验证确认"的闭环,是 SavvyCAN 面向 CAN 逆向的标准打法。
- 开发工具
- 逆向工程
- 嵌入式
【免费下载链接】SavvyCAN
QT based cross platform canbus tool
相关推荐
SavvyCAN Range State 窗口实战:利用平滑度启发式搜索候选 CAN 信号
SavvyCAN Range State 窗口实战:利用平滑度启发式搜索候选 CAN 信号 Range State(范围状态)窗口是 SavvyCAN(QT 跨
开发工具逆向工程嵌入式Yamtrack与Plex/Emby无缝联动:打造个人媒体中心的终极方案
Yamtrack与Plex/Emby无缝联动:打造个人媒体中心的终极方案 Yamtrack是一款强大的自托管媒体追踪工具,能够帮助用户轻松管理和追踪各类媒体内容
SavvyCAN 时间窗口(Temporal Window)实战指南:用密度热图定位 CAN 总线高流量时段与活跃 ID
SavvyCAN 时间窗口(Temporal Window)实战指南:用密度热图定位 CAN 总线高流量时段与活跃 ID Temporal Window 是 S
开发工具逆向工程嵌入式
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考