我在周五晚上搞了一个OBD-II的实战训练。这个比赛是从线上预赛开始的,只有拿到前12名才能进入线下复赛。这次比赛分两部分,理论和实操。我一个人在家监考,就像在考场一样。理论题包括车载网络、无线通信、密码学、OTA升级、APP安全和硬件安全,难度挺大的。我要学会CAN总线传输、RSA加密、TLS1.2握手等内容。实操题让我逆向CAN报文,先让大灯闪三下,然后抓包找出重复三次的帧,还得读取里程、故障码、VIN、车速和电池电量。 这次比赛把我难住了,我本来以为要读取车辆信息很复杂,但结果技术支持告诉我题目没那么难。我就把方向改了。刚开始我发现题目挺简单的,只要点亮大灯三次,然后抓包就能找到三组相同的报文。这三个报文一模一样,位置、长度和字节顺序都完全一致才能过关。 接下来是读取车辆信息的环节,我想直接用UDS标准来读取里程但没反应。后来才知道OBD-II接口藏得比较深,得先询问哪个ECU在线才能开始获取数据。首先是查询支持的PID(参数ID),一次最多问32个PID(0到0xC0),通过广播7DF[8] 02 01 00 55 55 55 55 55给所有ECU发送请求。ECU会回7E8[8] 03 41 xx yy zz这个数据包,其中xx是支持的数量,yy到zz是位图表示哪个PID被支持了。 拿到位图后再广播请求目标PID,CAN ID还是7DF,Mode是0x01(动力系数据),PID是0xD(车速),Length是0x02,其余部分填0x55占位。完整帧是7DF[8] 02 01 0D 55 55 55 55 55这个数据包发送出去后,ECU会回7E8[8] 03 41 0D 32 AA AA AA AA。 根据附录B把32拆成单字节解析出来就是50km/h的速度了。有了速度后我就轻松搞定了里程、VIN和故障码。VIN查询更简单直接发送模式9请求车辆信息即可获取到1G1JC5444R7252367这个VIN号码。 这次线上预赛让我对CAN总线有了更深的理解,五月中旬还要迎接线下大考呢。