1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
---
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.

*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!
|