固件加解密思路与D-Link固件解密实战操作

前言

当我们需要进行固件分析时,首先要做的就是获取固件,而获取固件无外乎就是从官网获取固件、通过流量拦截获取固件、使用编程器从闪存中读取固件以及通过串口调试提取固件。提取到固件之后,下一步就是对固件的进行分析,分析的对象主要是固件的内核与文件系统,包括Web应用、协议、核心控制程序等

但是现在大多数厂商对了保证自己家产品安全,防止被他人分析出攻击手法,就会对固件进行加密处理,可能是使用AES、DES、SM4等复杂的对称加密方式,也可能是使用XOR、ROT等简单的加密方式,加解密的程序一般放于Boot loader、内核或者文件系统。这种情况下我们就不能直接使用 binwalk 等工具提取,需要先对加密的固件进行解密。

而厂商对固件的加密一般以下面三种情况为主:

常见的固件加解密方式

1、固件出厂未加密,后续发布包含解密方案的未加密版本,最后发布加密版本

设备固件在出厂时未加密(假设此时的版本是 v1.0),也未包含任何解密释序。厂商后续会发布一个包含解密程序的 v1.1 版本的未加密固件,最后再发布一个含有解密程序的 v1.2 版本的加密固件。此时,我们可以从固件 v1.1 中获取解密程序,用它来解密 v1.2 版本的固件,然后进行固件提取。

image-20240727210019863

2、固件出厂加密,后续发布包含新版解密方案的未加密固件,最后发布新版加密版本

厂商直接在设备固件的原始版本中进行了加密,但是厂商决定更改加密方案并发布一个未加密的 v1.2 版本的新固件作为过渡,其中包含了新版本的解密程序。

image-20240727210036171

在更新固件版本之前,需要先看新固件版本的发布通告,这个通告会指示用户在将固件升级到最新版本之前,需要先升级到固件的一个中间版本,而这个中间版本就是这个未加密的固件版本。通过这个中间版本的固件进行升级,最终可获取新版本加密固件的解密程序。

3、固件出厂加密,后续发布包含新版解密方案的加密固件,最后发布新版加密版本

从网上下载的设备固件在原始版本中进行了加密,厂商决定更改加密方案并发布一个带新版解密程序的中间版迭代加密固件,但是由于对初始版本的固件就进行了加密,因此很难获得解密程序。

image-20240727210102988

此时,想对加密后的固件进行解密会比较困难。针对这种情况,一种思路是购买设备并使用 JTAGUART 调试等方法进入 Linux Shell或者 Uboot Shell,直接从设备硬件中提取固件中的文件系统。我们能做的就是对固件进行更深层次的分析,看看如何能够对加密的固件进行逆向,最后破解。

对加密的D-Link固件进行解密

准备工作

这里以 D-Link DIR-822-US 系列路由器 3.15B02 版本的固件为例进行分析。

该固件可以在官网中下载得到

1
wget <https://support.dlink.com/resource/PRODUCTS/DIR-822-US/REVC/DIR-822_REVC_FIRMWARE_v3.15B02.zip>

下载完后,我们如果用binwalk去分析固件会发现报告是空白

image-20240727210217007

我们这个时候可以用 binwalk -E 命令来查看固件的熵值(查看熵值是一种确认给定的字节序列是否压缩或加密的有效手段。熵值越大,意味着字节序列有可能是加密的或者是压缩过的)

image-20240727210203168

这里显示熵值几乎都是1,这意味着这个固件的各个部分都进行了加密

幸运的是,我们发现对应版本固件的发布说明中提到了The firmware v3.15 must be upgraded from the transitional version of firmware v303WWb04_middle.

image-20240727210226664

image-20240727210235410

利用过渡版本解密固件

结合之前固件的三种加密更新方式,这个 firmware v303WWb04_middle 很可能就含有解密程序的中间过渡用未加密固件。所以我们就可以想办法下载这个固件并找到解密方案,从而解密 DIR822C1_FW315WWb02 固件。

image-20240727210244140

这个固件我们可以去D-Link搭建的FTP服务器里下载(嫌麻烦可以在附件下载)

该中间过渡用的版本的固件没有加密,可以 binwalk -ME 直接提取

image-20240727210339167

image-20240727210351013

因为加密固件是由该未加密固件升级而来,所以我们可以在 squashfs-root 文件夹内搜索updatefirmwareupgradedownload等关键的字符串

1
grep -rnw './' -e 'update\\|firmware\\|upgrade\\|download'

image-20240727210400257

最终可以在 /etc/templates/hnap/StartFirmwareDownload.php 文件中找到线索,在浏览器中访问该文件就会执行下载固件的操作,这里有一行注释为 // fw encimg ,对应意思就是 firmwareencryptionimage

1
2
3
4
5
// fw encimg 
setattr("/runtime/tmpdevdata/image_sign" ,"get","cat /etc/config/image_sign");
$image_sign = query("/runtime/tmpdevdata/image_sign");
fwrite("a", $ShellPath, "encimg -d -i ".$fw_path." -s ".$image_sign." > /dev/console \\n");
del("/runtime/tmpdevdata");

前两行代码是用于获取固件映像签名的命令,使用 setattr 函数将属性 /runtime/tmpdevdata/image_sign 设置为 cat /etc/config/image_sign ,再使用 query 函数从属性 /runtime/tmpdevdata/image_sign 中获取固件映像签名,并将其存储在变量 $image_sign 中。

image-20240727210410466

即变量 $image_sign 将被设置为 wrgac43s_dlink.2015_dir822c1

第三行代码是用于执行固件映像解密操作,使用 fwrite 函数将命令字符串 encimg -d -i ".$fw_path." -s ".$image_sign." > /dev/console 写入文件 $ShellPath。后续会执行这个 shell

这个 encimg 程序位于 /usr/sbin

image-20240727210440383

然后使用 readelf 命令可以知道该程序是32位大端MIPS架构

image-20240727210428264

现在使用qemu用户模式进行模拟,并加上 encimg -d -i ".$fw_path." -s ".$image_sign. 等参数

.$fw_path. 就是需要解密的加密固件的路径,即 D-Link DIR-822-US 系列路由器 3.15B02 版本固件的路径

1
.$image_sign.` 即 `wrgac43s_dlink.2015_dir822c1

qemu-mips-static 与加密固件 DIR822C1_FW315WWb02.bin 复制到 squashfs-root 目录中用于运行 encimg

对固件进行解密:

1
sudo chroot . ./qemu-mips-static ./usr/sbin/encimg -d -i ./DIR822C1_FW315WWb02.bin -s wrgac43s_dlink.2015_dir822c1

Untitled

此时再用 binwalk 去查看 DIR822C1_FW315WWb02.bin ,不仅可以看到文件信息,还发现熵值也变了

Untitled

Untitled

提取解密后的固件

此时就可以使用 binwalk -Me 成功提取固件系统文件

image-20240727210609419

image-20240727210619407

成功提取出加密固件!!!