CAN 总线数据记录格式-ASC
文件结构
一个典型的 .asc 文件由三部分组成:
- 文件头 (Header):包含日志的元数据,如开始日期、时间戳格式等
1 | date Fri May 12 04:16:06.532 pm 2023 # 记录开始时间[reference:16] |
- 触发块 (Trigger Block):代表一段连续的记录会话。如果记录被停止并重新开始,一个文件里可能会有多个触发块
1 | Begin Triggerblock Fri May 12 04:16:06.532 pm 2023 0.000000 # 触发块开始[reference:20] |
- 报文/事件行 (Message/Event Lines):这是文件的主体,由一行行的CAN报文或事件记录组成
报文行格式
一条典型的 CAN 报文行格式如下:
1 | <时间戳> <通道> <ID> <方向> d|r <DLC> <数据字节> |
时间戳:报文的时间,单位是秒,通常是一个浮点数
通道:标识报文来自哪个 CAN 通道(如 0, 1, 2)
ID:报文的仲裁 ID,通常以十六进制表示
方向 (Direction):Tx 表示发送,Rx 表示接收
帧类型:d 表示数据帧(Data frame),r 表示远程帧(Remote frame)
DLC:Data Length Code,表示后续数据字节的长度
数据字节 (Data bytes):报文的具体数据,以十六进制字节列出
实战案例
teslaaaaa(CAN 总线数据记录格式-ASC)

题目给的附件是常见的 CAN 总线日志格式,其中
1 | 730 Tx = 测试设备发给汽车 ECU 的数据 |
所以我们重点关注 730 Tx,第 27 行有这么一段请求 10 0B 34 00 44 08 00 00
ISO-TP(ISO 15765-2)是一个传输层协议。它的核心作用就是解决 CAN 总线一帧最多只能传 8 字节数据的限制
1 | 10 0B 34 00 44 08 00 00 |
1 (PCI 高 4 位): 值为 1,表示这是一个首帧 (FF)。它宣告了一个多帧传输的开始
0B (PCI 低 12 位): 十六进制
0x00B,即十进制的 11。这表示整个 UDS 指令的总长度是 11 个字节34 00 44 08 00 00 (后续 6 字节): 这是原始 UDS 指令的前 6 个字节的数据
第二段请求则是 21 00 00 00 20 00 AA AA,取剩下的 5 个字节,21 00 00 00 20
得到 34 00 44 08 00 00 00 00 00 20 00:
1 | 34 RequestDownload |
所以后面 ECU 要被刷入一段大小为 0x2000 = 8192 bytes 的固件,加载地址是 0x08000000
紧接着后面出现大量这种数据,这里是 ISO-TP 多帧
1 | 10 82 36 01 28 04 00 20 |
10 82 表示本次 ISO-TP 数据总长度 = 0x82 = 130 bytes
重组后的 UDS payload 是 36 01 + 128 bytes 固件数据
附件里从 36 01 到 36 40 一共有 0x40 块,每块有效固件数据是 128 字节,正好对应前面的 RequestDownload 大小
1 | import re |
IDA 反编译可以看到一个 flag,但可惜是假的

去看看谁引用了它,因为这个固件没有 main 函数

这里在修改 flag 的每一位,跳过前面的 flag{

编写脚本解密得到 flag
1 | fake = "flag{canoecr7-zd9h-1emi-or8m-f8vm2od81nfk}" |
得到 flag{3dad13db-cb48-495d-b023-3231d80f1713}