Close

Chapter 1 – Recovering the Passwords

A project log for Wi-Fi Router Autopsy

Breathe new life into an old Wi-Fi router: explore hardware - software connections, reverse engineer components, and test security.

yalukeyaluke 10 hours ago0 Comments

The router had spent the last seven years forgotten in the back of a drawer. During that time, I used a device provided by my internet service provider. After connecting the old router to power, it booted successfully and started serving a network. However, I had no idea what the passwords were—neither for Wi-Fi nor for administration access. Before resorting to pressing the reset button, I decided to experiment and see if I could somehow retrieve the passwords.

Disassembling the Router

Disassembly was straightforward, though reading instructions beforehand would have been beneficial—I ended up breaking two fasteners in the process. A quick inspection of the PCB revealed two connectors: one 1x4-pin and one 2x7-pin connector. Documentation found on openwrt.org confirmed these connectors as UART and JTAG interfaces:

Connecting via UART Using Raspberry Pi 5

Since I didn't have a USB-to-serial adapter available, I decided to use a Raspberry Pi 5 (RPi) to communicate with the router through UART. The configuration was simple:

  1. First, I enabled the serial hardware interface on the Raspberry Pi using `raspi-config`.
  2. Next, with both devices powered off, I connected them as follows:
Raspberry Pi 5Router UART
GND (pin 6)pin 2
GPIO14/UART0 TX (pin 8)pin 3
GPIO15/UART0 RX (pin 10)pin 4

After making these connections, I powered on only the Raspberry Pi.

Using minicom to Access Router's Serial Console

The first tool I used for communication was `minicom`, installed on Raspberry Pi with:

sudo apt install minicom

Using communication parameters provided by OpenWrt documentation—baud rate: 115200, data bits: 8, parity: none, stop bits: 1, flow control: none—and the RPi UART device (`/dev/ttyAMA0`), the command line looked like this:

minicom -b 115200 -8 -D /dev/ttyAMA0

Minicom then waited for data from the router. Upon powering up the router, after a few seconds I saw this output:

When seeing "Autobooting in 1 second," I quickly typed `tpl` followed by <enter> to interrupt booting and enter the boot prompt. At this prompt, various commands were available (`help` lists them all). However, only one command seemed useful for inspecting memory contents: `md` (memory display).

Dumping Router Flash Memory

I assumed passwords were stored somewhere within flash memory, which should be mapped into address space. Based on OpenWrt documentation (flash layout and flashing instructions), I confirmed that flash memory starts at address `0xbf000000` and occupies an 8 MB address range. This was precisely the area I wanted to dump and analyze.

Minicom offers an option (`-C`) to log all communication into a file. Initially, my idea was to use this feature along with the `md.b` command to dump flash memory:

Output from `md` can be parsed easily and converted into binary format for an exact copy of flash data. Unfortunately, random chunks of data occasionally went missing during dumping—I wasn't sure if this was due to issues with the router itself, Raspberry Pi hardware limitations, or something else entirely.

Reliable Data Dumping with Python Script

To ensure reliable data dumping—checking for missing data and retrying failed reads—I decided to write a Python script using the `pyserial` library (`pip3 install pyserial`). Here's a snippet of Python code that automates connecting to the router's boot prompt (eliminating manual typing of `tpl`):

import serial
from time import sleep

with serial.Serial('/dev/ttyAMA0', 115200, timeout=1) as conn:
        # connect and "login"
        logged_in = False
        buffer = ''
        while(not logged_in):
            x = str(conn.read(), encoding='utf-8')
            buffer = buffer + x
            print(x, end='')
            if len(buffer) >= 24 and buffer[-24:] == 'Autobooting in 1 seconds':
                # now we have 1 second to "login"...
                sleep(0.1)
                # by sending 'tpl' string to device
                conn.write(bytes('tpl\n', 'utf-8'))
                # let's read all the stuff before sending next command
                x = str(conn.read(100), encoding='utf-8')
                print(x)
                logged_in = True

The rest of my Python script is straightforward—it reads memory data in small chunks, verifies integrity, retries failed reads if necessary, and saves valid data into three separate files:

The complete script is available here: https://github.com/yaluke/router_hack/blob/main/read_flash.py

Finding Passwords in Dumped Data

With all flash data collected successfully, it was time to search for passwords.

Wi-Fi Password Recovery

I started with recovering the Wi-Fi password since it seemed easier—especially because I already knew my network's SSID (network name). A quick search showed that my network name appeared exactly once in the dumped file. Just a few lines below it was something resembling a password:

Testing confirmed success—I could connect to my router's Wi-Fi network!

Admin Password Recovery

Recovering the administrator password proved trickier since I didn't know the username either. To identify potential usernames and passwords stored in binary form, I used Linux's built-in `strings` utility:

strings firmware.bin > strings_output.txt

 By default (`strings` with minimum length set at four characters), this yielded around 56k results—far too many lines to check manually. Assuming usernames/passwords would typically be longer than four characters, I adjusted string length filtering using `-n`. Setting minimum length at eight characters reduced results significantly—to about 1.5k strings—which was manageable for manual inspection:

strings -n8 firmware.bin > strings_output.txt

Given typical flash layouts where configuration data (including passwords) is usually stored toward memory's end region, I began checking strings from there first—and quickly found administrator credentials here (md output):  


A quick test confirmed success—I regained administrative access!

Conclusion

Mission accomplished! By inspecting router memory directly via UART connection and careful analysis of dumped flash memory contents, I successfully recovered both Wi-Fi and administrative passwords without resetting my device.

This experiment also revealed that these sensitive credentials were stored without any encryption or protection measures—a concerning practice. It makes me wonder if such insecure storage methods are common industry-wide...

Discussions