Firmware Emulation in the Cloud

firmware-fuckery

This week, I did not attend any CTF events, so there is no writeup. Instead, I spent my time working on firmware reverse engineering with some fellow ~most learned colleagues~. One significant hurdle in firmware reverse engineering is getting a multi-architecture emulation environment set up. This allows you to:

  • Run firmware binaries on a regular host
  • The above, but with gdb
  • As above, but in a screen session so you can actually multitask
  • Compile binaries for your target on a regular host (without the pain of cross-compiling)
  • Tamper with your target filesystem, such as inserting non-device objects into /dev

There are guides to doing this, but they are (to my experience) outdated – it’s even possible to do this entirely on a VPS. The instructions are as follows:

QEMU

We will be using QEMU in whole system emulation mode for the heavy lifting of emulation. QEMU runs without root privilege, and can completely isolate the guest’s filesystem from the host as an image file, making it perfect for our purpose.

At this point, if QEMU is available from your distribution’s repositories, you can install it using your package manager. Alternatively, you can build it from source – the source is available here.

While not necessary, you should patch the QEMU source to remove the check for e->phentsize in linux-user/elfload.c, which should allow you to emulate stripped single binaries (as opposed to the whole OS), should you desire:

firmware_qemu_patch

Then, perform a standard ./configure; make; make install. If you intend to emulate single binaries, you should use ./configure –static.

Debian Netboot

For our guest OS, we will use a Debian netboot image. The example I am using is Debian 8 on MIPSel, but this should work for any architecture. The official Debian website points us to this location for our install images. Grab the initrd and vmlinux files.

You will also need a QEMU image, which you can create with:

qemu-img create -f qcow2 harddisk.img 20G

You can then use qemu-system-mipsel to boot the system into a network install, with the following:

$ qemu-system-mipsel -kernel vmlinux<tab> -initrd initrd.gz -hda 
harddisk.img -append "root=/dev/hda1 console=ttyS0" -nographic
-no-reboot

This should boot into a text-mode Debian installer. Follow the steps to set up a build environment of your choice.

Emulating Firmware

Now, boot your emulated system, and copy your unpacked firmware image into a new directory: from here, you should be able to chroot into the environment as follows (assuming bin/sh exists in the firmware image):

chroot . bin/sh

From here, you should be in a normal shell, running as if you were on a device:

firmware-emusuccess

FAQ

As we stumbled through this process, we stumbled across a few hiccups, which we’ll document here for posterity:

  • Line 1: unexpected {
    This likely means you need to copy uClibc libraries (from your firmware binary) into /lib (in your emulated debian)
  • Exec format unsupported
    This likely means you’re running on MIPS when you should be on MIPSel (or vice versa)
  • apt-get update fails
    Sometimes, network autoconfiguration will fuck up, and leave you with a broken IPv6 configuration. Disable IPv6 via sysctl.
  • When I chroot into a firmware root, it can’t find things like libraries
    Recreate /proc, /sys and /dev based off your host (your qemu host, not your real host):

    • cd to the chroot home. ls should show bin/, etc/, lib/…
    • mount -t proc proc proc/
    • mount -t sysfs sys sys/
    • mount -o bind /dev dev/

Thanks to the below for helping me work this out:

For those of us who made it to Ruxcon this year, I hope everyone had a safe and enjoyable weekend. See you all at the ekoparty CTF 🙂

About Norman

Sometimes, I write code. Occasionally, it even works.
This entry was posted in Bards, Computers, Jesting and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s