找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

5480

积分

0

好友

738

主题
发表于 昨天 21:58 | 查看: 3| 回复: 0

挑战来源:https://vsec.blockharbor.io/
Challenge 网站:https://proving-grounds.blockharbor.io/

官方的在线环境似乎需要 $79,这里我使用的是 yichen 师傅的 Docker 版本:https://github.com/yichen115/UDSCTF

起步:你能找到接口吗?

题目问的是:虚拟终端上可用的 CAN 接口叫什么?

https://core.ed.vsec.blockharbor.io/block/test?tab=Simulations 页面中打开 UDS Challenge。

ip link 一查,CAN 接口正是 vcan0

Linux终端中执行ip link命令的输出,显示lo、vcan0和eth0三个网络接口的详细信息

UDS 挑战

VIN 码获取

题目:利用 UDS 协议获取模拟器的 VIN。

我们需要使用 22 号 UDS 服务来读取 VIN 码(车辆识别码,俗称车架号,由 17 位字符组成,每辆车独一无二)。

0xF190 就代表 VIN 码请求——22 是 SID(服务号),F190 是 DID(数据标识符)。VIN 码比较长,所以需要一次请求、多帧响应,这就用到了流控帧(FC)和连续帧(CF)。

第一条 7df#0322f190:向所有 ECU 广播一个 UDS 请求,读取 VIN(DID=F190)。CAN ID 7DF 正是功能地址。数据部分 03 22 F1 90 是 ISO-TP 单帧结构。其中 03 是 PCI(Protocol Control Information):高 4 位 0 表示单帧,低 4 位 3 表示后面跟 3 字节数据;22 F1 90 即服务号 ReadDataByIdentifier 和目标 DID VIN

第二条 7E0#3000000000000000:这是 ISO-TP 的流控帧(FC),7E0 是 ECU 的接收 ID。FC 的结构通常是 [PCI][BlockSize][STmin]...

PCI 常见值如下:

含义
30 继续发送
31 等待
32 中止

完整流程一览:

1. 我 → ECU
7E0#0322F190

2. ECU → 我
7E8#10 xx ...   (First Frame)

3. 我 → ECU(FC)
7E0#30 00 00 ...

4. ECU → 我
7E8#21 ...
7E8#22 ...

终端中分别执行candump与cansend命令的界面,展示CAN总线UDS请求与响应的完整交互过程

接收到的数据如下:

  vcan0  7E0   [4]  03 22 F1 90
  vcan0  7E8   [8]  10 1C 62 F1 90 55 44 53
  vcan0  7E0   [8]  30 00 00 00 00 00 00 00
  vcan0  7E8   [8]  21 43 54 46 7B 56 49 4E
  vcan0  7E8   [8]  22 59 49 43 48 45 4E 30
  vcan0  7E8   [8]  23 30 31 31 32 32 33 33
  vcan0  7E8   [2]  24 7D

10 1C 中,高 4 位 1 表示这是第一帧,1C 表示总长度 28 字节。去掉 UDS 响应头 62 F1 90,再去掉连续帧的序号字节(如 21 中的 1),就能拼出完整数据了。

解码界面截图,展示将十六进制数据转换为字符串并输出VIN码UDSCTF{VINYICHEN00112233}的过程

Level1 Flag 获取(安全级别 1)

题目描述:理解 UDS 安全访问机制,完成 seed-key 交换,在通过安全访问 Level1 后读取 DID:C1C2。

UDS 的安全访问机制即 SecurityAccess,SID = 0x27。它的核心作用是:在刷写固件、写入数据、清除故障码等敏感操作前,先让诊断仪“解锁”ECU。其核心流程是基于挑战-响应的 Seed-Key 机制,而非普通的账号密码。

流程如下:

Tester -> ECU: 27 01
请求安全等级 1 的 seed

ECU -> Tester: 67 01 xx xx xx xx
返回seed

Tester 本地计算:
key = f(seed)

Tester -> ECU:27 02 key
发送key

ECU -> Tester:67 02
解锁成功

27SecurityAccess 服务,正响应 67 是由 0x27 + 0x40 得来。

子功能一览:

子功能 含义
0x01 请求 Level 1 seed
0x02 发送 Level 1 key
0x03 请求 Level 2 seed
0x04 发送 Level 2 key
0x05 请求 Level 3 seed
0x06 发送 Level 3 key
奇数 请求seed
偶数 发送key

seed 是 ECU 返回给测试仪的随机数,比如 67 01 A1 B2 C3 D4,那么 seed 就是 A1 B2 C3 D4。诊断仪用这个 seed 算出 key 并返回,匹配则解锁。

针对本题,我们首先发送 27 01 指令,加上 ISO-TP 单帧长度字节后就是 7E0#022701

  vcan0  7E0   [3]  02 27 01
  vcan0  7E8   [7]  06 67 01 33 E5 9E 79

XOR计算器网页界面,计算seed与密钥deadbeef的异或结果ed482096

将返回的 seed 与固定 key 0xdeadbeef 进行异或运算,得到结果 ed482096。将其发送回去,即可收到成功响应。

  vcan0  7E0   [7]  06 27 02 ED 48 20 96
  vcan0  7E8   [3]  02 67 02

解锁后,就可以去读标识符 C1C2 对应的内容了。

  vcan0  7E0   [4]  03 22 C1 C2
  vcan0  7E8   [8]  10 1E 62 C1 C2 55 44 53

第一帧 10 1E1 为首帧标志,0x1E 表示总长 30 字节。接着,我们发流控帧让 ECU 继续吐出数据:cansend vcan0 7E0#3000000000000000

  vcan0  7E0   [4]  03 22 C1 C2
  vcan0  7E8   [8]  10 1E 62 C1 C2 55 44 53
  vcan0  7E0   [8]  30 00 00 00 00 00 00 00
  vcan0  7E8   [8]  21 43 54 46 7B 32 37 5F
  vcan0  7E8   [8]  22 73 65 63 75 72 69 74
  vcan0  7E8   [8]  23 79 58 30 72 5F 43 31
  vcan0  7E8   [4]  24 43 32 7D

这里看一下 30 00 00 00 00 00 00 00 的 FC 格式:

字节 含义
0x30 Flow Control + Continue To Send (CTS)
0x00 Block Size(一次允许多少帧)
0x00 Separation Time(帧间隔)

界面截图,展示通过SecurityAccess Level1后成功读取到的flag: UDSCTF{27_securityX0r_C1C2}

Level3 Flag 获取(安全级别 3)

题目描述:需切换到编程会话,运用更复杂的密钥算法,通过安全访问 Level3 后读取 DID:D1D2。

先切换到编程会话:7E0#021002
02:ISO-TP 单帧,后面跟 2 字节。
10:UDS 服务号 DiagnosticSessionControl,即切换会话。
02:子功能,Programming Session(编程会话)。成功响应是 50 020x10 + 0x40 = 0x50)。

  vcan0  7E0   [3]  02 10 02
  vcan0  7E8   [5]  04 50 02 00 32

接着请求 seed:02 27 03,并根据题目给定的算法算出 key。

# 步骤 3: 计算级别 3 key (复杂算法)
# key = ((seed << 7) | (seed >> 25)) ^ 0xCAFEBABE + 0x12345678
# key = (key & 0xFFFF0000) | ((key & 0x0000FFFF) ^ 0xABCD) ^ 0xDEADBEEF

把算出的结果 06270679278C05 发给 ECU 验证,通过后获取 D1D2 数据:

cansend vcan0 7E0#0322D1D2
cansend vcan0 7E0#3000000000000000

界面显示通过Level3安全访问后,读取DID D1D2得到的flag: UDSCTF{D1D2_Advanced_Flag}

内存 Dump 获取 Flag (安全级别 5)

题目描述:最高难度,需完成 Level 5 安全访问,然后用 0x23 服务 dump 内存寻找 flag。

先拿到 Level 5 的 seed,算出密钥并完成认证。

  vcan0  7E0   [3]  02 27 05
  vcan0  7E8   [7]  06 67 05 17 A8 18 7C
  vcan0  7E0   [7]  06 27 06 96 D9 AC 32
  vcan0  7E8   [3]  02 67 06

解锁后,要用的就不再是通过 DID 读取的 0x22 服务了,而是 ReadMemoryByAddress (0x23),它按地址+长度来读内存,刚好用来在 dump 出的数据里寻宝。格式为:0x23 + 格式标识符 + 地址 + 大小。例如,格式标识符 0x14 代表:1 字节大小 + 4 字节地址。

# 使用0x23 ReadMemoryByAddress服务
# 格式: 0x23 + 格式标识符 + 地址 + 大小
# 格式标识符0x14表示: 1字节大小 + 4字节地址

# 示例: 读取0x40000000开始的80字节
7DF#0723144000000050

复位启动获取 Flag

最后,还有一种思路是通过复位指令来触发 ECU 上报特定数据。

cansend vcan0 7E0#021101

ctfuser@1218612ee3c0:~/challenge$ candump vcan0 | grep 7E8
  vcan0  7E8   [8]  10 1F 62 00 00 55 44 53
  vcan0  7E8   [8]  21 43 54 46 7B 52 65 73
  vcan0  7E8   [8]  22 65 74 5F 54 68 45 5F
  vcan0  7E8   [8]  23 55 44 53 5F 53 65 72
  vcan0  7E8   [5]  24 76 65 72 7D

界面显示通过复位ECU后捕获到的flag: UDSCTF{Reset_The_UDS_Server}

熟悉 CAN 总线通信和 UDS 诊断协议的底层机制,是深入逆向工程与汽车安全研究的必备技能。这个系列的 CTF 题目从基础寻址一路深入到 Seed-Key 算法逆向与内存 dump,非常扎实地还原了真实车载网络的攻防思路。

如果你对这些技术实战感兴趣,云栈社区也汇集了不少同好,常常能挖到一些别处少见的硬核思路和深度分享。

一只戴着贝雷帽和单片眼镜的卡通企鹅,身处书房氛围中,充满极客气息




上一篇:.sorry1勒索病毒极限溯源:从零日志环境到黑产云存储桶的完整攻击链拆解
下一篇:存储巨头SK海力士一月三次起火:清州晶圆厂再发火灾,DRAM/HBM供应紧张或加剧
您需要登录后才可以回帖 登录 | 立即注册

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

GMT+8, 2026-6-13 00:26 , Processed in 0.616870 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

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