DIR842 A1 qemu 模拟

需要的 qemu 文件:debian_squeeze_mips_standard.qcow2,vmlinux-2.6.32-5-4kc-malta

首先修改一下自己虚拟机的IP,C段设成0,比如:192.168.0.142
然后使用命令:

1
2
3
4
5
6
7
# brctl addbr Virbr0
# ifconfig Virbr0 192.168.0.10/24 up

# tunctl -t tap0

# ifconfig tap0 192.168.0.2/24 up
# brctl addif Virbr0 tap0 qemu-system-mips -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda debian_squeeze_mips_standard.qcow2 -append "root=/dev/sda1 console=tty0" -netdev tap,id=tapnet,ifname=tap0,script=no -device rtl8139,netdev=tapnet -nographic

这里设置为 192.168.0.??? ,是有原因的,后面会说。

完成如下图。

启动 http 服务

qemu启动起来后,设置IP地址:ifconfig eth0 192.168.0.1/24

然后把DIR842的文件系统丢进去,然后操作命令。

1
2
3
mount -o bind /dev ./squashfs-root/dev/
mount -t proc /proc/ ./squashfs-root/proc/
chroot squashfs-root /bin/sh

接着参考之前的文章做法:CVE-2017-17215 - 拓展

把编译好的hook.so,测试程序test都放到 /var/tmp/ 下。在 /etc/ 目录下还是写一个 ld.so.preload文件,内容如下。

1
/lib/libdl.so.0:/tmp/hook.so

然后设置环境变量 export LD_PRELOAD=/lib/libdl.so.0:/tmp/hook.so

因为要启动http的服务,得找到哪个程序是http服务,或者是与http服务有关的。寻找一番,在 /sbin/ 目录下看到有 ncc2jjhttpd 。看名字jjhttpd多半与http服务有关。 ncc2 可能是启动http服务的。

那么,直接运行 ncc2 : ./sbin/ncc2 ,会看到ncc2运行起来会输出一大片。在最后部分会看到如下输出。

ifconfig查看一下多了个 网桥。

这样的情况,在之前遇到过。这个时候呢,修改下eth0 ,br0 的IP。

1
2
ifconfig eth0 192.168.0.1/24
ifconfig br0 192.168.0.11/24

接着去浏览器试试访问 192.168.0.1

可以看到http服务模拟成功。开始的时候,需要我们配置,但是我跳过了配置,所以这里的管理员密码为空。

这里之所以把IP都限制在C段地址为0开始,是因为ncc2程序执行完之后,它创建的网桥br0是192.168.0.1。如果把br0和eth0改成192.168.153.1或者其他的C段,且外面主机也是192.168.153.xxx 段的。按道理说,qemu与外面是互通的,但是实际实验发现qemu模拟的http无法与外面是不通的,qemu也Ping不通外面宿主机。不知道其中的原因。

DIR842 最新版

地址:https://support.dlink.com/ProductInfo.aspx?m=DIR-842

在D-link官网上找到的2019-12月的版本3.13。

最新版的DIR842固件版本已经是升到C系,从上述连接中下载到3.13B05,用 binwalk 进行解包,发现binwalk不认识,解不了。

这个时候,根据经验猜测它肯定加密了。

如果看过这篇文章:https://www.thezdi.com/blog/2020/2/6/mindshare-dealing-with-encrypted-router-firmware

那么,我们的思路就是从C系列的最基础版本开始,依次用Binwalk解包试试。

尝试之后发现,binwalk可以解出 DIR-842_C1_FW300b18.bin 。这个时候,可以看到 DIR-842_REVC_FIRMWARE_v3.10B05 这个版本大小很不正常。它比其他版本都大。

根据这些结果,能确定 DIR-842 C 系列,它的发现方式是:最初版本不加密,后来要加密,所以需要发布一个中间过渡版本,即就是 842_REVC_FIRMWARE_v3.10B05 ,它之所以20M多,就是多一个中间过度版。这个过渡版本,肯定是不加密的,而且一定包含了解密的程序

DIR842C1_FW302b03_middle.bin 看名字就知道是过度版,用binwalk 解包,果然是能解开的。

DIR842C1_FW310b05.bin 就是过版本后的第一个加密了的固件包。后面会用到它进行解密尝试。

寻找解密程序

解开了过度版DIR842C1_FW302b03_middle.bin,这里面肯定有用于解密的程序。因为固件更新的时候,肯定是需要解密的。那么,来 find 命令找一下,找关键字 decr , decrypt 等。

1
find squashfs-root/ | grep -r "decr" > decrypt

得到结果如下。

注意观察红框:encimg , decrypt_config.sh

chroot 切换到 squashfs-root 下,然后执行 encimg 看看效果。

看,找到了,这就是解密固件程序。现在,仔细看看它的参数。

1
2
3
4
5
6
7
8
 ./usr/sbin/encimg:
未指定签名!
-h:显示此消息。
-v:详细模式。
-i {输入图像文件}:输入图像文件。
-e:编码文件。
-d:解码文件。
-s:签名。

这的参数不需要多解释,特别的是 -s ,这是一个签名。如果我们直接用命令:

./usr/sbin/encimg -i DIR842C1_FW310b05.bin -d

会报错,需要一个参数S,也就是需要签名。 注意,这里我用的 DIR842C1_FW310b05.bin 来尝试,而不是用的 最新的3.13版本。我的考虑是,解密需要签名,那这个签名可能是会变的。所以先用和过度版一起发包的第一个加密版本固件进行实验。

这里可以把 encimg 丢到 Ghidra 中看看。

这里有2个主要函数 parse_argsbuild 。我简单说一下它们的作用。

  • parse_args :读取输入参数,其中 -s 参数会被保存到 g_signature ,若为 0 ,就会报no signature specified!
  • build:会使用 g_signature 作为解密的密钥,对固件进行解密。

所以 -s 参数必须有。

寻找签名

已经确定了 encimg 就是解密程序,现在缺签名。 还记得前面说到 decrypt_config.sh 这个文件吗。打开看看。

这里,可以看到有个 sign ,key 。最后 key 的内容来自 /tmp/imagesign

这里提供了2个与签名可能有关系的关键名字: imagesign image_sign

继续用 find 来查找

1
2
find squashfs-root/ |  grep -r  "imagesign" > imagesign
find squashfs-root/ | grep -r "image_sign"> image_sign

幸运的是在 image_sign 中看到了如下的一句代码。

直接去 etc/config/ ,看看有没有文件 image_sign

试试这个 wrgac65_dlink.2015_dir842 作为 -s 参数。

1
2
3
4
# ./usr/sbin/encimg -i DIR842C1_FW310b05.bin -d -s wrgac65_dlink.2015_dir842
The file length of DIR842C1_FW310b05.bin is 10985632
# ./usr/sbin/encimg -i DIR842C1_FW313WWb05.bin -d -s wrgac65_dlink.2015_dir842
The file length of DIR842C1_FW313WWb05.bin is 11280544

这次,用 binwalk 解包试试。

根据上图可以得知,wrgac65_dlink.2015_dir842 这个签名,对目前最新版的固件也是适合的。证明签名没有变化。

实际上签名在 /et/config/fw_sign 文件中也存在。