Emulating IoT Firmware Made Easy: Start Hacking Without the Physical Device

Blogs like these are a little out of character for me. However, having helped & debugged about a dozen friends weirdly configured environments, I feel there might be a lack of simple guidance publicly available. So to make my life easier, I've written down the steps I use to go through to emulate firmware.

I am by no means a SME on QEMU, this is nothing more then a blog I've been sending friends in private. I personally use Shambles full time, almost every day. I'll be releasing the long awaited blogpost covering Shambles very soon 😛.

QEMU stands for "Quick EMUlator" and is a free open-source emulator that can run a wide range of hardware architectures, including ARM, MIPS, PowerPC, and x86. In other words, its a framework to emulate the software of an embedded system to run tests, experiments from a simulated/virtual environment.

It's a great tool for hackers or security researchers. You may have come across situations where you want to test the security of a hardware product, but don't have the physical device on hand. In these cases, using a hardware emulator like QEMU can come in quite handy. By allowing users to run embedded devices/programs in a controlled environment, QEMU in conjunction with pwndbg can help identify and fix bugs, as well as facilitate reverse engineering and other forms of code analysis.

alt

That being said, if you enjoy physically holding and owning what you hack and don't want to deal with all the headaches and downsides of emulation (which there are many) I recommend reaching out to companies whose hardware you'd like to look at/hack and just ask them for it. Surprisingly/from experience, a lot of vendors respond favorably to the idea. A good handful of them will ask that you sign an NDA, but for the most part they're a mutual understanding that you'll operate/work in good faith. In the end, you get free hardware, gadgets, and most times they'll end up paying you for the vulnerabilities you discover. Under NDAs you wont be at liberty to share your discoveries.

I suggest reading the full blog before following any steps. I'm first demonstrating what I consider a ghetto/cowboy way to emulate embedded devices. This is what I find a lot of my friends are doing. It ultimately does works but its a YOLO approach which will cause you headaches down the line. Further in the blog I go through my old approach which TMI still works.

I strongly recommend using Ubuntu 18.04 to perform QEMU emulation. Not everyone will agree on this but I simply find it much to manage interfaces on this Linux distribution. The steps below will assume you're on 18.04.

On a fresh OS, we'll go ahead and get installs out of the way.

#Installing QEMU
sudo apt-get install qemu
sudo apt-get install qemu-user-static
sudo apt-get install qemu-system

#Install all the dependencies
sudo apt-get install libglib2.0 libglib2.0-dev
sudo apt-get install autoconf automake libtool

#Install the dependencies required by the network bridge
sudo apt-get install uml-utilities bridge-utils

#If you want to attach GDB to QEMU (not covered in this blog)
sudo apt-get install gdb-multiarch
git clone GitHub - pwndbg/pwndbg: Exploit Development and Reverse Engineering with GDB Made Easy
cd pwndbg
./setup.sh

To emulate any product we’ll first need to recover the firmware from the vendor’s page. Note that not all vendors make their firmware publicly available.

alt

Once our firmware is downloaded we’ll run binwalk to do some validations, see what the firmware contains and make sure we’ve pulled the proper firmware. Our goal here is to ultimately extract the embedded files off this firmware binary.

binwalk TOTOLINK_CS133E-EN_EX200_WX005_8196E_SPI_4M32M_V4.0.3c.7646_B20201211_ALL.web 

As seen below, this firmware image contains the squashfs file system, some UNIX path stuff, and an LZMA compressed file which should be relatively large.

alt

To extract these we’ll use binwalk with the -Me flag to extract the contents recursively.

binwalk -Me TOTOLINK_CS133E-EN_EX200_WX005_8196E_SPI_4M32M_V4.0.3c.7646_B20201211_ALL.web

As seen below we’re left with a large amount of everything.

alt

What we really care about is squashfs. This is a read-only file system that lets you compress whole file systems or single directories. By going into this directory we obtain the entire applications file system schema as seen below.

alt

For anyone whos interested, there is a tool called firmwalker, which can automatically analyze the file system and extract important files. Personally, I don’t think it is particularly easy to use. But I’m also not the brightest crayon in the box. Also I know you can use FAT instead of QEMU but its bad for reverse engineering IMHO.

This is something I personally like to do to make sure I don’t mess up down the line. I think its good practice to got to identify what arch we’ve got as this will impact how we emulate this router. As seen below It’s MIPS little endian.

alt

Another thing that is important to understand is how the app spawns and generally initiates itself. Most of this information pertaining to this is typically located in /etc/init.d for products such as routers.

We’re attempting to emulate a router that is administered through a local web UI. Therefore, there must be a webserver. For this product, its instantiation can be found in rcS

cat etc/init.d/rcS 

In this case, it’s a web server running lighttp and the command below is how the router spawns it.

cat etc/init.d/rcS 
alt

Since our architecture is MIPS little endian we will use qemu-mips-static to run this router on our systems localhost. The commands to do this are listed below.

cp $(which qemu-mips-static) .

sudo chroot . ./qemu-mips-static lighttpd -f lighttp/lighttpd.conf -m lighttp/lib/

When running the command we get an error saying that it’s missing a pid-file as seen below.

alt

Looking back at etc/init.d/rcS we see that it requires the existence of the following file.

alt

This isn’t rocket science, this file is required and doesn’t currently exist so we’ll just go ahead and create it manually. Files like these are normally generated uppon first full boot.

alt

If we run the command again, it runs successfully and we can go to the routers page.

altalt

The catch is that it’s likely all fucked up because chances are the etc/init.d/rcS paths & symlinks are all wrong.

alt

If you want to fix this manually and this is fine for you then by all means go live your best life. However, we’re likely going to run into a ton of problems since there are many crucial folders that didn’t get mounted. Because of this, I prefer to use a “fresh system mode” approach. We could change the paths to the proper UNC path where /squashfs-root is located. But we can do better and it won’t mess anything up on our system.

I won’t go into details about the “system mode” works because TBH you don’t need to. You can use the start-mipsel.sh script below in conjunction with the following downloads to be able to perform this system mode approach.

  1. vmlinux-3.2.0-4-4kc-malta
  2. debian_wheezy_mips_standard.qcow2

Any additional files you might need can be found here.

alt
sudo ./start-mipsel.sh

#set network
sudo brctl addbr virbr0
sudo ifconfig virbr0 192.168.5.1/24 up
sudo tunctl -t tap0
sudo ifconfig tap0 192.168.5.11/24 up
sudo brctl addif virbr0 tap0

qemu-system-mips -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mips_standard.qcow2 -append “root=/dev/sda1” -netdev tap,id=tapnet,ifname=tap0,script=no -device rtl8139,netdev=tapnet -nographic

Once all these files have been downloaded and are in our current working directory we’ll go ahead and start QEMU.

alt

We’re going to bring the interface up

alt
ifconfig eth0 192.168.5.12 up

From your main ubuntu machine use SCP to copy over the /squashfs-root/ directory into the QEMU environment.

scp -r squashfs-root/ [email protected]:/root/
alt

One of the most important steps is to mount.  

mount -o bind /dev ./squashfs-root/dev
mount -t proc /proc ./squashfs-root/proc
mount -o bind /sys ./squashfs-root/sys

Once this is done it’s time to start up the system. This is accomplished by using chroot command to change the root folder to the filesystem to run /bin/sh.

chroot ./squashfs-root/ /bin/sh
alt

And startup the server.

lighttpd -f lighttp/lighttpd.conf -m lighttp/lib/ 
alt

We can go to https://192.168.5.1 to see our app deployed.

alt

Now, this might still looks broken but it’s actually the proper login page for this app. It’s possible that your app looks kind of broken like mine just take the time to do your due diligence and check the code/sanity check. If it is broken simply revisit your mounts and compare them to the firmware initiation script running in /etc/init.d/*. It might be that the symlinks are messed up.

Regardless, you should now be able to use Burp Suite to capture the requests and interact with the application. However, you might not be out of the woods just yet. As you can see below we’re presented with the Cste MD5 failed error.

alt

The only real way to fix these errors is to start reversing. To find the culprit the easiest way is to simply grep for the error.

alt

Turns out that this error stems from FUN_00403b40 which occurs when a data stream cant read from a file named cstemd5.

alt

Simply adding a file in /var/cstemd5 with a random md5 string seems to have resolved this issue.

alt

At this point you’re ready to start reverse engineering and finding vulnerabilities.

To demonstrate that QEMU is stable and can be used to craft and test POC’s here is a little demo of a quite obvious command injection vulnerability.

alt

​In the downloadFile.cgi function, the QUERY_STRING environment parameter variable is the content of the GET request.  If we can control QUERY_STRING there’s a chance we could perform a command injection. To no ones surprise we are. As seen below we’re able to spawn the date.

alt

Here’s proof below of achieving arbitrary read on the device being emulated in our QEMU environment.  

alt

Summary:

This blogpost was never meant to see the light of day. However looking at my google analytics these are the blogs that seem to get the most traction, hence they must be helping people. Also the handful of friends who’ve used this blog have liked it, so I hope you did too. Follow me on twitter I sometimes post interesting stuff there too.

Other good QEMU references:

  1. https://www.zerodayinitiative.com/blog/2020/5/27/mindshare-how-to-just-emulate-it-with-qemu
  2. https://wiki.bi0s.in/hardware/firmware/firmware-re/

Thank you for reading!

Article Link: Emulating IoT Firmware Made Easy: Start Hacking Without the Physical Device