What's in the box?

This whole thing started with a blog post about a mini router changed into a CTF level. It was an exciting idea, and when they attached a special clip to the router's flash memory to dump all the data from it, I knew that I wanted to try that.

Soon after, I ordered the router and the special clip. The router was a bit newer V2 variant, but I hoped it won't cause any problems. All that was left to do was wait for the package to arrive.


We have two connections we can start with. The first one is the UART serial communication, and the second one is the clip and the SPI communication of the flash memory. I'll use a Raspberry Pi because it can handle both, so I got a 3B+ model out from a drawer. Most likely, any other model would work as well too, but the settings might be a bit different.

The UART connection on the Raspberry Pi gives access to the Pi's own console, which is in the way of our endeavor to talk to a different device. So our first task is to disable this function. For this, we need to remove the console=serial0,115200 part from the /boot/cmdline.txt file, add a dtoverlay=disable-bt line into the /boot/config.txt file, and lastly, run a systemctl disable hciuart command.

If we are already here, we can enable SPI with a raspi-config command (Interfacing Options > SPI). We will need that later.

Next, let's install some software to play with.

# apt-get install minicom binwalk python-lzma git
# pip install cstruct
# git clone https://github.com/sviehb/jefferson.git
# cd jefferson/
# python setup.py install

The minicom command handles the UART communication, binwalk will be able to unpack the dump from the flash memory, jefferson is needed by binwalk to handle JFFS2 filesystems, and the other stuffs are for jefferson.

If it's all done, we should do a reboot just to be safe, and we are ready with the setup phase.

Serial console

After the router arrived, we started to get to know each other in an unusual way. I took it apart. I quickly confirmed that the V2 version has the same chips and connections and turned it on to do the first-time setup.

Pins of the serial connection

I connected the router's pins with the Raspberry Pi's proper pins (ground to ground, RX to TX, and TX to RX), started a minicom -b 115200 -o -D /dev/serial0 command, and restarted the router.

The router connected to the Raspberry Pi

I started to get the usual boot output, and after it finished, I hit an Enter (because the output told me to) and got a root shell.

Well, this would be a disappointing CTF level, but it looks like there is no defense on the serial console by default. I thought that if I was already here, I could try to make things a bit harder for myself. I changed the ::askconsole:/bin/ash --login row to ::askconsole:/bin/login in the /etc/inittab file and restarted the router. After the boot, I hit an Enter and got a proper login prompt.

A bit better, but during the boot, an interesting line caught my eyes in the output. Another restart, an F key, and an Enter in the right moment, and I got another root shell because of the failsafe mode. After a bit of research, I found out that there is no easy solution for this, and it cannot be done with the factory firmware, so I let it go for now.

Flash memory

A bit closer look at the flash memory

Let's move on to the clip instead. I unplugged the device, connected the non-biting end of the clip to the Raspberry Pi (the documentation of the chip helped a lot here), and attached the biting end to the flash memory.

Dumping the contents of the flash memory

Based on the original blog post, I should have kept pressing the Reset button on the router so the chip could communicate with the Raspberry Pi, but the proper flashrom command didn't want to give me the favorable output. One of the LEDs should have also been lit if I bit the memory properly, but that didn't happen either.

# flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000
flashrom  on Linux 4.19.97-v7+ (armv7l)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
No EEPROM/flash device found.
Note: flashrom can never write if the flash chip isn't found automatically.

I checked all the connections. I suspected the jumper cables and the build quality of the clip, but according to the multimeter, everything was alright. So after a lot of clip-rearranging, I tried it without holding the Reset button, and it just worked. Maybe some differences in the V2 version; I don't know.

# flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r dump.bin
flashrom  on Linux 4.19.97-v7+ (armv7l)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on linux_spi.
Reading flash... done.

The result was a 16-megabyte binary file containing the device's file systems (what a freakishly small space for a Linux). It runs OpenWRT, so I had a pretty good idea of what will I find in this file.

It should contain a SquashFS that holds most of the system and is mounted as read-only during usage, and a JFFS2 filesystem which is read-write and keeps track of all the changes made by the user. This is the point where I was enlightened about the inner workings of router factory resets. They just throw away the content of JFFS2 file system, and it's done.

There is nothing left to do than unpacking it with the help of the binwalk -Me dump.bin command and examining the result.

# ls -Al _dump.bin.extracted/
total 14496
-rw-r--r--   1 root root 10442640 Apr  3 10:20 1CE416.squashfs
-rw-r--r--   1 root root  4390912 Apr  3 10:20 BD0000.jffs2
drwxr-xr-x 145 root root     4096 Apr  3 10:20 jffs2-root
drwxrwxr-x  16 root root     4096 Aug  5  2019 squashfs-root

As I expected, we got a squashfs-root, and its contents look like a standard Linux root directory. However, the contents of the jffs2-root directory look a bit weird.

From here, it's just a couple of find commands to find the original shadow file with the password hashes or maybe OpenVPN client settings so we can go forward to other networks from the router. The stolen password hashes then can be cracked at home with a password cracking monster containing 10 GPUs.

In conclusion, maybe it's not a stupid idea to physically protect the network equipment, and we should use passwords longer than 12 characters if we don't want to see them cracked in a matter of hours. It's true not only for routers but any IoT devices where the manufacturer didn't pay enough attention to close these backdoors.

Further reading

Ez a bejegyzés magyar nyelven is elérhető: Mit rejt a doboz?

Have a comment?

Send an email to the blog at deadlime dot hu address, or visit the tweet related to this post.

Want to subscribe?

We have a good old fashioned RSS feed if you're into that, and you can also follow the blog on Twitter.