Fixing Firmware File Systems

Here’s the scenario: you’ve downloaded the firmware for a device that you want to explore in more depth, and extracted out the updates.  You dig through them and see that they’re EXT4 systems, and say “jackpot!” while rubbing your hands together in glee.  “A quick mount and I can browse to my heart’s content” you say to yourself… and then you see “wrong fs type, bad option, bad superblock on {DEVICE}, missing codepage or helper program, or other error.”  Let’s get past that. 🙂

First the standard disclaimers:

  • I’ve tested all of these commands on up-to-date versions of Ubuntu 18.08 and Kali 2019.2
  • These commands were tested against multiple EXT4 firmware filesystems, but EXT2/3 should work just as well
  • These commands are being run as root and will assume you are as well… if you’re doing this in production then (1) don’t, and (2) use sudo for all of these
  • I’m using “loop55” for example purposes, but you can change this to any unused loop device number on your system.

There are a few common problems, but in general they come down to two areas: a sparse image or a file system that has been — either intentionally or not — improperly aligned with its stated block count.  I cover both below, but first let’s talk about how you’re mounting.

Mounting Using Loop Devices

When you’re dealing with a hardware device mounting is normally straightforward.  The operating system detects the hardware and creates a block device for programs to interface with.  When we’re dealing with firmware though we don’t have a physical device, so we need to create one that will associate to the file in the same way.  Since this creates a loop on the file system (e.g. block device to file) this is called a “loop” device.  We need this for most tools to understand how to handle the files.

Fortunately, there’s an easy command (losetup) that lets us quickly create and destroy these devices.  To create a new loop device that links to a file (e.g. /home/testuser/firmware.img) we first need to see what’s used on our system, which we can do like this:

root@system:# ls /dev/loop*
/dev/loop0
/dev/loop1
/dev/loop2
/dev/loop3
{etc}
/dev/loop20

On my test system you can see that loop[0-20] are being used, so I’m going to use loop55 here.  Grab whatever works for you. 🙂

root@system:# losetup /dev/loop55 /home/testuser/firmware.img

That’s it.  The operating system will create a block device, and now by using /dev/loop55 we can treat the file as if it were hardware.  All that being said, I’ve had issues with building loop devices prior to fixing firmware, so I’d recommend you destroy that newly created loop device as follows:

root@system:# losetup -d /dev/loop55

Now let’s fix that firmware, so we can use this properly!  When you’re ready to test you can mount with a quick command like so:

root@system:# mkdir -p /mnt/fwtest
root@system:# mount /dev/loop55 /mnt/fwtest

And of course you can unmount via:

root@system:# umount /mnt/fwtest

Converting Sparse Images to Regular Images

If you’re lucky (and likely dealing with firmware from an Android device) the issue is just that you have a sparse file system.  There’s a simple fix for that in the form of a command called simg2img, which just converts a sparse file system to a regular (raw) one.  If it’s not already installed by default you can do so with a quick apt command:

root@system:# apt install simg2img

Then to convert the image just call the program with the original and new filename, e.g.:

root@system:# simg2img /home/testuser/firmware.img /home/testuser/firmware.raw

Then build a loop device and test.  If that worked for you, you’re done!  If not, let’s dig deeper.

Fixing Block Count Issues

If you haven’t already, build a loop device and try to mount it, then let’s take a look at dmesg to see what went wrong.

root@system:# dmesg | tail

[102101.123456] EXT4-fs (loop55): bad geometry: block count 265188 exceeds size of device (214846 blocks)

If you see the above, that means that the EXT4 filesystem in your firmware says it’s one size (265,188 blocks in this case) but the loop device says it’s a different size (214,846 blocks in this case).  This can occur because the target of the firmware will actually be the size the EXT4 filesystem says it is, or by OEMs trying to make reverse engineering harder (in which case it somewhat worked if you’re reading this).  Make note of what size the device says it is, then let’s fix that!

To fix that, first destroy your loop device.

Next, we’re going to resize the filesystem.  If you’re working on your original file (don’t!) then make a backup before you do this.  Once that’s done, resize the device as follows:

root@system:# resize2fs /home/testuser/firmware.img {SIZE}

For example:

root@system:# resize2fs -f /home/testuser/firmware.img 214846
resize2fs 1.44.1 (24-Mar-2018)
Resizing the filesystem on firmware.img to 214846 (4k) blocks.
The filesystem on firmware.img is now 214846 (4k) blocks long.

The “-f” portion forces the resize, because otherwise resize2fs may try to help you out and adjust that value up, which leaves you in the same state.  Finally, we may need to clean up the filesystem to make it mount cleanly, which we can do with the e2fsck tool:

root@system:# e2fsck -f /home/testuser/firmware.img

The first question it will likely ask is if you want to abort.  Make sure you say no!  After that just hold down the “y” button until it finishes, then take your shiny new firmware, build a new loop device, and you’re (hopefully) done.

There you go!  You should now have an easily mountable image that you can play with to your heart’s content.  Until next time… good hunting!

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 )

Facebook photo

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

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Website Powered by WordPress.com.

Up ↑

%d bloggers like this: