一个完整的设备接管&第一次使用红外线的只读存储器转储,而不需要事先知道它运行的代码。
这是一篇相当长的文章。本文分为几个部分。对硬件的概述,对没有文档记录的硬件的非常酷的远程攻击,有很多血淋淋的细节,然后是许多反工程的精灵宝可梦特定的数据,这将是Romhacker感兴趣的。如果你愿意,请随时跳到技术部分,实际漏洞,ROM分析,更好的漏洞,精灵宝可梦游戏特定信息,或下载。
PokéWalker于2009年面世,与Pokémon HeartGold/SoulSilver并驾齐驱。它的目的是鼓励玩它的孩子更活跃。基本的想法是,作为游戏的伴侣,它会奖励玩家走路,从而鼓励更多的走路。奇怪的是,在PokéWalker问世时,一项研究认为它是当时最好的计步器之一。精灵宝可行者通过红外线与游戏进行交流。由于任天堂DS没有红外线硬件,所以实际的游戏盒包含一个红外线收发器。这实际上很有趣,因为假冒墨盒不会。这意味着eBay上的大多数精灵宝可梦红心/灵魂银游戏都不能与精灵行者一起玩。幸运的是,大多数卖家对此都很坦诚。
那么,精灵步行者到底是如何在其自然栖息地工作的呢?它计算步数,每走一步就给用户一个叫做瓦特的能源单位。瓦茨可以在步行器上用来交换迷你游戏,也可以被送回Nitendo DS游戏用来解锁那里的东西。这里有一个概念,那就是你正走在一条路线上,前面有两条没有锁的路线,随着更多瓦数的增加,还有更多的路线被解锁。根据路线的不同,你可能会发现不同的稀有精灵或物品。物品和精灵宝可梦的发现也会受到所采取的步骤数量的影响。这款游戏包含27条路线,其中20条可以通过瓦特解锁,7条可以通过特殊活动解锁。你也可以上传一个精灵宝可梦给步行者,带着它散步。有了足够的步骤,精灵宝可梦可能会更上一层楼。精灵步行者也可以与另一个精灵步行者互动!如果两个都在范围内,并且用户请求通信,他们将允许每个人中的精灵宝可梦与另一个人一起玩。每个屏幕上都会显示一个动画,每个玩家都会被随机赠送一件物品。关于另一个同龄人的团队数据将被保存并稍后转移到DS游戏中,因此该玩家可能会在教练之家进行战斗。
用户界面是96x64 2位灰度屏幕。前面有三个用于用户交互的按钮,它们的功能或多或少分别为";左";、";右";和";中";。界面可以拆分成几个独立的部分,我将每一个部分都称为微应用程序。这些微应用程序包括:睡眠、主页、菜单、雷达、Dowsing、Comms、Stats、Inventory和Setting。睡眠是一款处理低电量睡眠的微型应用。屏幕已关闭,正在清点步数。退出此微应用程序只需按住Enter按钮一秒钟即可完成。主页是主屏幕,展示了行走的精灵宝可梦动画、当前的步数、当前路线的小图像(洞穴、海滩等),以及屏幕底部显示当前库存的一些小图标。按下此屏幕上的任何按钮即可进入菜单。在这里,人们可能会推出其他微型应用程序。雷达可以让你寻找和捕捉路线可用的精灵,只需10瓦的成本。搜索功能可以让你以3瓦的价格搜索并获得路线上可用的物品。Comms是一款微型应用程序,可以处理与其他精灵宝可行者设备的红外线通信,以及任天堂DS中的精灵宝可梦红心金色/灵魂银(Pokémon HeartGold/SoulSilver)游戏。统计数据、库存和设置正是您所期望的。
精灵宝可梦红心金色/灵魂银牌游戏支持多种语言,包括一些亚洲语言,这些语言呈现起来很复杂。PokéWalker的制造商想出了一个非常聪明的解决方案,既可以在设备上呈现文本,又必须支持许多复杂的语言:Don;T。可能需要显示的每一个文本字符串都会转换为图像,并上传到设备的EEPROM中。这样,无论何时有什么需要说的,都很简单,只需展示一张图片即可。因此,当精灵宝可行者被绑定到一款游戏上时,所有的信息图像都会以适当的语言发送给它。他们有很多人。
口袋妖怪已经在精灵宝可梦黑客社区的雷达上出现了一段时间了,但尽管在十年后发布了,但在获得ROM转储方面并没有取得任何进展。
关于通信协议的文档很少(遗憾的是,我是在自己弄清楚之后才发现的),但它是不完整的,有时甚至是错误的。
EEPROM的数据也在某种程度上被解读了(遗憾的是,我是在自己弄清楚之后才发现的),但也是不完整的,有时甚至是非常错误的。
当然,识别硬件是入侵设备的第一步。根据标志和标记,EEPROM是第一个被识别为ST M95512 64KB SPI EEPROM的。接下来是CPU。它是瑞萨H8/38602R系列的成员。具体地说,就是鲜为人知的H8/38606病毒。加速度计是博世BMA150。红外收发机是一种通用的SIR兼容产品,没有任何明显的特点。这个显示屏更难辨认,我直到这个故事的后面很久才能辨认出来。EEPROM芯片用于存储数据,并可通过SPI轻松读出。
CPU是H8/300高级衍生产品。我以前从来没有使用过这种CPU,但是在你完成了100个CPU的组装工作之后,101是非常容易掌握的。这一次在几个方面很有趣。首先,我甚至不确定该怎么称呼它。它是8位、16位、24位和32位体系结构的混合。H8/300CPU可以对8位、16位和32位数量进行数学和逻辑运算。它可以进行多达16位的除法和乘法运算,指针长度为24位。这里的实际SoC,H8/38602R处于正常模式,这意味着它忽略任何地址的前8位,因此具有64KB的地址空间。地址空间是统一的,既包含代码又包含数据。有8个32位寄存器er0-er7(通常是堆栈指针)。每个32位寄存器ERX可以作为两个16位寄存器被访问:EX(高16位)和RX(低16位)。RX 16位寄存器中的每一个可以作为两个8位寄存器RXL(L0 8)和RXH(Hi 8)来访问。存储器映射如下:0x0000-0xBFFF-ROM、0xF020-0xF0FF-MMIO、0xF780-0xFF7F-RAM、0xFF80-0xFFFF-MMIO。传统上,使用完整的、向下的堆栈。CPU是大端的。支持在线调试,但芯片在编程时会自动擦除,因此无法以这种方式转储。
他们的目标是在不诉诸极端手段的情况下破解该装置。它唯一的通信方式是通过IR,所以我必须弄清楚它是如何工作的。使用红外收发器捕获脉冲时,显示的脉冲与115,200,8n1处的SIR信号一致。这似乎合乎逻辑,我就顺其自然了。我使用带有红外收发器的STM32F429开发板来捕获一些数据。往返发送的数据通常有很多0x55和0xAA字节。一般来说,你会期待更多的0x00和0xFF。重复操作表明正在使用简单的XOR运算。经过一些分析后,我得出结论,发送的每个字节在发送之前都只是与0xAA进行了XOR运算。对捕获的数据执行此操作会产生有意义的跟踪。又过了几个小时,最低层协议的框架浮出水面。
每个数据包前面都有一个8字节的报头,该报头由1个字节的命令、1个字节的额外数据、2个字节的校验和和4个字节的会话ID组成,总共8个字节。校验和花了一点时间才算出来,但在捕获了一些游戏到步行者的交换后,我想出了协议。后来证明,我几乎是正确的,但不是完全正确,但已经足够接近了。对整个数据包及其有效负载计算校验和,就好像校验和字节本身包含零一样。首先,将所有偶数字节相加,然后将奇数字节相加。偶数和乘以256,然后与奇数和相加。然后将和的前16位加到后一位上,直到在前16位中没有更多的设置位。验证是以同样的方式执行的:将校验和设置为零,计算正确的校验和,对照接收到的校验和进行检查。请参见0x0714:calcPacketCrc。步行器通过每几百毫秒发送0xFC字节来通告自己。这是唯一寄出的非包裹的东西。
一些更多的观察揭示了一个更高级别的协议。命令从DS发送,从步行器回复。当两个行尸交谈时,一个扮演主人,另一个扮演奴隶。来自主机的几乎所有命令都将额外的&34;字节设置为0x01,回复几乎总是将其设置为0x02。在看到0xFC字节通告后,主机将发送0xFA类型的数据包。会话ID将是一个随机的32位值,没有任何意义。从设备将回复0xF8数据包,会话ID将是另一个随机值,该值由从设备生成。这两个值的XOR将成为会话ID,对于通信的其余部分,两端都将忽略不包含此会话ID的所有数据包。
有很多命令用来启动和停止漫步,以及两个步行者之间的对等游戏,但所有的场景都很繁重,只能是EEPROM读/写命令(因为它们的内容与我后来在EEPROM芯片中找到的内容相匹配)。它变成了Clea
通常,当攻击某个设备时,人们首先会考虑哪些攻击载体是可用的。我可以给任何有志于学习这门黑暗艺术的人一个建议,那就是假设你遇到的任何代码都是由一个喝醉的学生写的。想象一下这样的人会犯什么错误,然后去督促,看看你能不能找到它们。这个方法还没有让我失望过。
因为我一开始对设备中运行的代码一无所知,所以第一要务就是看看我能否至少得到一些关于设备内部工作原理的情报。通过IR转储完整的64KB EEPROM除了通过SPI转储之外,并没有提供进一步的信息,而且很明显,它不包含任何代码或有用的提示。然而,压缩数据格式可能是数据外泄的载体。想想看,一个喝醉了的学生很可能不会对回溯引用进行范围检查。让我们试一试吧?让我们发送由10 80 00 00ff d0 7f d0 7f组成的压缩写入。这将精确地解压缩到128字节,但所有这些都是128字节后的反向引用,因此泄露给我们的是解压缩缓冲区之前的128字节。然后,我们读回该写入命令的EEPROM地址……然后……我们看到了一些东西。看来射程检查确实不存在了。然而,一些更多的勘探产生了一些悲哀的消息。看起来,虽然编码建议的反向引用可能高达4K,但似乎只有256字节的反向引用实际有效。看起来第一个字节的底部半字节被忽略了。对于一个解压程序来说,这实际上是有意义的,它的目标是最多128字节的解压缩有效负载,就像本例一样。不管怎样,这是一个开始。那么,我们学到了什么呢?
在解压缩缓冲区之前泄漏256个字节,表明它是我们上次发送的命令(压缩数据)的有效载荷之前的0x80个字节。在此之前(在-0x88)是命令本身的8个字节。在0x9C字节之前,这里有当前的会话ID。在这次泄漏中没有太多可以看到的其他信息。这不能告诉我们什么,但有总比没有好。至少我们现在知道,解压缩缓冲区至少有256个字节进入RAM。鉴于我们只有2KB的RAM,这实际上是有用的信息。
下一个任务是试着溢出一些东西,看看会发生什么。理想情况下,我们会看到一场崩盘。我尝试使用有效和无效的RC发送不同长度的有效和无效数据包。这条大道被封锁了。过长的命令(超过128字节的有效负载)被忽略。太短的命令被接受,垃圾被用作数据。因此,虽然他们检查了太多的数据,但却没有检查太少的数据。哎呀.。遗憾的是,据我所知,这是不可利用的。
那压缩数据呢?我们能不能让解压缩缓冲区溢出呢?我花了大约一天的时间来测试一些关于什么是重要的以及在哪里重要的理论。有几件事变得清晰起来。第一个字节,表示压缩类型被忽略。它可以是任何东西。通常接下来的三个字节表示解压缩长度,而PokéWalker只使用第一个字节(将解压缩长度限制为255个字节),其他两个字节被忽略,可以包含任何内容。将更多数据追加到有效的压缩缓冲区也不会导致崩溃。然而,调整解压后的长度byte确实产生了一些有趣的结果。但是,稍后会有更多关于这方面的内容。
由于我们被允许上传超过120个压缩字节,这意味着,从理论上讲,它可以解压缩到更多的数据。如果我们试图利用这一点发动缓冲区溢出攻击呢?第一步是看看我们是否能引发坠机。如果我们成功地用0xFFFF覆盖任何地址,我们将崩溃,因为这个CPU不喜欢从奇数地址执行,并且0xFFFF没有可执行代码。首先,让我们计算一下我们可以发送多少压缩数据。我们已经知道数据包有效负载被限制为128字节。我们知道压缩后的数据有一个4字节头,剩下124个字节可以处理。运行一些测试可以发现一些有趣的事情。如果压缩数据正好是128个字节,PokéWalker会将其视为未压缩数据,并将其直接写入EEPROM。所以,实际上我们有123个字节可以处理。这能扩大到什么程度?让我们来看看吧。每8个块前面有一个字节,每个块最多可以编码18个字节(最大反向引用长度)。因此,我们最多可以从每1+2*8=17字节的输入中产生18*8=144字节。这不是很好的压缩。最大可能的压缩比略低于8.5倍。如果您尝试实际编码的内容不是永久重复的一个字节,则此比率会降低。但我离题了.。
让我们尝试尽可能多地发送垃圾邮件0xFF字节。那个多少钱?首先,我们需要发出一个0xFF字节,然后我们将使用一个最大长度为1的反向引用来重复它。然后,我们继续讨论AS的反向引用
好的,我们知道我们可以解压超过123个字节,如果我们能以某种方式上传它们的话。我们需要的是。
.