Analyzing firmware from embedded devices

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

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$ ./ ~/WNAP320/ 
 4                               __           _
 5                              / _|         | |
 6                             | |_    __ _  | |_
 7                             |  _|  / _` | | __|
 8                             | |   | (_| | | |_
 9                             |_|    \__,_|  \__|
11                Welcome to the Firmware Analysis Toolkit - v0.3
12    Offensive IoT Exploitation Training
13                  By Attify -  | @attifyme
15[+] Firmware:
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', '')]
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 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 
 3  inflating: wnap320_V3.7.11.4_firmware.tar  
 4  inflating: wnap320_V3.7.11.4_firmware_Release_Notes.html  
 5iot@attifyos:~/WNAP320$ mkdir firmware
 6iot@attifyos:~/WNAP320$ tar -xvf wnap320_V3.7.11.4_firmware.tar -C firmware

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 
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

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 
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

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.

Extracting squashfs

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
 6[=============================================================\] 1319/1319 100%
 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 
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
19root@attifyos:/home/iot/WNAP320/firmware/squashfs-root# ls
20bin  dev  etc  home  lib  linuxrc  proc  root  rw  sbin  tmp  usr  var

Doing modifications

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
3root@attifyos:/home/iot/WNAP320/firmware/squashfs-root/etc# chmod 777 passwd
4root@attifyos:/home/iot/WNAP320/firmware/squashfs-root/etc# vim passwd
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%
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)
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$ ./ ~/WNAP320/firmware/firmware_modified.tar

Trying to SSH with sophie/super_secret_password:

1root@attifyos:/home/iot/WNAP320/firmware# ssh sophie@
2The authenticity of host ' (' 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 '' (RSA) to the list of known hosts.
6sophie@'s password: 
7[root@netgear123456 /root]# 

Using chroot

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
19/ # 

Wrapping up

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.

Built with Hugo
Theme Stack designed by Jimmy