通过USB入侵微控制器固件

商务办公
在本文中,我想演示如何从运行在Cortex M0上的安全USB设备中提取固件。

 在本文中,我想演示如何从运行在Cortex M0上的安全USB设备中提取固件。

谁入侵了视频游戏机?

在电子游戏机的世界里,充斥着各种假冒伪劣产品。所谓需求创造供给,不乏有不少投机者想要在这块产业价值数十亿美元的蛋糕上分一杯羹。而现今,你总能找到那么几款设备,让几乎所有的游戏控制器,在对盗版游戏,假冒的游戏手柄或配件,甚至外挂上都丧失所有限制。

从视频游戏机诞生起的二十年来,其游戏控制器都是由硬件制造商设定的专有系统。制造商在设计的过程中会涵盖各种保护措施,以确保这些控制器只运行签名过的代码,让用户只玩合法有执照的游戏,以及官方授权的配件。某些国家,试图破解自己的视频游戏机甚至是非法的。

但与此同时,这种高规格的保护措施也使得游戏机成为了一个有吸引力的目标。对信息安全和逆向工程感兴趣的爱好者来说,这个谜题越难,解起来就越有趣,尤其是如果你从小就喜欢电子游戏的话。

DualShock 4保护方案

关注我twitter账户的读者可能知道,我长期以来一直致力于对游戏控制器及其相关产品做逆向研究。在PlayStation 4(索尼公司出品的一款游戏机)刚问世那会儿,我就曾利用其FreeBSD内核(PlayStation 4基于FreeBSD内核)中的一个漏洞探究了该产品的内部架构和工作原理。我做了很多不同的研究,其中就包括,在PS4中USB认证是如何工作的,以及它如何区分授权设备并阻止未经授权的设备。这个主题很有趣,我之前在其他控制器上也做过类似的研究。PS4的认证方案比Xbox 360使用的要简单得多,但效果并不差。

图1.PlayStation 4 USB配件授权方案

过程如下:PS4向DualShock 4(一款游戏手柄)发送0x100个随机字节,DualShock 4则创建一个RSASSA-PSS SHA-256签名作为响应,并将其发送回验证它所需的加密常数N和E(公钥)之间,这些常数对于所有正规制造的DualShock 4游戏手柄来说都是唯一的。DualShock 4还会发送一个验证N和E所需的签名,它使用相同的RSASSA-PSS SHA-256算法,此加密常数存储在内核中,对所有PS4游戏机都是相同的。

这意味着,如果你想认证自己的USB设备,仅仅破解PS4的内核是不够的,你需要将私钥存储在游戏手柄中。然而即使有人成功破解了游戏手柄并获得了私钥,索尼仍然可以通过固件更新将私钥列入黑名单里。如果游戏控制器在8分钟后还没有收到身份验证响应,它就会停止与游戏手柄间的通信,只有将其从USB端口拔出并再次将其插入后它才能工作。这就是早期的假冒游戏手柄的工作机制,它每8分钟就模拟一个USB端口拔掉/插入过程。

关于假冒DualShock 4的谣言

自DualShock 4问世以来,没有任何迹象表明有人成功攻破了此项机制。然而最近,我听说市场上新冒出了一些假的DualShock 4,无论外观还是功能都与正品都一模一样。我的好奇欲让我从中国的商店里订购了一些。

在我等待包裹到达的时间里,我决定收集更多关于假冒游戏手柄的信息。在多次搜索之后,我找到了一个名为Gator Claw的游戏手柄。

图2.未经授权的Gator Claw游戏手柄

不过Reddit上也有评论说,它只能工作八分钟,不过后来开发人员通过固件更新成功的解决了这个问题,上图所示的购买页面里包含了固件更新的链接和使用手册。

图3.Gator Claw固件更新手册

嵌入式固件的基础分析

我做的第一件事是查看固件更新器可执行文件的资源部分。

图4.在Gator Claw固件更新器的资源中找到的固件

经常为嵌入式设备编写代码的读者可能不会对这种文件格式感到陌生。这是Intel HEX文件格式,通常用于编程微控制器,许多编译器(例如GNU Compiler)以这种格式输出编译代码。此外,我们可以看到固件的开头没有高熵,字节序列很容易识别,这意味着固件未经过加密或压缩。将该文件解码并以hex编辑器加载(十六进制编辑器能直接打开该格式文件)后,我立马看到了它的编译架构——ARM Cortex-M。

图5.Gator Claw的固件(左)和ARM Cortex-M的矢量表(右)

根据ARM Cortex-M的规范,前两个字(黄框和红框标出部分)是初始堆栈指针,之后的是异常向量表(绿框标出)。该表中,前两个字是复位向量,用作固件入口点,而其他异常处理程序的高地址则提示了固件的基址。

除固件外,固件更新程序的资源部分还包含一个配置文件,里面有对不同微控制器的描述。 说明开发人员最有可能使用的是来自微控制器制造商的公开可用源代码,这就能解释为什么这个配置文件中带有源代码。

图6.对不同的微控制器描述的配置文件

在配置文件中搜索微控制器标识符后,我们找到了制造商的站点——Nuvoton。不需要任何许可协议就可以下载技术文档和SDK的产品信息。

图7.Nuvoton微控制器制造商的网站

现在我们有了固件,知道了它的体系结构和微控制器制造商,还知道了基本地址、初始堆栈指针和入口点。

ARM处理器有两种不同的指令集:ARM(32位指令)和Thumb(使用Thumb-2 32位指令扩展的16位指令)。Cortex-M0仅支持Thumb指令,因此我们在IDA Pro中加载固件时将“Processor options – Edit ARM architecture options – Set ARM instructions”中的单选按钮切换为“NO”。

之后,我们可以看到固件已经加载到基址0,自动分析几乎可以识别每个功能。现在的问题是如何推进固件的逆向工程。

图8.固件功能之一

如果对固件作分析,会看到整个它使用基址0x40000000对内存执行读写操作,这是内存映射到输入输出(MMIO)寄存器的基本地址。这些MMIO寄存器允许你访问和控制所有微控制器的外围组件,固件所做的一切都是通过访问它们来实现的。

图9.外围控制器的内存映射

通过搜索地址0x40000000的技术文档,我们发现这个微控制器属于M451家族。既然已经了解了微控制器家族,就下载这个平台的SDK和代码示例。在SDK中,我们找到一个头文件,它定义了所有MMIO地址、位字段和结构。我们还可以用所有库编译代码示例,并将它们与IDB中的函数进行比较,或者在源代码中查找MMIO地址的名称,并将其与我们的反汇编进行比较。这使得逆向工程的过程非常简单。那是因为我们知道微控制器的架构和模型,并且我们对所有MMIO寄存器进行了定义。如果我们没有这些信息,分析就会复杂得多。 可以说,这就是为什么许多供应商只在签署了NDA之后才发布SDK。

图10.在固件中查找库函数

在巨人的阴影下

在等待假手柄到来之际,我分析了Gator Claw的固件,但对固件的内部并没有太多深挖的兴趣——无外乎是身份认证数据被发送到另一个可以通过I2C访问的微控制器,再将响应送回控制器。Gator Claw手柄的开发者可能也知道他们的固件会被逆向破解,继而被同行模仿生产出更多的纺织品,这样也会对他们的业务造成负面的影响。为了防止这种情况的发生,他们使用了另一种微控制器来保障机密,这个做法也是十分常见的,因为黑客们在他们的产品上投入了很多精力,他们也不想被其他黑客攻击。

在这个固件中,真正引起我注意的是一些看似没有使用过的字符串,它很可能是USB设备描述符的一部分。这个字符串是故意留下的吗?会不会是某种签名?上述猜想是很有可能的,因为该字符串是一家硬件制造商的名称,该厂商以制造逻辑分析仪而闻名,并且它还有一个专门游戏部门,正朝着成为原始设备制造商(OEM)的目标奋进。该公司还拥有许多游戏配件的生产专利。除此之外,通过它的网站我了解到,在其品牌下有大量待销的游戏配件。

在它出售的产品中,有二十几款适配器能让手柄与不同品牌的控制器相连。例如,可以把Xbox 360的游戏手柄连接到PS4,也可以把PS3的游戏手柄连接到Xbox one,等等。还有的适配器,可以将PC鼠标和键盘连接到PS4、Xbox One、任天堂游戏机、各种手柄和印刷电路板上。所有产品都提供了与Gator Claw类似的固件更新程序,但有一个显著的区别——所有固件都是经过加密的。

图11.其中一个产品的手动和加密固件示例

Gator Claw手柄在印刷电路板的设计上可能就是模仿了该厂商。在下图中我们可以看到两个微控制器,其中一个应该是Nuvoton M451,另一个则是额外用于保障机密的微控制器。所有线路最终都汇聚到了黑色的模件中(下图中红色圈出部分),它应该是主微控制器,而带有四个黄色引脚的微控制器(下图中黄色圈出部分)应该具备了I2C工作所需的功能。

图12.Gator Claw印刷电路板的设计

启示

这时我终于收到了来自深圳的包裹,打开后我简直大吃一惊,如果我不说,我想你也会以为这就是原版的DualShock 4。这是一款用制作精良的无线游戏手柄,带有工作触控板、扬声器和耳机接口。

[[260932]]

图13.假DualShock 4手柄的外观

手柄启动后进入DFU模式,在此模式下将游戏手柄连接到PC后,它被识别为具有不同标识符和特征的另一个设备。那么接下来的事情就昭然若揭了……

图14.假DualShock 4手柄的印刷电路板

我将几根导线焊接到看起来像JTAG点的地方,并将其连接到JTAG编程器。编程工具识别微控制器,但它设置了安全锁。

图15.编程工具识别微控制器,但它启用了安全锁

通过USB攻击微控制器固件

在前面这段相当冗长的介绍之后,现在是时候回到本文的主题。USB(通用串行总线)是外围设备的行业标准。它的设计非常灵活,可以广泛应用。USB协议定义了两个实体——一个主机与其他连接的设备,连接设备分为集线器、人机界面、打印机、成像、大容量存储设备等类。

图16.USB设备的连接方案

设备与主机之间的数据和控制交换的过程是通过一组单向或双向管道的进行的。一个设备可以具有许多不同的端点以交换不同类型的数据。

图17.数据传输类型

有四种不同类型的数据传输:

  • 控制传输(用于配置设备)
  • 批量数据传输(以相对较大和突发的数量生成或使用)
  • 中断数据传输(用于及时但可靠地传输数据)
  • 同步数据传输(通过预先协商的传输延迟占用预先协商的USB带宽量)

所有USB设备必须支持端点0处的特殊指定管道,USB设备的控制管道将连接到该管道。

这些类型的数据传输是使用根据以下方案提供的分组来实现的。

图18.USB协议中使用的数据包

USB协议实际是一个状态机,在本文中我们不会检查所有这些数据包。下图中可以看到控制传输中使用的数据包示例。

图19.控制传输

批量传输、中断传输和同步传输这三种类型的数据传输是可选的,它们的存在和使用与否将视目标而定,但控制传输则是所有USB设备都支持,且控制传输的格式很常见,这使得控制传输成为了分析漏洞时最常利用的方法。

下面的方案显示了用于执行控制传输的SETUP包的格式。

图20.SETUP包的格式

SETUP包占用8个字节,它可以根据请求的类型获得不同类型的数据。有些请求对所有设备都是通用的(例如GET DESCRIPTOR),而其他的取决于设备的类别和制造商许可。要发送或接收的数据长度是SETUP数据包中提供的16位字。

图21.标准的和特定类别的请求示例

总结:控制传输使用非常简单的协议,所有USB设备都支持。它可以有很多额外的请求,而我们可以控制数据的大小。所有这一切使控制传输成为模糊和干扰的完美目标。

漏洞利用

为了破解我买的假手柄,我不必模糊它,因为我在查看Gator Claw代码时发现了漏洞。

图22.HID类请求处理程序中的漏洞代码

函数HID_ClassRequest()用于模拟原始DualShock 4手柄的工作,并实现与PS4一起工作所需的最少请求。函数USBD_GetSetupPacket()用于获取SETUP包,根据报告的类型,它要么使用USBD_PrepareCntrlIn()发送数据,要么使用usbd_preparecntrout()接收数据。USBD_GetSetupPacket()不检查请求数据的长度,这应该能让我们读取固件内部的部分闪存,并读取和写入SRAM存储器的开始部分。

图23.控制传输期间缓冲区溢出

DATA数据包的大小在USB设备描述符中定义(也通过控制传输接收),但容易被忽略的是这个大小定义的是单个数据包的长度,可能有很多数据包的长度取决于在SETUP包中所设置的。

值得注意的是,Nuvoton网站上提供的代码示例也没有检查长度,可能导致的结果就是使用此代码作为参考的所有产品中都会留有类似的漏洞。

图24.利用SRAM存储器中的缓冲区溢出漏洞

SRAM(静态随机存取存储器)是一种被堆栈占用的存储器。SRAM通常也是可执行存储器(可配置的),这通常是为了将经常调用的代码片段(例如,实时操作系统)复制到SRAM来提高性能。虽然不能保证堆栈的顶部可以通过缓冲区溢出来访问,但这么做的可能性仍然很高。

令人惊讶的是,利用USB固件的主要障碍竟然是操作系统。我在使用Windows时观察到以下内容,但我认为大部分内容也适用于没有特殊补丁的Linux。

首先,操作系统不允许你在控制传输期间读取超过4kb;其次,根据我的经验,操作系统不允许在控制传输期间写入多个DATA数据包;第三,USB设备可能有隐藏的请求,所有使用它们的尝试都会被操作系统阻止。

这很容易用包括手柄在内的人机界面设备(HID)来演示。HIDs附带了其他描述符(HID描述符、报告描述符、物理描述符),而报告描述符与其他描述符非常不同,它由描述所支持报告的不同项组成。如果报告描述符中缺少报告,那么操作系统将拒绝完成它,哪怕它是在设备中处理的。这基本上减少了USB设备固件漏洞的发现和利用情况,而这些细微差别很可能在过去阻止了漏洞的发现。

为了解决这个问题而不必阅读和重新编译Linux内核的源代码,我只使用了我手边的低端仪器:Arduino Mega板和USB Host Shield(总计小于30美金)。

图25.连接方案

在使用上述方案连接设备后,我使用Arduino板来执行控制传输,而不必受到操作系统的任何干扰。

图26.Arduino Mega + USB Host Shield

我从深圳买的假游戏手柄与Gator Claw具有相同的漏洞,我做的第一件事就是转储部分固件。

图27.部分转储固件

查找固件转储基址的最简单方法是查找包含指向已知数据的指针的结构。之后,我们可以计算地址的增量并将固件的部分转储加载到IDA Pro。

图28.指向已知数据的指针的结构

固件转储允许我们找出printf()函数的地址,该函数输出工厂质量保证所需的UART信息。 更重要的是,我能够在转储中找到hexdump()函数,这意味着我甚至不需要编写shellcode。

图29.寻找有助于漏洞利用的函数

在游戏手柄的印刷电路板上找到UART点,焊接导线并将它们连接到TTL2USB适配器后,我们可以在串行终端中看到输出。

图30.游戏手柄启动期间的标准UART输出

Nuvoton微控制器的标准库附带一个非常方便的硬故障异常处理程序,它输出寄存器转储。这极大地促进了漏洞利用过程,并能对其进行调试。

图31.堆栈覆盖导致硬故障异常后的UART输出

转储固件的最终漏洞可以在下面的屏幕截图中看到。

图32.利用和shellcode在UART上转储固件

但是这种转储固件的方法并不完美,因为Nuvoton M451家族的微控制器可能有两种不同类型的固件—主固件(APROM)和用于设备固件更新的微型固件(LDROM)。

图33.不同模式下闪存和系统内存的存储器映射

APROM和LDROM映射到相同的内存地址,因此只能转储其中一个。 要获得LDROM固件转储,我们需要禁用安全锁并使用编程工具读取闪存。

图34.Shellcode禁用安全锁

加密失败

对负责更新的固件(LDROM)的分析表明,它主要是来自Nuvoton的标准代码,但是添加了用于解密固件更新的代码。

图35.用于解密固件更新的加密算法方案

用于解密固件更新的加密算法是自定义块密码。它是在密码块链接模式下执行的,但是块大小只有32位。该算法接受一个密钥,该密钥是产品的文本(ascii)标识符,以及定义应该在当前块上执行什么转换的指令数组。在遇到键和数组的末尾后,它们的当前位置被设置为初始位置。转换列表包括6个操作:异或、减法、减法(反向),以及相同的操作(但是交换了字节)。因为固件包含大量充满0的区域,所以很容易计算这个算法的秘密部分。

图36.固件更新加密密钥

将从假手柄的固件中提取的算法对比到上述的制造商所生产的产品中,发现所有产品都在使用这种加密算法,利用该算法的漏洞,我们可以计算所有设备的加密密钥并解密固件更新。换句话说,在假冒产品中使用的算法导致该制造商开发的所有产品的安全性都受到威胁。

结论

这篇博文写得很长,但我真的很想让广大观众做好准备。我给出了一个关于嵌入式固件分析,找到漏洞,并利用它们获取固件转储和在USB设备上执行代码的操作指南。

故障攻击的主题不包括在本文的范围内,但此类攻击对USB设备也非常有效。对于那些想要了解更多相关信息的人,我建议您观看此视频。对于那些想知道如何从DualShock 4获取算法和密钥以制作盗版产品的人,我建议阅读这篇文章。

至于用于保障机密的微控制器,我发现并不是所有的设备都使用它,只是为了增加隐蔽性。但该微控制器不保守任何秘密,仅用于SHA1和SHA256。这项研究还帮助爱好者创建自己的开源项目,用于游戏控制器。

对于购买假冒游戏手柄的用户来说,他们并不能因获得了利益而沾沾自喜,因为制造商会屏蔽非法使用的密钥,而用户最终也无法使用游戏手柄或获得固件更新的提示。

责任编辑:武晓燕 来源: 嘶吼
相关推荐

2021-09-16 09:11:31

物联网微控制器IOT

2022-03-10 15:54:45

嵌入式开发多核微控制器技术

2020-09-24 10:20:16

物联网

2022-10-19 10:26:46

2011-07-12 17:10:05

域控制器组策略

2015-09-16 11:13:16

WLAN无线控制器Tolly 测试华为

2011-07-14 10:28:54

额外域控制器

2016-09-23 16:20:47

2015-08-07 15:28:46

选取城市控制器源码

2023-08-13 18:31:45

SDN控制器

2015-02-02 09:37:42

SDN控制器

2011-07-12 09:29:10

主域控制器备份域控制器

2024-09-27 16:28:07

2017-11-23 11:28:07

德州仪器MCUTI

2011-04-18 09:45:02

USB嵌入式Linux

2009-01-12 11:16:58

控制器控制器行为行为结果

2013-12-19 09:32:01

SDN南向网络控制

2012-05-21 12:26:40

2015-02-27 10:52:17

SDN

2011-07-18 13:55:08

点赞
收藏

51CTO技术栈公众号