--- layout: post title: Reversing IOT Firmware thumbnail: /assets/img/posts/reversing_iot_firmware.webp categories: ['reversing'] tags: reverseengineering, reversing, reverse, iot, firmware, device description: Ever wondered how you could reverse IOT Firmware To Get To A Linux Filesystem? readtime: 14 min --- ### Introduction The goal of this article is to get a firmware binary file, reverse it and try to extract it's `Linux Filesystem`. Now, what is a `filesystem`? Think of a `filesystem` as a structured folder. Linux's filesystem consists of many different folders, most linux distributions follow the structure below but not all do. They are free to choose whatever structure they like, this is pretty standard. ![LinuxFileSystem](/assets/img/posts/linux_filesystem_tree.webp) *source: oreilly.com* ### Why Reverse Firmware? There are many reasons to reverse IOT/Device firmware. Here are some of them: * Security Auditing the Firmware. * Creating software compatible with the device if the manufacturer has not released an SDK. * To learn about it's innards. ### Tooling * Linux If you're on `Windows`, install `Linux` in a Virtual Machine (Oracle Virtualbox, VMware or Hyper-V). Preferably a `Debian` based distribution like `Ubuntu` or `Kali`, since it's the most supported. * dd `dd` is preinstalled on most if not all `Linux` distributions. * binwalk You can install `binwalk` with ```bash sudo apt-get install binwalk ``` * unsquashfs You can install `unsquashfs` with ```bash sudo apt-get install squashfs-tools ``` If `binwalk` is not present in your distribution's software repositories, you will have to manually install it. ### Actually Reversing It For this example we will be using [this](https://web.archive.org/web/20220509051908/https://www.downloads.netgear.com/files/GDC/WN3000RPV2/WN3000RPv2-V1.0.0.92.zip) firmware image. We first need to extract the `.zip` file with ```bash unzip WN3000RPv2-V1.0.0.92.zip ``` to get the actual firmware image, the `.img` file. Running ```bash file WN3000RPv2-V1.0.0.92.zip ``` will give us`WN3000RPv2-V1.0.0.92.img: data`. Not useful at all. Now, this is a proprietary firmware image, so we don't know it's structure. We can use `binwalk` to see all embedded files. Every file has `magic bytes` that tells us what format it is in. `binwalk` searches for these magic bytes in the file, for example, there could be a `.png` file thats magic bytes are correct, and it renders out correctly. But it can have a `.jpg` or any other file embedded at the end of the file. This would approximately be the file structure for it. ``` PNG file magic bytes PNG file data JPG file magic bytes JPG file data ``` This is essentially hiding/embedding the `.jpg` file in the png file. This is pretty common in `steganography`. Moving back to the firmware file, we can use `binwalk` to find the file structure. Running `binwalk WN3000RPv2-V1.0.0.92.img` will give us this output: ``` DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 128 0x80 uImage header, header size: 64 bytes, header CRC: 0xB66ED1F1, created: 2022-02-07 09:04:01, image size: 982848 bytes, Data Address: 0x80000000, Entry Point: 0x8000C570, data CRC: 0x9160FBE3, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "MIPS OpenWrt Linux-2.6.36" 192 0xC0 LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 3062516 bytes 983104 0xF0040 uImage header, header size: 64 bytes, header CRC: 0x863A1B34, created: 2022-02-07 09:04:01, image size: 2490372 bytes, Data Address: 0x80000000, Entry Point: 0x8000C570, data CRC: 0x65B10B31, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "MIPS OpenWrt Linux-2.6.36" 983168 0xF0080 Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 2412158 bytes, 715 inodes, blocksize: 131072 bytes, created: 2022-02-07 09:03:58 ``` We are looking for the `Squashfs filesystem`, since it contains the filesystem of this firmware image. ### Extracting The Filesystem There are two ways of extracting the filesystem, using `binwalk` itself and using `dd`. * binwalk Running ```bash binwalk -e WN3000RPv2-V1.0.0.92.img ``` Will extract all data/sections found. The `Squashfs` filesystem is one of them. After running the command, there will be a `_WN3000RPv2-V1.0.0.92.img.extracted` directory. `binwalk` automatically extracts the `Squashfs` filesystem in the `squashfs-root`. The `squashfs-root` directory is the root directory of the filesystem in the firmware. * dd From the output of the `binwalk` command, we can see the `Squashfs` section: ``` DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 983168 0xF0080 Squashfs filesystem, little endian, version 4.0, compression: lzma, size: 2412158 bytes, 715 inodes, blocksize: 131072 bytes, created: 2022-02-07 09:03:5 8 ``` We can extract the `Squashfs filesystem` with ```bash dd if=WN3000RPv2-V1.0.0.92.img skip=983168 of=filesystem.squashfs bs=131072 count=1 iflag=skip_bytes ``` We will have to replace `skip` with `DECIMAL` and `bs` with `blocksize` from the binwalk command. In this case, we replace `skip` with `983168` since the decimal value in the binwalk command is `983168` and `bs` with `131072` since blocksize is `bs=131072` from binwalk. Here are the parts of the command ``` |---------------------------------------------| | if | input file | |---------------------------------------------| | of | output file | |---------------------------------------------| | skip | number of bytes to skip | |---------------------------------------------| | bs | block size | |---------------------------------------------| | count | set number of blocks to copy | |---------------------------------------------| | skip_bytes | force skip to not consider bs | |---------------------------------------------| ``` This will create `filesystem.squashfs` in the current directory. When we run `file filesystem.squashfs` we can see that the output tells us it's a squashfs filesystem. ``` filesystem.squashfs: Squashfs filesystem, little endian, version 4.0, lzma compressed, 2412158 bytes, 715 inodes, blocksize: 131072 bytes, created: Mon Feb 7 09:03:58 2022 ``` We can now use `unsquashfs` to extract the filesystem. ```bash unsquashfs filesystem.squashfs ``` This will create a `squashfs-root` directory. The `squashfs-root` directory is the root directory of the filesystem in the firmware. #### Thank you for reading!