一段时间以来,我一直在剖析另一种嵌入式设备的固件,想看看是否能找到任何东西。几个小时后,我想通了!有难的方法,也有简单的方法,是我挖了难的路才找到的。这是一篇很长的文章,但我希望它能帮助其他类似的企业。
稍微谷歌一下,我发现http://wiki.qnap.com/wiki/Firmware_Recovery描述了完整的固件恢复方法和同一 wiki 上的另一个页面,用于“手动更新固件”和命令行示例。有几件事突出了......
NAS 操作系统有一个用于处理固件更新映像的脚本:
# /etc/init.d/update.sh /mnt/HDA_ROOT/update/TS-209_2.1.2_build1031.img
二进制文件中嵌入了校验和,然后输出中有这一行:
"Using 120-bit encryption - (QNAPNASVERSION4)"
我走了两条路:艰难的道路和非常简单的道路......
艰难的道路(但有有用的提示)
我从固件恢复页面下载了 TS-569 完整系统恢复映像,500MB 花了将近 2 个小时。现在我必须弄清楚我在做什么:
# file F_TS-569_20120628-1.2.2.img
F_TS-569_20120628-1.2.2.img: x86 boot sector; GRand Unified Bootloader, ...
一个完整的磁盘映像,如下所示:
$ fdisk -l F_TS-569_20120628-1.2.2.img
Device Boot Start End Blocks Id System
F_TS-569_20120628-1.2.2.img1 32 4351 2160 83 Linux
F_TS-569_20120628-1.2.2.img2 * 4352 488959 242304 83 Linux
F_TS-569_20120628-1.2.2.img3 488960 973567 242304 83 Linux
F_TS-569_20120628-1.2.2.img4 973568 1007615 17024 5 Extended
F_TS-569_20120628-1.2.2.img5 973600 990207 8304 83 Linux
F_TS-569_20120628-1.2.2.img6 990240 1007615 8688 83 Linux
分离分区(或者您可以将映像写入备用磁盘):
# dd if=F_TS-569_20120628-1.2.2.img bs=512 of=part1 skip=32 count=2160w
# dd if=F_TS-569_20120628-1.2.2.img bs=512 of=part2 skip=4352 count=242304w
# dd if=F_TS-569_20120628-1.2.2.img bs=512 of=part3 skip=488960 count=242304w
# dd if=F_TS-569_20120628-1.2.2.img bs=512 of=part5 skip=973600 count=8304w
# dd if=F_TS-569_20120628-1.2.2.img bs=512 of=part6 skip=990240 count=8688w
... which gives
-rw-r--r-- 1 root root 2211840 2013-08-30 15:41 part1
-rw-r--r-- 1 root root 248119296 2013-08-30 15:42 part2
-rw-r--r-- 1 root root 248119296 2013-08-30 15:42 part3
-rw-r--r-- 1 root root 8503296 2013-08-30 15:42 part5
-rw-r--r-- 1 root root 8896512 2013-08-30 15:42 part6
分区3是分区2的镜像,通过md5sum验证。分区 5 和 6 是空的,可能是暂存空间。分区 1 是/boot/grub,其中包含用于启动和硬件配置的模块等。所以让我们看看分区 2,引导分区。
# mkdir /mnt/ts2
# mount -r part2 /mnt/ts2 -o loop
# ls -la /mnt/ts2/boot
-rw-r--r-- 1 root root 3982976 2012-06-27 22:17 bzImage
-rw-r--r-- 1 root root 81 2012-06-27 22:17 bzImage.cksum
-rw-r--r-- 1 root root 8890727 2012-06-27 22:17 initrd.boot
-rw-r--r-- 1 root root 85 2012-06-27 22:17 initrd.boot.cksum
-rw-r--r-- 1 root root 73175040 2012-06-27 22:17 qpkg.tar
-rw-r--r-- 1 root root 83 2012-06-27 22:17 qpkg.tar.cksum
-rw-r--r-- 1 root root 33593992 2012-06-27 22:17 rootfs2.bz
-rw-r--r-- 1 root root 85 2012-06-27 22:17 rootfs2.bz.cksum
-rw-r--r-- 1 root root 31160679 2012-06-27 22:17 rootfs_ext.tgz
-rw-r--r-- 1 root root 87 2012-06-27 22:17 rootfs_ext.tgz.cksum
# file -z /mnt/ts2/boot/initrd.boot
/mnt/ts2/boot/initrd.boot: Linux rev 1.0 ext2 filesystem data, UUID=770ce31c-d03f-484e-81e8-6911340bdcbf (gzip compressed data, from Unix, last modified: Wed Jun 27 22:16:58 2012, max compression)
- bzImage 是压缩的内核映像
- initrd 是使操作系统运行的初始 ramdisk 根文件系统
- qpkg.tar 包含 NAS 的各种软件包
- rootfs2.bz 是一些 /home、/lib 和 /usr 文件的压缩包
- rootfs_ext.tgz 是 apache、php5、mysql 的 /opt/source 的另一个 ext2 文件系统的压缩 tarball,似乎是 NVRAM 设置的备份。
所有的魔法都在 initrd 文件系统映像中。仔细观察我们得到:
# gunzip -c /mnt/ts2/boot/initrd.boot >/tmp/initrd.boot.img
# mkdir /mnt/tsinitrd
# mount -r /tmp/initrd.boot.img /mnt/tsinitrd -o loop
# ls -la /mnt/tsinitrd
drwxr-xr-x 2 root root 2048 2012-06-27 22:05 bin
drwxr-xr-x 5 root root 13312 2012-06-27 22:11 dev
drwxr-xr-x 22 root root 2048 2012-06-27 22:15 etc
drwxr-xr-x 3 root root 3072 2012-06-27 22:05 lib
drwxr-xr-x 2 root root 1024 2010-11-03 04:53 lib64
lrwxrwxrwx 1 root root 11 2012-06-27 22:16 linuxrc -> bin/busybox
drwx------ 2 root root 12288 2012-06-27 22:16 lost+found
drwxr-xr-x 4 root root 1024 2012-06-27 22:04 mnt
drwxr-sr-x 2 root root 1024 2012-06-27 22:16 opt
lrwxrwxrwx 1 root root 19 2012-06-27 22:16 php.ini -> /etc/config/php.ini
drwxr-sr-x 2 root root 1024 1999-11-02 18:54 proc
lrwxrwxrwx 1 root root 18 2012-06-27 22:16 Qmultimedia -> /share/Qmultimedia
drwxr-xr-x 3 root root 1024 2007-07-18 05:24 root
drwxr-xr-x 2 root root 5120 2012-06-27 22:15 sbin
drwxrwxr-x 29 root root 1024 2006-02-28 00:57 share
drwxrwxrwx 4 root root 1024 2006-02-28 00:57 tmp
drwxrwxrwx 8 root root 1024 2012-06-27 22:15 var
还记得固件恢复页面上突出的两件事吗?更新脚本和加密参考:
# more /mnt/tsinitrd/etc/init.d/update.sh
...
... line 223
/sbin/PC1 d QNAPNASVERSION4 $path_name ${_tgz};
...
有对似乎是加密密钥和解密器的引用!由于此 NAS 固件映像基于 x86,而我在 x86 VM 中,不妨尝试一下:
# /mnt/tsinitrd/sbin/PC1
Usage: pc1 e|d "key" sourcefile <targetfile>
where: e - encrypt, d - decrypt & "key" is the encryption key.
The length of the key will determine strength of encryption
If no targetfile, output file name is equal to sourfile name
ie: 5 characters is 40-bit encryption.
最后:
# /mnt/tsinitrd/sbin/PC1 d QNAPNASVERSION4 TS-569_20130726-4.0.2.img TS-569_20130726-4.0.2.tgz
Using 120-bit encryption - (QNAPNASVERSION4)
len=1048576
model name = TS-569
version = 4.0.2
# tar -tvf TS-569_20130726-4.0.2.tgz
-rw-r--r-- root/root 106 2013-07-25 20:49 bios_layout
drwxr-xr-x root/root 0 2013-07-25 20:49 boot/
-rw-r--r-- root/root 4557984 2013-07-25 20:49 bzImage
-rw-r--r-- root/root 69 2013-07-25 20:49 bzImage.cksum
drwxr-xr-x root/root 0 2013-07-25 20:49 config/
-rwxr-xr-x root/root 48408 2013-07-25 20:49 dmidecode
-rwxr-xr-x root/root 356714 2013-07-25 20:49 flashrom
-rw-r--r-- root/root 2097152 2013-07-25 20:49 flashrom.img
-rw-r--r-- root/root 33 2013-07-25 20:49 fw_info
-rw-r--r-- root/root 8480290 2013-07-25 20:49 initrd.boot
-rw-r--r-- root/root 73 2013-07-25 20:49 initrd.boot.cksum
-rwxr-xr-x root/root 1606508 2013-07-25 20:49 libcrypto.so.1.0.0
-rwxr-xr-x root/root 372708 2013-07-25 20:49 libssl.so.1.0.0
-rw-r--r-- root/root 81090560 2013-07-25 20:49 qpkg.tar
-rw-r--r-- root/root 72 2013-07-25 20:49 qpkg.tar.cksum
-rw-r--r-- root/root 41185897 2013-07-25 20:49 rootfs2.bz
-rw-r--r-- root/root 74 2013-07-25 20:49 rootfs2.bz.cksum
-rw-r--r-- root/root 47500086 2013-07-25 20:49 rootfs_ext.tgz
-rw-r--r-- root/root 78 2013-07-25 20:49 rootfs_ext.tgz.cksum
drwxr-xr-x root/root 0 2013-07-25 20:49 update/
-rw-r--r-- root/root 105 2013-07-25 20:49 update_bios.conf
-rwxr-xr-x root/root 3188 2013-07-25 20:49 update_bios.sh
-rwxr-xr-x root/root 6088 2013-07-25 20:49 update_check
-rwxr-xr-x root/root 22041 2013-07-25 20:49 update_img.sh
所有这些都是为了获得一个为我们解密固件映像的可执行文件,一个以纯文本形式为我们提供解密密钥的脚本,以及一种如果我们想要修改某些内容将所有内容重新打包的方法。
......现在是完全不同的东西
非常简单的方法
一旦我走到了“艰难之路”的尽头,我决定在谷歌上搜索加密密钥“QNAPNASVERSION4”。第一个结果是 C 语言中的 PC1 enc/dec 算法,有人已经很友好地修改了它来为我们处理固件格式的细节:http : //www.r00ted.com/downloads/pc1.c
更新:据报道链接已损坏,这是一个转储:http : //pastebin.com/KHbX85nG
# gcc -o pc1 pc1.c
# pc1 d QNAPNASVERSION4 TS-569_20130726-4.0.2.img TS-569_20130726-4.0.2.tgz
# tar -tvf TS-569_20130726-4.0.2.tgz
-rw-r--r-- root/root 106 2013-07-25 20:49 bios_layout
drwxr-xr-x root/root 0 2013-07-25 20:49 boot/
-rw-r--r-- root/root 4557984 2013-07-25 20:49 bzImage
... same result as the hard way
现在您有一个实用程序,可以在您自己的操作系统中轻松解密您的固件文件,而无需物理访问 NAS。