Lately I have been analyzing some embedded devices such as routers, and want to share how to emulate, extract, and modify firmware.
We may want to do this for several reasons, such as enabling SSH/telnet to debug a service remotely, adding new features and looking for security vulnerabilities.
If you want to dump the firmware from a physical device, you will want to use something such as the CH341A, but it won’t be covered here.
We will need some tools to analyze and emulate firmware, but thankfully the nice folks at Attify have made a specialized VM for analyzing embedded devices.
It comes with Firmware Analysis Toolkit which we will use to emulate the Netgear WNAP320 firmware, since it works well, and this way buying the hardware is not required to follow along.
Running the firmware
Now that you have the VM downloaded, and running, open Terminator:
1iot@attifyos:~$ mkdir WNAP320 && cd WNAP320 2iot@attifyos:~/WNAP320$ wget http://www.downloads.netgear.com/files/GDC/WNAP320/WNAP320_V22.214.171.124.zip
Now we want to run the firmware, and for that we will use Firmware Analysis Toolkit. From their GitHub:
Firmware Analysis Toolkit (FAT henceforth) is based on Firmadyne with some changes. Firmadyne uses a PostgreSQL database to store information about the emulated images. However just for the core functionality i.e. emulating firmware, PostgreSQL is not really needed. Hence FAT doesn’t use it.
1iot@attifyos:~/WNAP320/firmware$ cd ~/tools/firmware-analysis-toolkit/ 2iot@attifyos:~/tools/firmware-analysis-toolkit$ ./fat.py ~/WNAP320/WNAP320_V126.96.36.199.zip 3 4 __ _ 5 / _| | | 6 | |_ __ _ | |_ 7 | _| / _` | | __| 8 | | | (_| | | |_ 9 |_| \__,_| \__| 10 11 Welcome to the Firmware Analysis Toolkit - v0.3 12 Offensive IoT Exploitation Training http://bit.do/offensiveiotexploitation 13 By Attify - https://attify.com | @attifyme 14 15[+] Firmware: WNAP320_V188.8.131.52.zip 16[+] Extracting the firmware... 17[+] Image ID: 1 18[+] Identifying architecture... 19[+] Architecture: mipseb 20[+] Building QEMU disk image... 21[+] Setting up the network connection, please standby... 22[+] Network interfaces: [('brtrunk', '192.168.0.100')] 23[+] All set! Press ENTER to run the firmware... 24[+] When running, press Ctrl + A X to terminate qemu
Press ENTER and wait a bit, then visit 192.168.0.100 on your browser to make sure everything worked.
Analyzing the firmware
For this firmware, it seems the interesting stuff are inside a tar archive. It’s usually not that simple.
Let’s extract it:
1iot@attifyos:~/WNAP320$ unzip WNAP320_V184.108.40.206.zip 2Archive: WNAP320_V220.127.116.11.zip 3 inflating: wnap320_V18.104.22.168_firmware.tar 4 inflating: wnap320_V22.214.171.124_firmware_Release_Notes.html 5iot@attifyos:~/WNAP320$ mkdir firmware 6iot@attifyos:~/WNAP320$ tar -xvf wnap320_V126.96.36.199_firmware.tar -C firmware 7vmlinux.gz.uImage 8rootfs.squashfs 9enc_dec.config 10root_fs.md5 11kernel.md5
The files ending in .md5 are not important, they are hashes of the files to check their integrity:
1iot@attifyos:~/WNAP320/firmware$ cat root_fs.md5 255e71f05c4dfdcf1ea1a611f05ca371b - 3iot@attifyos:~/WNAP320/firmware$ md5sum rootfs.squashfs 455e71f05c4dfdcf1ea1a611f05ca371b rootfs.squashfs
The two files of interest here are: rootfs.squashfs and vmlinux.gz.uImage.
Whenever we encounter a file format that we’re unsure about, we can use binwalk.
binwalk will scan the unknown file or archive for file signatures, and is often able to extract it by itself:
1iot@attifyos:~/WNAP320/firmware$ binwalk rootfs.squashfs 2 3DECIMAL HEXADECIMAL DESCRIPTION 4-------------------------------------------------------------------------------- 50 0x0 Squashfs filesystem, big endian, lzma signature, version 3.1, size: 6329666 bytes, 1417 inodes, blocksize: 65536 bytes, created: 2018-10-25 08:11:35 6
Great, it is simply a squashfs filesystem. This is a compressed read-only filesystem often used in embedded systems. We will extract it later.
1iot@attifyos:~/WNAP320/firmware$ binwalk vmlinux.gz.uImage 2 3DECIMAL HEXADECIMAL DESCRIPTION 4-------------------------------------------------------------------------------- 50 0x0 uImage header, header size: 64 bytes, header CRC: 0x8DD2855, created: 2018-10-25 08:11:29, image size: 983040 bytes, Data Address: 0x80020000, Entry Point: 0x8020E000, data CRC: 0x3663CBB2, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: gzip, image name: "Linux Kernel" 664 0x40 gzip compressed data, has original file name: "vmlinux.bin", from Unix, last modified: 2018-10-25 08:11:29 7
It seems this firmware uses U-Boot as a boot loader, which is very common in embedded devices. We also have the Linux kernel there. We also can see it’s meant to run on MIPS devices. Most embedded devices run either on ARM or MIPS architectures, as they are more energy efficient.
This is a very easy task, we can either use unsquashfs or binwalk to extract it:
1root@attifyos:/home/iot/WNAP320/firmware# unsquashfs rootfs.squashfs 2Reading a different endian SQUASHFS filesystem on rootfs.squashfs 3Parallel unsquashfs: Using 1 processor 41318 inodes (1319 blocks) to write 5 6[=============================================================\] 1319/1319 100% 7 8created 1053 files 9created 99 directories 10created 217 symlinks 11created 48 devices 12created 0 fifos 13root@attifyos:/home/iot/WNAP320/firmware# binwalk -e rootfs.squashfs 14 15DECIMAL HEXADECIMAL DESCRIPTION 16-------------------------------------------------------------------------------- 170 0x0 Squashfs filesystem, big endian, lzma signature, version 3.1, size: 6329666 bytes, 1417 inodes, blocksize: 65536 bytes, created: 2018-10-25 08:11:35 18 19root@attifyos:/home/iot/WNAP320/firmware/squashfs-root# ls 20bin dev etc home lib linuxrc proc root rw sbin tmp usr var 21
Now that we have access to the filesystem, we can do several things such as look for security vulnerabilities or modify the firmware.
This particular firmware has ssh enabled, and I don’t know what the default password for root is, so I will add another user:
1root@attifyos:/home/iot/WNAP320/firmware/squashfs-root/etc# openssl passwd -1 -salt salt super_secret_password 2$1$salt$GmyU7Z0gGyVy6JmSUPqHy1 3root@attifyos:/home/iot/WNAP320/firmware/squashfs-root/etc# chmod 777 passwd 4root@attifyos:/home/iot/WNAP320/firmware/squashfs-root/etc# vim passwd 5sophie:$1$salt$GmyU7Z0gGyVy6JmSUPqHy1:0:0:root:/root:/bin/sh 6root@attifyos:/home/iot/WNAP320/firmware/squashfs-root/etc# chmod 444 passwd
The reason I didn’t change the password of the root user directly, is because firmadyne appears to change the password.
Now that we finished our modification, we need to create a squashfs archive again.
1root@attifyos:/home/iot/WNAP320/firmware# mkdir firmware_modified 2root@attifyos:/home/iot/WNAP320/firmware# mv squashfs-root/ firmware_modified/ 3root@attifyos:/home/iot/WNAP320/firmware# mv enc_dec.config kernel.md5 root_fs.md5 vmlinux.gz.uImage firmware_modified/ 4root@attifyos:/home/iot/WNAP320/firmware# cd firmware_modified/ 5oot@attifyos:/home/iot/WNAP320/firmware/firmware_modified# mksquashfs squashfs-root/ rootfs.squashfs -comp lzma 6Parallel mksquashfs: Using 1 processor 7Creating 4.0 filesystem on rootfs.squashfs, block size 131072. 8[============================================================================================================================================================/] 880/880 100% 9 10Exportable Squashfs 4.0 filesystem, lzma compressed, data block size 131072 11 compressed data, compressed metadata, compressed fragments, compressed xattrs 12 duplicates are removed 13Filesystem size 5868.07 Kbytes (5.73 Mbytes) 14 22.66% of uncompressed filesystem size (25892.87 Kbytes) 15Inode table size 8537 bytes (8.34 Kbytes) 16 18.17% of uncompressed inode table size (46988 bytes) 17Directory table size 12655 bytes (12.36 Kbytes) 18 41.43% of uncompressed directory table size (30546 bytes) 19Number of duplicate files found 320 20Number of inodes 1417 21Number of files 1053 22Number of fragments 54 23Number of symbolic links 217 24Number of device nodes 48 25Number of fifo nodes 0 26Number of socket nodes 0 27Number of directories 99 28Number of ids (unique uids + gids) 1 29Number of uids 1 30 root (0) 31Number of gids 1 32 root (0) 33 34root@attifyos:/home/iot/WNAP320/firmware/firmware_modified# cd .. 35root@attifyos:/home/iot/WNAP320/firmware# tar -cvf firmware_modified.tar firmware_modified/
Now let’s emulate our new firmware:
1iot@attifyos:~/tools/firmware-analysis-toolkit$ ./fat.py ~/WNAP320/firmware/firmware_modified.tar
Trying to SSH with sophie/super_secret_password:
1root@attifyos:/home/iot/WNAP320/firmware# ssh firstname.lastname@example.org 2The authenticity of host '192.168.0.100 (192.168.0.100)' can't be established. 3RSA key fingerprint is SHA256:tK8/SfB/lQb+8MCX32XWyrTTYjiEHZZ6cAGs+FcO0Ug. 4Are you sure you want to continue connecting (yes/no)? yes 5Warning: Permanently added '192.168.0.100' (RSA) to the list of known hosts. email@example.com's password: 7[root@netgear123456 /root]#
I want to show another way of doing the same thing, by making use of QEMU to chroot onto the firmware filesystem.
1root@attifyos:/home/iot/WNAP320/firmware/squashfs-root# cp /usr/bin/qemu-mips-static usr/bin 2root@attifyos:/home/iot/WNAP320/firmware/squashfs-root# chroot . /bin/sh 3/ # uname -a 4Linux attifyos 4.15.0-88-generic #88-Ubuntu SMP Tue Feb 11 20:11:34 UTC 2020 mips unknown 5/ # adduser -G root -s /bin/sh -h /root sophie 6adduser: /root: File exists 7Changing password for sophie 8New password: 9Retype password: 10Password for sophie changed by root 11/ # cat /etc/passwd | grep sophie 12sophie:x:1001:1001:Linux User,,,:/root:/bin/sh 13/ # sed -i 's/1001/0/g' /etc/passwd 14/ # cat /etc/passwd | grep sophie 15sophie:x:0:0:Linux User,,,:/root:/bin/sh 16/ # su sophie 17/ # whoami 18root 19/ #
Not every manufacturer will publish their firmware online, and in those cases you may have to dump it from the device. Other manufacturers will sometimes encrypt their firmware. Even if you can download the firmware and it’s not encrypted, it’s not always a simple tar archive: in those cases, binwalk is your friend.
And of course, always backup the firmware of devices you are going to modify.