里程停止器拆解分析

admin 2025年6月13日19:50:03评论24 views字数 3515阅读11分43秒阅读模式
“最近太忙了”
“里程停止器”工作原理在上篇文章已经讲过,本文介绍拆解分析过程。
Hardware Teardown
首先拆开 PCB:
里程停止器拆解分析
为了更好地理解该设备,用 KiCad 重新实现了大部分设计,并将组件大致放置在相同的位置。
里程停止器拆解分析
这个设备包括:
  • 12V 转 5V 降压电路
  • 5V 转 3.3V LDO
  • STM32 微控制器
  • 两个 CAN接口

CAN 接口连接到电缆的每一端,使设备能够在仪表盘显示屏与汽车的其余ECU之间进行中间人攻击,从而可以过滤或修改发送或接收的任何消息。

首先,我们来研究排针的用途。使用万用表的连通性模式,我们可以追踪微控制器的每个引脚与排针的连接情况。根据 STM32 上的标签:

  • 顶部引脚连接到 PA13
  • 中间引脚连接到 PA14
  • 底部引脚连接到地(GND)
里程停止器拆解分析

发现了 SWD接口!

Connecting Debugger连接调试器:

里程停止器拆解分析
还需要为电路板供电。
里程停止器拆解分析

现在我们可以读取寄存器了

里程停止器拆解分析
不知何故,我们无法读取flash
里程停止器拆解分析
能读取 RAM吗?
里程停止器拆解分析
为什么读不了flash
发现 STM32 flash读保护
> stm32f1x options_read 0option byte register=0x3fffffewrite protection register=0xffffffffread protection: onwatchdog: software

One Exploit to Rule Them All

尝试复现《One Exploit to Rule them All?》中攻击来读取这颗受读保护的STM32F105 。

Wiring up the Target

幸运的是,GitHub 上有 CTzX 提供的适用于 Pi Pico 的攻击代码(https://github.com/CTXz/stm32f1-picopwner),其中包含加载到  STM32 SRAM 的payload 。在连接任何设备之前,先将此固件烧录到 Pi Pico 中。将在漏洞利用部分讨论此固件的功能。

该攻击需要对 STM32 的电源进行严格控制,并且能够快速响应 nRST 的变化,因此需要移除 3v3 电源线上的旁路电容和 nRST 上的电阻。此外,还将移除 BOOT0 引脚上的电阻,以便控制 STM 的启动模式。

所有需要移除的组件都用粉色标记了出来 :

里程停止器拆解分析

移除这些元件后,便可以开始将 STM32 连接到 Pi Pico 上。

里程停止器拆解分析

请注意:BOOT1 需要始终保持高电平状态。

里程停止器拆解分析

我们还需要重新连接调试器,以便将payload写入 SRAM。

Exploit

正如之前提到的,即使处于锁定状态,这款 STM32 仍然允许一定程度的调试访问,并且可以通过 BOOTCFG 引脚从 SRAM 启动。当连接调试器时,对 Flash 的访问会被禁用,只有在电源复位后才会重新启用。从 SRAM 启动时,对 Flash 的访问也会被禁用。此次攻击的第一步是将一个分两阶段的利用程序加载到 STM32 的 SRAM 中。

一旦加载了攻击代码,我们先断开调试器,接着拉高 BOOT0 引脚,让设备从 SRAM 启动。此时,由于之前连接过调试器,Flash 仍然处于锁定状态,并且会一直保持到电源循环复位,但电源循环复位会导致我们 SRAM 中的有效载荷丢失。重点是,切断电源时,SRAM 里的内容不会马上消失。我们在给设备降压时盯着 nRST 线,等 nRST 线的信号恢复正常,马上把电供回去,这样设备就能重新访问 Flash,而且 SRAM 里的重要数据也不会丢。

以下是一张 Saleae 的 VCC 故障截图:

里程停止器拆解分析

接下来,我们从SRAM启动,执行流程将从`_start`开始,这是第一阶段。在`entry.S`中,此方法仅设置一个闪存补丁块并进入等待循环。

@ -- Stage 1 --Set FPB to remap the reset vector to SRAM_start:ldrr0, =0xe0002000FP_CTRL, see https://developer.arm.com/documentation/ddi0337/e/System-Debug/FPB/FPB-programmer-s-model movs  r1, #3@ FP_CTRL: Enable FPBmovs  r2, #0x20@ FP_REMAP: Remap to stage 2 vtable entry (0x20)movs  r3, #0x05@ FP_COMP0: Set COMP0 to (rst_vector | EN) = 0x05stm  r0!, {r1, r2, r3}@ Apply to FPB          waitrst:           b  waitrst@ Wait for NRST pin to be toggled

Flash Patch Blocks主要用于调试,能够重映射读取操作或设置断点,且这些设置在设备复位后依然有效。该攻击利用其重映射模式,将真实的闪存入口点替换为我们存储在 SRAM 中的第二阶段方法。

接下来,我们将芯片配置为从flash启动,并通过 nRST 引脚对其进行复位。当芯片启动时,它会寻找入口点,此时Flash Patch Blocks生效,导致执行流程从第二阶段开始。由于芯片是“通过flash启动”的,因此第二阶段的处理程序可以完全访问flash。其在 entry.S 中的处理程序调用了 main.c,而 main.c 的作用仅仅是通过 UART 将flash的内容转储出来 :

// Called by stage 2 in entry.Sintmain(void){    iwdg_enabled = (_WDG_SW == 0); // Check WDG_SW bit.    refresh_iwdg();    usart = init_usart1();    /* Print start magic to inform the attack board that      we are going to dump */    for (uint32_t i = 0; i < sizeof(DUMP_START_MAGIC); i++)    {        writeChar(DUMP_START_MAGIC[i]);    }    uint32_t const *addr = (uint32_t *)0x08000000;    while (((uintptr_t)addr) < (0x08000000U + (1024UL * 1024UL))) // Try dumping up to 1M. When reaching unimplemented memory, it will cause hard fault and stop.    {        writeWord(*addr);        ++addr;    }    while (1// End    {        refresh_iwdg(); // Keep refreshing IWDG to prevent reset    }}

以下是 Saleae 逻辑分析仪对整个过程的截图:

里程停止器拆解分析

Load in Ghidra

将固件加载到 Ghidra 中,已知该架构为小端序的 Cortex,其 Flash 位于地址 0x8000000。

里程停止器拆解分析

根据数据手册,我们先要把 RAM 放在 0x20000000 这个地址位置,然后在地址 0 的地方做一个 Flash 的镜像。最后,用 SVD 加载器把芯片里剩下的外设都映射好。

通过查看字符串信息,我们发现 UART 上使用了类似 AT 指令风格的命令,这些命令很可能被用于蓝牙应用程序的通信,尽管我们并未购买此功能。或许,如果我们购买一个蓝牙模块并自行连接,它就能正常工作。

Reverse Engineering

先从复位向量入手,看看设备启动时是怎么初始化的。在 ARM 固件里,初始程序计数器的值就在 Flash 里,从开头往后数,排在初始堆栈指针值后面第四个位置。一般来说,在裸机固件中,顺着每个函数的最后一次调用一路追踪下去,就能找到程序的主循环。

里程停止器拆解分析

通过对app_loop的分析,开始了解这个设备的真实功能。伪代码如下:

void app_loop(){  if (10000 < ticks_since_fwd_can_msg) {    disable_bluetooth();  }  can_fwd_car2ipc();  can_fwd_ipc2car();  if (pending_config_changed_notif) {    send_config_changed_notif();  }  uart_command_handler();  if (selected_config != *p_flash_selected_config) {    flash_program(p_flash_selected_config, selected_config);  }}

原文始发于微信公众号(安全脉脉):“里程停止器”拆解分析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月13日19:50:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   里程停止器拆解分析https://cn-sec.com/archives/4162876.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息