1、信息收集
固件版本3971、4325。
首先对于Draytek的固件解密要用到draytools这个工具。我们先拿到这个加密固件,然后用binwalk看一下这两个文件的熵值。

这是3971的熵值,着我们还是第一次见到。再看一下4325版本。

最后面熵值有变化。我们看看这两个文件的16进制,有没有什么内容。
然后我们解包3971版本后出现了很多文件,我们找找有没有可用的。当我们把3910的3971解包后发现了关于AES 的字样,其中有S盒、SHA256 hash。这些提取的文件应该是未加密的,他们包含了AES和SHA256的常量,说明这段代码具备加密的能力,或者进行验证之类的。
在这之前我们尝试用binwalk解包3971版本,但是似乎无法直接提取文件系统,我们要换种方式,先用binwalk看下内容。

这个3971版本有超级多的内容,我们看下有没有需要用到的。

这里看到4325版本是加密的,需要一个enc_image的东西解密,我们在之前见到过类似解密方式,可能会有一个解密程序存在。
总结一下我们的发现,能确定4325版本是加密状态的。
2、尝试解包3971版本
我们使用binwalk解包。

通过binwalk发现3971文件系统通过LZ4加密,我们需要安装一个LZ4依赖让binwalk解包。

这里似乎找到了Key,是这样的,网上的旧版Key是0DraytekKd5Eason3DraytekKd5Eason,然后我们找他的特征,发现了这一段,还有一点就是ChaCha20的Key通常32字节,我们可以根据旧版Key调整。
0DraytekKd5Jason3DraytekKd5Jason
既然到了这里我们先去了解一下ChaCha20算法。
1、ChaCha20算法

2、安全问题所在
为什么这个算法很安全呢,但是这里Draytek出现了错误,加密很难,密钥管理更难,这应该算是对称加密的一个难题了。
1、硬编码Key,他把Key写死在路由器的升级程序里,这意味着所有型号路由器的密钥都是通用的,但是这个问题很难解决,如果每个设备密钥都不同,管理起来超级麻烦。
1、硬编码Nonce,他本意就是一次性数字,如果Key相同,Nonce每次都不同,但这里Nonce也是写死的,造成的安全问题就是我们抓到了两份同版本的固件,他的密文流是完全对应的,如果我们直到一个字节的明文,就能推出另一个。
3、寻找解密程序
我们追踪一下dd截出来的内核文件看一下有啥信息。
这里猜测Key为这个值原因在于Vigor有历史通用密钥,所以这里猜测一下。
strings kernel_proof.bin | grep "0Draytek"

提取密钥、加密逻辑文件

这里我们找到一个chacha20可执行程序,我们看一下,或者丢到IDA里面。

这里我们关注这个chacha20文件,因为前面分析了是chacha20加密算法,我们看下是谁调用了这个chacha20。

这里出现了经典的固件升级文件则有一个文件,后面应该是解密需要的东西。
chacha20 $enc_file $denc_file $TMP_FW_OUTPUT_FOLDER/nonce
chacha20 <输入文件> <输出文件> <Nonce文件>
一共需要3个参数,我们在系统中找一找所需要的文件。
1、密钥(Key)
这里我们的密钥(Key)没有通过命令行传输,说明密钥100%硬编码,我们到chacha20里面找找看。

这里就和我们之前的猜想一模一样了,这个确实是密钥Key。
0DraytekKd5Eason3DraytekKd5Eason
但是这里有些问题,就在下面几行,他进行了一个替换,把J替换成了E,也就是说我们原来的密钥明文的是无法使用的。
下面这段for循环,作用是与Json进行比对,在这个字符串中检索,发现的话会将第一个字符替换为ASCII码替换为69,就是E.
2、Nonce
我们在之前找到过这个值

UODAjyXZOzH0
3、FW_upload文件
接下来分析一下这个文件内容。

这个脚本就是解密程序了。

我们分析最核心的这一段,这里有些文件,我们一个一个分析。
1、$enc_file
这段就是固件被fw_unpacker切开,识别出的加密数据块,就是上了锁的压缩包
2、$denc_file
脚本里解密后的文件
3、$TMP_FW_OUTPUT_FOLDER/nonce
存放随机数的文件
4、尝试解密4325版本
现在我们收集了所有解密需要的,算法、密钥以及随机数。
总结一下我们手上有的信息。
1、chacha20
# 语法
./sbin/chacha20 <加密文件> <解密后输出文件> <Nonce文件路径>
# 举例(假设你在文件系统根目录,且已经有了 nonce 文件)
./sbin/chacha20 stage1.bin stage1_dec.bin nonce
2、 fw_unpacker
# 语法
./usr/sbin/fw_unpacker -i <完整固件包> -o <输出目录> -m <型号>
# 举例
./usr/sbin/fw_unpacker -i v4325.all -o ./output/ -m v3910
1、第一步
sudo qemu-aarch64-static . ./sbin/fw_unpacker -i /tmp/v3910_4325.all -o ./output_final/ -m v3910

我们先把4325版本解包。
2、第二步
这就是我们得到的结果了。
sudo qemu-aarch64-static .. chacha20 enc_Image decrypted_fs.bin nonce
nonce: 554f44416a79585a4f7a4830
Run time = 0 sec

解密成功。
5、分析启动项
我们已经解密成功,接下来就是想办法模拟起来,我们先找找启动项
查找 inittab 文件,并显示其内容
find . -name inittab -exec cat {} \;
这里找到了两个文件

我们之前的开机启动项是rcS,这个文件估计就是关于启动相关的文件。
rc文件

这个rc文件是开机启动项相关的信息,我们找找它是什么服务器。
./firmwalker.sh ~/cpio-root/ > 3910.txt

这里应该是httpd服务,但这里看到了个api key文件。
这个sohod64.bin可能是处理api密钥和OAuth认证的二进制文件。并且他的路径表明他可能是用于QEMU模拟环境或虚拟化的后端守护进程。

接下来我们就尝试模拟这个4325版本的固件。
在此之前我们需要去rc里面找启动前的条件。

在中间这又但,发现了一个run.sh,大概率就是模拟所需要的配置。

这个目录下全都是模拟相关的文件。
run.sh

这个run.sh应该是模拟所需要的文件了。

第一行就是需要一个run_linux.sh文件。

确定了就是这个启动的路由器,这里面有所需要的一切信息,集成了一起,用qemu模拟的。

这个应该就是启动的镜像。
这个脚本是官方开发人员用来启动QEMU模拟环境的原始脚本,sohod64.bin就是核心固件,充当Kernel,其次DrayTek设备树文件(DTB).
run_linux.sh文件

我们回顾一下这个文件。
首先根据这个文件,我们会引用一些文件并且放到脚本能找到的路径下。

但是这些应该自动会存在这些文件,也就是自动调用的,大概率不用管。

后来我们才找到了这里发现了启动流程。
看一下要干嘛,首先就是 fw_setenv purelinux 1,也就是我们设置为1时会进入Linux模式,禁用硬件加速,禁用专有硬件驱动,只跑Linux。
第二步是告诉我们如果开启了Linux模式,就不需要刚才的run.sh了,而是用run_linux.sh,我们就去run_linux.sh中尝试启动。
1、尝试模拟
先去看看提及到的两个脚本,一个是fw_setenv还有setup_qemu_linux.sh。并且让我们设置了什么东西。先去改模式吧

看一下这个文件,需要我们设置两张网卡,eth0和eth1这两张网卡。

启动报错,我们找到了原因。
我们报错的KVM信息意味着原厂脚本不仅硬编码了硬件加速,还用了TAP网络模式。应该是操作提示中要关闭的点,接下来我们要做以下操作。
首先关闭KVM,因为原厂脚本run_linux.sh写的KVM= --enable-kvm ,这是给ARM开发板用的,我们机器是x86架构,不支持跨架构KVM加速(kqemu开源加u收起,kvm只能模拟x86虚拟机)
接下来我们要改CPU,脚本的CPU=host,意思是物理机的CPU模型,必须改成ARM CPU。
网络模式就是最后一点,因为run_linux.sh默认是TAP模式,直接运行如果网卡没创建,QEMU也会报错并且卡住。
2、尝试模拟,发现报错

这里发现我们怎么去运行都会报错一个信息,找找其他方法。

在启动qemu时,发现了一个非标准参数,-dtb DrayTek,以此来判断是进行了魔改Qemu,我们需要重新编译GPL代码.
但是因为架构原因,我们需要重新编译一个,我们去官网下载对应GPL源码。
3、GPL源码编译

我们下载尝试编译.
tar -xvjf new_v3910_v396_GPL_release.tar.bz2

看一眼ReadMe,按照他需求来.
sudo apt-get install make
sudo apt-get install gcc
sudo apt-get install liblz4-tool
./build
我们现在需要找到Qemu去编译一个我们所需要的qemu-system-aarch64.
接下来我们到这个路径下编译.
Vigor3910_v396_GPL_release/source/linux/cavium-rootfs/src_dir/qemu-2.12.1/
./
