Reverse engineering the router Technicolor TG582N

During last months, my interest in hardware hacking got an exponential growth due to the fact I had the chance to get my hands on some so-ho routers unretired from local Telcos. So what a great opportunity to open and try to crack them, without worrying about irreparable damage?

Inspecting the device

My first device was the Technicolor TG582N distributed in Italy by Fastweb.

Front side
Back side

Nothing too much interesting externally: for this purpose, common useless informations about wireless access code, serial number, mac-address, etc.

A much more interesting view is the internal one: I was able to remove the two lower screws, under the rubbers and, with a gentle lever, the upper part can be unhooked giving access to the router motherboard.

Router motherboard with the relevant ICs

Internal components analysis

A pretty standard design for this kind of device, we can clearly see the main CPU Broadcom BCM63281KFBG and its two memory ICs (Integrated Circuits): RAM and Flash memory. There's also another Broadcom chip but its role is to manage wireless functionalities and, for now, is out of scope.

Winbond W9751G6KB-25
Spansion FL064PIF

For the volatile data, the device uses a DDR2 SDRAM module produced by Winbond with the capacity 512 Mbit (64 MByte). Obviously I'm interested in the EEPROM chip, because it's where the non-volatile data is stored and persists across reboots and shutdowns. This device has a flash memory module produced by Spansion (now Cypress) with the capacity of 64 Mbit (8 Mbyte).

Accessing to UART console

I didn't put too much effort in this because the nice guys of OpenWRT project did all the dirty job. Although the board perfectly matches to the devices described in that page, I noted a slight difference on the EEPROM chip. They mention three board type: DANT-1, DANT-T, and DANT-V. These boards have three types of EEPROM chip but none of them have this Spansion chip, only the DANT-V version has a Spansion chip but it's an FL129P, a 128 Mbit flash memory. We're definitely dealing with a slightly smaller memory chip. Anyway, UART pins are the same of other boards and we need to solder 3 pins (Tx, Rx, and GND) and short circuit R62 and R63 as noted in the above link.

Soldered UART pins

After this little soldering, we can attach a common interface based on the FTD232 and have a console access. Remember to NOT attach the VCC pin because the required power will be provided by the standard supply.

With this simple setup we can finally have access to the router console and see all the boot messages:

Welcome to minicom 2.7.1                                                                                
OPTIONS: I18n                                                                                           
Compiled on May  3 2018, 15:20:11.                                                                      
Port /dev/ttyUSB0, 17:40:25                                                                             
Press CTRL-A Z for help on special keys


D%G                                                                                                     
Decompressing Bootloader..............................                                                  
Gateway initialization sequence started.                                                                
Version BL: 1.0.5
Multicore disable; Booting Linux kernel
BOOTING THE LINUX KERNEL
Starting the kernel @ 0x801dfcd0
Extra parameters passed to Linux:
        [0]: bootloader
        [1]: memsize=0x3EDD000
Linux version 2.6.30 (gcc version 3.4.6) #1 Mon Mar 26 18:25:38 CST 2012
BCM63XX prom init
CPU revision is: 0002a075 (Broadcom4350)
Determined physical RAM map:
 memory: 03edb000 @ 00002000 (usable)
Wasting 64 bytes for tracking 2 unused pages
Zone PFN ranges:
  DMA      0x00000002 -> 0x00001000
  Normal   0x00001000 -> 0x00003edd
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
    0: 0x00000002 -> 0x00003edd
On node 0 totalpages: 16091
free_area_init_node: node 0, pgdat 80238480, node_mem_map 81000040
  DMA zone: 32 pages used for memmap
  DMA zone: 0 pages reserved
  DMA zone: 4062 pages, LIFO batch:0
  Normal zone: 94 pages used for memmap
  Normal zone: 11903 pages, LIFO batch:1
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 15965
Kernel command line: root=31:0 ro noinitrd memsize=0x3EDD000 console=ttyS0,115200 root=/dev/mtdblock2 rootfstype=squashfs
wait instruction: enabled
Primary instruction cache 32kB, VIPT, 4-way, linesize 16 bytes.
Primary data cache 32kB, 2-way, VIPT, cache aliases, linesize 16 bytes
NR_IRQS:128
PID hash table entries: 256 (order: 8, 1024 bytes)
console [ttyS0] enabled
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 61152k/64364k available (1882k kernel code, 3192k reserved, 331k data, 108k init, 0k highmem)
Calibrating delay loop... 318.46 BogoMIPS (lpj=159232)
Mount-cache hash table entries: 512
--Kernel Config--
  SMP=0
  PREEMPT=0
  DEBUG_SPINLOCK=0
  DEBUG_MUTEXES=0
net_namespace: 584 bytes
NET: Registered protocol family 16
registering PCI controller with io_map_base unset
registering PCI controller with io_map_base unset
bio: create slab <bio-0> at 0
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
pci 0000:00:09.0: reg 10 32bit mmio: [0x10002600-0x100026ff]
pci 0000:00:0a.0: reg 10 32bit mmio: [0x10002500-0x100025ff]
pci 0000:01:00.0: PME# supported from D0 D3hot
pci 0000:01:00.0: PME# disabled
pci 0000:02:00.0: reg 10 64bit mmio: [0x000000-0x003fff]
pci 0000:02:00.0: supports D1 D2
pci 0000:01:00.0: PCI bridge, secondary bus 0000:02
pci 0000:01:00.0:   IO window: disabled
pci 0000:01:00.0:   MEM window: 0x10f00000-0x10ffffff
pci 0000:01:00.0:   PREFETCH window: disabled
PCI: Enabling device 0000:01:00.0 (0000 -> 0002)
PCI: Setting latency timer of device 0000:01:00.0 to 64
BLOG Rule v1.0 Initialized
Broadcom IQoS v0.1 Mar 26 2012 18:23:40 initialized
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
NET: Registered protocol family 1
squashfs: version 4.0 (2009/01/31) Phillip Lougher
squashfs: version 4.0 with LZMA457 ported by BRCM
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
msgmni has been set to 119
io scheduler noop registered (default)
pcieport-driver 0000:01:00.0: device [14e4:6328] has invalid IRQ; check vendor BIOS
PCI: Setting latency timer of device 0000:01:00.0 to 64
Gateway flash mapping
flash mapping initialized
Creating 4 MTD partitions on "thomson-spi":
0x000000040000-0x0000000b0000 : "userfs"
0x000000020000-0x000000040000 : "mtdss"
0x000000180000-0x000000800000 : "rootfs"
0x0000000b0000-0x000000180000 : "kernel"
brcmboard: brcm_board_init entry
Serial: BCM63XX driver $Revision: 3.00 $
ttyS0 at MMIO 0xb0000100 (irq = 36) is a BCM63XX
ttyS1 at MMIO 0xb0000100 (irq = 36) is a BCM63XX
ttyS2 at MMIO 0xb0000120 (irq = 47) is a BCM63XX
TCP cubic registered
NET: Registered protocol family 17
NET: Registered protocol family 15
VFS: Mounted root (squashfs filesystem) readonly on device 31:2.
Freeing unused kernel memory: 108k freed
init started:  BusyBox v1.00 (2012.03.26-10:27+0000) multi-call binary
init started:  BusyBox v1.00 (2012.03.26-10:27+0000) multi-call binary
Starting pid 116, console /dev/ttyS0: '/etc/init.d/rcS'
Initializing random number generator
Using /lib/modules/kserport.ko
kserport: module license 'unspecified' taints kernel.
Disabling lock debugging due to kernel taint
Using /nmon/nmon.ko
loading geniodb kernel modules...
Using /lib/modules/geniodb.ko
 geniodb driver: Loading ...
 geniodb driver: Loading finished with SUCCESS
Button char device has been created and initialized.
[BCM ADSL] BcmAdsl_SetOverlayMode = 85 new=0
tmm_skb_desc.queuesize = 300
queue: 0xc09aa744
queue: 0xc09aa744, rp: 0xc09aa744, wp: 0xc09aa744
[BCM ADSL] ------    dslFileLoadImage : OverlayMode = 0 fname=ZXD3AA
pci 0000:00:09.0: firmware: requesting ZXD3AA
pSdramPHY=0xA3FFFFF8, 0x5CF9A 0xDEADBEEF
[BCM ADSL] Firmware load : 548088 548088 LMEM=(0xB0D80000, 11380) SDRAM=(0xA3F00000, 536700)
pci 0000:00:09.0: firmware: requesting phy
*** PhySdramSize got adjusted: 0x8307C => 0x98A20 ***
AdslCoreSharedMemInit: shareMemAvailable=423360
AdslCoreHwReset:  pLocSbSta=c09a2fd0 bkupThreshold=1600
AdslCoreHwReset:  AdslOemDataAddr = 0xA3F78090
[DSL driver] !-!-!-!-!-!-! ***** AFE ID = 0x1040a200
ADSL PHY version is A2pDT002a.d23k
b6w_init
FOUND WL DEVICE 0, bus=2, device=0, func=0, vendorid=14E4, deviceid=A8DC, regaddr=10F00000, irq=31
wl:srom not detected, using main memory mapped srom info(wombo board)
veth0 (): not using net_device_ops yet
NET: Registered protocol family 3
NET: Registered protocol family 9
NET: Registered protocol family 6
NET: Registered protocol family 4
NET: Registered protocol family 5
NET: Registered protocol family 18
NET: Registered protocol family 25
Device ipsec not present.
voice will be loaded
Device endpoint not present.
Device ikanos not present.
Starting pid 338, console /dev/ttyS0: '/etc/init.d/rc'
Switching to RUNLEVEL 1 ...
Disabling hotplug helper
route: SIOC[ADD|DEL]RT: File exists
linux application start ...
wait for linux_appl to initialize (1)
wait for linux_appl to initialize (2)
************* ERROR RECORD *************
000000:00:00.000000
Application NMON started after POWERON.
****************** END *****************
wait for linux_appl to initialize (3)
appl_init: BUILD VERIFIED!
wait for linux_appl to initialize (4)
[SS EMUL] ERR: opening config file /active/ss.conf failed
End of initialisation
wait for linux_appl to initialize (5)
 start fseventd ...
 fseventd is started.
 start storagepl ...
 storagepl is started
 start vfspl ...
 vfspl is started
MVFS plugin started
cifs plug-in: initializing ...
 cifs plug-in is started
upnpavpl start ...
/usr/bin/fusermount
Loading fuse modulefuse init (API version 7.11)
.
Mounting fuse control filesystem.
linuxappl: start loading after [  4459ms ]
WARNING: Unknown Parameter Type ifmfilter
WARNING: Unknown Parameter Type ifmfilter
S67stopload: wait until configuration load reaches phase 9...
S67stopload: wait until configuration load reaches phase 9 (now -1, 1s)
adsl: adsl_open entry
ADSL Line state is: DOWN
[adsl] trace = 5 0
S67stopload: wait until configuration load reaches phase 9 (now -1, 2s)
The OBC bridge interface cannot be removed from this VLAN, because OBC is defined as untagged.
S67stopload: wait until configuration load reaches phase 9 (now 3, 3s)
S67stopload: wait until configuration load reaches phase 9 (now 3, 4s)
S67stopload: wait until configuration load reaches phase 9 (now 3, 5s)
S67stopload: wait until configuration load reaches phase 9 (now 3, 6s)
S67stopload: wait until configuration load reaches phase 9 (now 3, 7s)
DyingGasp RIP BIT is set!
[ERROR : [DIAG 1004] -1 ]
ADSL configuration:
        adslmultimode = adsl2plus
        syslog = disabled
S67stopload: wait until configuration load reaches phase 9 (now 3, 8s)
S67stopload: wait until configuration load reaches phase 9 (now 3, 9s)
The OBC bridge interface cannot be removed from this VLAN, because OBC is defined as untagged.
Option not allowed => HostNotLocalDomain
Unsupported URL. The url must include http:// or https://.
Failed to add host 9c:97:26:0c:0c:e9
S67stopload: wait until configuration load reaches phase 9 (now 6, 10s)
S67stopload: wait until configuration load reaches phase 9 (now 6, 11s)
S67stopload: wait until configuration load reaches phase 9 (now 6, 12s)
S67stopload: configuration load reached phase 9...
Intel MicroStack 1.0 - Digital Media Server (DLNA 1.5)(pid = 835),
loc_generate_uuid:25e05aa9-8206-5b77-9aad-d5547194a957
nlplugd start ...
Initializing.
Starting netlink plugin
Daemonize netlink plugin
udhcpcd start ...
monitoripd start ...
anti_spoofd start ...
anti_spoofd : process exit !
 start mud ...
Using /lib/modules/2.6.30/kernel/drivers/usb/host/ehci-hcd.ko
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
PCI: Enabling device 0000:00:0a.0 (0000 -> 0002)
PCI: Setting latency timer of device 0000:00:0a.0 to 64
ehci_hcd 0000:00:0a.0: EHCI Host Controller
ehci_hcd 0000:00:0a.0: new USB bus registered, assigned bus number 1
ehci_hcd 0000:00:0a.0: Enabling legacy PCI PM
ehci_hcd 0000:00:0a.0: irq 50, io mem 0x10002500
ehci_hcd 0000:00:0a.0: USB f.f started, EHCI 1.00
monitoripd start ...
anti_spoofd start ...
anti_spoofd : process exit !
 start mud ...
Using /lib/modules/2.6.30/kernel/drivers/usb/host/ehci-hcd.ko
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
PCI: Enabling device 0000:00:0a.0 (0000 -> 0002)
PCI: Setting latency timer of device 0000:00:0a.0 to 64
ehci_hcd 0000:00:0a.0: EHCI Host Controller
ehci_hcd 0000:00:0a.0: new USB bus registered, assigned bus number 1
ehci_hcd 0000:00:0a.0: Enabling legacy PCI PM
ehci_hcd 0000:00:0a.0: irq 50, io mem 0x10002500
ehci_hcd 0000:00:0a.0: USB f.f started, EHCI 1.00
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
Using /lib/modules/2.6.30/kernel/drivers/usb/host/ohci-hcd.ko
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
PCI: Enabling device 0000:00:09.0 (0000 -> 0002)
PCI: Setting latency timer of device 0000:00:09.0 to 64
ohci_hcd 0000:00:09.0: OHCI Host Controller
ohci_hcd 0000:00:09.0: new USB bus registered, assigned bus number 2
ohci_hcd 0000:00:09.0: irq 49, io mem 0x10002600
usb usb2: configuration #1 chosen from 1 choice
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 1 port detected
Using /lib/modules/2.6.30/kernel/drivers/usb/class/usblp.ko
usbcore: registered new interface driver usblp
Using /lib/modules/2.6.30/kernel/drivers/usb/serial/usbserial.ko
usbcore: registered new interface driver usbserial
USB Serial support registered for generic
usbcore: registered new interface driver usbserial_generic
usbserial: USB Serial Driver core
Using /lib/modules/2.6.30/kernel/drivers/scsi/scsi_mod.ko
SCSI subsystem initialized
Using /lib/modules/2.6.30/kernel/drivers/scsi/sd_mod.ko
Driver 'sd' needs updating - please use bus_type methods
Using /lib/modules/2.6.30/kernel/drivers/usb/storage/usb-storage.ko
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
Using /lib/modules/2.6.30/kernel/fs/fat/fat.ko
Using /lib/modules/2.6.30/kernel/fs/fat/vfat.ko
Using /lib/modules/2.6.30/kernel/fs/nls/nls_cp437.ko
Using /lib/modules/2.6.30/kernel/fs/nls/nls_iso8859-1.ko
Using /lib/modules/2.6.30/kernel/fs/nls/nls_cp850.ko
Name: /etc/usbmgr/usbmgr.conf
Starting power manager...
Username :

After the boot, there's the good old login screen but without a valid username/password there's not much we can do. One way to proceed is to investigate the filesystem without any sort of access control. Filesystem can be obtained by dumping it directly from the flash memory.  

Dumping the flash

Reading the flash memory contents is not something overcomplicated but requires a bit of understanding of how integrated circuits work and how you can obtain the raw contents of the chip using the same interfaces and protocols used by the main CPU during the normal operation of the device.

For this purpose we're targeting the flash memory chip that was inspected above: a Spansion chip FL064pif with its datasheet is available on the manufacture site.

In order to read - and eventually write - its contents, we need to interface with the chip itself, using its pins and using a serial protocol, named SPI. The useful pins are Vcc, CS, SO, SI, SCK and GND and their description is available on the datasheet.

Dumping the chip can be done with BusPirate and Flashrom. In order to avoid any desoldering, we'll use a Pomona SOIC clip model 5252. In this case, power we'll be supplied by the BusPirate itself and the board must be switched off. This is because we don't want any interaction from the main CPU that will interfere with the memory chip while we're dumping its contents.

In-system programming

In this case we were lucky, because powering up the chip itself didn't wake up any other component of the board, like the main CPU. This can happens and depends on how the board is designed and how the components are connected and can vary from board to board. If there's such interference you'll end up with a corrupted dump and flashrom won't alert you in that case. This is why it's a good practice to verify the correctness of the dumping process.

Dumping the flash
Verifying the dump

We now have the entire content of the flash memory. We can read, eventually, bootloader, Linux kernel and, more interesting, the root filesystem. Basically we have the entire software stack the manufacturer has deployed on the device.

Firmware extraction

For the extraction we will use the Binwalk utility. It will read the dump and try to recognize and extract any known file format.

root@kali:~/Projects/tg582n# binwalk dump.bin 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
45066         0xB00A          LZMA compressed data, properties: 0x5D, dictionary size: 2097152 bytes, uncompressed size: 250804 bytes
132350        0x204FE         PEM certificate
133927        0x20B27         PEM certificate
135518        0x2115E         PEM certificate
262144        0x40000         JFFS2 filesystem, big endian
262496        0x40160         Zlib compressed data, compressed
262760        0x40268         JFFS2 filesystem, big endian
267824        0x41630         Zlib compressed data, compressed
269016        0x41AD8         Zlib compressed data, compressed
269332        0x41C14         Zlib compressed data, compressed
269648        0x41D50         Zlib compressed data, compressed
269844        0x41E14         JFFS2 filesystem, big endian
269960        0x41E88         Zlib compressed data, compressed
270176        0x41F60         Zlib compressed data, compressed
270444        0x4206C         Zlib compressed data, compressed
270892        0x4222C         Zlib compressed data, compressed
271452        0x4245C         Zlib compressed data, compressed
271552        0x424C0         JFFS2 filesystem, big endian
272436        0x42834         Zlib compressed data, compressed
273012        0x42A74         Zlib compressed data, compressed
273548        0x42C8C         Zlib compressed data, compressed
273888        0x42DE0         Zlib compressed data, compressed
274424        0x42FF8         Zlib compressed data, compressed
274764        0x4314C         Zlib compressed data, compressed
275300        0x43364         Zlib compressed data, compressed
275640        0x434B8         Zlib compressed data, compressed
276136        0x436A8         Zlib compressed data, compressed
276476        0x437FC         Zlib compressed data, compressed
277052        0x43A3C         Zlib compressed data, compressed
277268        0x43B14         Zlib compressed data, compressed
277536        0x43C20         Zlib compressed data, compressed
278608        0x44050         Zlib compressed data, compressed
279672        0x44478         Zlib compressed data, compressed
280084        0x44614         JFFS2 filesystem, big endian
280200        0x44688         Zlib compressed data, compressed
280684        0x4486C         JFFS2 filesystem, big endian
280872        0x44928         Zlib compressed data, compressed
281124        0x44A24         Zlib compressed data, compressed
281240        0x44A98         Zlib compressed data, compressed
281336        0x44AF8         Zlib compressed data, compressed
281432        0x44B58         Zlib compressed data, compressed
281460        0x44B74         JFFS2 filesystem, big endian
281676        0x44C4C         Zlib compressed data, compressed
281768        0x44CA8         Zlib compressed data, compressed
281864        0x44D08         Zlib compressed data, compressed
281960        0x44D68         Zlib compressed data, compressed
282056        0x44DC8         Zlib compressed data, compressed
282176        0x44E40         Zlib compressed data, compressed
282300        0x44EBC         Zlib compressed data, compressed
282668        0x4502C         JFFS2 filesystem, big endian
282808        0x450B8         Zlib compressed data, compressed
282932        0x45134         Zlib compressed data, compressed
283152        0x45210         JFFS2 filesystem, big endian
283772        0x4547C         Zlib compressed data, compressed
284068        0x455A4         Zlib compressed data, compressed
284624        0x457D0         JFFS2 filesystem, big endian
285552        0x45B70         Zlib compressed data, compressed
286000        0x45D30         JFFS2 filesystem, big endian
286764        0x4602C         Zlib compressed data, compressed
287224        0x461F8         JFFS2 filesystem, big endian
288020        0x46514         Zlib compressed data, compressed
288456        0x466C8         JFFS2 filesystem, big endian
289736        0x46BC8         Zlib compressed data, compressed
290484        0x46EB4         JFFS2 filesystem, big endian
291892        0x47434         Zlib compressed data, compressed
292352        0x47600         JFFS2 filesystem, big endian
293416        0x47A28         Zlib compressed data, compressed
294336        0x47DC0         JFFS2 filesystem, big endian
295984        0x48430         Zlib compressed data, compressed
296564        0x48674         JFFS2 filesystem, big endian
297632        0x48AA0         Zlib compressed data, compressed
298040        0x48C38         JFFS2 filesystem, big endian
299428        0x491A4         Zlib compressed data, compressed
299856        0x49350         JFFS2 filesystem, big endian
300880        0x49750         Zlib compressed data, compressed
301620        0x49A34         JFFS2 filesystem, big endian
303128        0x4A018         Zlib compressed data, compressed
303684        0x4A244         JFFS2 filesystem, big endian
304808        0x4A6A8         Zlib compressed data, compressed
305152        0x4A800         JFFS2 filesystem, big endian
305828        0x4AAA4         Zlib compressed data, compressed
306220        0x4AC2C         JFFS2 filesystem, big endian
306940        0x4AEFC         Zlib compressed data, compressed
307904        0x4B2C0         JFFS2 filesystem, big endian
309392        0x4B890         Zlib compressed data, compressed
309908        0x4BA94         JFFS2 filesystem, big endian
313324        0x4C7EC         Zlib compressed data, compressed
313900        0x4CA2C         Zlib compressed data, compressed
314436        0x4CC44         Zlib compressed data, compressed
314776        0x4CD98         Zlib compressed data, compressed
315312        0x4CFB0         Zlib compressed data, compressed
315652        0x4D104         Zlib compressed data, compressed
316188        0x4D31C         Zlib compressed data, compressed
316528        0x4D470         Zlib compressed data, compressed
317024        0x4D660         Zlib compressed data, compressed
317364        0x4D7B4         Zlib compressed data, compressed
317940        0x4D9F4         Zlib compressed data, compressed
318236        0x4DB1C         Zlib compressed data, compressed
319308        0x4DF4C         Zlib compressed data, compressed
320616        0x4E468         Zlib compressed data, compressed
323744        0x4F0A0         JFFS2 filesystem, big endian
323884        0x4F12C         Zlib compressed data, compressed
323944        0x4F168         JFFS2 filesystem, big endian
591524        0x906A4         Zlib compressed data, compressed
592100        0x908E4         Zlib compressed data, compressed
592808        0x90BA8         Zlib compressed data, compressed
593516        0x90E6C         Zlib compressed data, compressed
594224        0x91130         Zlib compressed data, compressed
594892        0x913CC         Zlib compressed data, compressed
595468        0x9160C         Zlib compressed data, compressed
595764        0x91734         Zlib compressed data, compressed
596836        0x91B64         Zlib compressed data, compressed
598144        0x92080         Zlib compressed data, compressed
599460        0x925A4         Zlib compressed data, compressed
600036        0x927E4         Zlib compressed data, compressed
600744        0x92AA8         Zlib compressed data, compressed
601452        0x92D6C         Zlib compressed data, compressed
602160        0x93030         Zlib compressed data, compressed
602828        0x932CC         Zlib compressed data, compressed
603404        0x9350C         Zlib compressed data, compressed
603700        0x93634         Zlib compressed data, compressed
604772        0x93A64         Zlib compressed data, compressed
606080        0x93F80         Zlib compressed data, compressed
606568        0x94168         JFFS2 filesystem, big endian
607900        0x9469C         Zlib compressed data, compressed
608608        0x94960         Zlib compressed data, compressed
609316        0x94C24         Zlib compressed data, compressed
610024        0x94EE8         Zlib compressed data, compressed
610692        0x95184         Zlib compressed data, compressed
611200        0x95380         JFFS2 filesystem, big endian
611564        0x954EC         Zlib compressed data, compressed
612568        0x958D8         JFFS2 filesystem, big endian
613128        0x95B08         JFFS2 filesystem, big endian
720922        0xB001A         LZMA compressed data, properties: 0x5D, dictionary size: 2097152 bytes, uncompressed size: 2394632 bytes
1572864       0x180000        Squashfs filesystem, little endian, non-standard signature, version 4.0, compression:gzip, size: 6626892 bytes, 1298 inodes, blocksize: 131072 bytes, created: 2012-10-15 13:38:44

Honestly, this is the first time I had so much results from binwalk. The first thing I noted is the SquashFS signature. From the boot log messages, we know that the root filesystem is in that format:

Kernel command line: root=31:0 ro noinitrd memsize=0x3EDD000 console=ttyS0,115200 root=/dev/mtdblock2 rootfstype=squashfs

So we'll start to dig in that directory first:

root@kali:~/Projects/tg582n/_dump.bin.extracted/squashfs-root# ll
total 68K
drwxrwxr-x 15 root root 4,0K ott 15  2012 .
drwxr-xr-x 34 root root  12K gen 20 12:06 ..
drwxrwxr-x  3 root root 4,0K ott 15  2012 archive
drwxrwxrwx  2 root root 4,0K mar 26  2012 bin
drwxrwxrwx  6 root root 4,0K mar 26  2012 dev
lrwxrwxrwx  1 root root    6 mar 26  2012 dl -> /rw/dl
drwxrwxr-x 10 root root 4,0K mar 26  2012 etc
drwxrwxrwx  3 root root 4,0K mar 26  2012 lib
drwxrwxrwx  2 root root 4,0K mar 26  2012 nmon
drwxrwxrwx  2 root root 4,0K mar 26  2012 proc
drwxrwxrwx  3 root root 4,0K mar 26  2012 rw
drwxrwxrwx  2 root root 4,0K mar 26  2012 sbin
drwxrwxrwx  2 root root 4,0K mar 26  2012 sys
lrwxrwxrwx  1 root root    8 mar 26  2012 tmp -> /var/tmp
drwxrwxrwx  2 root root 4,0K mar 26  2012 userfs
drwxrwxrwx  5 root root 4,0K mar 26  2012 usr
drwxrwxrwx  2 root root 4,0K mar 26  2012 var
root@kali:~/Projects/tg582n/_dump.bin.extracted/squashfs-root# 

We're interested into passwd file but looking up in the /etc directory, we find that, like most embedded device, that file is autogenerated and what we see is only a placeholder.

root@kali:~/Projects/tg582n/_dump.bin.extracted/squashfs-root/etc# ll
total 100K
drwxrwxr-x 10 root root 4,0K mar 26  2012 .
drwxrwxr-x 15 root root 4,0K ott 15  2012 ..
-rw-r--r--  1 root root  513 mar 26  2012 advancedservices.conf
-r--r--r--  1 root root  377 mar 26  2012 autoconf.conf
-r--r--r--  1 root root  133 mar 26  2012 autoip.conf
drwxrwxrwx  2 root root 4,0K mar 26  2012 config
-rw-rw-rw-  1 root root  345 mar 26  2012 fileprofiler.conf
-r--r--r--  1 root root   73 mar 26  2012 fstab
-r--r--r--  1 root root   17 mar 26  2012 fuse.conf
lrwxrwxrwx  1 root root   15 mar 26  2012 group -> ../rw/etc/group
lrwxrwxrwx  1 root root   17 mar 26  2012 gshadow -> ../rw/etc/gshadow
-r--r--r--  1 root root   26 mar 26  2012 host.conf
drwxrwxr-x  2 root root 4,0K mar 26  2012 init.d
-r--r--r--  1 root root  513 mar 26  2012 inittab
-r--r--r--  1 root root  17K mar 26  2012 mime.types
lrwxrwxrwx  1 root root   14 mar 26  2012 mtab -> ../proc/mounts
-r--r--r--  1 root root  465 mar 26  2012 nsswitch.conf
lrwxrwxrwx  1 root root   16 mar 26  2012 passwd -> ../rw/etc/passwd
drwxr-xr-x  2 root root 4,0K mar 26  2012 rc0.d
drwxr-xr-x  2 root root 4,0K mar 26  2012 rc1.d
drwxr-xr-x  2 root root 4,0K mar 26  2012 rc2.d
drwxr-xr-x  2 root root 4,0K mar 26  2012 rc3.d
lrwxrwxrwx  1 root root   21 mar 26  2012 resolv.conf -> ../rw/etc/resolv.conf
lrwxrwxrwx  1 root root   16 mar 26  2012 shadow -> ../rw/etc/shadow
drwxrwxr-x  2 root root 4,0K mar 26  2012 udhcpc
drwxrwxrwx  2 root root 4,0K mar 26  2012 usbmgr
-rw-rw-rw-  1 root root    8 mar 26  2012 version
root@kali:~/Projects/tg582n/_dump.bin.extracted/squashfs-root/etc#
```

passwd file is a link to another file in the /rw directory that, right now, is empty. How that file is generated during every boot? What script is in charge of managing it? We need to find the answers...

Hunting for the system users

Poking around in /etc directory can be useful because, in the end, this is a standard Linux based system and something in that directory must exist that will reveal us what are the allowed users to the system.

root@kali:~/Projects/tg582n/_dump.bin.extracted/squashfs-root/etc# tree
.
├── advancedservices.conf
├── autoconf.conf
├── autoip.conf
├── config
│   ├── secrets.tdb -> /rw/etc/secrets.tdb
│   ├── smb.conf -> /rw/etc/smb.conf
│   └── smbpasswd -> /rw/etc/smbpasswd
├── fileprofiler.conf
├── fstab
├── fuse.conf
├── group -> ../rw/etc/group
├── gshadow -> ../rw/etc/gshadow
├── host.conf
├── init.d
│   ├── anti_spoofd
│   ├── autoipd
│   ├── checkd
│   ├── cifs
│   ├── clinkd
│   ├── cryptomount
│   ├── dropbear
│   ├── fseventd
│   ├── fuse
│   ├── initrandom
│   ├── jffs2contentcheck
│   ├── ledstatus
│   ├── linuxappl
│   ├── longops
│   ├── mbusd_util
│   ├── mocad
│   ├── monitoripd
│   ├── mud
│   ├── mvfs
│   ├── mvfspl
│   ├── network
│   ├── nlplugd
│   ├── no_hotplug_helper
│   ├── powermgr
│   ├── print_server
│   ├── pureftp
│   ├── rc
│   ├── rcS
│   ├── rcS.mountfs
│   ├── rcS.ro
│   ├── rssplugin
│   ├── samba
│   ├── stopload
│   ├── storagepl
│   ├── todd
│   ├── udhcpcd
│   ├── upnpavpl
│   ├── usb-host
│   ├── usb_storage
│   └── vfspl
├── inittab
├── mime.types
├── mtab -> ../proc/mounts
├── nsswitch.conf
├── passwd -> ../rw/etc/passwd
├── rc0.d
├── rc1.d
│   ├── K01mvfs -> ../init.d/mvfs
│   ├── S01jffs2contentcheck -> ../init.d/jffs2contentcheck
│   ├── S10no_hotplug_helper -> ../init.d/no_hotplug_helper
│   ├── S20network -> ../init.d/network
│   ├── S21vega -> ../init.d/vega
│   ├── S21wps -> ../init.d/wps
│   ├── S22linuxappl -> ../init.d/linuxappl
│   ├── S41fseventd -> ../init.d/fseventd
│   ├── S45storagepl -> ../init.d/storagepl
│   ├── S45vfspl -> /etc/init.d/vfspl
│   ├── S46mvfspl -> ../init.d/mvfspl
│   ├── S47checkd -> ../init.d/checkd
│   ├── S47cifs -> ../init.d/cifs
│   ├── S48todd -> ../init.d/todd
│   ├── S48upnpavpl -> ../init.d/upnpavpl
│   ├── S49rssplugin -> ../init.d/rssplugin
│   ├── S55fuse -> ../init.d/fuse
│   ├── S56mvfs -> ../init.d/mvfs
│   ├── S67stopload -> ../init.d/stopload
│   ├── S68su_intf -> ../init.d/su_intf
│   ├── S69la_intf -> ../init.d/la_intf
│   ├── S71nlplugd -> ../init.d/nlplugd
│   ├── S72udhcpcd -> ../init.d/udhcpcd
│   ├── S73monitoripd -> ../init.d/monitoripd
│   ├── S74anti_spoofd -> ../init.d/anti_spoofd
│   ├── S80dropbear -> ../init.d/dropbear
│   ├── S97mud -> ../init.d/mud
│   ├── S97usb-host -> ../init.d/usb-host
│   └── S99powermgr -> ../init.d/powermgr
├── rc2.d
├── rc3.d
│   ├── S01jffs2contentcheck -> ../init.d/jffs2contentcheck
│   ├── S10no_hotplug_helper -> ../init.d/no_hotplug_helper
│   ├── S20network -> ../init.d/network
│   ├── S21vega -> ../init.d/vega
│   ├── S22linuxappl -> ../init.d/linuxappl
│   ├── S47checkd -> ../init.d/checkd
│   ├── S67stopload -> ../init.d/stopload
│   ├── S71nlplugd -> ../init.d/nlplugd
│   ├── S72udhcpcd -> ../init.d/udhcpcd
│   ├── S73monitoripd -> ../init.d/monitoripd
│   └── S74anti_spoofd -> ../init.d/anti_spoofd
├── resolv.conf -> ../rw/etc/resolv.conf
├── shadow -> ../rw/etc/shadow
├── udhcpc
│   └── udhcpc.script
├── usbmgr
│   ├── class -> /var/usbmgr/class
│   ├── dextension
│   ├── host -> /var/usbmgr/host
│   ├── preload.conf
│   ├── storage
│   ├── umts_custom
│   ├── update_usbmgrconf
│   ├── usbledctrl
│   ├── usbmgr.conf -> /var/tmp/usbmgr.conf
│   ├── usbmgr.conf.ro
│   └── vendor -> /var/usbmgr/vendor
└── version

For what it seems, interesting files in /etc directory are symlinks to the relative ones in /rw and, for me, rw has something to do with Read and Write operations. Let's search some evidence of this path in configuration files:

root@kali:~/Projects/tg582n/_dump.bin.extracted/squashfs-root/etc# grep -ir rw
init.d/clinkd:CLINKCONF_DEST=/rw/etc/
init.d/clinkd:    #CPE_P00075123:CJ:Change clink.conf to a rw location
init.d/usb_storage:		# eb 3c 90, we're definitely dealing with a FAT boot sector. Otherwise, we
init.d/usb_storage:    SMBD_STATUS=0 # 0 means that cifs service is stopped (otherwise it is running)
init.d/jffs2contentcheck:#    push down of dl partition content into /rw/dl
init.d/jffs2contentcheck:	# New layout: (USERFS mounted on /rw)
init.d/jffs2contentcheck:	#      /dl --> /rw/dl
init.d/jffs2contentcheck:	if [ "`cat /proc/mounts | grep /dev/mtdblock0 | grep /rw`" ]; then
init.d/jffs2contentcheck:		[ -d /rw/etc ] || mkdir -m 775 /rw/etc
init.d/jffs2contentcheck:		if [ ! -d /rw/dl ]; then
init.d/jffs2contentcheck:			echo " Detected old jffs2 partition layout! Converting /rw to new layout"
init.d/jffs2contentcheck:			mkdir -m 775 /rw/dl
init.d/jffs2contentcheck:			for file in /rw/*; do
init.d/jffs2contentcheck:				([ "${file}" = "/rw/dl" ] || [ "${file}" = "/rw/etc" ]) && continue
init.d/jffs2contentcheck:				mv ${file} /rw/dl/
init.d/jffs2contentcheck:	#     /rw --> /userfs/config-bank-X
init.d/jffs2contentcheck:	#     /dl --> /rw/dl
init.d/jffs2contentcheck:	# Set /rw correctly: since /rw is on rootfs which is read-only, we
init.d/jffs2contentcheck:	mount -o bind $CONFDIR /rw
advancedservices.conf:HDTOOLSDIR="/rw/disk"
advancedservices.conf:FLASHCONFIGDIR="/rw/etc/"
mime.types:application/vnd.vectorworks

We found thatclinkd, jffs2contentcheck and advancedservices.conf have something to do with the /rw directory. Let's review these evidence.

  • clinkd: in the comment section of the script: "This is the init script for the Entropic clinkd daemon". I wasn't able to find useful informations about this daemon.
  • advancedservices.conf: nothing too much interesting here, only a small nudge to the fact that /rw/etc is the writable part of the flash.
  • jffs2contentcheck: this is interesting, we found plenty of informations in this script. For better understand its purpose, this is the full source and, actually, it's pretty well commented.
#!/bin/sh

####
# This script checks and converts the layout of the writable partition to its
# latest version.
#
# Changelog:
#  * 7.4.4 > 8.1.1:
#    push down of dl partition content into /rw/dl
#    [Steven Aerts -- 2008/03/12]
####

. /etc/autoconf.conf

start () {

	# Verify 7.4.4 to 8.1.1 userfs migration
	# Old layout: (USERFS mounted on /dl)
	#      USERFS/user.ini
	#      USERFS/etc/...
	#      USERFS/tls/...
	# New layout: (USERFS mounted on /rw)
	#      USERFS/etc/...
	#      USERFS/dl/user.ini
	#      USERFS/dl/tls/...
	#      /dl --> /rw/dl
	if [ "`cat /proc/mounts | grep /dev/mtdblock0 | grep /rw`" ]; then
		[ -d /rw/etc ] || mkdir -m 775 /rw/etc
		if [ ! -d /rw/dl ]; then
			echo " Detected old jffs2 partition layout! Converting /rw to new layout"
			mkdir -m 775 /rw/dl
			for file in /rw/*; do
				([ "${file}" = "/rw/dl" ] || [ "${file}" = "/rw/etc" ]) && continue
				mv ${file} /rw/dl/
			done
		fi
	fi

	# Migrate to dual bank layout
	# New layout: (USERFS mounted on /userfs)
	#     USERFS/config-bank-X/etc/...
	#     USERFS/config-bank-X/dl/...
	#     /rw --> /userfs/config-bank-X
	#     /dl --> /rw/dl
	
	# Determine booted bank from command line
	BOOTID=$(sed -n "s/.*btab_bootid=\([0-9]\+\).*/\1/p" /proc/cmdline)

	# If BOOTID is empty, set it to a certain value (single-bank case)
	[ -z "$BOOTID" ] && BOOTID=999

	CONFDIR="/userfs/config-bank-$BOOTID"

	# Create a config directory for the booted bank if it does not yet exist
	[ ! -d $CONFDIR ] && mkdir $CONFDIR
	# Set /rw correctly: since /rw is on rootfs which is read-only, we
	# cannot use a symlink. However, mount supports the bind option which
	# essentially does the same.
	mount -o bind $CONFDIR /rw
	# If there are any files/directories in /userfs (config-bank-X
	# directories excluding), move them to the config directory of the
	# booted bank. This indicates a first boot from BLI.
	for i in $(ls /userfs | grep -v "^config-bank-*" | grep -v "^common$"); do
		mv /userfs/$i $CONFDIR
	done
	# If the config directory is still empty, copy the configuration
	# from another bank to allow a 'correct' boot. This can happen when
	# you upgrade an rbi with the bootloader.
	# NOTE: there is no guarantee that this configuration will work, but
	# it's better to have something.
	if [ -z "$(ls $CONFDIR | grep -v "^version$" 2>/dev/null)" -a -x /usr/bin/copyconfig ]; then
		/usr/bin/copyconfig "lastboot" $BOOTID
	fi

	# Set the 'lastboot' symlink to the current configuration
	rm -f /userfs/config-bank-lastboot
	ln -sf $CONFDIR /userfs/config-bank-lastboot

	# Copy the version file from /etc to /userfs/config-bank-X
	if [ -f /etc/version ]; then
		cp /etc/version $CONFDIR
	else
		echo "Unknown" > $CONFDIR/version
	fi

	# Create a common userfs directory
	[ ! -d /userfs/common ] && mkdir /userfs/common

}


case $1 in
start)
	start
	;;
stop)
	;;
restart)
	;;
*)
	echo "Usage $0 [start|stop|restart]"
	exit 1
	;;
esac

What's JFFS2 filesystem?

JFFS2 (Journaled Flash File System v2) is a file system designed for use on Flash devices such as those commonly found in embedded systems. Unlike some other file systems which may be stored on the Flash device and then copied into RAM during boot (i.e. ramdisk) JFFS2 actually resides on the Flash device and allows the user to read/write data to Flash. This is particularly useful in embedded devices that wish to save some persistent data between reboots. [cit]

We finally found where the persistent informations are saved. Coming back to the binwalk analysis, I remember many signature related to JFFS2 filesystem. Let's review the evidences extracted:

root@kali:~/Projects/tg582n/_dump.bin.extracted# tree jff*
jffs2-root
└── fs_1
    ├── common
    │   └── flash_image_fii
    ├── config-bank-999
    │   ├── dl
    │   │   ├── persistent.cnf
    │   │   ├── phy.conf
    │   │   ├── seed.dat
    │   │   ├── stsZWEADQ8.CM0.upg
    │   │   ├── tls
    │   │   │   ├── cert0001.pem
    │   │   │   └── pkey0001.pem
    │   │   ├── user.ini
    │   │   └── xdsl.inf
    │   ├── etc
    │   │   ├── group
    │   │   ├── gshadow
    │   │   ├── passwd
    │   │   ├── resolv.conf
    │   │   ├── secrets.tdb
    │   │   ├── shadow
    │   │   ├── smb.conf
    │   │   └── smbpasswd
    │   └── version
    └── config-bank-lastboot -> /userfs/config-bank-999
jffs2-root-0
└── fs_1
    ├── common
    │   └── flash_image_fii
    ├── config-bank-999
    │   ├── dl
    │   │   ├── persistent.cnf
    │   │   ├── phy.conf
    │   │   ├── seed.dat
    │   │   ├── stsZWEADQ8.CM0.upg
    │   │   ├── tls
    │   │   │   ├── cert0001.pem
    │   │   │   └── pkey0001.pem
    │   │   ├── user.ini
    │   │   └── xdsl.inf
    │   ├── etc
    │   │   ├── group
    │   │   ├── gshadow
    │   │   ├── passwd
    │   │   ├── resolv.conf
    │   │   ├── secrets.tdb
    │   │   ├── shadow
    │   │   ├── smb.conf
    │   │   └── smbpasswd
    │   └── version
    └── config-bank-lastboot -> /userfs/config-bank-999
jffs2-root-1
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── phy.conf
    ├── secrets.tdb
    ├── smb.conf
    ├── smbpasswd
    ├── stsZWEADQ8.CM0.upg
    ├── user.ini
    └── xdsl.inf
jffs2-root-10
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-11
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-12
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-13
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-14
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-15
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-16
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-17
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-18
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-19
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-2
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── secrets.tdb
    ├── smb.conf
    ├── smbpasswd
    ├── stsZWEADQ8.CM0.upg
    ├── user.ini
    └── xdsl.inf
jffs2-root-20
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-21
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-22
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-23
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-24
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    └── smbpasswd
jffs2-root-25
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    └── smbpasswd
jffs2-root-26
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    └── smbpasswd
jffs2-root-27
└── fs_1
    ├── passwd
    └── smbpasswd
jffs2-root-28
└── fs_1
    ├── passwd
    └── smbpasswd
jffs2-root-29
└── fs_1
    └── smbpasswd
jffs2-root-3
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── secrets.tdb
    ├── smb.conf
    ├── smbpasswd
    ├── user.ini
    └── xdsl.inf
jffs2-root-4
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── secrets.tdb
    ├── smbpasswd
    ├── user.ini
    └── xdsl.inf
jffs2-root-5
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    ├── user.ini
    └── xdsl.inf
jffs2-root-6
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    ├── user.ini
    └── xdsl.inf
jffs2-root-7
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    ├── user.ini
    └── xdsl.inf
jffs2-root-8
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini
jffs2-root-9
└── fs_1
    ├── config-bank-lastboot -> /userfs/config-bank-999
    ├── group
    ├── passwd
    ├── persistent.cnf
    ├── smbpasswd
    └── user.ini

41 directories, 210 files

Honestly I don't know why there are so much copies of same files but, definitely, we found what we were looking for: not only the passwd file but also certificates with private keys, user configurations, xdsl line configurations, etc.

Let's try to understand if there are any differences between files inside that directories, so we can narrow our analysis. With a basic bash scripting knowledge, we can use md5sum to find if files are the same. Turns out that almost every file are copies and the only variable is user.ini. Also, the .upg file appears to be the same of smbpasswd.

group b6645876780362adfefe6ae7aa2aa970
passwd ccfbeda0bfe6a969d9f3e95284e450be
persistent.cnf 0169902625104a21be24f44df679d610
phy.conf c176b13932e5bf01930a066491877986
secrets.tdb cbe77f45cae8dad41cb9bef73ed69ed6
smb.conf 7c6ed2fab7571c3441d3af6740f9d067
smbpasswd d41d8cd98f00b204e9800998ecf8427e
stsZWEADQ8.CM0.upg d41d8cd98f00b204e9800998ecf8427e
user.ini 080b575f72aa410d0d2606ed9f152c18
user.ini 1b37b14685d303d192c80e5e8c3e68c7
user.ini 1d57ab52d6fa5d4d61cf6f520ac62b29
user.ini 2113deb10fd3cc6e5e5d5fc44489ee13
user.ini 2fbe85cc5305473ad68ae9b842134696
user.ini 3a4860416befea32f5a6952f75c1073e
user.ini 4388cd21843a0e1dbc7ec8b9d6b0fe81
user.ini 59499065a1243c0fd0bc3aec77eb5052
user.ini 6281deec4ac9389b797afc4873b9a90a
user.ini 6400c4bc913e682e32e055d262c058d4
user.ini 8165fea871781c7320bd6ef3b201c90f
user.ini 8504dfd01106e4f2e2a21c6e7460964e
user.ini 919573ff12d4eabf968a6dfd97a7d616
user.ini c4f70675bc732dd93fc8bb9c9219fb74
user.ini cab37a7859e4cb319aa1684f9fbee277
user.ini e9930518fb8db6670f14af642e177083
xdsl.inf 25daad3d9e60b45043a70c4ab7d3b1c6

Let's analyze them:

group: standard file, the same you can find on all *nix systems but with interesting groups.

SuperUser::101:
TechnicalSupport::102:
Administrator::103:
WebsevUser::104:
LAN_Admin::105:
PowerUser::106:
User::107:
WAN_Admin::108:

passwd: the file we were looking for. This file will be slightly modified during boot because root access is somehow disabled but at least we found two users: Administrator and tech with relative hash.

root::0:0:Super User:/:/bin/sh
nobody:*:1:1:nobody:/:/bin/sh
mvfs:*:499:1::/var/mvfs:/bin/sh
Administrator:ANpAYtow5vx0U:500:103:Linux User:(null):/bin/sh
tech:RB6zAiLmCT4zM:501:102:Linux User:(null):/bin/sh

If you search on Google, turns out that the hash ANpAYtow5vx0Uwas generated by the command mkpasswd and here we can read that:

If your password is on this list, it is not secure. It was generated by using the program 'mkpasswd' and then not typing anything. It turns out that 'mkpasswd' doesn't make passwords, it makes password hashes. If you enter a blank password, it generates one of 4096 possible passwords.

So, Administrator user has a simple blank password, I didn't find anything similar with the hash of the tech user. For this user I started a simple crack session with john, and without any fancy cracking rig or powerful graphic video card, after an affordable cracking time (~ 2days) I managed to crack the password: it appears to be 55058391.

secrets.tdb: related to Samba services, it stores passwords in clear text. This file can be opened with the tdbdump:

{
key(23) = "SECRETS/SID/TECHNICOLOR"
data(68) = "\01\04\00\00\00\00\00\05\00\00\00\15\89+\B5\E1jD\15P\1A\92\F03\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
}
{
key(17) = "INFO/random_seed\00"
data(4) = "y\04\00\00"
}

user.ini: router clear text configuration file.

There are some other files but, for now, we have enough to start.

Accessing the device...in some way

We found that the Administrator user has blank password. We can now login via console access. Tech user access is somehow disabled.

Username : Administrator
Password : 
------------------------------------------------------------------------

                             ______  Technicolor TG582n
                         ___/_____/\ 
                        /         /\\  8.C.M.0
                  _____/__       /  \\ 
                _/       /\_____/___ \  Copyright (c) 1999-2012, Technicolor
               //       /  \       /\ \
       _______//_______/    \     / _\/______ 
      /      / \       \    /    / /        /\
   __/      /   \       \  /    / /        / _\__ 
  / /      /     \_______\/    / /        / /   /\
 /_/______/___________________/ /________/ /___/  \ 
 \ \      \    ___________    \ \        \ \   \  /
  \_\      \  /          /\    \ \        \ \___\/
     \      \/          /  \    \ \        \  /
      \_____/          /    \    \ \________\/
           /__________/      \    \  /
           \   _____  \      /_____\/
            \ /    /\  \    /___\/    F.D.C. FW 14
             /____/  \  \  /
             \    \  /___\/
              \____\/

------------------------------------------------------------------------
{Administrator}=>
contentsharing          firewall                printersharing          
pwr                     service                 connection              
cwmp                    dhcp                    dns                     
download                dsd                     dyndns                  
eth                     atm                     config                  
debug                   env                     expr                    
grp                     hostmgr                 ids                    
igmp                    interface               ip                      
ipqos                   label                   language                
mbus                    memm                    mlp                     
mobile                  nat                     ppp                     
pptp                    ptrace                  script                  
sntp                    software                statecheck              
syslog                  system                  tls          
{Administrator}=>

I spent a lot of time poking around in this weird restricted shell. I wasn't able to escape to our beloved Busybox that I know is running below. No matter what I tried, I always ended up in this jail I could not escape. It seems to manage everything from the console access.

To confirm this theory, I found this old post:

And suddenly I remembered this two sneaky files laying in the /nmon directory.

I'm quite sure this program is run at boot time and, basically, take the control of the entire router. This can now be confirmed in the boot log above:

linux application start ...
wait for linux_appl to initialize (1)
wait for linux_appl to initialize (2)
************* ERROR RECORD *************
000000:00:00.000000
Application NMON started after POWERON.
****************** END *****************
wait for linux_appl to initialize (3)
appl_init: BUILD VERIFIED!
wait for linux_appl to initialize (4)
[SS EMUL] ERR: opening config file /active/ss.conf failed
End of initialisation
wait for linux_appl to initialize (5)

And this is the script that, at boot time, runs the linux_appl.exe

#
#/etc/init.d/linuxappl
#
#!/bin/sh

. /etc/init.d/mbusd_util

case $1 in
    start)
        TELLER=0
        # linux application configuration
        /bin/echo "linux application start ..."
        rm -f /var/run/linux_appl
        rm -f /var/run/init_finished
        mbusd_set_loadapp
        ../../nmon/linux_appl.exe /dev/nmon/nmontrace /dev/nmon/nmonerr /archive/ &
        while [ ! -f /var/run/linux_appl ]
        do
           TELLER=`expr ${TELLER} + 1`
           echo "wait for linux_appl to initialize (${TELLER})"
           sleep 1;
        done
        ;;
    stop)
        killall -9 linux_appl
        ;;
    *)

esac

Next steps

This ends up this phase of my journey. Honestly, I was (am) not prepared to impact in a so restricted and particular environment. My next steps will be to look the router from a network point of view, analyzing it while it's up & running, trying to find information within the services it runs and offers.

I hope you will find this post useful and if you have any hints or ideas to help me, please drop me a note.