Selfnet Blog

Feb 09, 2015

Plastikonf, dumping the flash

The last time, I analyzed the the hardware and figured out where the firmware is stored. So let's dump it. The datasheet tells us, that the flash IC has an SPI interface. Now we need something that adapts SPI to a more common interface like preferably USB. There are several devices to to this:

  • Use some microcontroller and write firmware for it that reads the SPI flash and dumps its contents via UART/USB. Downside: have to write code for microcontroller, hard to debug
  • Bus Pirate already supports SPI flashes. Unfortunately, Selfnet doesn't have one.
  • FTDI also makes USB to SPI converters besides USB to UART. I didn't have one at hand either, but I've had existing code for using certain FTDI bridges as USB - SPI converts.

So I purchased the FT2232H Mini Module and built an adapter to connect the SPI flash to it.

Picture of FT2232H Setup

The FT2232H contains a so called MPSSE (Multi-Protocol Synchronous Serial Engine) to do SPI. Side note: FTDI claims that the MPSSE also supports I²C, but since the FT2232H doesn't have open-drain outputs and has some glitching issues, it's really painful to implement. Since my existing code was developed on Windows™, it used the proprietary FTD2XX driver. After some fiddling, I got ftd2xx to work on python 3. Sorry, libftdi people :(

Implementing the protocol used by the SPI flash was rather straightforward since its datasheet is available. One particular nice aspect of the protocol is that you can read an arbitrary amount of data after sending the start address. So I hacked an IPython notebook to dump the flash. Magically, it worked the first time, therefore I didn't bother to clean it up to make it publishable.

That's inside the romdump:

$ binwalk romdump

94976         0x17300         U-Boot version string, "U-Boot 1.1.3 (Dec  4 2013 - 08:55:41)"
131584        0x20200         LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 3515396 bytes
1441792       0x160000        Squashfs filesystem, little endian, version 4.0, compression:lzma (non-standard type definition), size: 5051300 bytes,  627 inodes, blocksize: 131072 bytes, created: Fri Jun 20 05:19:24 2014
8126480       0x7C0010        XML document, version: "1.0"

In the next post, we'll dig into the romdump.

Jan 29, 2015

Plastikonf, new routers, new problems

To provide our members with the latest and greatest budget routers the market has to offer, we buy updated models when restocking. So it happened that procurement ordered some boxes of TP-Link Archer C2.

Since plastikonf writes the configuration to the router by creating a custom configuration file, the first thing to do is to get a configuration backup and decrypt it to base the custom configuration on. Fortunately other people already figured out the crypto stuff for all models we've had so far. But when trying to decrypt the new router's configuration file, the MD5 check failed. After disabling the MD5 check, we're left with garbled XML:

$ xxd cmpr | head -n 16
0000000: d186 bc52 606a da8c 8d2a abcc d855 f4b1  ...R`j...*...U..
0000010: fa80 0000 3c00 003f 786d 6c20 7665 7273  ....<..?xml vers
0000020: 696f 6e3d 2231 2e00 0030 223f 3e0a 3c44  ion="1...0"?>.<D
0000030: 736c 4370 6543 6f6e 6600 0069 673e 0a20  slCpeConf..ig>. 
0000040: 203c 496e 7465 726e 6574 4708 0061 7465   <InternetG..ate
0000050: 7761 7944 6576 6963 6500 0a19 2020 3c0c  wayDevice...  <.
0000060: 5375 6d6d 61af 0072 7920 7661 6c3d 2200  Summa..ry val=".
0000070: 002e 3a31 2e31 5b5d 2842 6173 656c 6960  ..:1.1[](Baseli`
0000080: 006e 653a 312c 2045 7468 564c 4160 014e  .ne:1, EthVLA`.N
0000090: 3a31 2922 202f 524c 4100 504e 554e 756d  :1)" /RLA.PNUNum
00000a0: 6265 724f 6687 0145 6e74 7269 6573 5d31  berOf..Entries]1
00000b0: 018a 2623 496e 666f 0040 3720 203c 4d61  ..&#Info.@7  <Ma
00000c0: 6e75 6661 63c0 0074 7572 6572 4f55 4930  nufac..turerOUI0
00000d0: 4538 4400 1c45 3237 3520 203c 5365 722b  E8D..E275  <Ser+
00000e0: 1469 616c 5b56 0021 4143 4445 3443 1400  .ial[V.!ACDE4C..
00000f0: 2748 6172 6477 6172 6556 00b0 1f2a 2241  'HardwareV...*"A

Looks as if they changed the crypto... Reverse engineering time :) Since the router knows how to decrypt the configuration file, we need to get its firmware for further investigation. Unfortunately, the firmware upgrade files are encrypted as well, so we somehow have to extract the firmware from the device itself. The guy who reverse engineered the crypto for the previous models did so by loading a custom build of openwrt into the RAM and then using openwrt to read out the firmware.

Since I'm a hardware guy and the Archer C2 seems to be unsupported by openwrt, let's open the case. This is what we're looking at: (Ignore the missing U18 for now, we'll get to that later)

Picture of C2-PCB with annotations

  • U11, U12, U14 and surrounding components: Voltage regulators
  • T2-T4: Ethernet isolation Transformers
  • U14: Realtek RTL8367RB Switch, one port is connected to the processor via (R)GMII link
  • U1: Mediatek MT7620 MIPS SoC, integrated 2.4GHz WLAN
  • U504: Winbond W9751G6KB-25 64MByte DDR2 SDRAM
  • U620: Mediatek MT7610 5GHz WLAN
  • U619: Skyworks SKY85703 5GHz WLAN Frontend
  • U18(missing): Winbond W25Q64BV 8MByte SPI Flash
  • J2: UART

The device containing the firmware is U18, as it's the only one with considerable amount of nonvolatile memory. It's commonplace for embedded systems like these routers to store the firmware in serial flash chips like we've got one here.

So I removed U18 in order to get hold of its contents. See the next post on how that has been accomplished.

Jan 12, 2015


Ever wondered where all these wifi networks with strange names like WH-Derki or WH-Bulu come from? These are the preconfigured wireless routers WH-Netz sells. During the last several years, one of our members has continously been developing and improving plastikonf, our custom solution for automatically configuring budget routers. Finally, it's available on Github!

See upcoming posts for recent developments.