如何对西数硬盘固件进行逆向分析

2016-04-25 +12 450057人围观 ,发现 11 个不明物体 极客

Hardware-CPU-l.jpg

几年前我就开始BIOS rootkits方面的东西(在UEFI成为主流之前)。我知道在初始化启动过程的后期阶段,大多数硬件都有一个BIOS类型设置 我的主要关注GPU和硬盘。本文所做的是我曾经 spritesmods 上看到的一些东西。

硬盘破解

我发现一个老版本的西部数码硬盘驱动器很适合现在的研究,所以我把控制器卸下来。

图片1.png 

Spritesmods上的那个家伙把固件的闪存芯片弄下来然后把里面的内容全部拷贝出来了,这里唯一的问题是红圈中闪存芯片这个地方。

红圈的上方是Marvell 88i8846-TFJ2 ARM处理器,有内部的闪存。

图片2.png 

JTAG的头是很知名的,虽然可以被颠倒(在我的案例中头部的第一个pin点用1标识)。Pins  611是我们需要的JTAG金属圈。

正如你可以看到的,我们决定不焊接pins点。主要原因是其有点生锈并且离得太近,所以很容易把单板弄坏掉。作为替代我决定使用测试点,这可以用万用表的“连续”模式实现。

图片3.png 

通过设置万用表的这个模式能够得到两点之间的电阻,‘1’代表完全绝缘(这意味着这两点是不通电的),‘0.01’代表互通性很好。当电阻很低的时候,仪表会发出声音(难以忍受的噪音),所以我们只需要通过声音来判断两点之间是否连接即可。

将硬盘驱动器断开,只要把你要测的两点用万用表测一下即可。然后移动其中一段到其他点上,直到听到蜂鸣声为止。在我的单板上你会发现从头部的pin点到测试点有可见的数据行,这给了你很好的入口(前提是你的视力很好)。

我不想将硬盘插入到我的电脑电源上以免出现一些错误,并且我的电脑在房间的对面,所以我也不想搞个10米长的SATA数据线。下面是我的解决方案:

图片4.png 

如果你有备用电源,在没有连接到主板的情况下,你可以将ATX的第三个和第四个pin点短路来将它开启。我的备用电源很老并且少一个风扇,所以我很惊讶居然没有短路和起火(我的房子的所有设备都在一个断路器上,所以短路的话我得花一个小时重启所有设备)。

图片5.png 

我使用5美元的SATA来连接USB,这是一个很好的方法。右边的红色单板使用了一个30美元的TIAO USB多协议适配器,基于FT2232H同时以可以用SPIJTAG

图片6.png 

在这里我有一个愚蠢复杂的设置,由于我的windows机器放在房间的另一边,iMacJTAG软件运行了一个linux虚拟机(FTDI驱动和OpenOCD)因为这在windowsOSX上安装很麻烦。 Windows系统运行IDA来逆向和调试(当我开始动态调试时我打算在本地网络上用IDA连到OpenOCDGDB服务器上去)。

现在所有要连接的东西都已经准备好了,给硬盘插上电源然后输入下面的命令:

openocd -f interface/<your interface here>.cfg -f target/test.cfg

需要先为你的硬盘控制CPU配置test.cfg文件,对于大部分marvellCPU这个配置都有效。我不知道khz适配器行不行,所以我将mine设置成100(由于这个值低于它正常的工作值)。

图片7.png 

如果一切正常,你会看到这些信息。现在你可以telnet4444端口然后发送命令了。

图片9.png 

硬盘控制器用的Marvell芯片没有公开的文档,所以如果你想了解相关信息比如内存布局,你需要在NDA上注册然后付费。作为替代,我想要做的是尽可能在固件上和通过探测电路找到更多的信息。

如果你们没有办法焊下闪存并导出信息要得到固件并不容易,所以我们将会在boot进程下工作。 大部分ARM CPU的起始执行地址是0xFFFF0000,这是复位向量。如果我们从这个地址导出65536字节,我们将会找到启动代码,这是一个很好的入口点。

为了导出内存,我们首先要停止CPU,可以使用命令reset halt(这是必要的因为我们没有办法在任何一个阶段都能停下来)。如果这个命令没有效果可能是JTAGRST pin点没有连接,你需要断开并重连硬盘的电源然后快速的修复这个JTAG问题。内存导出用以下命令

dump_image <file name> <address> <size>

图片8.png 

 

当我们将导出的镜像文件反汇编时,它是一个很小的只有4KB的启动代码,这段代码能够引导剩下的固件。

我发现JTAG的重置点不是真的系统重置(SRST)只是一个TAP重置(TRST),这对调试不是很有用。这里是对系统重置信号的添加(这样允许重置停止命令在重置向量上中断下来,在任何指令执行之前)。

图片10.png 

在我的例子中没有SRST行的测试点,但是在序列标签下面有暴露出非常小的镀铜位,这个可以用来连接CPUSRST pin点。

红迪网上的Ceriand指出JTAG头跟MICTOR连接器很像(通常是3840pin点)。所以如果你不想做任何焊接工作你可以找一个MICTOR连接器和数据线。

图片11.png 

同时我发现老版本的PSU硬件无法在低电压下使用(内部的组件可能会爆炸),所以我推荐为Molex电源适配器买一个好的AC(不要买便宜的,一天就坏掉了)。

 图片12.png

最后,由于JTAG头有一个RTCK连接器,你需要将opencdadapter_khz配置为0. 这样JTAG能够使用自适应时钟,这样你能够防止所有超时错误。

引导和引导程序

通过一些逆向我确定第二部分的引导代码无法在正常的启动中使用。执行的时候在一个端口上等待一些数据(最有可能是串行端口),然后采取相关的行动。如果没有数据到来,这段代码将进入一个死循环驱动将永远不会启动。

图片13.png 

PCB周围的端口和测试点映射到CPU0x1C00A000-0x1C00AFFF范围上。现在,由于我没有钱买示波器或者像样的逻辑分析仪。我不得不通过这些端口映射,这样会使事情变得更容易。

所有的这些代码都是为了基于一些值读取进入系统特殊模式的开关:

4-不确定,当它为了一些端口的值进行无限循环。我猜这些值是允许开发者读取/写入/ 擦除处理器内部的闪存。

3-跳转到R4的地址(我的例子中这个值为0,但可能是设计的原因)

6-串行端口的串行控制台可以用ASCII字节(rwjh),可以让开发者发送读取, 写入,跳转和停止命令。

我对端口如何映射到内存不太熟悉,0x1C00A030总是为00x1C00A03A总是为0xFFFF(我认为这一个是低电压常数一个是高电压常数)。

有趣的是在“cmp R1#R3”上设置断点将R3设置成3,代码会跳到地址0然后正常启动(这就是我认为为什么0不代表未初始化)。让我们看看地址0有什么。

图片14.png 

地址0通常是RAM,但已经有一些有效的代码了,所以很可能是在启动过程中CPU临时映射地址0到一些内部只读存储器。这是标准的ARM IVT,你可以在任何ARM设备的启动地址看到;使我想到CPU检测到JTAG附加进来时0xFFFF0000上的启动只是被执行了。在我买到逻辑分析仪并找到哪个端口允许我控制启动模式跳转之前,唯一通过JTAG正常启动硬件的办法是在校验之前执行“重置”然后将R1设置成3.

在这个例子中启动代码是节与节之间差距最大的地方,后续有机会我会将它进行映射,导出,并逆向。

*参考来源:malwaretech.com ,FB小编老王隔壁的白帽子翻译,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

这些评论亮了

  • manfeel (1级) 回复
    翻译的质量很差啊 :smile:
    原文:Above the red circle is a Marvell 88i8846-TFJ2 ARM processor which has internal flash.
    这么关键的地方,居然被翻译错了
    )16( 亮了
  • occdasoiday 回复
    看到这个我想起来硬盘里以前学数据恢复的时候备份的一大堆固件了
    )10( 亮了
  • @ manfeel  不好意思,漏看了above.... 马上修改。
    )9( 亮了
  • 虽说看不明白楼主在说什么,不过还是支持一下楼主吧
    )9( 亮了
  • 把病毒写入bin里面就无敌了。别想杀软能找出来
    )8( 亮了
发表评论

已有 11 条评论

取消
Loading...

特别推荐

推荐关注

填写个人信息

姓名
电话
邮箱
公司
行业
职位
css.php