Firmware is the software counterpart of IoT devices. There are many technologies involved in building a functional IoT Firmware, and there are many vendors contributing to the development of these technologies some of which are like Cisco, Linux, Wind River, etc. In this post when I say firmware, I will mostly be referring to the software component of the device. Firmwares has varying complexity from a Bare-Metal firmware driving tiny less powerful micro-controller to microprocessor-based full-fledged Operating systems like Linux, which is used in more complex devices like router, television, etc.
In this post, we will look at different components involved in building a firmware, and then we will discuss how you can use various open-source tools to reverse engineer firmware. Reversing is an important step which will help you to do further analysis of the device and the firmware. So let’s start looking at what bare-metal firmwares are?
Depending upon the device’s application, the technology stack is used. So, if you consider a device whose task is to read and report surrounding temperature and humidity, it won’t need something very complicated software, like Linux. For those cases, Bare-Metal firmware is used. Now, what is a Bare Metal Firmware you might Ask? In simple terms, this type of firmware directly interfaces with the hardware, there is no driver or kernel involved.
Bare Metal firmware doesn’t do much complicated things, they are usually tasked with not more than 3 or 4 tasks, and those tasks are put in the loop as they are scheduled to run in specific order/condition. The SDK’s provided by the vendor for these devices provide life cycle methods that programmer write those functions are run in the loop. Some little complex feature variants of these SDK’s are FreeRTOS, mbed-os which are real-time operating systems which allow you to do task scheduling and have a very quick response to some of the interrupt requests.
Base Metal firmwares are written in C, so all attacks like buffer overflow related vulnerabilities are also valid for these firmwares. These devices usually collect data and send it to the central server or communicate with other devices connected via UART/SPI Bus(its peripherals). There are chances of finding the vulnerability in the communication protocol, incorrect handling of packets, key exchange, buffer overrun, etc.
Micro-controller based devices are not just used in sensor networks; they are everywhere, from the refrigerator, microwave oven, security alarm system, your car has dozens of these, and so does your laptop/computers. Usually, when you don’t have source code for this firmware, you take the approach of reverse engineering.
Reversing these binaries is a little different from reversing Windows EXE and Linux ELF files; they then don’t have a predefined structure. For bare-metal binaries, you need the data-sheet for the chipset and create memory-map in your disassembly tool like IDA, Ghidra, etc, to get a proper disassembly. Another very critical question memory-map also helps users to answer is what GPIOs, other peripherals is the device interacting with? This information will help to understand the functionality of the device. Now lets look at what is fully-blown operating system based firmware.
When you see more complex systems like Routers, Smart Home Dashboard, Drones, and healthcare devices, they do little more than what bare-metal systems do. Take, for example; a typical wireless router has features like connecting by LAN and WIFI; they can blacklist/whitelist specified MAC addresses and some modern routers have antivirus software and other protection features. To implement all these functions you need a full-fledged Operation System to support all these sophisticated features.
There are many different Operating System options for embedded systems, like Linux, Windows CE, Cisco IOS, Symbian, Android, VxWorks, etc. Some of them are special-purpose like Cisco for routers, and most of them are more general purpose. General statics say that the most popular choice of OS amongst embedded system products is Linux. There are many reasons for that, some of which is its open-source nature, flexibility, and most importantly, it’s free. You can find Linux powered Devices around like internet routers, infotainment systems, etc.
This kind of firmwares is usually packaged with at least three components, Bootloader, Kernel, and the file-system. The Bootloader is the piece of software that helps in loading Operating System, Kernel and passes various information needs. Once the bootloader has done executing the Kernel take over. Once the kernel has started executing, it starts other user applications to make an Operating System usable by the end-user. This usually involves starting various applications and services in the background. Once all this is done then the user can interact with the system. All the user application and app data are stored on the file-system.
Security assessments of these devices usually start with auditing applications running on these devices; Most juicy targets are the remote application services. Issues discovered in these services have a high impact on the security of the device as attackers don’t need to be anywhere near it to compromise it. Anyone on the internet can take control of it if they can exploit the vulnerability. These services are usually web-servers used to configure and control the device features or other services like UPnP, which help in discovering the device by other devices.
Now that we have a high-level overview of how firmware looks like, the next question that comes to your mind is how do you start dissecting the firmware and start analyzing the firmware. An analysis can broadly be classified into the static and dynamic analysis. In static analysis, you read the code and look for bugs. If you don’t have the source code you start reverse-engineering the binary and read the assembly instructions to understand the functionality. While on the other side, dynamic analysis involves running the application and observing its behaviours.
When analyzing a firmware, I usually used a combination of both the analysis techniques to achieve my goal. Below are the list of some of the tools which I frequently use:
My workflow when working with firmware involves all of these tools. The first step usually starts with unpacking the firmware with Binwalk. Next, try to emulate the application of interest in the firmware with the Qemu. If I am not able to emulate the binary, then I investigate the issue with gdb and patch it so that Qemu can run it and look for security issues. This setup also helps me to fuzz the service.
We looked at what the firmware is and what are different types of IoT Firmware you will encounter when assessing an IoT Device. I gave you an overview of how to deal with a different kind of firmware, and we also looked at how different tools can help us to security analysis of a firmware.