Manual Firmware Analysis
Having obtained an overview of the target’s firmware in the Automated Firmware Analysis chapter, further analysis was conducted in a manual manner.
For this analysis, tools such as binwalk and dd were employed in order to unpack the contents of the different memory partitions of the firmware, which were then checked for vulnerabilities.
Sanity checks
The first action performed on the firmware upon its extraction from the router’s flash was to confirm its content type by using the file command line utility. As seen in the log below, the contents of the firmware were identified as data.
┌──(lucas㉿localhost)-[~]
└─$ file archer_c7_flash.bin
archer_c7_flash.bin: data
Subsequently, in order to get an overview of the firmware’s contents, the strings command was used on the file. A snippet of the obtained output is presented below.
┌──(lucas㉿localhost)-[~]
└─$ strings -n 20 archer_c7_flash.bin
ath_ddr_initial_config
U-Boot 1.1.4 (Jan 14 2018 - 10:37:14)
...
bootargs=console=ttyS0,115200 root=31:02 rootfstype=jffs2 init=/sbin/init mtdparts=ath-nor0:256k(u-boot),64k(u-boot-env),6336k(rootfs),1408k(uImage),8256k(mib0),64k(ART)
bootcmd=bootm 0x9f020000
ethaddr=0xba:0xbe:0xfa:0xce:0x08:0x41
ipaddr=192.168.1.111
serverip=192.168.1.100
lu=tftp 0x80060000 ${dir}u-boot.bin&&erase 0x9f000000 +$filesize&&cp.b $fileaddr 0x9f000000 $filesize
lf=tftp 0x80060000 ${dir}ap135${bc}-jffs2&&erase 0x9f050000 +0x630000&&cp.b $fileaddr 0x9f050000 $filesize
lk=tftp 0x80060000 ${dir}vmlinux${bc}.lzma.uImage&&erase 0x9f680000 +$filesize&&cp.b $fileaddr 0x9f680000 $filesize
TP-LINK Technologies
21232f297a57a5a743894a0e4a801fc3
TP-LINK_Guest_1E55_5G
21232f297a57a5a743894a0e4a801fc3
21232f297a57a5a743894a0e4a801fc3
http://www.tp-link.com
...
Next, the entropy of the file was analysed using binwalk. This was done through the following command.
┌──(lucas㉿localhost)-[~]
└─$ binwalk -E archer_c7_flash.bin
Entropy consists of a measure of the randomness, disorder or unpredictability of data within a file. In this case, data with entropy close to 0 can be considered predictable while entropy values close to 1 signify unpredictable data which is either encrypted or compressed. The obtained entropy graph can be seen in the image below.
The graph shows that some memory partitions within the firmware appear to be encrypted/compressed (entropy=1) while others do not (entropy=0).
Identifying memory partitions with binwalk
The next step consisted in identifying the memory partitions of the firmware with binwalk, which listed 6 different ones as seen in the output below.
┌──(lucas㉿localhost)-[~]
└─$ binwalk archer_c7_flash.bin
/usr/lib/python3/dist-packages/binwalk/core/magic.py:431: SyntaxWarning: invalid escape sequence '\.'
self.period = re.compile("\.")
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
71008 0x11560 Certificate in DER format (x509 v3), header length: 4, sequence length: 64
98048 0x17F00 U-Boot version string, "U-Boot 1.1.4 (Jan 14 2018 - 10:37:14)"
98224 0x17FB0 CRC32 polynomial table, big endian
131072 0x20000 TP-Link firmware header, firmware version: 0.0.3, image version: "", product ID: 0x0, product version: -956301310, kernel load address: 0x0, kernel entry point: 0x80002000, kernel offset: 16252928, kernel length: 512, rootfs offset: 855833, rootfs length: 1048576, bootloader offset: 15204352, bootloader length: 0
131584 0x20200 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 2451644 bytes
1179648 0x120000 Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 9626626 bytes, 741 inodes, blocksize: 131072 bytes, created: 2018-01-14 02:55:46
However, it was recalled that the full log of the boot process in the Boot and Runtime Analysis chapter presented the following snippet of output, which corresponds to the exact flash memory layout of the router (which is also subject of the previous identified INFO-02 finding).
[ 0.412000] Creating 5 MTD partitions on "ath-nor0":
[ 0.416000] 0x000000000000-0x000000020000 : "u-boot"
[ 0.420000] 0x000000020000-0x000000120000 : "kernel"
[ 0.428000] 0x000000120000-0x000000fa0000 : "rootfs"
[ 0.432000] 0x000000fa0000-0x000000ff0000 : "config"
[ 0.436000] 0x000000ff0000-0x000001000000 : "ART"
Therefore, when comparing the actual partition layout with the binwalk identified partitions, it was found that binwalk was unable to identify or misidentified some of the partitions.
Firmware unpacking using binwalk
Regardless of binwalk’s misidentified/unidentified memory partitions, unpacking of recognized partitions using this tool was conducted, as seen in the output below.
┌──(lucas㉿localhost)-[~]
└─$ binwalk -e archer_c7_flash.bin
/usr/lib/python3/dist-packages/binwalk/core/magic.py:431: SyntaxWarning: invalid escape sequence '\.'
self.period = re.compile("\.")
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
71008 0x11560 Certificate in DER format (x509 v3), header length: 4, sequence length: 64
98048 0x17F00 U-Boot version string, "U-Boot 1.1.4 (Jan 14 2018 - 10:37:14)"
98224 0x17FB0 CRC32 polynomial table, big endian
131072 0x20000 TP-Link firmware header, firmware version: 0.0.3, image version: "", product ID: 0x0, product version: -956301310, kernel load address: 0x0, kernel entry point: 0x80002000, kernel offset: 16252928, kernel length: 512, rootfs offset: 855833, rootfs length: 1048576, bootloader offset: 15204352, bootloader length: 0
131584 0x20200 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 2451644 bytes
WARNING: Symlink points outside of the extraction directory: /home/lucas/embedded-device-pentesting/tp-link-archer-c7-v2/pentest/5_appendix/5_07_firmware-analysis/_archer_c7_flash.bin.extracted/squashfs-root/etc/passwd -> /tmp/passwd; changing link target to /dev/null for security purposes.
WARNING: Symlink points outside of the extraction directory: /home/lucas/embedded-device-pentesting/tp-link-archer-c7-v2/pentest/5_appendix/5_07_firmware-analysis/_archer_c7_flash.bin.extracted/squashfs-root/bin/iptables-xml -> /lzm/qca_dual/rootfs.build.2.6.31_ap135v2_wifi/sbin/iptables-multi; changing link target to /dev/null for security purposes.
1179648 0x120000 Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 9626626 bytes, 741 inodes, blocksize: 131072 bytes, created: 2018-01-14 02:55:46
The resulting _archer_c7_flash.bin.extracted folder (which can be found in the Appendix) was then listed in order to ascertain the partitions binwalk was in fact able to unpack correctly.
┌──(lucas㉿localhost)-[~/_archer_c7_flash.bin.extracted]
└─$ ls
120000.squashfs 20200 20200.7z squashfs-root squashfs-root-0
Therefore, binwalk was able to correctly unpack two memory partitions, namely:
LZMA compressed dataSquasfs filesystem
The ability to unpack these partitions is associated to the previous identified INFO-03 finding.
Firmware analysis - binwalk unpacked partitions
LZMA compressed data
The LZMA compressed data was automatically unpacked, generating the 20200.7z 7-Zip archive, and then uncompressed, producing the 20200 file. A quick sanity check was performed on this file, by first using the file command, which revealed the contents to be of the data type.
┌──(lucas㉿localhost)-[~]
└─$ file 20200
20200: data
Also, relevant strings were searched for and found within this file, such as the already identified outdated Linux kernel version (subject of finding INFO-04).
┌──(lucas㉿localhost)-[~]
└─$ strings -n 30 20200
Linux version 2.6.31--LSDK-9.2.0_U6.616 (root@liaozhiming) (gcc version 4.3.3 (GCC) ) #1 Sun Jan 14 10:40:16 CST 2018
%s version %s (root@liaozhiming) (gcc version 4.3.3 (GCC) ) %s
<2>BUG: recent printk recursion!
2.6.31--LSDK-9.2.0_U6.616 mod_unload MIPS32_R2 32BIT
...
Squashfs filesystem
In terms of the Squashfs filesystem partition, when unpacked by binwalk, generated the 120000.squasfs compressed filesystem, which was then uncompressed, producing the squashfs-root filesystem. A squashfs-root-0 folder was also generated but was found to be empty for unknown reasons. Therefore, the next step performed in the analysis of the firmware was to enumerate the squashfs-root filesystem and search for any underlying vulnerabilities.
Finding a hardcoded decryption key
In the following Web Interface Analysis chapter, one of the found features of the web interface was the ability to download a backup file which could subsequently be used to restore the user’s router configurations if required. However, attempting to check the contents of the downloaded configuration file revealed that it was encrypted beforehand. As will be later seen in that chapter, methods to decrypt the file were searched for and found online, revealing that the target employed DES ECB encryption/decryption.
It was then concluded that the logic behind the encryption and decryption conducted on the configuration file must be present within the firmware, meaning the key used for these operations was likely stored in firmware too. With this in mind, the “des” string was searched for in relevant firmware binaries, so as to find the relevant function responsible for the encryption and decryption. A relevant result regarding a file_md5_des function was found when searching the httpd binary, as seen below.
┌──(lucas㉿localhost)-[~/…/_archer_c7_flash.bin.extracted/squashfs-root/usr/bin]
└─$ strings httpd | grep -i "des"
...
des_min_do
file_md5_des
FreeListDestroy
sock_destroy
...
Ghidra, an open-source reverse engineering software, was used in order to view the source code of the file_md5_des function, by importing and decompiling the httpd binary file. A search for the function name using Ghidra’s Program Text feature revealed the source code required, present in the image below. Upon further investigation of the source code, the decryption key was found to be hardcoded in memory, as seen highlighted below. This has been added as finding MEDIUM-05.
Looking for Private Identifiable Information
Private identifiable information, such as usernames, passwords, API keys and URLs, were also searched for within the firmware by using the following commands.
$ grep -r "admin" .
$ grep -r "root" .
$ grep -r "password" .
$ grep -r "key" .
$ grep -r "api" .
$ grep -r ".com" .
These command did not yield any relevant results.
Manual firmware unpacking
The discrepancies between the actual memory layout and the one identified by binwalk as well as the already unpacked partitions were noted in the table below.
This allowed for the identification of memory partitions yet to be unpacked, namely:
- u-boot (0x00000 - 0x20000)
- kernel: TP-Link firmware header (0x20000 - 0x20200)
- config (0xfa0000 - 0xff0000)
- ART (0xff0000 - 0x1000000)
Since binwalk was unable to unpack these correctly, a manual approach using the dd command line utility was taken, as detailed below. The ability to unpack these partitions is directly related to the unencrypted nature of the firmware previously identified in the INFO-03 finding.
-
u-boot
Start address: 0x00000 (skip=0)
End address: 0x20000 = 131072 (count = 131072 - 0 = 131072)
┌──(lucas㉿localhost)-[~] └─$ dd if=archer_c7_flash.bin bs=1 skip=0 count=131072 of=uboot.bin 131072+0 records in 131072+0 records out 131072 bytes (131 kB, 128 KiB) copied, 0.116992 s, 1.1 MB/s -
TP-Link firmware header
Start address: 0x20000 = 131072 (skip=131072)
End address: 0x20200 = 131584 (count = 131584 - 131072 = 512)
┌──(lucas㉿localhost)-[~] └─$ dd if=archer_c7_flash.bin bs=1 skip=131072 count=512 of=tp_link_firmware_header.bin 512+0 records in 512+0 records out 512 bytes copied, 0.000468264 s, 1.1 MB/s -
config
Start address: 0xfa0000 = 16384000 (skip=16384000)
End address: 0xff0000 = 16711680 (count = 16711680 - 163840000 = 327680)
┌──(lucas㉿localhost)-[~] └─$ dd if=archer_c7_flash.bin bs=1 skip=16384000 count=327680 of=config.bin 327680+0 records in 327680+0 records out 327680 bytes (328 kB, 320 KiB) copied, 0.288013 s, 1.1 MB/s -
ART
Start address: 0xff0000 = 16711680 (skip=16711680)
End address: 0x1000000 = 16777216 (count = 16777216 - 16711680 = 65536)
┌──(lucas㉿localhost)-[~] └─$ dd if=archer_c7_flash.bin bs=1 skip=16711680 count=65536 of=ART.bin 65536+0 records in 65536+0 records out 65536 bytes (66 kB, 64 KiB) copied, 0.0908209 s, 722 kB/s
Firmware analysis - manually unpacked partitions
At this point, all other partitions had been unpacked and were available for analysis. The partitions were stored in the following files/folder:
For the four listed partitions, checks were performed using the file and strings commands in an attempt to reveal relevant information.
-
uboot.bin
┌──(lucas㉿localhost)-[~] └─$ file uboot.bin uboot.bin: dataRelevant strings such as the used U-Boot version and firmware memory partition information were revealed, as seen below. This is related to the previous INFO-02 finding.
┌──(lucas㉿localhost)-[~] └─$ strings -n 12 uboot.bin ... U-Boot 1.1.4 (Jan 14 2018 - 10:37:14) ... bootargs=console=ttyS0,115200 root=31:02 rootfstype=jffs2 init=/sbin/init mtdparts=ath-nor0:256k(u-boot),64k(u-boot-env),6336k(rootfs),1408k(uImage),8256k(mib0),64k(ART) ... -
tp_link_firmware_header.bin
┌──(lucas㉿localhost)-[~] └─$ file tp_link_firmware_header.bin tp_link_firmware_header.bin: firmware c700 v2 TP-LINK Technologies ver. 1.0, version 3.15.3 (US), 16252928 bytes or less, UNKNOWN1 0x1, at 0x200 855833 bytes , at 0x100000 15204352 bytesNo relevant strings were found in this file.
-
config.bin
┌──(lucas㉿localhost)-[~] └─$ file config.bin config.bin: BIOS (ia32) ROM Ext. (3*512) instruction 0x0f000000Relevant strings such as the SSID, WPS PIN and Wi-Fi PSK, and the md5 hash of the web interface password were revealed, as seen below. This has been added as finding HIGH-02.
┌──(lucas㉿localhost)-[~] └─$ strings -n 8 config.bin ... TP-LINK_1E55_5G TP-LINK_Guest_1E55_5G TP-LINK_1E55_5G_3 TP-LINK_1E55_5G_4 32901528 32901528 32901528 32901528 111000010 sm-server TP-LINK_AA1E56 WORKGROUP /tmp/passwd root:x:0 21232f297a57a5a743894a0e4a801fc3 21232f297a57a5a743894a0e4a801fc3 http://www.tp-link.com Archer C7 -
ART.bin
┌──(lucas㉿localhost)-[~] └─$ file ART.bin ART.bin: dataNo relevant strings were found in this file.