Simple command line utility to convert TP-Link TD-W9970 modem router backup config files from binary to XML and back:
- conf.bin ➡ decrypt, md5hash and uncompress ➡ conf.xml
- conf.xml ➡ compress, md5hash and encrypt ➡ conf.bin
May or may not work with other TP-Link modem / routers (not tested)
Single python file, download, optionally chmod +x, and run.
First, download a backup conf.bin file from your router using its web interface (System Tools → Backup & Restore → Backup).
[python3] tpconf_bin_xml.py -h [python3] tpconf_bin_xml.py conf.bin conf.xml # decrypt, md5hash and uncompress
optionally make changes to conf.xml
[python3] tpconf_bin_xml.py conf.xml conf_new.bin # compress, md5hash and encrypt
- Python 3.x
- apt install python3-crypto
- OR pip install pycrypto
- OR pip install pycryptodome
To recover your router's account/password or simply make changes to your router's configuration using the XML file.
Exploring inside the router (advanced users)
To explore inside your router you can start by adding the following line to the <DeviceInfo> section of your router's configuration XML:
<Description val="300Mbps Wireless N USB VDSL/ADSL Modem Router`telnetd -p 1023 -l login`" />
After converting to .bin and uploading this new configuration you can telnet to your router's port 1023 and login using: admin/1234. (Leaving this port open without changing the password is a security risk)
The TD-W9970's configuration XML Description val is passed as a quoted parameter when launching upnpd (regarless if disabled in config) using sh -c around 20 seconds after boot (~ 35 seconds from power on).
A drive connected to the TD-W9970's USB port will be mounted around 4 seconds later. So it is possible to directly execute a script located on the USB drive during boot using something like this (note that XML special characters must be escaped, and we redirect output to null otherwise upnpd launch would wait until our script finished):
<Description val="Modem Router`(sleep 10;/var/usbdisk/sda1/myscript)>/dev/null &`" />
Unfortunately TP-Link did not include ext4 filesystem support in their Linux kernel, only FAT and NTFS (fuse). Using NTFS consumes a few more MB of RAM (running ntfs-3g) than FAT32, but offers the significant advantage of supporting symbolic links and large files.
You can download the latest busybox-mips from the busybox binaries repository and run it from your USB drive to have a more complete set of command line tools. To get started very quickly, even using a FAT filesystem, you could source (.) something like this:
alias b='/var/usbdisk/sda1/busybox-mips' for c in $(b --list); do alias $c="b $c"; done
SSH can be used instead of telnet to log in to your router. You can download a recent compatible (MIPS32 version 1) dropbear_static ssh server compiled by Martin Cracauer. Follow the instructions in the README there to set up the needed host keys (on a real PC:
apt install dropbear-bin). The router's /etc is read-only, so you'll need to start dropbear_static with the -r option for each key, pointing to your USB drive, e.g.:
Alternatively you can use the pre-compiled OpenSSH sshd daemon in this repository; read the sshd notes for more information.
Once you've made changes to the admin password / added new accounts, simply copy the passwd file to your usb; then your startup script can copy it over during each boot, e.g.:
cp -af /var/usbdisk/sda1/etc/passwd /var/passwd
For debugging you can download a pre-compiled gdbserver that works on the TD-W9970 from the TL-WR940N V5's code repository at TP-Link GPL Code Center.
Your (latest busybox) scripts or cross-compiled programs can also control LED lights on the TD-W9970 modem router using:
printf "%02x%02x" lednum ledmode > /proc/tplink/led_ctrl
Where lednum is:
- 2 = Internet
- 3 = WPS (padlock)
- 17 = Power
- 18 = USB
- 20 to 23 = LAN1-4
And ledmode is:
- 0 = off
- 1 = on
- 3 = flash slow
- 4 = flash fast
- 5 = flash fast pause
- 7 = flash fast 5 times + slow pause
How do I get my favourite tool running on the router?
Sadly due to lack of Broadcom xDSL support it is difficult at this time to run OpenWrt while using xDSL with this modem. However, it is possible to cross-compile many console / server programs and run them directly on this device using a script on your USB drive (see above). The TD-W9970 has a single core 600Mhz dual-CPU with ≈64MB of RAM. If you know which built-in services you do not need, you can first disable them via the web interface, then kill remaining unused processes to free up the RAM they use in order to run many of your own tools and services. For example:
sleep 15 # give router opportunity to finish setting up before we cleanup and setup our own services killall -1 upnpd # SIGHUP required to kill upnpd killall telnetd dyndns noipdns cwmp ushare # etc. - make sure you do not depend on any of the services you kill # setup my services here
The easiest way to cross compile popular tools for this device is by using Buildroot. Compiling static binaries using uClibc will generate small efficient portable executables. Some Buidroot settings to use for this device are: Target options: Architecture = MIPS (big endian), Binary Format = ELF, Architecture Variant = Generic MIPS32, use soft-float; Build options: strip target binaries, libraries = static only; Toolchain: C library = uClibc-ng.
On the v1 firmware DES keys are stored in
libcmm.so. The locations of the keys, the functions called, and the files targeted are (found using
478DA50FF9E3D2CB > p8 8 @0xc0000-0x21a0 dm_loadCfg (/etc/default_config.xml) > dm_decryptFile dm_init (/etc/reduced_data_model.xml) > dm_decryptFile 478DA50BF9E3D2CF > p8 8 @0xf0000-0x5cf0 rdp_backupCfg & rdp_restoreCfg (conf.bin) > cen_desMinDo, > cen_md5VerifyDigest, > cen_uncompressBuff rdp_saveModem3gFile > rsl_3g_saveModem3gFile
Therefore to decrypt
reduced_data_model.xml after copying the files to a PC:
openssl enc -d -des-ecb -nopad -K 478DA50FF9E3D2CB -in default_config.xml -out default_config_decrypted.xml openssl enc -d -des-ecb -nopad -K 478DA50FF9E3D2CB -in reduced_data_model.xml -out reduced_data_model_decrypted.xml
Similarly, to encrypt:
openssl enc -e -des-ecb -nopad -K 478DA50FF9E3D2CB -in default_config_decrypted.xml -out default_config.xml openssl enc -e -des-ecb -nopad -K 478DA50FF9E3D2CB -in reduced_data_model_decrypted.xml -out reduced_data_model.xml
Before encryption files must be zero padded to a file size multiple of eight. A simple script like this could be used to do this:
#!/bin/sh fsize=$(stat -c%s $1) pad=$(($fsize%8)) if [ "$pad" != "0" ]; then dd if=/dev/zero bs=1 count=$((8-$pad)) | cat $1 - > $1.padded fi