前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用STM32开发板学习UDS诊断

使用STM32开发板学习UDS诊断

作者头像
yichen
修改2024-01-26 11:00:50
4802
修改2024-01-26 11:00:50
举报
文章被收录于专栏:陈冠男的游戏人生

前言

搞车联网安全的肯定都会涉及到 UDS 诊断,但除非能接触到实际项目,否则目前没见过有开源的能进行真实 UDS 诊断的练习板,只能看网上的一些理论知识,不咋过瘾

我在闲鱼买了一套 UDS_bootloader 的源码,目前跑通了几个 UDS 服务的功能,水一篇文章,介绍一下如何通过一块 STM32 的开发板实际练习 UDS 诊断

鉴于公众号文章发完了改不了几个字了,所以后面的读者可以去语雀查看最新的文档:

代码语言:javascript
复制
https://www.yuque.com/hxfqg9/iot/mawulsqfigf258x7

固件可以去语雀下载,也可以去 github 下载

代码语言:javascript
复制
https://github.com/yichen115/STM32_UDS_Demo/releases

另外本文不涉及理论知识的讲解,需要自己网上找其他文章学习或者直接读标准文档

硬件设备

下面说一下怎么攒一套硬件设备

首先是主体,STM32F103ZE 开发板,用来跑我们的 UDS 代码的

然后是 TJA1050 CAN 控制器,用来转换 CAN 信号的,淘宝卖的默认是没有排针的,要是自己有电烙铁可以焊上排针,方便接杜邦线

CAN 调试仪,用来与 STM32 建立 CAN 通信的,什么品牌无所谓,我用 PCAN 习惯了

Jlink 或其他可以刷写 STM32 的编程器,用来给 STM32 刷写固件的,注意最好是买个带排线的,可以直接连接调试器与 STM32,否则自己去找丝印接杜邦线嗷

最后就是若干杜邦线了

硬件连线

硬件连接情况如下图

Jlink 直接通过排线与 STM32 开发板相连即可,STM32 右边的 USB 接口是个串口可以看 UART 日志

TJA1050 的 RX 接 STM32 的 PA11,TX 接 STM32 的 PA12,VCC 接STM32 的 5V,GND 接 STM32 的 GND

TJA1050 的 CANH 接 CAN 分析仪的 CAN_H、CANL 接 CAN 分析仪的 CAN_L( 这里以 PCAN 为例)

固件刷写

安装好 Jflash 之后打开,选择新建项目

点击三个点,在输入框输入 STM32F103ZE 过滤出来,选择下面那个短的,然后 ok

把两个固件都拖到右边的数据文件窗口,然后点击 Target -> Production Programming 烧写固件(hex 文件都是记录着地址信息的,直接烧录即可)

然后打开串口调试工具,波特率设置为 115200,按下复位键看看是不是有输出了,如下输出说明正常

UDS通信

UDS 定义了一系列的服务,每个服务都有自己的 ID 即 SID(Service Identifier),接下来通过开发板实际进行 UDS 诊断通信体验一下

22 通过ID读数据

22 服务通过 ID 读取数据,例如读取当前会话状态的 ID 是F1 86,那么可以使用7DF # 03 22 F1 86来读取当前会话,接收数据中F1 86后面跟的01就是当前会话状态

在 14229 标准里面还有很多 ID,比如F1 90读取 VIN 码等(开发板暂未实现),以及厂商也会自定义 ID

10 诊断会话控制

使用7DF # 03 22 F1 86读取当前会话

切换到扩展会话7DF # 02 10 03然后 0x22 读取会话确认一下7DF # 03 22 F1 86,一般在扩展会话进行一些高权限的操作,比如读写数据

切换到编程会话7DF # 02 10 02此时观察串口可以看到进入到了 bootloader 的代码中,一般在这个会话状态进行刷写烧录相关操作

当进入非默认会话后如果不及时发送 3E 维持会话,过一阵就会退回默认会话

3E 会话维持

前面 10 服务提到,如果不及时发送会话维持,过一阵就会退回到默认会话,会话维持的服务是 3E,有两种子功能,00 和 80

7DF # 02 3E 00表示需要诊断服务端响应

7DF # 02 3E 80表示不需要诊断服务端响应,具体表现为你发送之后并不会收到回应

27 安全访问

这时候就得注意区分一下物理寻址和功能寻址了,前面通过 7DF 进行功能寻址,所有 ECU 都能收到的,虽然我们的实验只有 STM32 这一块板子,但实际在车上肯定不是,而且可能一堆不同厂商的 ECU,那解锁安全访问的算法必然也要不同,所以 27 服务的时候要使用物理寻址,指定哪个 ECU

但这玩意都是代码里定义的呀,我们咋知道呢,可以使用 CaringCaribou 这个工具去探测嗷,比如我这里探测的结果是:0x721

那接下来就可以请求 seed 了,发送721 # 02 27 01发现报错了

查阅 NRC 响应,是因为当前会话状态不支持此操作

那么切换到扩展会话7DF # 02 10 03,然后发送维持会话7DF # 02 3E 80,再次请求便可得到种子

但是我们并不知道怎么从种子算出密钥呀,这时候就要反编译固件分析逻辑了

可以把 app.hex 拖到 IDA 里面以 ARM 小端格式打开,搜索字符串,我把 SeedToKey 字符串加在了代码里方便定位😋

转成伪代码可以看到具体逻辑,a1 就是传进来的 seed,v2 就是计算出来的 key

让 chatGPT 写个 Python 脚本计算一下

代码语言:javascript
复制
def factory_security_seed_to_key(seed):
    seed = int.from_bytes(seed.to_bytes(4, 'little'), 'big')  #切换大小端序
    xor = 0x4368656e  # ASCII "Chen"
    key = seed ^ xor
    print(f"Key after xor: 0x{key:08X}")
    for i in range(32):
        if key & 0x80000000:
            key = (key << 1) ^ xor
        else:
            key = key << 1

    return key & 0xFFFFFFFF # 限制为32位整数

seed_value = 0x34023105  # 用你实际的种子值替换这里的数值
result = factory_security_seed_to_key(seed_value)
print(f"Seed: 0x{seed_value:08X}, Key: 0x{result:08X}")

请求种子

计算

返回密钥,成功通过安全访问

如果你多次发错密钥,则会得到一个否定响应,表示尝试解锁次数已经达到了设定的上限

11 复位功能

先进拓展会话,再发送7DF # 02 11 01

可以在串口中观察到设备重启,与按下复位按键效果是一样的

TODO

因为原来那个卖家是卖 UDS_bootloader 的,也就是通过 UDS 刷写升级 app 的,因此很多功能并没有实现,也没有实现的必要。等把目前他实现的功能梳理出来之后试试能不能自己写点,有需要源码的师傅可以加我私聊嗷,人家卖钱的东西就不公开发出来了(有良心但是不多)

文中有理解错的地方师傅们给指点指点嗷

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 陈冠男的游戏人生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档