The Xbox 360 reset glitch hack

来源:互联网 发布:平克弗洛伊德知乎 编辑:程序博客网 时间:2024/04/30 17:33

Xbox360 reset毛刺攻击

原文来自

http://libxenon.org/index.php?topic=145.0


介绍

====

tmbinc说,就他个人观点,在xbox360上通过软件的方法来运行未经签名的程序基本是不可能的,因为从软件的角度这种认证体制是安全的。

处理器从ROM中启动1bl,1bl再从NAND中加载CB(这是一个经过RSA签名和RC4加密的程序)。

CB随后就初始化了安全引擎,他会实时的对物理内存中的数据进行加密和hash比对。我们知道他采用了AES128算法,和一个健壮的hash算法(疑似Toeplitz). 因为有不同的种子来源,所以每个bootloader阶段的加密都不相同,种子的来源至少包括:

-保存在处理器内的电子熔丝

-一个基于时间的计数器

-处理器内置的硬件随机数产生器。在fats机型上,可以尝试让随机数产生器输出固定的值,但是在CB中有对其随机性进行校验的功能,它只等待一个看似正确的随机数。

 

CB然后运行一些基于软件引擎的简单的字节码,主要的任务也就是初始化DRAM这些,CB然后从NAND上加载下个阶段的bootloader(CD)来运行。

 

CD从NAND上加载内核,打完补丁后随即运行。

 

内核中包含了一小块特权代码(hypervisor),然后游戏机就完整运行起来了,特权代码是唯一的有权限运行不需要签名认证代码的代码。

我们知道在内核版本4532和4548中存在着严重的缺陷,我们需要在这些内核版本上通过溢出的方法才能运行没有签名的代码。

在当前的360上,CD里保存了上面2个内核版本的hash值,如果尝试加载这2个版本的内核,那么CD就停止工作。

 

hypervisor相对所有代码是很小的一部分,我们分析他的安全性,找到可以被利用的缺陷来运行没有签名的代码,显然我们在后面的内核版本中没有收获。

 

另一方面,tmbinc说360的设计无法阻止来自于硬件的攻击,例如timing attack 和"glitching".

 

Glitching在这里的意思是指通过破坏电器特性的方法来触发处理器缺陷的过程。这也就是我们用来运行未签名程序的方法。

 

简单描述

========

我们发现当处理器工作在降频模式时,发送短小的脉冲信号,并没到真正导致复位,而是改变了代码的运行方式,看起来进行bootloader内存比对的函数总是返回"没有差异"的信息。内存比对函数用来检查下一个运行阶段的bootloader中的SHA哈希,如果和当前bootloader中的保存值一样就运行。所以我们可以在NAND里随便放一个bootloader,其实他的SHA哈希是不正确的,但通过reset glitch方法来攻击前一个bootloader,这样我们放在NAND里的bootloader就可以运行,基本上任何代码都可以运行。

 

fats上的实现详细

================

我们攻击的bootloader是CB,期望运行的是CD。

 

cjak发现,通过发送CPU_PLL_BYPASS信号,可以让CPU的时钟降低很多,这里有个例子,当dash运行时频率是200Mhz,游戏机启动的时候是66.6Mhz,当发送上面的信号的时候只有520Khz。

 

所以操作的流程是:

-当POST码到0x36的时候发送CPU_PLL_BYPASS信号

-等待POST码0x39启动的时候启动一个计数器(POST 0x39完成当前保存的hash和下个阶段hash的比对工作)。

-当计数器到达一个特定值时,通常是整个比对工作62%左右的时间,我们发送一个100ns的复位信号到CPU_RESET管脚。

-等一段时间,释放CPU_PLL_BYPASS信号。

-这时CPU的时钟恢复到正常的情况,这时需要一定的运气,如果没有看到启动错误码0xAD,启动的过程就会继续,我们期望的CD就可以运行。

 

在我们的测试样例中,NAND里包括一个零填充的CB,我们的CD和一个改过的SMC镜像文件。

这种glitch的方法并不可靠,所以我们采用修改后的SMC来实现无限重启,直到正常启动为止。通常情况下,我们会在上电的30秒内获得成功。

 

slim 上的实现细节

=================

我们通过glitch攻击的bootloader是CB_A,期望运行的是CB_B。

 

对于slim机型,我们在主板上没有能找到CPU_PLL_BYPASS这个信号。

我们开始的想法是使用自己产生的时钟来替换那个27Mhz主时钟,但是修改很麻烦,而且也没有取得什么结果。

我们随即寻找另外的使CPU降频的方法,然后找到HANA芯片上有一个可以配置的PLL寄存器,用于产生一个100Mhz的差分对时钟信号提供给CPU和GPU使用。

很显然,这些寄存器是SMC通过I2C总线来访问的。

I2C总线可以自由的访问,甚至于主板上有一个现成的连接器(J2C3).

所以HANA芯片就成了我们使CPU降频的武器。

 

所以总体实现过程是:

-在POST码到0xD8的时候,发送I2C命令来做CPU降频

-等待POST码0xDA开始执行,启动一个计数器。(0xDA完成当前保存的hash和下个阶段hash的比对工作)

-当计数器到达一个特定值时,发送一个20ns的信号到CPU_RESET管脚。

-等一段时间,发送I2C命令使CPU频率恢复正常

-等CPU频率恢复正常后,包含一定的运气成分,如果没有看到错误码F2,CB_A就会加载我们的CB_B来运行。

 

当CB_B开始运行时,DRAM还没有初始化,我们通过打一些补丁就可以实现运行所有的CD,这些补丁是:

-zero-paired模式总是有效,这样我们可使用一个修改后的SMC镜像文件

-不要解密CD,这样可以运行一个没有经过加密的CD

-在CD hash校验不通过的时候也不要停下来

 

CB_B是通过RC4加密的,密钥来自于CPU内部,那么我们怎么在不知道CPU密钥的时候来完成CB_B的补丁(译者注:应该是加密的意思,或者叫签名)工作呢?

 

RC4基本是这样一种情况:

  crypted = plaintext xorpseudo-random-keystream

所以如果我们知道了明文和加密后的数据,我们也就得到了pseudo-random-keystream,通过这个keystream我们就可以加密我们的代码。像这样:

  guessed-pseudo-random-keystream = crypted xorplaintext

  new-crypted = guessed-pseudo-random-keystreamxor plaintext-patch

 

这就变成了一个鸡蛋问题,我们又如何能够得到第一个情况下的明文呢?

答案很简单:因为我们有fat机型的明文,我们认为他和新的CB_B在前面的一些字节上应该是一致的,所以我们就可以加密一小段代码来读出CPU Key再来加密CB_B。

 

在我们的测试样例中,NAND里包含原始的CB_A,一个打过补丁的CB_B,一个明文的用户自制的CD和一个修改后的SMC镜像。

修改后的SMC可以实现无限重启,并阻止他定期的发送I2C命令,因为我们要用I2C总线。

 

现在,你可能还没有意识到,在CB_A中没有任何关于保险丝的检查,所以该破解方法是无法得到修正!!!

 

注意事项

========

-虽然我们认为这种方法已经是比较有效的了,成功率平均在25%,但是也有可能需要等上几分钟才能看到无签名的代码运行起来

-成功率依赖于我们修改的bootloader中的hash值(fats上是CD,在slims上是CB_B)

-需要使用高精度快速的硬件设备来发送复位信号

 

我们当前的实现情况

==================

我们使用了Xilinux的CoolRunner II CPLD (xc2c64a) 板卡,因为他快,高精度,可更新,便宜而且可以同时工作在2个电平等级上。

我们使用从360上来的48Mhz的备用时钟,作为计数器的时钟。在slim的情况下,计数器工作在96Mhz,因为在上升沿和下降沿都进行了计数。

CPLD的代码使用了VHDL来编写。

我们需要知道当前的POST码,在早期的实现是使用了8个信号线连接到POST的端口上,现在我们可以通过检测一个POST bit位的变化来实现,所以飞线更容易了。

 

结论

====

我们在放出来的hack工具中尽量不包括任何有MS版权的东东。

我们的设想是通过这种hack方法来运行Xell和别的自由软件,我(GliGli)这样做并不是为了促进盗版及其相关的产业,我只想在我买来的硬件上做我想做的事情,包括在上面运行我自己的代码。

 

鸣谢

====

GliGli,Tiros: 逆向工程和hack工具开发

cOz:逆向工程和beta测试

Razkar,tuxuser: beta测试

cjak,Redline99, SeventhSon, tmbinc, 和所有我在这里忘记的人: 早期对360的逆向和破解工作

原创粉丝点击