In this article I will explain how to reverse the firmware of the embedded Linux part of the Technicolor (TC) 7210 router by leveraging the usual tools of the trade.
In a previous article, I explained how to get root
on the embedded Linux part of the TC7210 router by leveraging a remote code execution (RCE). With that level of access, I was able to image the various flash partitions of the router. The first thing I tried was to use binwalk
to identify what files may be contained in the images.
1#!/bin/bash
2ls -l
3# total 132416
4# -rw-r--r-- 1 501 dialout 65536 Jul 25 2017 mtd0.img
5# -rw-r--r-- 1 501 dialout 33423360 Jul 25 2017 mtd10.img
6# -rw-r--r-- 1 501 dialout 131072 Jul 25 2017 mtd1.img
7# -rw-r--r-- 1 501 dialout 262144 Jul 25 2017 mtd2.img
8# -rw-r--r-- 1 501 dialout 1048576 Jul 25 2017 mtd3.img
9# -rw-r--r-- 1 501 dialout 393216 Jul 25 2017 mtd4.img
10# -rw-r--r-- 1 501 dialout 16777216 Jul 25 2017 mtd5.img
11# -rw-r--r-- 1 501 dialout 16777216 Jul 25 2017 mtd6.img
12# -rw-r--r-- 1 501 dialout 8257536 Jul 25 2017 mtd7.img
13# -rw-r--r-- 1 501 dialout 46006272 Jul 25 2017 mtd8.img
14# -rw-r--r-- 1 501 dialout 12451840 Jul 25 2017 mtd9.img
15
16binwalk mtd8.img mtd10.img
17#
18# Scan Time: 2018-08-09 14:52:38
19# Target File: /mnt/hgfs/Temporary/tc7210/mtd8.img
20# MD5 Checksum: 09a51282fcc93a2f0fd02736e0e0f313
21# Signatures: 344
22#
23# DECIMAL HEXADECIMAL DESCRIPTION
24# --------------------------------------------------------------------------------
25# 0 0x0 UBI erase count header, version: 1, EC: 0x2, VID header offset: 0x800, data offset: 0x1000
26#
27#
28# Scan Time: 2018-08-09 14:52:42
29# Target File: /mnt/hgfs/Temporary/tc7210/mtd10.img
30# MD5 Checksum: b78fa525eba4d388a9aeb74db578b189
31# Signatures: 344
32#
33# DECIMAL HEXADECIMAL DESCRIPTION
34# --------------------------------------------------------------------------------
35# 0 0x0 UBI erase count header, version: 1, EC: 0x2, VID header offset: 0x800, data offset: 0x1000
The partitions mtd8.img
and mtd10.img
appear to have a valid UBIFS file system on them. Using ubidump it is possible to extract the file system. First, we download the tool repository and then setup a virtual Python environment to where the tool dependencies are installed.
1#!/bin/bash
2git clone https://github.com/nlitsme/ubidump.git
3# Cloning into 'ubidump'...
4# remote: Counting objects: 53, done.
5# remote: Total 53 (delta 0), reused 0 (delta 0), pack-reused 53
6# Unpacking objects: 100% (53/53), done.
7
8virtualenv .tc7210-env
9# Running virtualenv with interpreter /usr/bin/python2
10# New python executable in /mnt/hgfs/Temporary/tc7210/.tc7210-env/bin/python2
11# Also creating executable in /mnt/hgfs/Temporary/tc7210/.tc7210-env/bin/python
12# Installing setuptools, pkg_resources, pip, wheel...done.
13
14. .tc7210-env/bin/activate
15
16pip install -r ubidump/requirements.txt
17# Collecting python-lzo>=1.11 (from -r ubidump/requirements.txt (line 1))
18# Collecting crcmod>=1.7 (from -r ubidump/requirements.txt (line 2))
19# Installing collected packages: python-lzo, crcmod
20# Successfully installed crcmod-1.7 python-lzo-1.12
The next step is to extract the file system of both images.
1#!/bin/bash
2python ubidump/ubidump.py -s . mtd8.img mtd10.img
3# ==> mtd8.img <==
4# 1 named volumes found, 2 physical volumes, blocksize=0x20000
5# == volume linuxapps ==
6# saved 75 files
7# ==> mtd10.img <==
8# 1 named volumes found, 2 physical volumes, blocksize=0x20000
9# == volume rootfs ==
10# saved 173 files
This creates two directories, rootfs
and linuxapps
. The first contains the root file system and the second ancillary applications and files. From this point onwards, it is possible to read configuration files, reverse engineer executables, libraries, etc.
1#!/bin/bash
2ls -l linuxapps/ rootfs/
3# linuxapps/:
4# total 2
5# drwxr-xr-x 1 501 dialout 256 Aug 9 17:16 CVS
6# -rw-r--r-- 1 501 dialout 306 Aug 9 17:16 readme.txt
7# drwxr-xr-x 1 501 dialout 128 Aug 9 17:16 usr
8# -rw-r--r-- 1 501 dialout 184 Aug 9 17:16 version.txt
9#
10# rootfs/:
11# total 5
12# drwxr-xr-x 1 501 dialout 768 Aug 9 17:16 bin
13# drwxr-xr-x 1 501 dialout 256 Aug 9 17:16 CVS
14# drwxr-xr-x 1 501 dialout 960 Aug 9 17:16 etc
15# drwxr-xr-x 1 501 dialout 1568 Aug 9 17:16 lib
16# drwxr-xr-x 1 501 dialout 224 Aug 9 17:16 sbin
After this, I wanted to see if I could run the executables using QEMU (similar to what I did when reversing the ArubaOS). To do that, I needed to confirm the processor architecture of the executables, copy the respective statically linked QEMU executable to the rootfs
directory and then use the chroot
command.
1#!/bin/bash
2file rootfs/bin/busybox
3# rootfs/bin/busybox: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
4
5which qemu-mips-static
6# /usr/bin/qemu-mips-static
7
8cp /usr/bin/qemu-mips-static rootfs/
9
10sudo chroot rootfs/ ./qemu-mips-static /bin/busybox
11# Error while loading /bin/busybox: Permission denied
12
13ls -l rootfs/bin/
14# total 8684
15# -rw-r--r-- 1 501 dialout 39964 Aug 9 17:16 brctl
16# -rw-r--r-- 1 501 dialout 526180 Aug 9 17:16 busybox
17# -rw-r--r-- 1 501 dialout 61640 Aug 9 17:16 ebtables
18# -rw-r--r-- 1 501 dialout 210764 Aug 9 17:16 ip
19# -rw-r--r-- 1 501 dialout 7808 Aug 9 17:16 lxginit
20# -rw-r--r-- 1 501 dialout 14876 Aug 9 17:16 mscapp
21# -rw-r--r-- 1 501 dialout 1219244 Aug 9 17:16 nmbd
22# -rw-r--r-- 1 501 dialout 154140 Aug 9 17:16 ntfs-3g
23# -rw-r--r-- 1 501 dialout 24200 Aug 9 17:16 ntfslabel
24# -rw-r--r-- 1 501 dialout 14204 Aug 9 17:16 portmap
25# -rw-r--r-- 1 501 dialout 18988 Aug 9 17:16 remoteapi
26# -rw-r--r-- 1 501 dialout 4612 Aug 9 17:16 rmtshutdown
27# -rw-r--r-- 1 501 dialout 4924 Aug 9 17:16 rpc_test_client
28# -rw-r--r-- 1 501 dialout 5408 Aug 9 17:16 rpc_test_service
29# -rw-r--r-- 1 501 dialout 4444 Aug 9 17:16 setappsver
30# -rw-r--r-- 1 501 dialout 114004 Aug 9 17:16 smbapp
31# -rw-r--r-- 1 501 dialout 3900616 Aug 9 17:16 smbd
32# -rw-r--r-- 1 501 dialout 2203476 Aug 9 17:16 smbpasswd
33# -rw-r--r-- 1 501 dialout 242844 Aug 9 17:16 tc
34# -rw-r--r-- 1 501 dialout 37716 Aug 9 17:16 ubimkvol
35# -rw-r--r-- 1 501 dialout 39748 Aug 9 17:16 ubinfo
36# -rw-r--r-- 1 501 dialout 35344 Aug 9 17:16 ubirmvol
37
38chmod +x rootfs/bin/*
39
40sudo chroot rootfs/ ./qemu-mips-static /bin/busybox
41# BusyBox v1.19.3 (2015-03-04 13:37:03 CST) multi-call binary.
42# Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko
43# and others. Licensed under GPLv2.
44# See source distribution for full notice.
45#
46# Usage: busybox [function] [arguments]...
47# or: busybox --list[-full]
48# or: function [arguments]...
49#
50# BusyBox is a multi-call binary that combines many common Unix
51# utilities into a single executable. Most people will create a
52# link to busybox for each function they wish to use and BusyBox
53# will act like whatever it was invoked as.
54#
55# Currently defined functions:
56# [, [[, arp, arping, ash, awk, basename, cat, chgrp, chmod, chown,
57# chroot, cp, cttyhack, cut, date, dd, deluser, df, dmesg, echo, egrep,
58# expr, false, fgrep, find, flash_eraseall, free, fsync, ftpd, ftpget,
59# getty, grep, halt, hexdump, httpd, ifconfig, inetd, init, insmod, ip,
60# kill, killall, klogd, less, linuxrc, ln, logger, login, ls, lsmod,
61# lsusb, mkdir, mknod, mount, mv, netstat, od, passwd, pidof, ping,
62# ping6, poweroff, ps, pwd, reboot, rm, rmdir, rmmod, route, sed, sh,
63# sleep, start-stop-daemon, sync, sysctl, syslogd, tail, tar, tcpsvd,
64# telnetd, test, tftp, time, top, true, tty, udhcpc, umount, uname,
65# uptime, vconfig, vi, which, whoami, xargs, zcip
Next, I tried to run the smbapp
(the executable that was previously identified as the one responsible for managing the NAS file sharing functionality). After fixing some of the errors, I was also successful :D
1#!/bin/bash
2sudo chroot rootfs/ ./qemu-mips-static /bin/smbapp
3# NAS: Network Attached Storage Control Application [Version 1.3 Build Mar 4 2015 13:42:04]
4# found 0 USB devices
5# NAS: Will retry bind in 15 seconds
6# Launching mscapp
7# MSC: Media Server Control Application [Version 1.2 Build Mar 4 2015 13:42:04]
8# MSC: waiting for data on port UDP 49181
9# Fatal Error: unable to open /var/tmp/smbapp_hotplug_fifo
10
11sudo chroot rootfs/ ./qemu-mips-static /bin/busybox mkdir -p /var/tmp
12
13sudo chroot rootfs/ ./qemu-mips-static /bin/busybox sh
14#
15#
16# BusyBox v1.19.3 (2015-03-04 13:37:03 CST) built-in shell (ash)
17# Enter 'help' for a list of built-in commands.
18#
19# ${debian_chroot:+($debian_chroot)}:/# busybox echo ""> /var/tmp/smbapp_hotplug_fifo
20# ${debian_chroot:+($debian_chroot)}:/# exit
21
22sudo chroot rootfs/ ./qemu-mips-static /bin/smbapp
23# NAS: Network Attached Storage Control Application [Version 1.3 Build Mar 4 2015 13:42:04]
24# found 0 USB devices
25# NAS: Will retry bind in 15 seconds
26# Launching mscapp
27# SmbApp: waiting on port 49182 to recvfrom...
28# MSC: Media Server Control Application [Version 1.2 Build Mar 4 2015 13:42:04]
29# MSC: waiting for data on port UDP 49181
30# smbapp: sigterm_handler(): Caught signal(2)
31# smbapp: shuting down child processes
32# umounting all USB devices
33# pid 3756 terminated by a signal 2
34# smbapp: mscapp pid 3756 exit status 0
35# smbapp: closing the socket to ecos
The ability to run the executables makes the reverse engineering and vulnerability finding process a lot easier. In upcoming posts, I will detail how I found and exploited some yet to be released vulnerabilities. Cheers :)