Firmware Analysis for IoT Devices
This is the second post in the IoT Exploitation and Penetration Testing series. In this post, we are going to have a look at a key component in an IoT device architecture – Firmware.
Any IoT device you use, you will be interacting with firmware, and this is because firmware can be thought of as the actual code that runs on an IoT or embedded device. For this post, we will start by looking at various ways to extract file system from firmware, and then move into going deeper into analysing binaries for vulnerabilities. The most common architectures for IoT devices are ARM and MIPS, which is also something we will cover later in this series.
Before starting digging deep into the firmware, we would have a look at the components and related aspects, such as file system types, compressions, encryptions, and bootloader.
File system types:
During the entire firmware analysis journey, we will come across various kinds of file systems such as Squashfs, Cramfs, YAFFS2 and so on. The choice of file system is solely to the developers creating the embedded devices, and the other functionalities they want to offer, which might be available in one file system and not in the other. For example, Squashfs is a compressed Linux read-only file system, which is one of the most common file systems you will come across in embedded devices.
For a complete list of file systems, please refer to this link: http://elinux.org/File_Systems.
One of the things we can do, once he has the firmware image is based on the file system type, we could try to mount it and analyse the contents inside it.
So to analyze what location is the filesystem located in, we can use Binwalk. we will discuss Binwalk in detail later on in this post, but for now, it can help us give the exact addresses where the file system is located in.
To mount the jffs2 image on our system, the first thing we will do is to provide an MTD partition in the RAM whose size is specified by total_size.
modprobe mtdram total_size=25247744
Next, we will create a block device through which we can access the partition, and then load up support for jffs2 filesystems which might not be enabled by default.
The next thing is to copy the file system from the location derived above and output to a new file using dd.
Once done, we will simply copy the file system from the file created (filesys) to the mtdblock0 .
Once done, we can then use mount to mount the filesystem so that we can access it. We can quickly look at the main page of the mount and see how we can mount our image.
Since we know that the type of the filesystem is jffs2, we can simply go ahead and use the mount command as mentioned in the man page. So we simply create a new folder in our current location named jffs2 and mount the mtdblock to that directory.
As you can see from the above image, we now have access to the entire filesystem. This is just an example of how we can get access to the file system of firmware. Later on, we will see other simpler techniques to do the same.
Compressions and Encryptions:
Once we have understood the file system, we need to understand the other aspects associated with firmware – namely the compression and encryption in use. The file system in embedded devices are usually compressed to save up space. Some of the most common compressions used by IoT device file systems are LZMA, GZIP, Zlib, Zip and ARJ to name a few.
Let’s put some of this knowledge to practical use. We know that some vendors for LZMA compressed Squashfs file system use the magic number shsq. So, we can perform a hexdump on our firmware and grep for shsq to know the starting address of the firmware.
As we can see above that we found the shsq magic number at the location 0x000e0080. Now that we know the starting address of the file system, we can dump the content using dd.
Since that we know that it’s a squashfs file type, we can run unsquashfs on it to get to the file system. The -l simply list down the contents of the file system.
If you run a unsquashfs -h, it will show that the tool unsquashfs already supports lzma compression.
So we can simply go ahead and extract the file system from filesystem.bin.
This will create a folder called squashfs-root, which will have the entire filesystem extracted. From here, we can now analyse individual binaries or look in the configuration files for identifying vulnerabilities.
The bootloader is the component of any device which helps the entire system to boot up, to put it in the simplest terms possible. It helps the entire system to set up the system settings and then load up the kernel which will be used to load up the entire filesystem.
Some of the most common bootloaders are Das uBoot, Redboot, CFE to name a few. We will come across bootloader again later on in this blog series, but for now, we will keep it limited to this.
You could read more about bootloaders here – http://www.informit.com/articles/article.aspx?p=1647051 .
Once we have understood the firmware,
To be able to perform firmware analysis, it is important to understand how to get hold of the firmware in the first place. Typically, there are two ways to obtain a firmware for a particular device:
Obtaining the firmware from the vendor’s website: Many of the IoT device manufacturers will have the firmware listed down in the Downloads or Support section of the website so that users could download and manually update the device.
Dumping the firmware from the device through hardware exploitation techniques: This can be achieved by either dumping the firmware using serial communication such as UART or JTAG or using SPI Flash. We will discuss this technique in our later posts.
Once you have obtained the firmware, we can now proceed further and start with our analysis techniques. For this exercise, we will use the Damn Vulnerable Router Firmware, which can be obtained from here – https://github.com/praetorian-inc/DVRF.
Once we have the DVRF.bin with us, which is the firmware, we can run a quick hex dump on it to see if we can identify what device does it belong to and maybe some additional information as well.
As we can see from the hex dump, that even though most of the information doesn’t make sense, two of the strings stand out – u2nd and hdr0. Just by a quick google search, we come to know that this is related to a Linksys product which is indeed the case.
Even then, we don’t have enough information about the firmware which we could use for our exploitation. So moving on from hex dump, the next thing we will do is to run binwalk on it.
Binwalk is a firmware reverse engineering tool created by Craig Heffner(@devttys0) to help pen testers and security researchers analyse and understand the firmware. The tool supports various file system compressions and encryptions and is a de-facto tool when it comes to firmware reverse engineering. Installing binwalk on your system is straightforward, and you can follow the instructions given on the Github page of the project located here – https://github.com/devttys0/binwalk/blob/master/INSTALL.md.
Once you have set up binwalk on your system, the next step would be to use binwalk to analyse the firmware and understand the different sections present in it. When we run binwalk on DVRF.bin, below is what we will see.
As we can see from above, the header starts from 0x20 and continues till 0x3c, which is then followed by the gzip compressed data with file name piggy, and finally the squashfs file system starting from 0x192728.
So, let’s use binwalk to extract both piggy, as well the squashfs file system. You can also use dd for the same purpose; binwalk just simplifies the entire process.
Running binwalk on DVRF.bin for extraction, we will be able to achieve the contents of the file system and additional data that is stored inside the firmware.
binwalk -e DVRF_0.3.bin
As we can see from the extracted file system, that it is a Linux-based operating system. Linux is one of the most common OS, which you will encounter while reversing firmware, followed by other OSes such as VxWorks and eCOS.
Once we have extracted the firmware, the next step is to look at the various binaries present in the firmware and analyse them to identify vulnerabilities. One of the easy ways to catch low hanging fruit is to check the version of common binaries such as busybox and see if you can find a corresponding exploit for that given version.
Let us, for now, have a look at another firmware of a Dlink device (mention the device name and firmware download URL). So, we will simply download the firmware from the website and use binwalk to extract file system from the firmware.
binwalk -e Dlink.bin
Let’s try to search for a sensitive credential in this firmware. Telnet seems like a good starting point as it can grant us access to the device on which this firmware is running on.
If we grep for telnet, we can see that there is a file located at /etc/scripts/misc/telnetd.sh.
If we open up this file, below is what the content looks like.
As we can see from the file that it indeed contains code to login to a telnet session with the username of Alphanetworks and the password is the content of a file specified by $image_sign. If we look closely, just in the second line of the script, $image_sign variable is mentioned to be the content of the file /etc/config/image_sign.
So, if we simply cat the /etc/config/image_sign file, we will have the password of the telnet login. Below is the same.
Thus, we were able to reverse the file system from a Dlink router firmware and were able to grab the telnet login credentials from it.
There exist several automated tools to perform static and dynamic analysis of firmware. One such popular tool is firmwalker, developed by Craig Smith, which performs a static analysis on the firmware by performing checks on interesting strings.
To run firmwalker, clone the github repo and point firmwalker.sh on any of the extracted file systems of firmware.
git clone https://github.com/craigz28/firmwalker.git
Once done, simply go ahead and run firmwalker.sh on any of the extracted file systems from binwalk. In this case, we will run it on the file system of Damn Vulnerable Router Firmware.
Overall firmwalker is a nice tool to help you get started with firmware analysis and enable you to find interesting files which you can look further into.
There are other automated tools as well which could be used for static and dynamic analysis of firmware. Since they are a bit more complicated to set up and requires much deeper instructions, we would take it up in the upcoming posts.
Analysing Binaries using disassembly
One of the most important exploitation techniques, once we have the firmware extracted, is analysing the interesting binaries through disassembly. Once you extract Damn Vulnerable Router Firmware, you will find interesting binaries located at squashfs-root/pwnables/Intro/.
You can disassemble them through tools such as objdump, IDA or even online disassembler. For example, if we try out the binary located at pwnables/Intro/stack_bof1 in onlinedisassembler.com, we can see the various functions in the binary and the disassembly for each of them.
The below screenshot shows a disassembly of stack_bof1 on the onlinedisassembler.com.
Also, just like any other advanced disassembler, the onlinedisassembler also has the functionality of showing you a graph layout of the entire disassembly, as shown below.
That is all for this post on Getting started with firmware analysis. In the next post, we will go through how you can emulate firmware and even debug the binaries inside the firmware in real time.
Binwalk installation guide
BH USA 2013: Firmware Reverse Engineering by Jonas Zaddach and Andrei Costin
Reversing Auerswald firmware: https://cweiske.de/tagebuch/auerswald-firmware.htm
Embedded system bootloader: https://en.wikibooks.org/wiki/Embedded_Systems/Bootloaders_and_Bootsectors