# Firmware 5: Binary Manipulation (Spoilers)

**URL:** <https://discourse.securinghardware.com/t/firmware-5-binary-manipulation-spoilers/51>\
**Category:** APA #1: Embedded & IoT Systems\
**Created:** [May 31, 2021, 8:00pm UTC](https://discourse.securinghardware.com/t/firmware-5-binary-manipulation-spoilers/51 "2021-05-31T20:00:06Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![abc](https://discourse.securinghardware.com/letter_avatar_proxy/v4/letter/a/2bfe46/32.png) [@abc](https://discourse.securinghardware.com/u/abc)\
**Post date:** [May 31, 2021, 8:00pm UTC](https://discourse.securinghardware.com/t/firmware-5-binary-manipulation-spoilers/51/1 "2021-05-31T20:00:06Z")

</div>

I have the modified kernel running! 🎉

Key steps required:

1. The uImage header contains 2 CRCs and an image size. These three values must be modified.
2. The squashfs filesystem starts immediately after the compressed kernel (based on the size in the header), so if the compressed kernel size has changed, the squashfs must be dd’d into the correct place. Otherwise: `VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6`

So the procedure is:

1. Modify kernel
2. Compress kernel
3. Put size and CRC of compressed kernel into header
4. Calculate CRC of header with null CRC, then put this CRC in the header.
5. dd header + compressed kernel + squashfs rootfs

Hope this helps.

---

<div class="post-metadata">

**Author:** ![joefitz](https://discourse.securinghardware.com/letter_avatar_proxy/v4/letter/j/838e76/32.png) [@joefitz](https://discourse.securinghardware.com/u/joefitz)\
**Post date:** [June 1, 2021, 6:04pm UTC](https://discourse.securinghardware.com/t/firmware-5-binary-manipulation-spoilers/51/2 "2021-06-01T18:04:10Z")

</div>

congrats, good work!  
Were there any external references you found particularly helpful that i should include in the ‘hints’ section of that lab?

-joe

---

<div class="post-metadata">

**Author:** ![abc](https://discourse.securinghardware.com/letter_avatar_proxy/v4/letter/a/2bfe46/32.png) [@abc](https://discourse.securinghardware.com/u/abc)\
**Post date:** [June 1, 2021, 8:32pm UTC](https://discourse.securinghardware.com/t/firmware-5-binary-manipulation-spoilers/51/3 "2021-06-01T20:32:46Z")

</div>

Not really.

I just started by looking at the binwalk output:

> 327680 0x50000 uImage header, header size: 64 bytes, header CRC: 0xC525C4D1, created: 2016-09-13 04:48:02, image size: 1138908 bytes, Data Address: 0x80000000, Entry Point: 0x80000000, data CRC: 0x2E6A1444, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: “MIPS OpenWrt Linux-3.18.36”

I then looked for the CRCs within the header hex so that I knew where to edit.

The file which binwalk uses to describe the uImage firmware header structure could be useful: [binwalk/src/binwalk/magic/firmware at 772f271f0bcce18771f814b5f20cb19b29082831 · ReFirmLabs/binwalk · GitHub](https://github.com/ReFirmLabs/binwalk/blob/772f271f0bcce18771f814b5f20cb19b29082831/src/binwalk/magic/firmware#L4-L67) or even the uImage source [u-boot/include/image.h at d8729a114e1e98806cffb87d2dca895f99a0170a · u-boot/u-boot · GitHub](https://github.com/u-boot/u-boot/blob/d8729a114e1e98806cffb87d2dca895f99a0170a/include/image.h#L345-L362)

Running `crc32 50040.7z` gave the expected 2e6a144 so I knew how to calculate the data CRC. The compressed image size in hex is `wc -c 50040.7z | awk '{printf("%x",$1)}'`.

I found [How do I calculate the CRC32 of u-boot header? - Installing and Using OpenWrt - OpenWrt Forum](https://forum.openwrt.org/t/how-do-i-calculate-the-crc32-of-u-boot-header/76611) (and later [how do I calculate crc32 of a u-boot header in a modified firmware image? - Reverse Engineering Stack Exchange](https://reverseengineering.stackexchange.com/questions/26108/how-do-i-calculate-crc32-of-a-u-boot-header-in-a-modified-firmware-image)) to help me calculate the header CRC but you can probably find some proper resource.

As for moving the rootfs squashfs to the correct place, I don’t know how things work. That was just a guess based on the error messages and comparing the screen output between the working and broken versions. You’ll see that if you don’t move the squashfs then the following lines are missing (among others) showing a problem finding partitions:

```
[0.390000] 2 uimage-fw partitions found on MTD device firmware
[0.390000] 0x000000050000-0x00000016611c : "kernel"
[0.400000] 0x00000016611c-0x000000800000 : "rootfs"

```

I tried hexedit for the first time, so I needed to use [https://linux.die.net/man/1/hexedit](https://linux.die.net/man/1/hexedit) to find out the keyboard commands as it’s a little tricky.

---

<div class="post-metadata">

**Author:** ![joefitz](https://discourse.securinghardware.com/letter_avatar_proxy/v4/letter/j/838e76/32.png) [@joefitz](https://discourse.securinghardware.com/u/joefitz)\
**Post date:** [June 7, 2021, 7:06pm UTC](https://discourse.securinghardware.com/t/firmware-5-binary-manipulation-spoilers/51/4 "2021-06-07T19:06:38Z")

</div>

Thanks for the details!  
Something I miss from face-to-face classes is the ability to talk to everyone about how they arrive at the solutions they find - it’s really helpful to me to know when people ‘get’, and also helpful when i see where people are lead astray - both are what i keep in mind as i continually revise the content to gently (not too firmly, but not too gently either) guide people in the right direction.

-joe

---

<div class="post-metadata">

**Author:** ![SKBG](https://discourse.securinghardware.com/letter_avatar_proxy/v4/letter/s/838e76/32.png) [@SKBG](https://discourse.securinghardware.com/u/SKBG)\
**Post date:** [October 8, 2026, 4:51pm UTC](https://discourse.securinghardware.com/t/firmware-5-binary-manipulation-spoilers/51/5 "2026-10-08T16:51:27Z")

</div>

Nice! I forgot this forum existed and conversed with Joe over e-mail about the same lab, but putting it here in case others might be inspired too.

It seems people tend to take basically one of 3 approaches:

1. Remove the code that does checksum comparison altogether (e.g. via JTAG, not sure whether modifying the UBoot part of the firmware offline isn’t also feasible - kind of a “big gun” approach, but checksums were meant to help, so removing them when they become a burden might actually make sense)
2. Manually placing correct magic values (checksums, sizes) at the appropriate places - like what OP did
3. Utilizing the tools which are normally used for creating kernel images for UBoot - I was able to quickly make use of mkimage to generate an entirely new 64-byte uImage header (but then double checked the data CRC32 value, cause I didn’t trust the tool :D)

Another interesting topic which OP also mentions is about placing things around the firmware, when the kernel becomes bigger.

- My hacked kernel, for example, ended up being 4 bytes bigger than the original. So I moved everything after it (both SquashFS and JFFS2) 4 bytes towards the end (checked that the JFFS2 partition ends with empty bytes). However, this ended up producing some errors in JFFS2 after all - “CLEANMARKER node found at 0x00000004, not first node in block (0x00000000)” - seem there are sparse markers for “free” space in JFFS2 which need to be aligned to the block size.
- OP’s alternative, of moving just SquashFS, might actually be more sensible, because there is some free unused space between the SquashFS an JFFS2 partitions (the JFFS2 starting offset is bigger than the SquashFS offset + size).
- Joe advised on alternative tricks to actually lower the size of things. For filesystem images - deleting non-significant files, for kernel images - zeroing-out non-significant strings in them.

I love how the Firmware 5 Lab was set-up to challenge us with the “this does not work” warnings - it felt very rewarding to push through it and learn some new tricks while doing so. (Also Joe advised that this is a good preparation for the mostly-hands-off approach that APA#2 takes … and probably for the real world, haha). Thanks Joe!

P.s. What was useful for me to get started was actually the hint in the warning that even “minor modifications” prevent booting - I sensed some checksum immediately. Then when I was actually doing the lab and went back to check the binwalk output … lo and behold - not one, but 2 checksums in the uImage header … which we were instructed to directly copy with dd in the lab 😃  
After that I googled around for uImage headers and stuff and ended up with mkimage as a good tool for generating (and reading) them.
