找回密码
立即注册
搜索
发回帖 发新帖

6197

积分

0

好友

756

主题
发表于 3 小时前 | 查看: 1| 回复: 0

上回说到 OBD-II 那条 16 针线把诊断仪接进 CAN 总线。但 CAN 总线上跑的是帧,帧里塞什么、谁来解、按什么规则解,全是 UDS 在管。UDS 是 ISO 14229 定义的一套诊断协议栈,覆盖从读故障码、读传感器到刷写固件、跨域控制的全套操作。今天拆协议栈、十大核心服务、Seed-Key 安全访问,再配合 UDSim / UnlockECU 实战,最后盘一遍红队攻击面,下一讲直接上攻击面建模。

一、ECU 不是"一台电脑",而是一片域

现代汽车每辆搭载 70-150 个 ECU(Electronic Control Unit,电子控制单元),按域分布:

  • 动力域(Powertrain) — EMS(发动机控制单元)、TCU(变速箱控制单元)、BMS(电池管理系统,纯电/混动)
  • 底盘域(Chassis) — ABS(防抱死刹车)/ESC(车身稳定控制)/EPS(电动助力转向)
  • 车身域(Body) — BCM(车身控制单元,负责灯光/中控锁/雨刮)
  • ADAS 域(Advanced Driver Assistance Systems,高级驾驶辅助) — 毫米波雷达控制器、摄像头控制器、域控制器
  • 信息娱乐域(Infotainment) — IVI(In-Vehicle Infotainment,车载信息娱乐系统)、T-Box(远程信息处理盒)

UDS 是这些 ECU 都认的"普通话"。Tier 1(一级供应商)不管给哪家 OEM(整车厂)供货,UDS 接口几乎必须按 ISO 14229 实现。

汽车UDS诊断系统协议栈架构图

二、UDS 协议栈:跑在 OSI 第 5-7 层

UDS 本身定义在 OSI 7 层模型的会话/表示/应用层(第 5-7 层),不关心底层物理传输。实际部署时最常见的承载方式:

  • DoCAN(Diagnostic over CAN)— ISO 15765,主流方案
  • DoIP(Diagnostics over Internet Protocol)— ISO 13400,车载以太网 OBD 口的标配
  • DoLIN(Diagnostic over LIN)— ISO 17987,低速车身件
  • DoFlexRay — ISO 17458,奔驰 / BMW 部分高端车

红队做渗透测试时,第一步永远先确认用的是 DoCAN 还是 DoIP。DoCAN 使用 11/29 位 CAN ID 寻址(诊断 ID 一般落在 0x7DF-0x7EF 区间),DoIP 则直接通过 UDP/TCP 走车载以太网,两者工具链完全不同。

三、十大核心服务(必须背熟)

UDS 的每个服务用 SID(Service Identifier,服务标识符)一个字节标识。请求 SID 是奇数偏移,响应 SID 是请求 + 0x40。十大高频服务:

请求 SID 响应 SID 服务名 用途
0x10 0x50 DiagnosticSessionControl 切换诊断会话(默认/扩展/编程)
0x11 0x51 ECUReset ECU 软重启/硬重启
0x14 0x54 ClearDiagnosticInformation 清故障码(DTC)
0x19 0x59 ReadDTCInformation 读故障码列表
0x22 0x62 ReadDataByIdentifier 按 DID 读数据
0x23 0x63 ReadMemoryByAddress 按地址读裸内存
0x27 0x67 SecurityAccess Seed-Key 安全访问
0x2E 0x6E WriteDataByIdentifier 按 DID 写数据
0x29 0x69 Authentication 替代 0x27 的新机制(PKI 证书交换)
0x31 0x71 RoutineControl 跑 ECU 内部例程(自检/标定/特殊动作)

数 0x10 是"进门",0x27 是"解锁",0x2E 是"改值"。这三步连贯起来就是你远程调 ECU 的最短路径。

四、Negative Response Code:UDS 的错误字典

UDS 出错时 ECU 不回正常响应,而是回 7F <SID> <NRC> 三字节格式,NRC(Negative Response Code,负响应码)一个字节标识错误类型。最常碰到的几个:

NRC 名称 实战含义
0x12 SubFunctionNotSupported 子功能不支持 — 目标 ECU 没实现你发的那个 sub-function
0x13 IncorrectMessageLengthOrInvalidFormat 报文长度错 — 漏带 sub-function 字节
0x14 ResponseTooLong 响应太长 — 触发 ISO-TP 多帧传输(下面讲)
0x22 ConditionsNotCorrect 条件不满足 — 比如车速不为 0 时拒绝刷写
0x24 RequestSequenceError 请求顺序错 — 没先 0x10 切到编程会话就发 0x27
0x31 RequestOutOfRange 参数越界 — DID 编号超范围
0x33 SecurityAccessDenied 安全访问拒绝 — 0x27 没解锁就调 0x2E
0x35 InvalidKey Seed-Key 算错 — 算法或参数错了
0x36 ExceededNumberOfAttempts 超过最大尝试次数 — ECU 锁定一段时间
0x72 GeneralProgrammingFailure 刷写失败 — Flash 校验出错
0x78 RequestCorrectlyReceivedResponsePending 忙,等待中 — ECU 在算长 key,让你别急
0x7E SubFunctionNotSupportedInActiveSession 当前会话不支持 — 没切到 Programming Session
0x7F ServiceNotSupportedInActiveSession 服务不支持 — 比如 Default Session 下禁止 0x2E

红队视角下最常打交道的两个:0x22(车速/电压/P 挡条件)和 0x33(认证失败)几乎每个项目都会遇到。0x36 触发多了 ECU 会进入锁定状态,严重的直接锁死,必须拆电池或者长按某键才解得开。

五、ISO-TP:UDS 在 CAN 上的多帧传输

CAN 单帧最多 8 字节载荷(CAN FD 最多 64),UDS 一条诊断消息动辄几十上百字节。ISO 15765-2(即 ISO-TP)定义了四种帧类型解决这个问题:

  • 单帧 SF(Single Frame)— 第一字节低 4 位表示后续数据字节数(0-7)
  • 首帧 FF(First Frame)— 数据超过 7 字节时用,前两字节标识总长度(最大 4095 字节)
  • 连续帧 CF(Consecutive Frame)— 按 0-15 序号循环发送剩余数据
  • 流控帧 FC(Flow Control)— 接收方告诉发送方块大小(BS)和最小间隔时间(STmin)

进行模糊测试(fuzz)时常见坑:FF 没收完就发完 CF,ECU 直接回 NRC 0x14(ResponseTooLong)把你踢出去。下一篇讲攻击面建模时会专门拆这块。

六、SecurityAccess 0x27:Seed-Key 流程拆解

UDS 的安全访问用挑战-应答(Challenge-Response)模式,规则简单:

Tester → ECU:  27 01              # requestSeed (sub-function = 0x01)
ECU   → Tester: 67 01 AA BB CC DD  # positiveResponse + 4 字节 seed
Tester → ECU:  27 02 XX XX XX XX  # sendKey (sub-function = 0x02) + 计算出的 key
ECU   → Tester: 67 02              # 解锁成功

算法藏在 ECU 里,Tester 必须算出匹配的 key 才能解锁。算法各家不同:

  • Bosch(博世) PowertrainBoschContiSecurityAlgo1
  • Conti(大陆) ContiSecurityAlgo
  • Delphi(德尔福) DelphiAlgo
  • 日系 OEM 自研

Seed 长度通常 2-8 字节,Key 长度一般等于 Seed 长度。

UDS SecurityAccess Seed-Key安全访问流程

七、UDSim 实战:图形化 ECU 模拟器

UDSim(github.com/zombieCraig/UDSim)是 Craig Smith 写的 UDS 模拟器 + 模糊测试器,三种模式:

  • Learning 模式 — 监听 CAN 总线,自动学习 ECU 的 UDS 行为并保存
  • Simulation 模式 — 用学习好的配置模拟 ECU,对诊断仪做应答
  • Attack 模式 — 对目标 ECU 做主动 UDS 模糊测试

配置用纯文本 key=value,比如定义一个 0x7E0 的服务端:

[7e0]
pos = 300,131
responder = 1
positiveID = 7e8
negativeID = 7e8
{Packets}
7e8#0650030096177000

经典组合是 ICSim(Instrument Cluster Simulator,仪表盘模拟器)+ UDSim + SocketCAN(Linux 内核原生 CAN 协议栈) 一起跑,搞个虚拟仪表盘 + 虚拟 ECU 出来,练手写 UDS 注入时不用上真车。下一篇讲攻击面建模时会用到这套环境。

八、UnlockECU:Seed-Key 不再神秘

seed-key 算法一般藏在车厂的私有 DLL 里,逆向门槛高。UnlockECU(github.com/jglim/UnlockECU)做的事很关键:把 30+ 家供应商的安全访问算法逆向实现成 C#,配上 db.json 数据库免去额外 DLL 依赖。

用法直接:

  1. 从实车抓 seed(UDS 0x27 01 应答)
  2. 在 UnlockECU 选 ECU 型号(如 ME97)
  3. 工具自动选算法 → 算 key → 给你 UDS 0x27 02 应答帧
  4. 直接用 key 解锁 ECU,进入编程会话刷写

实战链:caringcaribou 枚举 UDS 服务 → 抓到支持 0x27 → UnlockECU 算 key → 进入编程会话 → 刷写恶意固件。整个链路开源 + 自动化,红队视角下这是教科书级别。

九、红队攻击面:UDS 常见被砍姿势

按实战中被利用的频率排序:

  1. 默认开放编程会话 — 不少车的 0x10 0x02(Programming Session)默认无认证,进入后 0x34/0x36/0x37 直接刷固件
  2. Seed-Key 算法被泄露 — 供应商 DLL 反编译后 key 算法全公开,等于 0x27 形同虚设
  3. DID 误用 — 0x22 读 VIN、里程、密钥等敏感 DID 没设访问控制
  4. 0x23 裸读内存 — 给个内存地址就能 dump 整个 Flash(闪存),密钥、私钥全暴露
  5. 0x31 RoutineControl 滥用 — 标定/工厂测试 Routine 在售后仍开放,可改写关键参数
  6. DoIP 远程访问 — 现代车 OBD 口背后就是 DoIP 设备,攻击者远端进 CAN 就是这一步

十、思考题

  • Q1:拿到一台车的 OBD 口,怎么在不接真实 ECU 的情况下练 UDS 注入?(提示:上文的 UDSim)
  • Q2:如果某 ECU 的 0x27 安全访问只用 OEM 私钥签名证书,但固件可以从公开渠道下载,会有什么后果?
  • Q3:0x31 RoutineControl 的 sub-function 0x01(Start Routine)能不能跑出 0x10 之外的会话切换?

十一、素材出处

UDS 是整车诊断体系的一块基石,上面承载的每个服务都可能是攻击面。这些知识会在下一篇攻击面建模中继续展开。云栈社区汽车安全板块会持续跟进相关技术动态,也欢迎各位带着实战案例一起讨论。




上一篇:WebSocket 协议漏洞解析:握手流程与八大致命风险
下一篇:知识图谱替GSK省4亿美元:AI制药供应链溯源的能与不能
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-6 22:53 , Processed in 0.074434 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表