logo elektroda
logo elektroda
X
logo elektroda

Analysis of the inside of the router, memory ripping, bootloader, custom program for UART

p.kaczmarek2  0 150 Cool? (0)
📢 Listen (AI):

TL;DR

  • Teardown of the Cyfrowy Polsat LT-6408n, an Edimax-based LTE/HSPA+ router built around the RTL8196C and RTL8192CE.
  • Inside are a W9825G6JH 32 MB RAM chip, a 25L6406E 8 MB flash chip, UART pads, and a 3.3 V power section.
  • A CH341 programmer and UART capture exposed the bootloader, and pressing Escape at boot unlocked Realtek commands like D, IPCONFIG, AUTOBURN, LOADADDR, J, and FLW.
  • Binwalk found LZMA boot fragments and a SquashFS filesystem containing web sources, modem support, iPhone tethering tools, and init.sh, but boot stops at 'Initialize AP MIB failed!'.
Generated by the language model.

This time we take a look inside the Cyfrowy Polsat LT-6408n router. This is actually a model manufactured by Edimax and sold to the operator as the Edimax LT-6408n with its branding. The router was primarily developed to share internet from LTE or HSPA+ modems connected via USB.

The whole thing works with a 5 V power supply, which is typical of slightly newer hardware already. The bottom sticker shows the default IP, name and administrative password. The FCC ID of the device is NDD9564081112.

On the back we have an On/Off button, WPS/Reset, four LAN ports, one WAN port, a power supply input (DC Jack) and a USB port, this is often used to connect the aforementioned LTE/4G modem (Huawei E3372s-153 as an example).

Interior of the router
Simply unscrew the screws on the bottom. These can be hidden under the legs.

The first thing that catches the eye is the USB cable routed through the middle of the board. Someone seems to have changed their mind about the location of the port. It was supposed to be on the front, but has been moved to the back.
The router is based on the RTL8196C together with the W9825G6JH memory (4194304 words * 4 banks * 16 bits, or 32 MB).

The memory connects to the main controller via a 16-bit interface. The whole thing additionally has GPIO, USB 2.0, EJTAG, UART and Switch and PCIE controllers.

The actual program is on a separate flash memory, the 25L6406E. The 64 in the name suggests a large size - 64 megabits, or 8 megabytes.

Next to the memory are four pads, which look like a UART-derived location.

In the power section, I can see the IT76520M voltage drop inverter. There is also room for a second inverter, but it is not soldered in. One would think that the whole thing runs on a single voltage.

Measurement confirms that the whole thing is running at 3.3 volts:

There are no additional components on the bottom of the board, although you can see that someone planned to put the coils there.

That leaves the RTL8192CE - a WLAN controller with PCI-Express miniCard, or Wi-Fi. Interestingly, despite a border suggesting a screen, that screen is not there.





Reading Flash memory via CH341

The first thing I always do is a full fair copy of the Flash memory via the CH341 programmer. I don't use a clip, it's not reliable, I think I find it fails more often than it works, so I prefer to solder the chip with flux and hot air instead. Then I still remove the lead-free solder from the pads and re-solder it with lead, then subsequent soldering operations will be easier. For subsequent operations I don't even clean the pads anymore, I just use the binder what is there.



I used to remove such circuits with a regular soldering iron, but now I have hot air on hand all the time.
NeoProgrammer recognises the memory:

The reading is carried out without any problems. To be sure, I still performed the verify operation. I saved a copy on my repository:
https://github.com/openshwprojects/FlashDumps/commit/823f9895317a5984cb99fcc468382662b3e52137



UART connection - boot log
You can now connect to the UART and view the router's boot log. First you need to find the pins - there are usually four pads next to the main CPU. The most common are: GND, TX, RX and VCC (3.3 V). For communication, I used a USB-UART converter (CH340) set to 3.3 V. There is no need to connect VCC, three wires are enough: GND, TX, RX (TX from router to RX of the converter and vice versa).
I selected the baud experimentally. In routers, the most common values are the same, such as 57600, 38400, less often 115200 - in the case of Realtek chips, the 38400 8N1 is very common.
This is how I managed to pick up the first characters. I saved them to a file via "Capture to file" in Realterm.


Booting... 

========== SPI =============

 

---RealTek(RTL8196C)at 2013.05.22-07:15+0800 version v1.1f [16bit](390MHz)


DRAM Spreading Spectrum: [ON] TRX Timing: [T:4 R:6]


<=== GPIOA4 off/on 9/1 2197619 times ===>

Jump to image start=0x80500000...

decompressing kernel:
Uncompressing Linux... done, booting the kernel.
done decompressing kernel.
start address: 0x80003770
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 26632k/32768k available (2696k kernel code, 6136k reserved, 697k data, 108k init, 0k highmem)
Calibrating delay loop... 388.30 BogoMIPS (lpj=1941504)
Mount-cache hash table entries: 512
net_namespace: 528 bytes
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)


The log shows information about the boot process of the device, including decompression of the Linux kernel. After that, however, the router limps on:

WEBS Restarting !
Initialize AP MIB failed!

It appears to fail to correctly initialise the configuration stored in flash memory (the so-called MIB - Management Information Base in Realtek's implementation).



UART connection - command line
After the MIB message, the process stalls and the router does not start. It also does not respond to commands. Could it be that the command line is blocked? Nothing could be further from the truth. I quickly discovered that pressing the Escape key at boot time locks the process and frees the command line:

Furthermore, the help command works - it provides us with a list of commands:

The commands seem to be already known, I see that the OpenWRT guys have documented them:
https://openwrt.org/docs/techref/bootloader/realtek
In a nutshell, here we have:
- D <Address> <Len> - memory dump (preview of RAM/flash area)
- DB <Address> <Len> - byte dump
- DW <Address> <Len> - word dump
- EB <Address> <Value1> ... - writing bytes into memory
- EW <Address> <Value1> ... - word write
- CMP <dst> <src> <length> - comparison of two memory areas
- IPCONFIG <TargetAddress> - IP configuration (e.g. for TFTP / recovery)
- AUTOBURN 0/1 - enables/disables automatic flash programming (so called "autoflash")
- LOADADDR <Load Address> - sets the address to which the data is loaded (e.g. from the network or the UART)
- J <TargetAddress> - jumps to the address (starting the code in RAM)
- FLW ... - write to flash via SPI (from RAM to SPI flash)

Satisfied with the results, I started testing the commands on my own. IPCONFIG was the first to go:

From what I understand, it sets the destination IP of the router where the firmware can be uploaded via a PUT request. Interestingly, this IP doesn't even respond to pings, but arp seems to see it:

I then started testing the D - dump command, which is a memory preview. I quickly realised that it would be possible to go one step further here, and automate the flash reading just by such a primitive command. It won't be efficient, but it will allow us to verify that we have a good understanding of how it works.

UART connection - custom flash dumper
The dump command response consists of the data address and the contents of consecutive 32-bit words in hexadecimal format:

80008000:       00001021        0800200D        00000000        8FA40014

This can be easily parsed and saved to a file. The only puzzle remains the offset - where is the flash memory mapped? I checked this experimentally, with a script. The batch read from CH341 starts at 0xBD000000. In this way I was able to develop a simple tool to read data over the UART:


The screenshot shows the offset $F2A80 with the data available there. What is in the ripped file under this offset?

The data matches and the ripped memory is 1:1 compatible with the contents of the Flash.

Further search - firmware analysis by binwalk
Having a snapshot of the 8 MB Flash memory, it can be analysed with the tool binwalk , which automatically looks for known signatures in the binary file. Here is what binwalk found:

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
5344          0x14E0          LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 52128 bytes
76824         0x12C18         LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 3586380 bytes
1179648       0x120000        Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 4942768 bytes, 744 inodes, blocksize: 131072 bytes, created: 2038-04-12 00:51:12

We see three key fragments:
- under offset 0x14E0 there is a small compressed LZMA fragment (probably part of the bootloader or recovery)
- at offset 0x12C18 there is a compressed Linux kernel (LZMA) - it is the bootloader that decompresses it and runs it at address 0x80003770
- at offset 0x120000 the SquashFS file system version 4.0 starts
In theory this should extract the switch -e, but in my case it dumps with a sasquatch compression error:

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
5344          0x14E0          LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 52128 bytes
76824         0x12C18         LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 3586380 bytes

WARNING: Extractor.execute failed to run external extractor 'sasquatch -p 1 -le -d 'squashfs-root-0' '%e'': [Errno 2] No such file or directory: 'sasquatch', 'sasquatch -p 1 -le -d 'squashfs-root-0' '%e'' might not be installed correctly

WARNING: Extractor.execute failed to run external extractor 'sasquatch -p 1 -be -d 'squashfs-root-0' '%e'': [Errno 2] No such file or directory: 'sasquatch', 'sasquatch -p 1 -be -d 'squashfs-root-0' '%e'' might not be installed correctly
1179648       0x120000        Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 4942768 bytes, 744 inodes, blocksize: 131072 bytes, created: 2038-04-12 00:51:12

In addition, and even more interestingly, the antivirus was responding at the same time:

I tackled it with a Python script:
Code: Python
Log in, to see the code

The extracted system turned out to be .... quite rich:

In /bin itself we have interesting files such as:
- scripts to manage the router (e.g. firewall.sh, init.sh)
- files and drivers for 3G/LTE modem support (cdc-acm.ko, cdc-wdm.ko, usb_modeswitch, qmicli, comgt, bpalogin)
- and even scripts and daemons designed for tethering from iOS devices (iPhones)! Here we find iphone_connect.sh, ipheth-pair, usbmuxd or ideviceinfo, among others. This is a very interesting find, given the age of the hardware.
- webserver, which is the main process responsible for the configuration and communication side.
The second interesting directory is /web, there are the server sources themselves. Immediately striking:
- an overabundance of .asp files - at first I thought this was Active Server Pages (ASP) technology from Microsoft, but it doesn't look like it - it's a different solution, also containing HTML, Javascript, but also special tags, retrieving variables from the system. For example:

- among the .asp I see the command interface:

- image files - gif, jpg and even by some miracle also PSD:

- in the file directory I also see variables - var files, including translations:

var alertFunctionRule=new Array
(
"Rule Name ",
"Regelname ",
"Nombre de la regla ",
"Nom de la règle ",
"Nome regola ",
"Regelnaam ",
"Nome da regra ",
"Název pravidla ",
"Nazwa reguły",
"Nume Regula",
"Имя правила",
"Názov pravidla",
"規則名稱",
"规则名称",
"ชื่อกฎ",
"Regelnavn ",
"Regelnamn ",
"Kural Adı"
);

Looking in the /etc directory, on the other hand, one comes across the default passwd account file. In addition to root and network services, strange account names are listed there, "john", "dliu", "odysseus", "ygtai" or "hcjong", could it be that they belong to the programmers?
The compilation date of all software appearing in the compiler_date file - Thu Jan 2 09:13:20 CST 2014 - indicates 2 January 2014.

The main boot script operating on all these systems is /bin/init.sh. This is a very comprehensive file dealing with initialising network interfaces, loading settings (including MIB configurations using calls to the built-in system flash utility, e.g. flash test-hwconf) and running a whole range of services - from dhcpd, to the pppoe client, to WPS and watchdog support ("wps_daemon", "watchdog.sh").

The screenshot shows the watchdog - when a particular host does not respond, the router is rebooted. Below is the reboot script:
Screenshot of a code editor showing a shell script fragment in /web/FUNCTION_SCRIPT

Summary
The adventure turned out to be more interesting than I thought. The router, although already quite old, can still be useful for hobbyist and educational purposes as well. There is a lot of potential for changing the batch and running a program uploaded to RAM. I'll try to show this in a separate topic, although I don't know yet how successful it will be. I've seen some of the sources from Realtek on GitHub, but will they really fit on this board? We'll find out! The whole thing doesn't look like it's officially supported by OpenWRT, but that doesn't mean you have to cross it out straight away.
Do you see any use for the old router? Feel free to discuss.
Attachments:
  • realtek_dumper_draft_202605.zip (4.87 KB) You must be logged in to download this attachment.

About Author
p.kaczmarek2
p.kaczmarek2 wrote 14451 posts with rating 12428 , helped 650 times. Been with us since 2014 year.

Comments

%}