This is a write-up of the room Dumping Router Firmware from TryHackMe.

Task 1: Preparation

Let’s first download the router firmware from this repository.

Then make sure that binwalk has JFFS2 with the following commands:

~ sudo pip3 install cstruct
~ git clone https://github.com/sviehb/jefferson
~ cd jefferson && sudo python3 setup.py install

Task 2: Investigating Firmware

Analyse the firmware with strings by typing:

~ strings FW_WRT1900ACSV2.img 
Linksys WRT1900ACS Router
@ #!
!1C "
 -- System halted
Attempting division by 0!
Uncompressing Linux...
decompressor returned an error
 done, booting the kernel.
invalid distance too far back
invalid distance code
invalid literal/length code
incorrect header check
unknown compression method
invalid window size
invalid block type
invalid stored block lengths
too many length or distance symbols
invalid code lengths set
invalid bit length repeat
invalid literal/lengths set
invalid distances set
incorrect data check
...

You will notice that in the output, there is some clear text allowing for further analysis with binwalk. Here we can see that the first line is:

~ Linksys WRT1900ACS Router

And that the device is running Linux.

Next we will use binwalk to analyse further. To get the available commands we run:

~ binwalk -h

Binwalk v2.2.0
Craig Heffner, ReFirmLabs
https://github.com/ReFirmLabs/binwalk

Usage: binwalk [OPTIONS] [FILE1] [FILE2] [FILE3] ...

Disassembly Scan Options:
    -Y, --disasm                 Identify the CPU architecture of a file using the capstone disassembler
    -T, --minsn=<int>            Minimum number of consecutive instructions to be considered valid (default: 500)
    -k, --continue               Don't stop at the first match
...
Extraction Options:
    -e, --extract                Automatically extract known file types
...

We see from the output that -e allows us to extract files from the firmware image. So we can now run:

binwalk -e FW_WRT1900ACSV2_2.0.3.201002_prod.img 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0xFF40CAEC, created: 2020-04-22 11:07:26, image size: 4229755 bytes, Data Address: 0x8000, Entry Point: 0x8000, data CRC: 0xABEBC439, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "Linksys WRT1900ACS Router"
64            0x40            Linux kernel ARM boot executable zImage (little-endian)
2380          0x94C           device tree image (dtb)
17280         0x4380          device tree image (dtb)
22528         0x5800          device tree image (dtb)
26736         0x6870          gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
4214256       0x404DF0        device tree image (dtb)
6291456       0x600000        JFFS2 filesystem, little endian

We can see that the first item extracted is uImage header and the creation date is 2020-04-22 11:07:26. We can also see that the CRC is 0xABEBC439, the image size is 4229755 bytes and it is an ARM device. You will notice that binwalk created two new files, 600000.jffs2 and 6870.

If we run string on 6879, we get the following output:

~ strings 6870
Q 0X
Q!PU
PFV8@-
ARMv7 Processor
Tainted:
6A_p
6A_p
6A_p
Q8@-
;p@-
...
PACKET
standard
filter
INPUT
FORWARD
OUTPUT
PREROUTING
OUTPUT
POSTROUTING
*@+T
L2CAP
named UNIX socket
tcp NFSv4.1 backchannel
PPPOL2TP
atst
nl80211
mlme
config
scan
regulatory
...

You’ll notice that there is some clear text in this file so we can run:

~ binwalk -e 6870 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
492           0x1EC           device tree image (dtb)
1904228       0x1D0E64        SHA256 hash constants, little endian
4112676       0x3EC124        SHA256 hash constants, little endian
5877920       0x59B0A0        Linux kernel version 3.10.3
6176102       0x5E3D66        Unix path: /var/run/rpcbind.sock
6261498       0x5F8AFA        MPEG transport stream data
6261758       0x5F8BFE        MPEG transport stream data
6902132       0x695174        Unix path: /dev/vc/0
6993884       0x6AB7DC        xz compressed data
7027944       0x6B3CE8        Unix path: /lib/firmware/updates/3.10.39
7194599       0x6DC7E7        Copyright string: "Copyright 2005-2007 Rodolfo Giometti <[email protected]>"
7218153       0x6E23E9        Copyright string: "Copyright(c) Pierre Ossman"
7301128       0x6F6808        Unix path: /etc/init.d/ipv6_react_to_ra.sh
7304520       0x6F7548        Neighborly text, "NeighborSolicits6InDatagrams"
7304540       0x6F755C        Neighborly text, "NeighborAdvertisementsorts"
7309086       0x6F871E        Neighborly text, "neighbor %.2x%.2x.%pM lost rename link %s to %s"
7946423       0x7940B7        LZMA compressed data, properties: 0xC0, dictionary size: 0 bytes, uncompressed size: 64 bytes
7970360       0x799E38        ASCII cpio archive (SVR4 with no CRC), file name: "dev", file name length: "0x00000004", file size: "0x00000000"
7970476       0x799EAC        ASCII cpio archive (SVR4 with no CRC), file name: "dev/console", file name length: "0x0000000C", file size: "0x00000000"
7970600       0x799F28        ASCII cpio archive (SVR4 with no CRC), file name: "root", file name length: "0x00000005", file size: "0x00000000"
7970716       0x799F9C        ASCII cpio archive (SVR4 with no CRC), file name: "TRAILER!!!", file name length: "0x0000000B", file size: "0x00000000"
7996352       0x7A03C0        CRC32 polynomial table, little endian
8075823       0x7B3A2F        LZMA compressed data, properties: 0xC0, dictionary size: 0 bytes, uncompressed size: 32 bytes
8227376       0x7D8A30        Copyright string: "Copyright 2000~2013, Marvell International Ltd."
8275455       0x7E45FF        LZMA compressed data, properties: 0xC0, dictionary size: 0 bytes, uncompressed size: 192 bytes

You’ll dicover that is is running Linux kernel version 3.10.3.

Task 3: Mounting and Analysis of the Router’s Filesystem

Follow the instructions to mount the filesystem:

#Step 1 
#If /dev/mtdblock0 exists, remove file/directory and re-create the block device
rm -rf /dev/mtdblock0
mknod /dev/mtdblock0 b 31 0

#Step 2
#Create a location for the jffs2 filesysystem to
mkdir /mnt/jffs2_file/

#Step 3
#Load required kernel modules
modprobe jffs2
modprobe mtdram
modprobe mtdblock

#Step 4
#Write image to /dev/mtdblock0
dd if=/root/Router/600000.jffs2 of=/dev/mtdblock0

#Step 5
#Mount file system to folder location
mount -t jffs2 /dev/mtdblock0 /mnt/jffs2_file/

#Finally
cd /mnt/jffs2_file/

Note: You will need to change some of the paths. After that is mounted you can list the files by typing:

~ ls -la
total 3
drwxr-xr-x 17 root root  0 Jan  1  1970 .
drwxr-xr-x  1 root root 20 Jun 10 19:28 ..
drwxr-xr-x  2 root root  0 Apr 22 12:10 bin
drwxr-xr-x  2 root root  0 Apr 22 12:44 cgroup
drwxr-xr-x  2 root root  0 Apr 22 12:44 dev
drwxr-xr-x 17 root root  0 Apr 22 12:42 etc
drwxr-xr-x  2 root root  0 Apr 22 12:42 home
drwxr-xr-x  3 root root  0 Apr 22 12:39 JNAP
drwxr-xr-x  2 root root  0 Apr 22 12:44 lib
lrwxrwxrwx  1 root root 11 Apr 22 12:10 linuxrc -> bin/busybox
lrwxrwxrwx  1 root root  8 Apr 22 12:42 mnt -> /tmp/mnt
-r--r--r--  1 root root 20 Apr 22 12:44 .mtoolsrc
lrwxrwxrwx  1 root root  8 Apr 22 12:42 opt -> /tmp/opt
drwxr-xr-x  2 root root  0 Apr 22 12:42 proc
drwxr-xr-x  2 root root  0 Apr 22 12:42 root
drwxr-xr-x  2 root root  0 Apr 22 12:44 sbin
drwxr-xr-x  2 root root  0 Apr 22 12:42 sys
drwxr-xr-x  2 root root  0 Apr 22 12:42 tmp
drwxr-xr-x  2 root root  0 Apr 22 12:36 usr
lrwxrwxrwx  1 root root  8 Apr 22 12:42 var -> /tmp/var
drwxr-xr-x  2 root root  0 Apr 22 12:37 www

We can see from the output that linuxrc links to /bin/busybox and that mnt, opt and var link to /tmp/. www would store the HTTP Server. We can now look at bin.

By listing the files we can see that most of them point to busybox:

~ ls -la
total 1357
drwxr-xr-x  2 root root      0 Apr 22 12:10 .
drwxr-xr-x 17 root root      0 Jan  1  1970 ..
lrwxrwxrwx  1 root root      7 Apr 22 12:10 addgroup -> busybox
lrwxrwxrwx  1 root root      7 Apr 22 12:10 adduser -> busybox
lrwxrwxrwx  1 root root      7 Apr 22 12:10 ash -> busybox
-rwxr-xr-x  1 root root   7112 Apr 22 12:44 attr
-rwxr-xr-x  1 root root 593280 Apr 22 12:44 busybox
lrwxrwxrwx  1 root root      7 Apr 22 12:10 cat -> busybox
lrwxrwxrwx  1 root root      7 Apr 22 12:10 catv -> busybox
-rwxr-xr-x  1 root root   8644 Apr 22 12:44 chacl
lrwxrwxrwx  1 root root      7 Apr 22 12:10 chgrp -> busybox
lrwxrwxrwx  1 root root      7 Apr 22 12:10 chmod -> busybox
lrwxrwxrwx  1 root root      7 Apr 22 12:10 chown -> busybox
lrwxrwxrwx  1 root root      7 Apr 22 12:10 cp -> busybox
lrwxrwxrwx  1 root root      7 Apr 22 12:10 cpio -> busybox
-rwxr-xr-x  1 root root  88232 Apr 22 12:44 curl
-rwxr-xr-x  1 root root   6039 Apr 22 12:16 curl-config
lrwxrwxrwx  1 root root      7 Apr 22 12:10 date -> busybox
lrwxrwxrwx  1 root root      7 Apr 22 12:10 dd -> busybox
...

We can see from the output that sqlite3 would be running.

We can now look at etc:

~ ls -la
total 325
drwxr-xr-x 17 root root      0 Apr 22 12:42 .
drwxr-xr-x 17 root root      0 Jan  1  1970 ..
-r-xr-xr-x  1 root root   1226 Apr 22 11:47 24G_power_table_AP
-r-xr-xr-x  1 root root   1036 Apr 22 11:47 24G_power_table_AU
-r-xr-xr-x  1 root root   1036 Apr 22 11:47 24G_power_table_CA
-r--r--r--  1 root root   1226 Apr 22 11:47 24G_power_table_CE
-r--r--r--  1 root root   1036 Apr 22 11:47 24G_power_table_FCC
-r-xr-xr-x  1 root root   1036 Apr 22 11:47 24G_power_table_PH
-r-xr-xr-x  1 root root    860 Apr 22 11:47 5G_power_table_AP
-r-xr-xr-x  1 root root    860 Apr 22 11:47 5G_power_table_AU
-r-xr-xr-x  1 root root    860 Apr 22 11:47 5G_power_table_CA
-r--r--r--  1 root root    380 Apr 22 11:47 5G_power_table_CE
-r--r--r--  1 root root    860 Apr 22 11:47 5G_power_table_FCC
-r-xr-xr-x  1 root root    860 Apr 22 11:47 5G_power_table_PH
-rw-r--r--  1 root root     16 Apr 22 12:44 builddate
-rw-r--r--  1 root root     10 Apr 22 12:44 builddate.timet
-rw-r--r--  1 root root    113 Apr 22 12:44 builddetails
-rw-r--r--  1 root root      6 Apr 22 12:44 buildrev
drwxr-xr-x  3 root root      0 Apr 22 12:44 certs
-r--r--r--  1 root root     46 Apr 22 12:43 cloud_dns_names
...

We can get the date is was built by running:

~ cat builddate
2020-04-22 11:44

Note: this time won’t work. Try 2020-04-22 11:07:26 instead. We can see that SSH is running on dropbear. Cisco developed the media server from mediaserver.ini. We can view services and ports by running:

~ cat services 
# Network services, Internet style
#
# Note that it is presently the policy of IANA to assign a single well-known
# port number for both TCP and UDP; hence, officially ports have two entries
# even if the protocol doesn't support UDP operations.
#
# Updated from http://www.iana.org/assignments/port-numbers and other
# sources like http://www.freebsd.org/cgi/cvsweb.cgi/src/etc/services .
# New ports will be added on request if they have been officially assigned
# by IANA and used in the real-world or are needed by a debian package.
# If you need a huge list of used numbers please install the nmap package.

tcpmux		1/tcp				# TCP port service multiplexer
echo		7/tcp
echo		7/udp
discard		9/tcp		sink null
discard		9/udp		sink null
systat		11/tcp		users
daytime		13/tcp
daytime		13/udp
...

system_defaults contain default settings. We can get the firmware version by running:

~ cat version
2.0.3.201002

Note: Once again thisvalue won’t work. Use 2.0.2.188405 instead. We can get the networks by running:

~ ls -la
total 109
drwxr-xr-x 5 root root     0 Apr 22 12:39 .
drwxr-xr-x 3 root root     0 Apr 22 12:39 ..
-r--r--r-- 1 root root  6274 Apr 22 12:39 core_server.lua
-r--r--r-- 1 root root  1486 Apr 22 12:39 ddns_server.lua
-r--r--r-- 1 root root  2242 Apr 22 12:39 devicelist_server.lua
-r--r--r-- 1 root root  3767 Apr 22 12:39 diagnostics_server.lua
-r--r--r-- 1 root root  5247 Apr 22 12:39 dynamicportforwarding_server.lua
-r--r--r-- 1 root root  2786 Apr 22 12:39 dynamicsession_server.lua
-r--r--r-- 1 root root  5144 Apr 22 12:39 firewall_server.lua
-r--r--r-- 1 root root  1874 Apr 22 12:39 firmwareupdate_server.lua
-r--r--r-- 1 root root  2004 Apr 22 12:39 ftpserver_server.lua
drwxr-xr-x 2 root root     0 Apr 22 12:39 guest_lan
-r--r--r-- 1 root root   488 Apr 22 12:39 guestnetworkauth_server.lua
-r--r--r-- 1 root root  6156 Apr 22 12:39 guestnetwork_server.lua
-r--r--r-- 1 root root  1446 Apr 22 12:39 httpproxy_server.lua
drwxr-xr-x 2 root root     0 Apr 22 12:39 lan
-r--r--r-- 1 root root  2296 Apr 22 12:39 locale_server.lua
-r--r--r-- 1 root root   983 Apr 22 12:39 macfilter_server.lua
-r--r--r-- 1 root root  1644 Apr 22 12:39 networkconnections_server.lua
-r--r--r-- 1 root root  2216 Apr 22 12:39 networktraffic_server.lua
...

The three networks are guest_lan, wan, lan

And that is the room complete!