浅析硬盘攻击面

badmonkey 2021年10月29日 1,329次浏览

硬盘攻击(Hard disk hack)

背景

硬盘使用的非常广泛,用起来也比较简单,只要接到sata口就可以在硬盘上进行读写操作。那硬盘是如何处理损坏的block,以及是否存在缓冲机制呢?种种迹象表明,硬盘也是存在某种管理机制的,既然存在管理的机制那么也是可能被hack的!本文研究硬盘是否可以被hack,并利用hacked的硬盘绕过软件的安全检查机制。

PCB

为了更好的了解硬盘的攻击面,需要了解硬盘本身。作者首先将目光聚集到了硬盘的PCB板子上,这个板子负责电源以及SATA的工作。

IMG_2271.JPG

板子上有几个芯片需要关注一下,作者拿的这块板子,有单独的flash(flash用于保存硬盘的固件)

tmb-ic_flash.png

但是有的板子没有单独的flash,flash存在于hard disk controller中

tmb-ic_hddctl.png

难点

这些hard disk controller没有公开的手册

JTAG

虽然没有详细的手册,但是板子上存在JTAG,通过JTAG口可以控制controller,比如stop,restart,modify memory,甚至下断点。有人还找到了dump出controller boot rom的方法。作者研究的西数(western digital)controller使用的是arm架构,可以通过JTAG访问到arm-core,同时还可以通过没有被使用的串口做调试信息的输出口。作者用于调试的板子

http://meuk.spritesserver.nl/foto/foto/hdhack/IMG_2294c.JPG

红色板子连接硬盘的JTAG和Serial口,使用openocd驱动JTAG。

通过JATG可以看到如下的一些信息

multicore.png

发现存在三个tap,每个tap对应一个arm-core,研究发现这个芯片确实存在三个core,两个arm9-core一个cortex-m3,每个芯片的功能不太一样。

  • core1(Feroceon1)负责硬盘的物理读写
  • core2(Feroceon2)负责sata接口以及缓存,和LBA到CHS的转换
  • cortex-m3功能暂时不清楚

首先要确定攻击点,毕竟有三个core,那么攻击那么core呢?

作者的思路是如果一个core能够在数据从disk转移到sata-cable时,对数据进行修改(或者修改cache中的数据),那么就可以实现数据的动态修改(用户无法发觉到,也很难检测到)

作者通过cpu的读写速率和硬盘的读写速率推测出,数据读写使用到了DMA(直接从memory中读取数据),那么DMA使用的memory位于哪里呢?答案是硬盘的cache,而Feroceon2负责管理cache,所以作者将攻击目标定为了Feroceon2.作者对Feoceon2的内存布局分析

memmap.png

通过挂载硬盘,然后向硬盘写magic string,然后定位magic string的方式,发现cache对应的是64MB的DRAM区域。

cachedemo.png

难点

需要逆向分析出core的内存分布

代码注入

想要任意修改cache的内容,需要dump并逆向硬盘的固件,寻找并理解硬盘的缓存机制(对应可以修改cache的function)

西数的固件arm架构的包含了ARM和thumb指令,没有反编译器不好搞(ida应该可以操作)

难点

逆向的时候几乎没有字符串信息(比如一些便于理解函数作用的字符串"Couldn't open a logfile"固件中几乎没有),所以只能通过看伪代码理解函数的用途,而且比较恶心的是,固件的代码风格比较差,一些修补bug的代码,让伪代码看起来比较奇怪,加大了逆向的难度。

不过这仅仅是13年西数的一款硬盘,其他硬盘的固件是否也想这款硬盘一样难以逆向还不得而知

优点

没有代码混淆,可以通过JTAG进行动态调试
经过作者的逆向分析,发现了缓存时,在RAM中存了一个table,cache descriptor table,表项中每一项都描述了缓存中的一个块,包括了对应缓存在硬盘扇区的起始LBA,用于指示缓存在内存中的位置的一个数字,缓存状态的标记,等等。

知道了缓存表的存在,还需要让Hard disk conroller执行恶意代码,让其在正确的时间修改从硬盘中读取的数据为恶意的内容。作者找到了一个function,这个function主要是负责在SATA从缓存中读取数据之前做准备工作。通过hook这个代码,更改程序流,执行恶意代码。

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
000167C8                 ADDS    R6, R1, R0
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,然后跳回去

000167BE ; r0 - slot in sata_req
000167BE sub_0_167BE:
000167BE                 PUSH    {R4-R7,LR}
000167C0                 MOVS    R7, R0
000167C2                 LD      R6, =hookedAddr
000167C4                 BX      R6
000167C6                 .dw     checksumFix;填充的checksum 保证程序不会跑飞
000167C8                 .dd     hookedAddr;
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
...
FFE3F000                 PUSH    {R0-R12, LR}
FFE3F004                 BX      changeThingsInCache
FFE3F008                 POP     {R0-R12, LR}
FFE3F00C                 LSLS    R1, R0, #4
FFE3F010                 LDR     R0, =sata_req
FFE3F014                 SUB     SP, SP, #0x14
FFE3F018                 ADDS    R6, R1, R0
FFE3F01C                 LDRB    R1, [R6,#0xD]
FFE3F020                 BX      0x167CC

插入的伪代码

void hook() {
  foreach (cache_struct in cache_struct_table) {
    if (is_valid(cache_struct)) {
      foreach (sector in cache_struct.sectors) {
        sector[0]=0x12345678;
      }
    }
  }
}

通过JTAG可以注入代码

1sthack_1.png

效果示意图

tmb-1sthack_2.png

Persistence

上述的方法,需要每次通过JTAG注入代码,才能任意修改硬盘数据,想要不用JTAG维持注入的代码,考虑将flash进行注入。

IMG_2106.JPG

flash的格式已经有人研究过了。其包含了一系列的block data,在起始位置有一个表记录了blocks的信息,表中记录了blocks在flash中的位置,以及blocks是如何被压缩的,blocks要被放在RAM的位置,和loader程序执行的起始地址。

不幸的是,无法直接修改flash中的程序,因为其被压缩过了,但是作者通过添加block的方式,然后更改程序执行的起始地址,实现程序的劫持,此时可以将恶意代码写入到flash中去。

难点

提取flash固件

Software flashing

之前刷写flash的方式,需要将flash拆下来,然后再焊回去,在真实场景中,不可能给你拆flash的机会,所以需要考虑能否通过不拆flash的方式,重新写flash。

西数官方的固件升级软件,可以将固件刷写到flash和硬盘的保护扇区中。具体的名称是Vendor Specific Commands,作者将其集成了一下,写成了一个工具(fwtool),通过这个工具,可以dump flash 固件然后修改flash 固件,最后将其刷入flash。

应用场景:

更改/etc/shadow

结语

总的来说,攻击硬盘的思路分为两步,第一步提取硬盘固件(通过JTAG),逆向分析芯片工作原理,并编写恶意代码,实现任意数据改写,第二部是改写flash,由于flash一般不能写,可能需要官方的或者非官方的软件对flash进行刷写操作(不考虑硬件刷写flash,真实场景难以实现),在flash中进行恶意代码的植入(将之前编写好的恶意代码写到内存中),就可以实现恶意代码的维持。

不过由于不同的硬盘的固件可能不一样,而且逆向的工作量太大,这么多时间完全可以去寻找其他的0day(原文作者说的,本菜鸡逆向起来可能需要更多的时间),所以虽然攻击面有了,但是做起来还是吃力不讨好。但也算是了解了硬盘攻击的基本流程。

部分源码

http://spritesmods.com/hddhack/hddhack.tgz

参考链接

Hard disk hacking - Intro

How hackers could attack hard drives to create a pervasive backdoor

Hard Disk Firmware Hacking (Part 1) - MalwareTech

Hard Disk Firmware Hacking (Part 2) - MalwareTech

Hard Disk Firmware Hacking (Part 3) - MalwareTech

Hard Disk Firmware Hacking (Part 4) - MalwareTech

Hard Disk Firmware Hacking (Part 5) - MalwareTech