While I was evaluating a research idea about a SCADA network router during the past week, I used available tools and resources on the Internet to unpack the device firmware and search for interesting components. During security assessments, you may find interesting embedded devices available on the network. Whilst many don’t look at the feasibility of doing firmware analysis, I decided to document the steps I took to analysis my target firmware, so you can take the similar approach in the case of assessing such devices. This could also be a good indication on the feasibility of automating this process (An unfinished project was launched in 2007: http://www.uberwall.org/bin/project/display/85/UWfirmforce).
The following process would be easy for most of you who use *nix systems on a daily bases:
Step 1) Scanning the firmware image
The BinWalk tool is useful for scanning firmware image files to identify embedded file systems and compressed streams inside. It can detect common bootloaders, file systems and compressed archives inside a given firmware image file. Since it works by scanning for signature and magic values, it usually has false positives and the results need to be verified manually.
U-Boot bootloader (yes, it’s German :-)) signature was identified at offset 262144 and the uImage header information, such as creation date, CPU type, etc appears to be valid. This bootloader was followed by a gzip compressed stream, which probably is the zImage kernel and a squashfs file system at offset 1522004. We will attempt to extract this file system in the next step. The following are common bootloaders that are used in embedded devices with ARM CPU:
The bootloader’s task is to load the kernel image at the correct address and pass initial parameters to it. So in most cases we are not interested in analysing the bootloader itself, but in the root file system.
Step 2) Extracting file systems
First, I extracted the uImage content at offset 262144 by using dd command and then used uboot-mkimage (packages.debian.org/uboot-mkimage) to test if it’s a valid uImage file and to discover more information about it:
The image format was valid and it contained two other file system images with 1MB and 2MB sizes, which probably are kernel zImage and root file systems (RAMdisk). If you check the uImage file format, you will notice a 64 bytes long header. There is a “multi-file” image list that contains each image size in bytes and this list is terminated by a 32bit zero. So, I would need to skip 64+2*4+4=76 bytes from start of the uImage file to get to the first Image content that would be kernel zImage:
The file command could not detect kernel image or squshfs in the extracted file systems; this might be due to lack of squashfs (with LZMA compression) in my Ubuntu kernel. I proceed by using Firmware Mod Kit which contains a set of programs to decompress various file system images including squashfs-LZMA. After trying the various unsquashfs version 3.x scripts, I was able extract the rootfs image files successfully:
Step 3) Searching the root file system
Once the root file system files were extracted, we can file and strings search tools to look for interesting files and patterns such as RSA private key files, password and configuration files, SQL database files, SQL query string and etc. In my case, I was looking for RSA certificate or private key files and found the following: (a database of private keys in embedded devices was published in 2011 but it’s not actively maintained, you can access it at http://code.google.com/p/littleblackbox/)
One can write shell scripts to automate the file system search process.
Step 4) Running and debugging the Executables
The Qemu emulator supports multiple CPU architectures including ARM, MIPS, PowerPC, etc and can be used to run and debug the interesting executable extracted from the firmware image on your system for dynamic analysis purposes. You would need to build the Qemu with –static and –enable-debug options. The following figure demonstrates how to run the web server (httpd) that was extracted from my target firmware using chroot and Qemu:
As you can see from the above screenshot, the web server was working fine, but was not able to display the bootloader version, because it couldn’t read this value from the NVRAM (not volatile RAM) normally mounted by the kernel in a real device (there is an interesting post here about resolving the NVRAM access errors while emulating embedded device executables). Some of the executables, like the remote management agent example below, could have more severe problems running under emulator.
For troubleshooting such cases, or monitoring an emulated process while fuzzing it, we would need to attach a debugger to it. This can be achieved by using –g switch in Qemu and using a debugger out of the emulator process or even on a remote windows machine. I used IDA pro remote GDB debugging tool as shown in the figures below:
Once successfully attached to the remote emulated process, IDA pro can be used to simply trace the execution of the process, placing breakpoints or running IDA scripts.
Often overlooked during assessments, firmware analysis of devices can yield results and often do when we target them at SensePost. Our methodology includes the above steps and we recommend yours does too.