Custom firware on the MPR-L8 cheap Wireless Router
This post is about experiences with hacking into the MPR-L8 and my attempts to install modified firmware to the router. At the end of the post there will be links to the simply uploadable OpenWrt firmware along with the original firmware to be able to restore the router.
EDIT: This is a relatively old post, the process of hacking the router is well described here, but the provided images are not working very well. If you are planning to upload some special firmware I have written a newer post, which is exactly about that.
!!!WARNING!!! Do all of this at your own risk, there are high chances that you brick your router, do not blame me afterwards. Please read the comments before you continue.
The MPR-L8 is a cheap WiFi 3G mini router, with own built in battery, and the main purpose is to share the mobile internet from an USB 3G/4G modem. If you look it from a different angle it is a very cheap and nice mini computer with wired Ethernet, WiFi, USB and serial connection. If you can customize it's firmware you can do very nice things with it, like bandwidth controlling, remote access to industrial applications, or with an USB sound card a DLNA endpoint to convert your analogue HiFi to a smartphone controlled speaker system.
There are several HW and SW versions of the router, mine came with 4M ROM and 32M RAM. The original firmware (version 18.104.22.168) is a rather powerful, with very good functionality (3G USB modem handling, USB NAS functionality, advanced WAN, LAN and WiFi functionality, web interface), on the other side OpenWrt versions fitting into 4M ROM usually come without any WEB interface and with a very limited functionality. However the original firmware is very buggy, for example mine is not always able to handle the USB modems.
Most of the information I used during this process can be found on the OpenWrt forum under the HAME MPR-A1 topic. Actually the people on that forum built in full support for this router into OpenWrt, but somehow I felt that it is not fully documented everything what they did.
Hacking step 1 - Port scanning
Scanning with nmap gives the following open ports:
23/tcp open telnet
53/tcp open domain
80/tcp open http
Telnet is interesting so let's telnet into the router.
Promising, but after looking around it has nothing really useful. It has no root command line possibility to let's try to make it, by accessing files.
Hacking step 2 - Accessing the file system trough Samba
The router is able to share the content of an USB flash or USB disk, we can misuse this and force it to share the full internal Linux file system. To do this on the Server/Permission setup page of the router enable sharing and add an account with the "Operation Directory" set to "/". It is important that an USB storage device has to be plugged in in order to start the sharing functionality.
Browsing the file system is interesting, however it is not possible to overwrite anything :-( and at least I did not found any weak point where I could hack into the system.
On the other side if not used for hacking it is possible to connect an USB hub to the router and then you can connect a 3G USB modem and a USB hard disk at the same time, and get internet access and file sharing parallel!
Hacking step 3 - Connecting to the serial port
After failing with the soft method the next step is to solder a serial connector to the router, and get into the boot loader to dump the contents of the ROM.
The position of the serial connectors are listed in this post. I have used a TTL serial to USB cable, the only specialty that I had to insert a 1K resistor between the adapters TXD line and the modems RX line to function properly.
Here again I had no luck, as the uBoot boot loader, which is a standard open source program, was modified in order not to dump the content of the ROM. Instead of the hexadecimal values it just displays BAAD - which is in some sense clever.
Hacking step 4 - Compliling an OpenWrt image
Dumping the ROM content was not possible, but it was possible to boot a different image from a TFTP server. The idea was to build an OpenWrt image which is loaded from a TFTP server and is running entirely in the RAM. With this image running it will be possible to save the contents of the ROM.
To do this I have set up a new Linux virtual machine with Ubuntu server 14.04, then following the instructions of the OpenWrt site installed a complete build environment and built the image. The important setting is that it should be in initramfs format. This device is a ramips/rt305x/mpr-a1 type device.
I was lucky, I could compile the image without mayor problems and even I could boot it up from the TFTP server.
After doing this I have used the dd Linux command to copy the mtd partitions and transferred them using scp to the OpenWrt development Linux virtual machine.
Structure of the original firmware
Binwalk is the tool to analyze and take out parts of binary firmware. I compiled a version of binwalk to the development machine and looked into the just obtained mtd partition.
The main container is an uImage header. This is a 64 byte header for the boot loader. Binwalk can extract the contents and mkimage -A mips -O linux -T kernel -C lzma -a 0x80000000 -e 0x80307000 -n "Linux Kernel Image" -d kernel_image_filename uImage_filename creates it back.
2) Decompress kernel image
The kernel image is stored lzma compressed, so first we need to decompress (or can let binwalk do it for us):
To compress the lzma tool from the OpenWrt package is needed (standard lzma utilities produce archives that do not boot with the uBoot boot loader):
~/openwrt/staging_dir/host/bin/lzma e bzImage.cpio bzImage.lzma
3) Kernel image + initramfs
After extracting the kernel image it is actually a kernel image and an initramfs copied together. Again binwalk is doing a good job to extract the initramfs. To get the kernel itself, copy the beginning of the kernel image file, till the position of the beginning of initramfs, which is displayed by binwalk.
The initramfs is an lzma compressed cpio archive. For decompressing the lzma:
To compress it back, the lzma tool from the OpenWrt package is needed:
~/openwrt/staging_dir/host/bin/lzma e initramfs.cpio initramfs.lzma
5) File system cpio
To extract the root file system from the cpio:
cpio -i --no-absolute-filenames < ../initramfs.cpio
To extract all files you need to use sudo and be very careful, because it can easily overwrite your main filesystem on the development machine. (Better to run first without sudo, to check if it is extracting to the right place and only the use it with sudo, when everything is ok.)
To archive back a subdirectory tree, the following command is needed:
sudo -s ; find . | cpio -H newc -o > initramfs.cpio
So the total process is as follows:
uImage -> bzImage.lzma->bzImage->kernel+initramfs.cpio.lzma->initramfs.cpio->initramfs
6) Patching initramfs size
Unfortunately the size of the initramfs is hard-coded into the kernel image. In order to change the initramfs the kernel has also to be patched. The calculation of the initramfs size is done by the following MIPS assembler code:
30dde0 3c 04 80 33 lui a0,8033
30dde4 3c 05 80 5c lui a1,805c
30dde8 24 84 a0 00 addui a0,a0,a000
30ddec 24 a5 fb b3 addui a1,a1,fbb3
In hex dump this looks like this:
30dde0: 33 80 04 3c 5c 80 05 3c 20 a0 84 24 b3 fb a5 24
So after creating the new initramfs image, concatenating it to the original kernel image, you have to check the new size of the concatenated file and write it in to the bytes marked with red. If the most valuable bit in the lower 16 bits (word) of the address is 1 then you should add one to the higher word of the address. In the original image the end of the initrd was 5B fb b3.
Hacking step 4 - Looking into the WEB interface
The best way to customize the system would be to change the WEB scripts, however the router side processing of the asp files is compiled in to the http daemon httpd. this means, that only minor modifications can be done. What is interesting yet, that there is an apply.cgi which can be used to write any nvram parameter to the router and the updateNvram.cgi can be used to read any nvram parameter from the router. With some patience an "expert" web page can be created, where all the nvram parameters can be made available for the user.
I gave up this direction, it may be a next step to optimize the web interface.
Hacking step 5 - Adding root command line
After looking around it became obvious the there is no command line shell in the system, that's why even with telnet nothing useful could be done.
To add a command line I decided to compile the dash shell from source and add it to the image.
For the compilation I used the Ralink SDK 22.214.171.124 which can be found on the net under the name Ralink_ApSoC_SDK_3600_20110715.tar.bz2.
After decompressing an extra link had to be added to make it work:
/home/winfred/RT288x_SDK/toolchain/buildroot-gdb -> /home/laco/ralink/RT288x_SDK/toolchain/buildroot-gcc342-laco/
Probably it would had also helped if I create a winfred account on the Linux machine and extract the SDK there.
To compile dash to the mips target architecture, the compiling command in the dash makefile has to be changed to mipsel-linux-gcc and make this new compiler available in the path when compiling dash.
After successfully compiling and testing dash, I added it to the root filesystem, by replacing the link which pointed /bin/sh to busybox and created the image doing the extraction steps in the opposite order:
rootfilesystem->initramfs.cpio->initramfs.lzma->bzImage->patch initramfs length->bzImage.lzma->uImage
Making the images loadable with the original web interface
The guys at OpenWrt did a good job, because they also created a program to convert an uImage to a web interface loadable bin file. With the following command you can convert an existing mtd image to an uploadable image:
~/openwrt/build_dir/host/firmware-utils/bin/mkporayfw -B MPR-L8 -f sourceImage -o destnationImage
Ready uploadable images for download
Original 126.96.36.199 firmware
Modified 188.8.131.52 with command line shell on telnet
OpenWrt with SqashFS
Original 184.108.40.206 firmware in RAW (uImage) format to restore with openwrt
Restoring the original firmware from OpenWrt
- Connect to the router using a telnet client (e.g. Putty). The default address is 192.168.1.1. You have to setup your computer to be on the same network e.g. 192.168.1.2.
- Copy the firmware from the development machine to the router. On the router issue the following command: scp firstname.lastname@example.org:/home/user/mtd3 /tmp "user" is the user name on the development machine, the first path is the path to the image on the development machine, the second is the path on the router.
- Copy the firmware to the ROM, issue the following command: dd if=/tmp/mtd3 of=/dev/mtdblock3
- Restart the router: reboot