USG310 4.70 固件解密分析
2022-6-9 14:29:41 Author: www.secpulse.com(查看原文) 阅读量:43 收藏

0x01 前言

关于Zyxel 固件的解密和提取的分析,最近的这篇文章给了我一个很好的idea,感兴趣的可以去看一下。

文章连接:https://security.humanativaspa.it/zyxel-firmware-extraction-and-password-analysis/

对固件进行漏洞挖掘的第一步,就是从固件中提取我们需要的一些文件和组件,从而进行漏洞分析,但是如果解开固件包的过程中,显示固件已被加密,并且无法确定如何进行解密,那么是特别难受的。从一些常见的固件解密的方式来看,有的固件是压缩的时候进行加密的,那么解密程序或者生成解密密钥的二进制文件有可能会存在和固件包一起的打包出来,那么可以根据确定一些与解密有关的关键信息,和逆向加密算法对加密方式进行对应的破解,但是,i am lazy :) 。所以通过收集固件的信息,了解其中的加密的一些命令和方式,比如zyxel固件解密所描述,根据一些特殊的组件猜测其解密的方式,尝试去解密固件,虽然这个过程也很艰难,但相对去逆向晦涩难懂的加密算法而言,难度就小很多了。

另外也可以根据linux中常见的解密工具,比如unzip 来确定固件中的解密方式,如下图所示的这个案例,通过检索unzip信息,获取到了解密的方式和解密密钥。

接下来我来讲述一下关于Zyxel 固件的另一种固件解密的idea, 虽然在固件解密这一块,也并不怎么擅长,但仍希望能给大家带来不一样的想法。

0x02 固件解包 1

固件版本:USG310 4.70

固件下载连接:https://firmware.cdn.cloud.zyxel.com/firmware/AAPJ/4.72(AAPJ.0)/firmware.zip

固件指令架构:ELF 32-bit MSB executable, MIPS, N32 MIPS64 rel2 version 1 (SYSV), statically linked, stripped

这里我使用的是 firmware_USG310_4.70(APPJ.0) 固件包, 下载下来之后,这是一个zip 压缩的压缩文件,解压之后的目录如下所示

后的目录如下所示

我们要解开的固件是 470AAPJ0C0.bin , 使用zip 查看 470AAPJ0C0.bin。

同时使用zip 解压提取固件包的时候,显示是需要密码的。

但是在 dbetczyxelftpconf目录中,看到了system-defalut.conf 文件,这个文件的大小为 72871和 470AAJ0C0.conf 文件 (72870) 的大小只相差1字节。

如此的巧合让我猜测这两个文件应该是同一个文件,我尝试使用pkcrack 明文攻击来破解,很遗憾,并没有达到我要的破解效果,甚至我在 470AAJ0C0.conf 文件中增加了一个字节,让这两个文件的大小相同,同样没有达到效果。

于是根据https://security.humanativaspa.it/zyxel-firmware-extraction-and-password-analysis/,我使用binwalk 解开470AAJ0C0.ri 文件。

接着使用binwalk 解开 _470AAPJ0C0 文件中的240 文件。

[email protected] ~/i/g/z/firmware_USG310_4.70> cd _470AAPJ0C0.ri.extracted/
[email protected] ~/i/g/z/f/_470AAPJ0C0.ri.extracted> ls
240  240.7z
[email protected] ~/i/g/z/f/_470AAPJ0C0.ri.extracted> binwalk -e 240

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ELF, 64-bit MSB MIPS32 rel2 executable, MIPS, version 1 (SYSV)
5107864       0x4DF098        Linux kernel version 3.10.8
5179656       0x4F0908        gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
5196240       0x4F49D0        Unix path: /home/sdd1/buildbot/470-share1100-k3-slave/470-share1100-k3/build/share1100-r102127-k3/share1100/src/kernel
5284016       0x50A0B0        DES SP2, big endian
5284528       0x50A2B0        DES SP1, big endian
5824472       0x58DFD8        Unix path: /usr/bin/magic-seed
5853384       0x5950C8        Unix path: /home/sdd1/buildbot/470-share1100-k3-slave/470-share1100-k3/build/share1100-r102127-k3/share1100/src/kernel/arch/mips/include/as
5939112       0x5A9FA8        xz compressed data
6040223       0x5C2A9F        Copyright string: "Copyright 2005-2007 Rodolfo Giometti <[email protected]>"
6092400       0x5CF670        Nei***orly text, "Nei***orSolicits"
6092424       0x5CF688        Nei***orly text, "Nei***orAdvertisementsorts"
6097330       0x5D09B2        Nei***orly text, "nei***or %.2x%.2x.%pM lost rename link %s to %s"
6463872       0x62A180        CRC32 polynomial table, little endian
6643248       0x655E30        Unix path: /usr/local/zld_udev/sbin/uevent_helper.sh
7060288       0x6BBB40        Flattened device tree, size: 7847 bytes, version: 17
7068160       0x6BDA00        Flattened device tree, size: 12032 bytes, version: 17
7085520       0x6C1DD0        ASCII cpio archive (SVR4 with no CRC), file name: ".", file name length: "0x00000002", file size: "0x00000000"
7085632       0x6C1E40        ASCII cpio archive (SVR4 with no CRC), file name: "init", file name length: "0x00000005", file size: "0x0000000D"
7085764       0x6C1E**        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit", file name length: "0x00000007", file size: "0x00000000"
7085884       0x6C1F3C        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/zld_fsextract", file name length: "0x00000015", file size: "0x00017098"
7180376       0x6D9058        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/etc_inittab", file name length: "0x00000013", file size: "0x00000BB8"
7183508       0x6D9C94        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/rw.zip", file name length: "0x0000000E", file size: "0x001330BD"
8441296       0x80CDD0        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/zyinit_gpl", file name length: "0x00000012", file size: "0x00055128"
8789880       0x861F78        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/sw_cn60xx.ko", file name length: "0x00000014", file size: "0x000073E0"
8819676       0x8693DC        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/e2fsck", file name length: "0x0000000E", file size: "0x0006B64C"
9259684       0x8D4AA4        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/zld_udev", file name length: "0x00000010", file size: "0x0008B460"
9830276       0x95FF84        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/zld_mrd.ko", file name length: "0x00000012", file size: "0x000016D0"
9836244       0x9616D4        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/lkm.lst", file name length: "0x0000000F", file size: "0x00000050"
9836452       0x9617A4        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/db.zip", file name length: "0x0000000E", file size: "0x00003829"
9850956       0x96504C        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/mke2fs", file name length: "0x0000000E", file size: "0x0004239C"
10122340      0x9A7464        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/unzip", file name length: "0x0000000D", file size: "0x0002B8B0"
10300816      0x9D2D90        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/platform_support.ko", file name length: "0x0000001B", file size: "0x000048C0"
10319580      0x9D76DC        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/switchdev_char.ko", file name length: "0x00000019", file size: "0x00004DE8"
10339660      0x9DC54C        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/switchdev.ko", file name length: "0x00000014", file size: "0x00009A90"
10379360      0x9E6060        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/fwversion", file name length: "0x00000011", file size: "0x00000158"
10379832      0x9E6238        ASCII cpio archive (SVR4 with no CRC), file name: "zyinit/zyinit", file name length: "0x0000000E", file size: "0x000C0AEC"
11169184      0xAA6DA0        ASCII cpio archive (SVR4 with no CRC), file name: "TRAILER!!!", file name length: "0x0000000B", file size: "0x00000000"

解开240 如下的文件目录包含一下内容,我看到了db.zip。这让我联想到了 "firmware_USG310_4.70_2470AAPJ0C0.bindbetczyxelftpconf" 目录中的system-defalut.conf 文件

于是使用unzip解开db.zip 文件,很幸运,这个zip 并没有同 470AAPJ0C0.bin 一样被加密。

可以看到里面有一个 system-default.conf 文件,可以看到这个文件的大小和名称和前面看到的一样大。我认为这个文件和"firmware_USG310_4.70_2470AAPJ0C0.bindbetczyxelftpconf" 目录中的system-defalut.conf 文件是同一个文件。这样我又可以使用 pkcrack 进行破解了。

在使用pkcrack 明文攻击进行破解之前,简单的描述一下pkcrack 的攻击原理。

0x03 pkcrack 明文攻击

明文攻击 该攻击是已知的纯文本攻击,这意味着您必须知道部分加密数据才能破解密码。比如:加密压缩包中有10张图片,其中1张图片你有未加密的源文件。常用工具: ARCHPR 4.53、pkcrack 原理:明文攻击是一种较为高效的攻击手段,大致原理是当你不知道一个zip的密码,但是你有zip中的一个已知文件(文件大小要大于12Byte)或者已经通过其他手段知道zip加密文件中的某些内容时,因为同一个zip压缩包里的所有文件都是使用同一个加密密钥来加密的,所以可以用已知文件来找加密密钥,利用密钥来解锁其他加密文件 速度:非常快

pkcark 进行明文破解 使用pkcrack进行明文破解需要注意一点:压缩包中可能包含多个加密文件,但我们只要持有其中一个文件即可,该文件必须和压缩包中的某个文件一模一样。在破解前,需要先把明文文件进行压缩。如果使用zip命令直接压缩可能会出现压缩率的问题。windows下可以使用7-zip一类的桌面应用进行压缩。使用7-zip进行压缩时,会有一个压缩率的选项,可以调整word size的大小,如果这个压缩率和加密文件的压缩率不匹配,破解时可能会出现文件长度不匹配问题 查看压缩率可以借助 zipdetails、360压缩、7zip等查看。https://github.com/keyunluo/pkcrack

pkcrack 破解需要两个文件

  • 需要解密的ZIP文件
  • 另一个zip文件,其中至少包含未加密的加密存档红的一个文件。必须使用与加密文件相同的压缩方法压缩该文件。

pkcrack -C encrypted-ZIP -c ciphertextname -P plaintext-ZIP -p plaintextname -d decrypted_file -a

encrypted-ZIP:是加密的ZIP归档文件的名称(和路径) ciphertextname:是存档中文件的名称,对于该文件,您具有-纯文本 plaintext-ZIP:是包含压缩明文的ZIP归档文件的名称(和路径) plaintextname:是归档文件中包含已知明文的文件名 unlocked_file:是解密档案将被写入的文件的名称

示例

demo ├── demo.zip # encrypted-ZIP ├── pkcrack ├── pkcrack.exe ├── README.txt # plaintext └── README.zip # plaintext-ZIP

用shell 命令用于破解

../bin/pkcrack -C demo.zip -c README.txt -P README.zip -p README.txt -d cracked.zip -a

0x04 固件解包2

使用pkcrack 解开固件

[email protected] ~/i/g/z/firmware_USG310_4.70> 
zip -9 470AAPJ0C0.zip system-default.conf 
  adding: system-default.conf (deflated 84%)
[email protected] ~/i/g/z/firmware_USG310_4.70> 
/home/tigerortiger/tools/pkcrack/bin/pkcrack -C 470AAPJ0C0.bin -c db/etc/zyxel/ftp/conf/system-default.conf -P 470AAPJ0C0.zip -p system-default.conf -d cracked.zip -a
Generating 1st generation of possible key2_11532 values...done.
Found 4194304 possible key2-values.
Now we're trying to reduce these...
Lowest number: 989 values at offset 6926
Lowest number: 954 values at offset 6924
Lowest number: 898 values at offset 5324
Done. Left with 898 possible Values. bestOffset is 5324.
Stage 1 completed. Starting stage 2 on 
Ta-daaaaa! key0=184108c9, key1=a102a710, key2=8f550772
Probabilistic test succeeded for 6213 bytes.
Ta-daaaaa! key0=184108c9, key1=a102a710, key2=8f550772
Probabilistic test succeeded for 6213 bytes.
Stage 2 completed. Starting zipdecrypt on
Decrypting compress.img (624a9fbe5fcf76c1bdf8eb86)... OK!
Decrypting db/ (863c636d34664e0e43c3858b)... OK!
Decrypting db/etc/ (9438acbd8959952d160c858b)... OK!
Decrypting db/etc/zyxel/ (51b87c5ec94917155458858b)... OK!
Decrypting db/etc/zyxel/ftp/ (b28c0fca7cc7f78ffa8e858b)... OK!
Decrypting db/etc/zyxel/ftp/conf/ (2525dc17bac05f9a4da7858b)... OK!
Decrypting db/etc/zyxel/ftp/conf/system-default.conf (c4c22bea727241c6f6816779)... OK!
...
Decrypting etc_writable/zyxel/conf/__system_default_device_ha.xml (c83a53734113602259af6779)... OK!
Decrypting etc_writable/zyxel/conf/__system_default_dynamic_guest_log.xml (2061195d4ef1dfcb2b2d6779)... OK!
Decrypting etc_writable/zyxel/conf/__wantrunk_default.xml (d06c63f2a332c4dc718dc085)... OK!
Decrypting etc_writable/zyxel/conf/__zwo.xml (5d594289e3ff7f8d5bebcf86)... OK!
Decrypting etc_writable/zyxel/conf/dynamic_guest_log.xml (f66649f9e313ccd24136868b)... OK!
Decrypting etc_writable/zyxel/coredump_script/ (ae137544f7ad54f9eebd868b)... OK!
Decrypting etc_writable/zyxel/coredump_script/common.sh (dfcc6000cb3ca1609dec1786)... OK!
Decrypting etc_writable/zyxel/coredump_script/samples.sh (5fb2e2a1cae7bbddfe761786)... OK!
Decrypting etc_writable/zyxel/coredump_script/sdwan_common.sh (5160662af82248b81a751786)... OK!
Decrypting etc_writable/zyxel/printer/ (76acf8b17a486b36cfbb868b)... OK!
Decrypting etc_writable/zyxel/printer/SP350E.dat (d8b9df979471623787e18e81)... OK!
Decrypting etc_writable/zyxel/printer/double_print.sh (9f01ea1939359e15be448e81)... OK!
Decrypting etc_writable/zyxel/secuextender/ (0e53686443987b96c859868b)... OK!
Decrypting etc_writable/zyxel/secuextender/applet.html (9df9661a81cfa97ff5ba2e82)... OK!
Decrypting etc_writable/zyxel/secuextender/sslapp.jar (f407182e1b0743d27b67a982)... OK!
Decrypting etc_writable/zyxel/selector/ (296a84395ffc890845b1437f)... OK!
Decrypting filechecksum (b48c0dec79379e4cac83898b)... OK!
Decrypting filelist (878dcff5a799dfe9ef6c8a8b)... OK!
Decrypting fwversion (e223b319d7586e29573e848b)... OK!
Decrypting kernelchecksum (8d701dd63dd56aa385810987)... OK!
Decrypting kernelshare1100.bin (0ef2d6fb1ee26b107de40987)... OK!
Decrypting wtp_image/ (2423c9bb7b21b8c347cb898b)... OK!
Decrypting wtp_image/cloud_checksum (5dd7bf2962fa3637a954898b)... OK!
Decrypting wtp_image/nwa5123-ac (3d4ca00fc39c85554711878b)... OK!
Decrypting wtp_image/nwa5123-ac-hd (fb86ad6cc45e1e0a12e9888b)... OK!
Decrypting wtp_image/wtpinfo (298480fe98ba3898b2b3888b)... OK!
Decrypting wtpinfo (9deeef6c027ef4bd1420888b)... OK

成功解开zip 文件。其实为什么470AAJ0C0.conf 文件不能爆破,我解开之后,大概的看了一下system-default.conf文件,这两个文件的内容是大概是一模一样的,没仔细找,那多出的一个字节是啥。

0x05 提取文件系统

查看compress.img 的文件格式,可以看到这是Squashfs

解开之后整个文件目录结构

├── _470AAPJ0C0.ri.extracted
│   └── _240.extracted
│       ├── cpio-root
│       └── etc
├── _compress.img.extracted
│   └── squashfs-root
│       ├── bin
│       ├── dev
│       ├── etc
│       ├── lib
│       ├── lib32 -> lib/
│       ├── lib64
│       ├── sbin
│       ├── usr
│       ├── util
│       └── var
├── db
│   └── etc
│       └── zyxel
├── etc_writable
│   ├── budget
│   ├── ModemManager
│   ├── usb_modeswitch
│   └── zyxel
│       ├── conf
│       ├── coredump_script
│       ├── printer
│       ├── secuextender
│       └── selector
└── wtp_image

0x06 zld_fsextract 解开固件

关于 zld_fsextract 的讲解,原文讲的很详细了,这里就复现一下

https://security.humanativaspa.it/zyxel-firmware-extraction-and-password-analysis/

[email protected] ~/i/g/z/f/_470AAPJ0C0.ri.extracted [1]> chmod -R 777  ./_240.extracted/
[email protected] ~/i/g/z/f/_/_240.extracted> file zld_fsextract 
zld_fsextract: ELF 32-bit MSB executable, MIPS, N32 MIPS64 rel2 version 1 (SYSV), statically linked, stripped
[email protected] ~/i/g/z/f/_/_240.extracted> which qemu-mipsn32-static 
/usr/bin/qemu-mipsn32-static
[email protected] ~/i/g/z/f/_/_240.extracted> cp /usr/bin/qemu-mipsn32-static  ./
[email protected] ~/i/g/z/f/_/_240.extracted> chmod 777 qemu-mipsn32-static 
[email protected] ~/i/g/z/f/_/_240.extracted> 
sudo strace -f -s 199 qemu-mipsn32-static ./zld_fsextract ../../470AAPJ0C0.bin  ./unzip -s extract -e code
[sudo] password for tigerortiger: 
execve("/usr/bin/qemu-mipsn32-static", ["qemu-mipsn32-static""./zld_fsextract""../../470AAPJ0C0.bin""./unzip""-s""extract""-e""code"], 0x7fffa6cc8d20 /* 17 vars */) = 0
brk(NULL)                               = 0x62813000
brk(0x62814280)                         = 0x62814280
arch_prctl(ARCH_SET_FS, 0x62813940)     = 0
uname({sysname="Linux", nodename="ubuntu", ...}) = 0
set_tid_address(0x62813c10)             = 64399
set_robust_list(0x62813c20, 24)         = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x6014ccc0, sa_mask=[], s
...
[pid  3040] wait4(-1, strace: Process 3048 attached
 <unfinished ...>
[pid  3048] set_robust_list(0x64384c20, 24) = 0
[pid  3048] rt_sigprocmask(SIG_SETMASK, ~[RTMIN RT_1], ~[KILL STOP RTMIN RT_1], 8) = 0
[pid  3048] clone(child_stack=0x7fd85d2dcdb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fd85d2dd9d0, tls=0x7fd85d2dd700, child_tidptr=0x7fd85d2dd9d0) = 3049
[pid  3048] rt_sigprocmask(SIG_SETMASK, ~[KILL STOP RTMIN RT_1], NULL, 8) = 0
[pid  3048] rt_sigprocmask(SIG_SETMASK, ~[RTMIN RT_1], NULL, 8) = 0
[pid  3048] rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
[pid  3048] execve("./unzip", ["./unzip""-o""-q""-P""RvP5AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXFmhjdq.rqDqX.cPD9BG3eq/Y""../../470AAPJ0C0.bin""-d""/""db/etc/zyxel/ftp/conf/""db/etc/zyxel/ftp/conf/system-default.conf"], 0x643d4*** /* 16 vars */strace: Process 3049 attached
 <unfinished ...>
[pid  3049] +++ exited with 0 +++
[pid  3048] <... execve resumed> )      = 0
[pid  3048] brk(NULL)                   = 0x64372000
[pid  3048] brk(0x64373280)             = 0x64373280
[pid  3048] arch_prctl(ARCH_SET_FS, 0x64372940) = 0
[pid  3048] uname({sysname="Linux", nodename="ubuntu", ...}) = 0
[pid  3048] set_tid_address(0x64372c10) = 3048
[pid  3048] set_robust_list(0x64372c20, 24) = 0
[pid  3048] rt_sigaction(SIGRTMIN, {sa_handler=0x60142520, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x6014a9b0}, NULL, 8) = 0
[pid  3048] rt_sigaction(SIGRT_1, {sa_handler=0x601425c0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x6014a9b0}, NULL, 8) = 0
[pid  3048] rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
[pid  3048] prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
[pid  3048] readlink("/proc/self/exe""/usr/bin/qemu-mips-static", 4096) = 25
[pid  3048] brk(0x64394280)             = 0x64394280

主要是查看这一句,密钥有一部分我就不公布了。

[pid  3048] execve("./unzip", ["./unzip""-o""-q""-P""RvP5AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXFmhjdq.rqDqX.cPD9BG3eq/Y""../../470AAPJ0C0.bin""-d""/""db/etc/zyxel/ftp/conf/""db/etc/zyxel/ftp/conf/system-default.conf"], 

最终用整个密钥也可以解开470AAPJ0C0.bin

0x07 总结

这个固件解密的方式主要用的方式pkcrack,利用的就是一个未加密的conf文件,进行解密,总的来说,在分析加密固件的时候,应该对那些伴随加密固件一起发布出来的其他文件进行详细的信息收集,以便了解更多与固件相关的信息,另外,加密固件在更新到设备上的时候,是需要解密后提取文件系统才能使用的,如果设备上原本是没有密钥或者生成密钥的算法,那么解密的密钥或者解密的方式大概率会和加密固件一起发布出来。

end

本文作者:ChaMd5安全团队

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/180605.html


文章来源: https://www.secpulse.com/archives/180605.html
如有侵权请联系:admin#unsafe.sh