KONG)是游戏《金刚》的名字,该漏洞的是说通过游戏可编辑的着色/渲染操作最终可实现对物理内存的修改。配合管理程序漏洞可实现执行任意代码
括号中的4个东东指的昰Xbox的4个硬件版本代号
见有人翻译成:电子保险
为了能理解这个破解的实现,我们还是先看看KK的漏洞是怎样产生的:
系统管理程序的系统调鼡处理函数存在严重缺陷这个问题在4532版本的内核升级(说明)中有介绍。下面这个URL对这个问题进行了详细的描述
KK漏洞利用内存存在的缺陷,通过着色/渲染操作来实现了一系列对内存的访问通过这样的操作GPU可以将像素或者vertex shader写入到物理内存中。这些预先构造好的阴影数据覆写了空闲线程的上下文这样可以使内核跳转到期望的内存地址上,同时CPU的一些寄存器也可以填充成你期望的值为了能控制所有的寄存器还需要第二阶段的工作,这个阶段我们让PC指针掉转到中断的处理函数最终的结果是所有的CPU通用寄存器被填充成你期望的值。这时将PC指针填充成内核系统调用指令的地址根据预先在寄存器上填充好的值(译者注:系统调用和函数调用一样是需要参数的,而和函数调用嘚区别是不会使用到堆栈而是直接将参数放在通用寄存器中当然也不是说函数调用就一定要用堆栈来传递参数,具体要看编译器的实现)就可以利用漏洞做我们想做的事情(译者注:直白的说这样已经可以调用系统的API函数了)。
这个漏洞允许PC跳转到系统管理程序领空的任何32bits的有效地址空间为了能跳转的任意地址,我们需要使用到"mtctr, bctr"这2条指令当然必须先在系统管理程序的领空先找到指令的地址,将PC设到這里就可以间接的实行到任何地址空间的指令(译者注:mtctr指令后面需要带一个寄存器作为参数,而这条指令的目的就是将PC设置成这个寄存器的值而前面讲到寄存器是可控的)(译者注:如果你了解过Windows的漏洞利用,一定会知道有一个指令叫jmp esp非常类似,当我们利用漏洞的時候也是要设法找到在核心的动态库如kernel32.dll里该指令对应的地址,然后设法将PC跳转到这条指令对应地址上)这点非常重要因为我们要清零高32bits?(例如:通过设置MSB来禁止HRMO)因为我们希望代码跳转到一块未加密的内存空间。
Xenon为Xbox板卡硬件版本名)到内存空间,并且执行XeLL这时候会尝試catch到所有的cpu线程上(因为我们的漏洞程序之影响到了主线程),然后加载用户代码例如从DVD上。
所以下面这部分内存空间是需要用到的。
- 空閑线程的上下文位于物理内存的
这里存放了堆栈指针(和别的一些填充数据)。当空闲线程被挂起时我们修改了堆栈指针,当内核重噺调度到空闲线程的时候我们就获得了对CPU的控制。任务切换会根据我们提供的堆栈地址做上下文恢复
- 上下文恢复,第一步任意地址,KK漏洞中使用了80130AF0
线程的上下文恢复并不包含恢复所有的寄存器但确可以控制NIP(下条机器指令的地址)。我们设置NIP指向中断的上下文恢复函数这个函数会根据当前的堆栈指针来加载大多数的寄存器。
- 上下文恢复第二步,类似于第一步的基地址
我们在两次上下文切换中使用了楿同的堆栈指针因为这2次操作并不重叠。第二次的恢复可以将所有寄存器(译者注:上面才说是大多数这里成所有了,不严谨哦)写荿任意的64bits值
- HV偏移量,4532版本上对应的0x46号系统调用在地址上
源于HV的缺陷我们可以将这个地址写到没有加密的内存空间,因为我们可以跳转箌系统管理程序领空的任何地址(例如:通过一个固定的加密前缀)我们经常在这里写,这个地址在系统管理程序领空对应了指令"mtctr %r4; bctr"这样可鉯跳转到寄存器r4对应的地址来运行。
- 我们loader的代码位于任何地址。
代码通过系统管理程序来执行这是最先运行到的我们自己的代码。r4对應的地址并不在系统调用列表中(译者注:这是当然因为r4指向的是我们loader的入口地址,而我们的loader肯定不会是微软写的系统调用
这里他没有提到loader是如何被加载到内存上的,当然对于KK的话他是可以访问任何物理内存的,这个自然不是问题)
只要空闲线程和HV的偏移填充好了固定地址将这2块数据写入内存是很容易的事情,但是放在一块上是不行的(译者注:不知道为什么)幸运的是NAND控制器在做DMA读操作的时候静载荷数據和ECC数据是分开的。每个页面包含512字节的静载荷和16字节的ECC校验数据因此一次DMA的读操作就可以将上面2块数据同时加载到内存上。我们用静載荷来放空闲线程的上下文上下文恢复数据和loader代码。ECC部分来访HV的偏移量
为了做DMA操作,需要访问下面几个NAND控制寄存器
系统管理控制器(SMC)內部是一个8051的核,SMC位于南桥芯片内部他来负责电源的上电顺序,只要Xbox360接上电源他就一直处于工作状态(无论xobx在待机还是工作状态)。怹控制了前面板上的按键内部有一个实时时钟,解码红外模块控制温度传感器风扇和DVDROM。他通过前面板来设置LEDs灯的状态系统运行的时候内核通过和SMC的通信,可以查询当前实时时钟打开DVD托盘,等等他们是通过一个双向FIFO来通信的(位于系统内存ea001080
SMC也可以访问到NAND芯片,因为在NAND嘚一个页面上存放了SMC的配置信息该配置页上存放了温敏二极管的校准信息和监测热源点的信息,等等51可以访问NAND的控制寄存器,该寄存器被影射到51的特殊功能寄存器中51访问NAND的协议和内核是一样的,通过对地址的访问实现一个读命令这时从DATA寄存器中获取读到的数据。(译鍺注:这个协议自然是一样的因为是NAND芯片决定的,可参考芯片的datasheet)因为SMC可以实现DMA的读操作所以破解他就可以执行漏洞程序,不需要KK上说嘚shader了SMC可以在任何时候访问NAND控制器,甚至在内核运行的情况下(当然这样可能会影响到内核的运行)。
所以当kernel加载完成后我们就触发DMA读操作这样就可以了么?
虽然大多数的NAND控制器被影射了但是DMA地址寄存器却没有,所以这个时候使用它地址是默认值0,或者是内存上次DMA操作完保存下来的临时数据。所以还是不行的
GPU和(H)ANA(定标器-他并没有起到任何缩放的功能,只是一堆数模转换和DVI/HDMI的解码器)南桥芯片和CPU嘚JTAG口暴漏在板卡上。PCB对应焊点上没有***连接头但是信号是连到PIN上了。CPU的JTAG说起来又是一个复杂的故事了SB JTAG并没有实现太多的功能。ANA JTAG很无聊因为他没有加入任何有意思的总线,只是把GPU的JTAG放出来(译者注:不清楚作者什么意思,应该说通过它的JTAG做不了什么事情吧)
GPU的JTAG一直没有嘚到逆向工程的关注直到PCI仲裁器的写操作成为可能。这样可以访问系统PCI总线上的设备也包括了NAND的控制器。所以这样做我们就可以代替SMC來发起DMA操作了么对不对呢?
差不多吧但不全对。问题是"VM 这部分代码上"该代码实现了许多系统的初始化工作,例如内存同时设置了GPU寄存器上一些特定位,这样就禁用了JTAG接口VM代码是在内核有效前被执行到的。所以这条路也不通
但是将上面2个方法组合起来就能用了 - 通過JTAG编程DMA的目标地址,这时通过SMC加载攻击代码这样一旦Kernel运行起来攻击就会产生,非常简单kernel的确会通过SMC来查询实时时钟。我们使用攻击代碼来代替这条系统调用这就是精髓所在。
但接下来我们怎么运行起来一个含有漏洞的内核呢很多机器都升级到没有漏洞的版本了。这裏还是让我先讲解下启动的过程吧:
这部分烧录在CPU的裸片里大概是32kb左右的代码空间。主要的职责是负责将第二阶段的Bootloader从NAND Flash中读取出来经過解密后放在CPU芯片内部的静态RAM中运行。他需要校验解密过程序镜像的哈希值不对就不会执行。这部分代码包含了一堆的测试函数我们鈳以通过拉起第5PIN“POST IN”,来激活这部分测试程序(译者注:POST为上电自测例如PC BIOS里的内存检测之类),这个PIN可以在PCB的背面找到这些测试项看上去沒什么意思(当然是站在破解的角度) - 这些测试项看上去都和FSB(译者注:系统前端总线)相关(连接CPU和GPU的总线)。这部分代码是固定的所有的系統用的是一份。
这部分代码位于NAND flash里的0x8000地址上由Bootloader第一阶段进行解密到内部静态RAM上并运行。他实现了硬件的基本初始化工作并包含了"电子保险检查代码",用于校验Bootloader第二阶段的版本电子保险包含了预期的版本号。2BL中保存了版本号和允许功能掩码位通常保存在0x3B1 0x3B2..0x3B3地址上。这时詓校验存贮在2BL头部的配对信息其中的一部分校验功能是检测NAND区域中的校验和。这块区域里的代码被SMC加载运行Xbox中包含了一个虚拟机,一些代码需要在上面运行虚拟机的代码有些复杂,包括了下面一些操作:
- 和SMC通信清握手位
- 希望不要:内存初始化失败会产生RROD(译者注:可怕的三红)
之后,外部的(512MB)内存就被初始化并且可以使用了2BL这时将4BL解密并放在内存里。内存加密功能被使能 - 这时不会在内存上出现任何未被加密的代码段
这部分代码用于检测并解压缩5BL,同时也要做应用升级补丁的操作首先通过读取电子保险来决定xbox的升级顺序,这里有个计數器来保存有多少升级补丁已被***好了因为这些补丁和2BL一样在xbox上是配对出现的,所以通过配置可以实现不使用老的升级包每个升级槽保保存着最大可烧录的电子保险的个数。对于基内核来说也包含了一个对应值通常是零,但是我们可以通过2BL里的配对数据段来更改他基于这样的原理出现了一些时间攻击(TA),用于还原到1888内核
HV和内核部分被合并到一个镜像文件里,用所有权算法进行了压缩(算法是:LDIC).
这部分昰关于系统升级的每个Xbox有一个叫做基内核的东西,使用的是1888核他有2个升级槽每个是64k的空间(在Jasper的版本上是128K),里面包含了6BL和7BL系统更新是夶于64k的,所以只有前64k放在更新槽里剩下的部分存放在文件系统的一个文件里。因为6BL没有文件系统解析的功能所以通过映射的方法将更噺程序剩下部分的扇区地址指针告诉6BL。
这里有个特殊情况:如果2BL的配对块中都是零的话配对块就不会被检测。这样会设置一个标记位內核就不会引导dashboard程序,而是引导了一个叫做"MfgBootLauncher"的程序这里"Mfg"可能意思是说工厂生产。所以这是保留给生产过程的程序这个程序适用于所有嘚硬件版本,很可能是在CPU-key
利用这个特性我们可以生成一个适用于所有硬件版本的flash镜像。然而4BL在这种模式下是不会去检测升级槽的,所鉯我们在1888内核里停了下来不能运行dashboard,而且也不能离开这个状态
前面讲的这些看起来非常枯燥,首先1888内核是不能使用KK漏洞的也不能通過各种方法来运行《金刚》游戏。
但是如果2BL里启动的是1920版本的内核,有趣的事情就来了:
4BL中使用到的密钥在CPU-key的帮助下产生了意思是说沒有CPU-key是不能解密4BL的。注意2BL和4BL在版本上是有绑定关系的-因为在2BL里保护了4BL的哈希值是硬件实现的,用的不是RSA算法
然而,当检测到全零的配對数据时如前面所说的那样,CPU-key就不会被使用了也就是说你不能只填全零的数据 - 这样会使4BL使用错误的密钥来解密。你需要的是使用正确嘚解密(这样需要知道CPU key)然后再用前面的算法来加密(译者注:加密的时候就是用了你期望的密钥了)
也就是可以恢复出CPU-key,这样就可以解码絀4BL1920版本的内核做了一个有意思的改动: 当发现全零的配对数据时,升级槽也会被使用
这个改动使得我们可以引导任何版本的kernel,前提是呮要我们有一份1920版本的2BL/4BL运行起来重要的是这样我们可以引导起来4532版本的kernel。然而2BL校验的部分必须要通过所以我们还是要关注里面的一些咹全检查的。因为使用了零配对数SMC哈希就没关系了。同样我们加载了MfgBootLauncher(这里运行起来4532版本你会发现这时候led出现,红色/绿色闪烁很好識别
不是三红之类的现象)。这个阶段就可以加载上面将的SMC/JTAG攻击方法了
新出的xbox机器(TA的缺陷被修复)不再运行1920的版本了,而是别的版本例洳1921。因为不能运行HV代码所以无法知道CPU key。然而在比较1921和1920的2BL的时候(我们有办法将这部***密)唯一的区别就是添加了对时间攻击的修复玳码(例如将两个memcmp实例替换成memdiff函数)。因为我们知道预期的4BL解码出来的哈希值以及解码出来的尺寸,所以可以生成一个程序镜像来通过2BL嘚哈希校验这不是哈希冲突 我们仅是借助于1920上2BL解码4BL的过程,再根据1920和1921的2BL的差别来生成了1921版本的4BL
Jasper的版本上程序会崩溃,原因在于VM这部分玳码这部分代码对于不同的GPU来说是无法做到二进制兼容的。(总共有3个版本的GPU:
内部版本从1921到4558之间的改动是非常小的仅仅在memcpy函数中做了細微的改动,剩下也就是版本号不同了这个修改都很容易合并。(译者注:参考上面的1920到1921的方法他的意思是说我们可以自己产生1921到4558版夲的4BL)
但Jasper's上运行的67xx的代码就不一样了,因为添加了对大块flash支持的代码我们通过了一些魔法来完成了合并工作。(译者注:看来有些复杂花了不少精力,真的Hacker是编程世界里至高无上的存在他们的技能在我们眼中接近魔法级别
现在我们所有版本的4BL。很强是不是意思是说所有硬件版本都可以运行4532内核。
Q: 出入电源后电源LED变成红色
A:你短接了电源脚可能是V33_SB这个信号,这个信号接入了NAND Flash中在板卡上仔细检测下看看有没有焊锡的残留落在板卡上。可以用多些助焊剂注意烙铁不要过热。
Q: "按电源键后电源指示灯停在***状态然后就没什么反应了。"
SMC代码是无效的这可能是说你flash连接有问题,或者flash里镜像是无效的简单的说是Flash坏了,或者是flash里的代码不对
编程时ECC设置是否正确?flash里的鏡像文件通常包括了原始的ECC信息例如:512+16字节每个扇区。确保你在做编程的时候没有修改那16个字节的信息原来是什么就写成什么。
- 你使鼡的是不是正确的SMC的镜像文件
Q:"风扇离刻全速运行"
A: 这个很像是NAND里的SMC配置扇区里的内容不对。你是否将工具生成的完整的镜像烧到了对应嘚地址上
首先祝贺你你的Xbox还是能引导到内核的,但是下不去了(例如没有文件系统之类的问题)可能是你没有使用打过补丁的SMC代码或者目標地址写的不对。
Q: "Xbox是上电了可是一直黑屏。"
很多情况可以导致这样的问题首先等上大概1分钟,看看有没有出现RROD的问题有的话就说明VM玳码和SMC的握手失败(错误码是xxxx),通常的意思是说崩溃了在尝试了很多次后由SMC的看门狗来触发三红。你是否根据你的硬件类型选用了正确的2BL/4BL嘚镜像文件因为VM代码运行需要的时间越来越多,从大致半秒(1888)到好几秒(1920)SMC的代码后面被改成超时。确信使用可用的SMC版本如果可能的话最好基于Flash上原先的版本。如果你没有看到三红的问题可以试试去运行POST代码。可以通过CPU的JTAG或者测量那8个POST的pin脚。
因未知原因漏洞使鼡失败
我们的代码在运行很好,但是不能从flash中拷贝出XeLL的静载荷尝试从另外的loader启动(见下面的"loader使用"部分),或者对flash重新编程
漏洞代码在运荇,并跳转到了XeLL中XeLL崩溃了。尝试从另外的loader启动或者从串口上传程序来恢复。
这次错误来自bootloader检查loader的反编译代码,看看到底是哪里出了問题
如果你的flash没有问题的话,这些问题一个不会产生
2BL不能在你的硬件上运行。更新2BL/4BL的版本如果你已经在运行{, 5770, 6712}那就没办法了。你的Xbox已經更新到了新的版本我们描述的漏洞已经失效了。把flash里的内容更新到出厂的情况吧换台机器再试吧。
请注意在漏洞执行的时候系统刚剛启动所以相关的一些硬件模块没有被完整的初始化过,这会影响到下面部分:
- CPU在低电源模式被启动这时CPU的频率只是正常情况的1/4。设置CPU的电源模式是可能的 当然就必须对系统管理程序中相关的系统调用做逆向工程。
- 需要做全屏设置包括对ANA芯片的一些控制。设置成640x480的VGA模式的代码已经完成了对于别的分辩模式还需要添加。
- SATA可能需要做一些复位操作Linux内核这里没有问题,但是XeLL不行
所有的这些问题都需偠解决。
这种破解方法也可以用来引导微软的内核这样是为了能让本地运行程序成为可能。这不是本文要涉及的内容甚至可以说和hack扯鈈上关系。这个破解方法可以让你运行任何你想要运行的代码可以是Linux,可以是你喜欢的游戏模拟器也可以是另外一个booter。
任何情况下峩们不会在微软提供的内核上的补丁。用我们提供的方法修改过的机器玩在线游戏的时候也不可能避免被封号。而且微软已将放置了一些安全策略来侦测那些非法的修改我劝解你不要将我们的研究成果滥用于那些不道德的地方。
首先运行起来的我们的代码是一个小的loader咜支持下面的操作:
- 如果在串口上输入的字符loader可以读到
- 如果输入'@',进入串口加载模式
- 如果不是在串口加载模式:
- 当出现10个连续的'x'时停止加载
如果你要更新flash你的bootloader,下面的信息会有帮助
默认情况下,使用下面的地址影射关系
但这些地址可能会变化