c语言sscanf函数的用法是什么
285
2022-11-19
硬盘可以被恢复 具体做法分享
硬盘:如果你在看这篇文章,我肯定你起码用过一两个硬盘。硬盘很简单,基本就是一些512字节的扇区,由递增的数字标明地址,称之为 LBA,也就是“逻辑块寻址”。电脑可以向连接的硬盘的扇区中读写数据。通常会有个文件系统把这些扇区抽象成文件或文件夹。
要想知道硬盘是否可
以被破解,我需要更了解它们。如咋们大多数人一样,我们手上也有一摞或坏或旧的硬盘,下面来一看究竟:
可以看见PCB上有四块芯片。接下来说说这些芯片:
这个是电机控制器。这不是个标准器件,数据手册不好找,但是这些控制器一般都有容易找的差不多的同系列产品。ST Smooth控制器大概是最常用的一种了;除了驱动电机,它还能进行电源整流,还带一些A/D变换通道。
这是一块串行闪存。这个也好处理,容量一般在64KB到256KB之间。看起来这个是用来存储硬盘控制器的启动程序。有些硬盘没有这个芯片,而是在控制器芯片内部有闪存来存储程序。
不幸的是,这些芯片都没有文档。话说这些制造控制器的厂商不公开文档有些不厚道真是说轻了:他们甚至在自己的网站上都不提这些芯片!更不幸的是,整个互联网也帮不了我:搜这些芯片手册只能找到没有手册的手册网站,和卖芯片的中国厂商……
那么,没有最重要的芯片手册,就意味着我们的计划搁浅了么?
连接JTAG
幸运的是,总有些办法找到除了芯片手册以外的有用信息。我就搜到这么一个。
嗯,这些是我的准备工作:
现在的问题是:这玩意真能工作么?Dejan用的是88i6745控制器的2.5” 250G硬盘,他检测到的是ARM9内核。我找的是88i6745控制器的3.5” 2TB硬盘,有不同的格式因素,而且有点新。幸运的是,OpenOCD可以自动检测JTAG连接的设备。如下所示:
这我就有点搞不懂了……我本来估计会有一个tap,就是单独的ARM内核……可这里竟然有三个tap……难道这个片子有三个ARM内核?
Feroceon 1 处理对磁盘的物理读写操作
Feroceon 2 处理SATA接口
Feroceon 2 同时处理缓存以及将逻辑块寻址翻译成柱面/磁头/扇区
Cortex-M3 貌似啥都不管?我给他关掉硬盘也没啥问题。
现在从哪个核心开始破解呢?我的目标是通过使用修改的硬盘固件来影响系统的安全。最简单的方法,同时也可能是最难检测的方法就是直接修改数据。这种方法不需要修改磁盘上的数据,固件可以使自己隐身不可见。为此,我需要找到一个合适的核心来进行监听:我需要一个能在从硬盘到SATA线的传输过程中接触到数据的核心,同时可以被操纵在磁盘和SATA线缆之间修改数据。
如果是这样的话,DMA引擎指向的内存会在哪呢?硬盘的缓存是个好地方:数据从磁盘读出来总是要放进缓存的,所以当读取磁盘的时候马上去那里复制也就说的通了。我之前发现第二个Feroceon负责管理缓存;于是它就成了我的首选目标。
没错,找到了!看起来Feroceon2号可以读取缓存,并对这块64MB的DRAM进行了地址映射。
注入代码
当然了,如果我想要在缓存里修改数据,我可不能每次都完全扫描整个64MB的缓存:我需要知道缓存是如何工作的。为此,我需要进行反汇编并理解硬盘的固件,至少要明白缓存的函数。
对固件进行反汇编,可不是个简单的活。首先,代码混合了ARM和Thumb指令,如果你没有自动切换两种指令的反汇编器就很令人抓狂了。而且,没有那些能使反汇编更简单的信息了:一般程序都被写好了,当有东西出错总会弹出类似「Couldn’t open logfile!」的信息。这些信息对于了解代码功能有很大帮助。而这个固件,一条信息都没有:你得自己看代码来知道代码在做什么。代码库好像有点老,而且有些时候反汇编的感觉就像给代码加了很多特性,把所有事情都搞得更复杂。
当然,也有几件事使得反汇编相对简单些。首先呢,西部数据没有故意混淆代码:没有在指令中间用些跳转的招数。还有,因为JTAG接口的存在,你可以干预代码的执行,设置断点,或者直接修改,让你非常容易地知道程序在做什么。
缓存描述表的每一项描述了缓存中的一个块。它包含了可能在缓存中的磁盘扇区的起始LBA、缓存中存有多少硬盘数据、一些标明了缓存项的状态标志符,还有一个标明了缓存数据在内存中未知的数。
现在,缓存描述符表的秘密还没有被揭开,我能否在数据送出SATA口之前截断磁盘读取码?为此,我需要在磁盘控制器上执行我自己的代码。不仅如此,我还需要确定代码能否在正确的时间运行:如果它修改缓存太早,数据还没进去;如果太晚的话,数据已经送到PC了。
我的方法是绑定在一个已存在的任务上。我破解的是Feroceon2号,这个CPU负责所有的SATA传送,所以肯定有个服务是负责设置SATA硬件去缓存中读取数据。如果我找到这个服务,我就可能在它之前运行我的代码。
在看了很多代码,设置了很多断点,修改了很多次之后,我最终找到了某个符合条件的服务。我通过连接让这个服务在执行前先运行我的代码。这是原来的代码:
000167BE ; r0 - slot in sata_req
000167BE sub_0_167BE:
000167BE PUSH {R4-R7,LR}
000167C0 MOVS R7, R0
000167C2 LSLS R1, R0, #4
000167C4 LDR R0, =sata_req
000167C6 SUB SP, SP, #0x14
000167CA LDRB R1, [R6,#0xD]
000167CC LDR R2, =stru_0_40028DC
000167CE STR R1, [SP,#0x28+var_1C]
000167D0 LDRB R0, [R6,#(off_0_FFE3F108+2 - 0xFFE3F0FC)]
000167D2 LDRB R5, [R6,#(off_0_FFE3F108 - 0xFFE3F0FC)]
000167D4 LSLS R0, R0, #4
这是改成连接到我的代码之后:
如你所见,原来的指令被跳转到的新代码替代了,新代码放在本来没用到的地址0xFFE3F000,然后又加了一句,保证代码域的校验和有效。如果没这么做的话,硬盘会尝试从盘片上读取备份,那可不是我想要的。跳转的代码执行了一个服务,叫做「changeThingsInCache」然后执行修改代码本该做的指令。最后接着执行本来的服务好像什么也没发生过一样。
这一小段代码会在每次调用的时候用0×12345678代替缓存中每个扇区的前四个字节,所以如果我把这个上传到硬盘的话,我在我看到的每个扇区前面都会看到这个数字。我通过JTAG上传了代码……
然后你看:
一劳永逸
当然了,我可以将固件完全破解,但是每次硬盘启动都需要用JTAG修改RAM,这就得不偿失了。我得让它保持不变,也就是说,我要把我的修改存在某个地方,每次硬盘启动都会带上这段修改程序。
现在,应该在闪存里写什么呢?很幸运的是,芯片中存储的格式已经找到了:它包含了多块数据,还有一个表在最开始描述了这些数据。这个表描述了闪存中代码块的位置,如何压缩的(如果压缩了的话),代码块应该在放在RAM的什么位置,而且在最后的地址中是一个执行指针,标记了启动器应该跳到什么地方去执行程序。
不幸的是,我不能修改闪存中的代码;我想加钩子的地方的数据被某种不知道的压缩算法压缩了,我就不能修改了。然而我能做的是增加一个额外的代码块,修改执行地址这样这个代码块就可以在其他之前执行了。这样一来就简单多了。当我的代码块执行的时候,我就可以在已经解压的代码中加入我的钩子了。
结果并不新鲜:就是我之前做过的。唯一的变化就是我不用JTAG就能办到了。
刷软件
虽然闪存这边有了很大进展,我还是不能开始我的黑客脚本:我相信不会有任何一个服务器公司会接受这些带有反汇编又重汇编的芯片的硬盘。我需要想个办法能让芯片不从板子上摘下来就可以刷固件,最好是能直接在硬盘安装的电脑上刷。
有了这个工具,我的攻击基本完成了,如果一个黑帽子黑客获得了一个带有这样硬盘驱动器的服务器的最高权限,他就可以使用fwtool远程获取硬盘闪存,修改然后刷回去。最终,主机的主人会发现我用他的主机为非作歹,然后可能会重装系统,断掉黑客原来进入主机的路。
但是有了这个破解了的固件,攻击者可以操纵硬盘在新安装的系统里继续为非作歹。首先他需要触发行为,这需要事先在硬盘里写入一个破解固件需要的某个特定字符串。这个字符串可以在任何一个文件中:攻击者可以向服务器上传一个带有代码的.jpeg文件。他也可以通过向服务器发送在URL中追加了特定代码的文件请求来实现。这最终会在服务器的记录文件中结束,触发利用。
接下来,被破解的硬盘固件就开始捣乱了。比如,他会等待主机读出/etc/shadow中的文件,其中存储了Unix/Linux的所有密码,然后立即修改成攻击者之前写进去的一些东西。当攻击者之后尝试用他自己的密码登入系统的时候,主机会根据修改过的/etc/shadow判断密码,攻击者就可以再次轻松登录。
这是我做的演示。你可以看见我没能成功登录主机的根用户。然后我启动破解,给它一个代替密码的哈希值,也就是密码「test123」。因为Linux系统把影子文件缓存了(如同所有最近存取的文件),我需要制造很多硬盘活动把缓存清出去;这样,当我再次登录的时候,Linux系统会再次读取磁盘上的影子文件。最终,缓存已清空,我可以用假的「test123」密码登录根用户了。
其他用法
当然了,恢复服务器中清除的隐秘登录方法并不是我研究成果的唯一用法。这同样可以用于防御目的。
例如,你可以做一个不可复制的硬盘:如果扇区的读取模式是随机的话,像正常的操作系统读取文件系统,硬盘会正常工作。如果硬盘是有序的读取,像硬盘复制设备那样的话,硬盘会篡改数据,无法复制出原来的内容。
在此多解释一下这是怎么工作的:内核和启动都封装成每块大小都是一个扇区的一个个的包,包的前面带有特殊字符串和编号数字。通过从磁盘读取数据,内核和启动最终会进入缓存。写入特殊字符串「HD, Inx!」最终触发了修改过的固件,在缓存中搜索所有扇区,重编译内核然后启动。但是一个没有内存控制单元的内核也需要特殊格式的用户空间。我不能把这个也编译了,所以内核最终因为找不到init来执行而崩溃。
结论
是的,就是这样。虽然硬盘控制器如同一个不知其究竟的野兽,它仍能通过逆向工程加以了解,并为其写出代码以执行。对控制器的未知,使得通用破解充满难度,令我怀疑这东西是不是永远不会出现一个恶意的固件补丁:相比对每个服务器的每个硬盘固件进行逆向工程加以破解,还是找一个0day漏洞更加简单吧。
我还希望证实一个坏掉的硬盘仍然能够使用。当硬盘的机械部分坏掉的时候,PCB仍然带有可用的嵌入式系统,其性能相当不俗,尤其是坏的硬盘基本都不要钱就能拿到。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~