-
-
[翻译]HUBCAP:攻破ChromeCast 第一部分
-
发表于:
2017-11-5 14:14
4211
-
[翻译]HUBCAP:攻破ChromeCast 第一部分
如果你正在寻找本文的根源,最早是发布在这里的:
我原本想在这里告诉你们关于Chromecast的所有内容,但我认为维基百科已经涵盖了这部分内容,所以相关信息请查阅Wikipedia。 为了达到我们的目的,您只需要知道这是一个基于ARMv7的设备,具有WiFi,HDMI接口和微型USB端口形式的维护端口。 此外,您可以打开盒子得到一个串行调试端口。 设备所运行的是一个没有Dalvik引擎的精简版Android。
Chromecast处理器支持“安全”引导,这意味着它只会启动Google授权的引导加载程序和内核。 但是如果我想运行我自己的内核呢? 那么,我们的故事就从这里开始了。 Chromecast的独特之处在于Google向大多数系统发布了源代码,包括第二阶段的引导程序。 该引导程序是由SoC制造商Marvell维护的U-Boot的分叉版本。为了启动Android映像,对其做出了相应的修改。
因为我们可以访问源代码,所以我们可以简单地对它进行审计。 如果不打开盒子,只有通过维护端口这唯一的方法可以将数据导入引导加载程序。 那么,在这种情况下,该端口被配置为USB主设备,所以让我们来看看负责处理设备插入的代码。 在负责解析USB配置描述符的函数中,我们发现:
第7行和第23行显示的memcpy调用是有界(255字节)调用。 但更重要的是,负责计算接口描述符数量的“ifno”变量也不受限制。 您可以根据需要,提供尽可能多的接口头文件,因为代码不会察觉。 看起来我们可以在这个“设备”结构之外溢出一个合适数量的设备。 所以我们插入一个经过变形的配置描述符的USB设备,我们就赢了,对不对? 那么...当然这还不完全。 这些设备结构体的分配在usb_alloc_new_device中完成:
usb_dev中的每个条目大约为1300个字节,而USB_MAX_DEVICE为32个。这意味着这个数组大约为42k。 我们的设备只是第二个插入的设备(第一个是根集线器),所以我们后面有大约40k的未使用的内存。 我们不能溢出那么多的内存! 我们将不得不找出一个增加dev_index的方法,直到我们能够找到一些有趣的东西。
要介绍的是Teensy 2.0 ++,我们将用它来攻击这个平台的硬件。 我使用这个方便设备的部分原因是因为我已经有了它,另一部分原因是我已经熟悉它的环境,我之前已经使用它进行了USB开发。 我们将利用Teensy的灵活性来增加device_index,从而到达一个数组之外的某一处内存。
我们只需要插入大量的“假”设备。 我们可以假装成一个USB集线器,并插入大量的设备。 这里涉及到一些小花招,因为我们必须同时成为集线器和设备,但Teensy一次只能听一个USB地址。 看代码是如何完成的。 所以我们现在有一个插入到最后一个插槽的设备。 我们赢了,对吧? 还是不完全。 与传统的平台不同,引导程序是特殊的。 通常没有堆,没有动态分配,结构都非常简单。 怎么办? 我们不能破坏堆的元数据,并且附近没有函数指针。 让我们看看我们附近有什么:
我们可以将dev_index设置为-1到126的任意值。 该数组有32个条目,所以32-126会在数组之后覆盖内存,-1将允许我们在数组之前进行覆盖。 在dev_index之外的usb_dev数组之后的内存里没有什么有趣的东西(它在内存空间的末尾塞满了)。 这就让我们只能写入usb_dev数组前面的内存。 恰巧这段内存包含了一些有趣的东西。
引导加载程序支持两种设备,USB集线器和USB大容量存储设备。 它有类似于我们的usb_dev阵列的数组来跟踪与这些设备相关的设备特定数据。 与设备阵列类似,它使用索引来跟踪这些设备。 其中一个索引(用于集线器)位于usb_dev数组的前面,因此我们可以覆盖它! 但是,看看集线器分配代码,它有点严格:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)