Debian on the Intenso Memory 2 Move
Intenso Gmbh distributes a line of cheap, battery -powered portable 2.5'' external USB hard-drives which furthermore include WiFi and Ethernet capability. Such devices are very interesting for a variety of applications beyond those envisioned by the manufacturer, and would make for an ideal "PirateBox" among other things.
These notes refer in particular to the 1TB "Black" model:
Basic operating modes:
As described in the manual (mirrored here for convenience), the device has at least two operating modes. When connected via USB to a computer in the initial "power off" state, it behaves as a simple USB-to-SATA bridge, making the whole hard-disk externally accessible.
When indipendently switchted on, the internal embedded SoC Linux system takes over, and after a relatively fast booting sequence it will make a series of services available through the WiFi / Ethernet ports, while using any later USB connection only as a power source for topping up the internal battery of about 3000 mAh.
The SoC is rated for a typical power load of about 3W, to which the hard-disk consumption must be added - see below. If the chemistry would be a standard 3.7 V one, we would have 3.7*3=11.1 Wh of energy, or little more than 2 hours of continuous, standalone use once the top disk load of about 2 W is also accounted for.
Notice that while the hard-disk is properly spinned down after 3 minutes of uninterrupted idle, the default kernel appears to be compiled without any power management support, see below. Longer running time than the advertised 5 hours may be achievable.
The SoC is rated for a typical power load of about 3W, to which the hard-disk consumption must be added - see below. If the chemistry would be a standard 3.7 V one, we would have 3.7*3=11.1 Wh of energy, or little more than 2 hours of continuous, standalone use once the top disk load of about 2 W is also accounted for.
Notice that while the hard-disk is properly spinned down after 3 minutes of uninterrupted idle, the default kernel appears to be compiled without any power management support, see below. Longer running time than the advertised 5 hours may be achievable.
Hardware description and default working modes:
The internal hard-disk seems to be a Seagate / Samsung part:# hdparm -I /dev/sdb:
[...]
Model Number: ST1000LM024 HN-M101MBB
[...]
... which should have the following specifications:
- Form factor: 2.5", 9.5mm
- Rotation speed: 5400rpm
- Cache: 8MB
- Power consumption: 2.20W (load), 0.70W (idle)
- Loudness: 26dB(load), 24dB (idle)
- SMART feature set: supported.
- When driven in standalone mode, from the embedded SoC Linux system:
# hdparm -tT /dev/sda
/dev/sda:
Timing cached reads: 114 MB in 2.03 seconds = 56.21 MB/sec
Timing buffered disk reads: 28 MB in 3.10 seconds = 9.04 MB/sec - When driven from the USB bridge mode, from an external PC:
[...]
The internal SoC is very flexible, if somehow resources -limited.
The devices uses a Ralink RT5350 MIPS24 KEc (cat /proc/cpuinfo: MIPS 24 Kc V4.12, corresponding to gcc -march=24kec switch, see below) with 32MiB of RAM, in a little-endian layout. As remarked here, this particular CPU variant lacks a hardware floating point unit (FPU), which has to be emulated in software. This is fine for the current deployment as portable NAS unit, or for the other common usage in routers etc. More demanding mathematical tasks, such as video compression in IP cameras etc., are based on variant with FPU included.
Some device -specific details are also tabulated on https://wikidevi.com/wiki/Intenso_Memory_2_Move_1TB_White.
Some device -specific details are also tabulated on https://wikidevi.com/wiki/Intenso_Memory_2_Move_1TB_White.
Default services in the stock firmware ver. 1.1 are based on ulibc (the system will also re-create, if needed, and use an extra 64MiB of swap as a rather inefficient ".vst/swapfile" on the first VFAT/NTFS partition /dev/sda1 of the internal hard-disk) and include:
- minidlna: DLNA (via UPnP) multimedia files serving, for instance to clients such as Android WonderShare player or Apple IOS analogus;
- smbd: SMB protocol support for filesystem access from Microsoft Windows / Apple OSX / Linux;
- lighttpd: HTTP protocol support for configuration and/or filesystem access from standard browsers
- ...
Source code for all the GPL components is available as an archive from the manufacturer, and is mirrored here (MD5SUM: 296fce876c589c181aeabd1dcdcdb127) for convenience.
These notes report on the installation of a complete, if slightly out-of-date, Debian MIPSEL distribution "Lenny". This makes readily available for installation and use all packages listed i.e. here.
The instructions below mitigate the problem by switching off such daemon, and offering instead SSH access with a chosen password instead. This must however be repeated at every reboot, as by default the system starts in insecure mode.
Further notes below document a different attempt to address the issue by rebuilding the embedded Linux firmware. One should consider the security implication of the classic "Trusting trust", and more recent discussions such as this post by Bruce Schneier.
Compiling and running standalone code:
It is possible to develop and cross-compile standalone programs for the default embedded Linux system, working i.e. on a standard x86 Debian PC and just copying the resulting MIPS executables on the device as generic files.
This requires availability of a cross-compilation toolchain. A suitable one for Jessie/Sid may be installed by adding to /etc/apt/sources.list the lines:
# INTENSO MIPS
deb http://www.emdebian.org/debian/ squeeze main
deb http://www.emdebian.org/debian/ squeeze main
Then simply:
apt-get install gcc-4.3-mipsel-linux-gnu
apt-get install gcc-4.3-mipsel-linux-gnu
...will pull in all required dependencies.
A nice example of what can be compiled and run this way is the CLI "Tetris" game by Victor Nilsson.
Installing a full, ready-to-use Debian release:
Better capabilities can be made accessible through installation of a complete Debian environment.
"Lenny" i.e. Debian release 5.0 is the latest release that can run with the stock kernel 2.6.21. This allows in particular easiest and safest deployment on top of the existing firmware, as the whole system can work in a "chroot" jail with no risk of bricking the device.
"Lenny" i.e. Debian release 5.0 is the latest release that can run with the stock kernel 2.6.21. This allows in particular easiest and safest deployment on top of the existing firmware, as the whole system can work in a "chroot" jail with no risk of bricking the device.
Gaining root:
The stock firmware ver. 1.1 (mirrored here for convenience, MD5sum: 8acc9d9bbb8d18d5da2ad6b6a20a043d ) contains a backdoor. To my eyes this is by the way very useful, but an extremely dangerous data securety issue too.
In practice the system will boot in standalone mode with a telnetd daemon running on default port 23, and offering root login with:
username: root
password: 20080826
In practice the system will boot in standalone mode with a telnetd daemon running on default port 23, and offering root login with:
username: root
password: 20080826
The instructions below mitigate the problem by switching off such daemon, and offering instead SSH access with a chosen password instead. This must however be repeated at every reboot, as by default the system starts in insecure mode.
Further notes below document a different attempt to address the issue by rebuilding the embedded Linux firmware. One should consider the security implication of the classic "Trusting trust", and more recent discussions such as this post by Bruce Schneier.
Choosing a suitable Debian version:
After logging in as root through the stock firmware telnet backdoor, the system reveals itself as:
- Processor brand and featurs:
# cat /proc/cpuinfo
system type : Ralink SoC
processor : 0
cpu model : MIPS 24K V4.12
BogoMIPS : 239.61
wait instruction : yes
microsecond timers : yes
tlb_entries : 32
extra interrupt vector : yes
hardware watchpoint : yes
ASEs implemented : mips16 dsp
VCED exceptions : not available
VCEI exceptions : not available
- The physical RAM is:
# free
free
total used free shared buffers cached
Mem: 28008 26028 1980 0 2016 13384 - The kernel version in use is:
# uname -a
Linux M2M 2.6.21 #256 Thu Apr 25 09:35:37 CST 2013 mips GNU/Linux - The default booting arguments were:
# cat /proc/cmdline
console=ttyS1,57600n8 root=/dev/mtdblock8 rootfstype=squashfs quiet
(a serial console should in other words be available for debugging, if interfacing with the appropriate pins on the mainboard); - The default flash memory layout reads:
# cat /proc/mtd
dev: size erasesize name
mtd0: 00800000 00010000 "ALL"
mtd1: 00030000 00010000 "Bootloader"
mtd2: 00010000 00010000 "Config"
mtd3: 00010000 00010000 "Factory"
mtd4: 00180000 00010000 "Kernel_RootFS"
mtd5: 00010000 00010000 "params"
mtd6: 00010000 00010000 "user_backup"
mtd7: 00010000 00010000 "user"
mtd8: 00600000 00010000 "Rootfs
All the above points to the conclusion that a viable option for full Linux environment installation will be Debian 5.0.10 "Lenny", in the little endian "MIPSEL" architecture.
A later, more up-to-date distribution release will not be compatible with the stock firmware kernel.
A later, more up-to-date distribution release will not be compatible with the stock firmware kernel.
Debian root filesystem option 1: As a loopback image within the default hard-disk partion scheme:
Advantages:
- Simplest deployment;
- Safer against unmounting;
- Fairly inefficient I/O, which makes many operations painful to use on the rather resources -starved SoC;
In view of the above considerations, a different installation scheme based on proper hard-disk re-partitioning and ext2 formatting (outlined below) is preferred. In either cases, the first steps of passing through a loopback image are shared, and detailed in the instructions below:
- Prepare and mount an image filesystem to work on:
# dd if=/dev/zero of=/tmp/debianfs bs=1M count=2000
(something smaller than 2GiB may also be sufficient);
# mkfs.ext2 /tmp/debianfs
mount /tmp/debianfs /tmp/db -o loop
(modprobe loop may be required); - Fill the image filesystem with a basic Debian "Lenny" installation:
# apt-get install debootstrap
# debootstrap --foreign --verbose --arch=mipsel lenny /tmp/db/ http://archive.debian.org/debian-archive/debian/
(apt-get install debootstrap may be required); - Transfer the image filesystem to the device:
# umount /tmp/db ; mount -t cifs //10.10.10.254/WiFiDisk1_Volume1/ /mnt -o username=admin
(or just switch the disk off and connect & mount it as USB mass storage, to perform a faster copy); - Log on the stock firmware Linux system through the backdoor:
# telnet 10.10.10.254
(default IP assignment for WiFi connection),
username: root
password: 20080826 - Mount the empty filesystem image to complete the Debian base installation, automatically downloading all the needed "base" packages from the network:
# mount data/UsbDisk1/Volume1/debianfs /mnt/ -o loop
(on a single line:)
# DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt /debootstrap/debootstrap --second-stage
DEBIAN_FRONTEND=noninteractive
(on a single line:)
# DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt dpkg --configure -a - Set up the Debian system network and virtual filesystems: verify that its /etc/resolv.conf points to a proper nameserver, i.e. contains something like:
# cat /mnt/etc/resolv.conf
nameserver 192.168.43.1
...and that these mountpoints are present and properly populated:
# mount none /mnt/proc -t proc
# mount -t sysfs sysfs /mnt/sys/
# mkdir /mnt/dev/pts
# mount -t devpts devpts /mnt/dev/pts/
# mount -t usbfs usbfs /mnt/proc/bus/usb/
Further useful devices may be creted with:
# mknod /dev/sda b 8 0
# mknod /dev/sda1 b 8 1
# mknod /dev/sda2 b 8 2
... and the default VFAT partition may be made visible to the Debian system too with:
# mount /dev/sda1 /mnt/mnt - Set up the correct time zone:
# dpkg-reconfigure tzdata
The command:
# ntpdate-debian
... may later be used for precise NTP clock syncronization. - Install any other needed Debian package as usual. At the very least, a SSH server is advised, such as dropbear:
# apt-get install dropbear - Verify SSH is working:
# netstat -tan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:8200 *:* LISTEN
tcp 0 0 *:netbios-ssn *:* LISTEN
tcp 0 0 *:www *:* LISTEN
tcp 0 0 *:81 *:* LISTEN
tcp 0 0 10.10.10.254:5880 *:* LISTEN
tcp 0 0 192.168.43.246:5880 *:* LISTEN
tcp 0 0 localhost:6010 *:* LISTEN
tcp 0 0 *:microsoft-ds *:* LISTEN
tcp 0 0 10.10.10.254:www 10.10.10.2:56894 ESTABLISHED
tcp 0 0 localhost:81 localhost:3122 TIME_WAIT
tcp6 0 0 [::]:ssh [::]:* LISTEN
tcp6 0 0 10.10.10.254:ssh 10.10.10.2:35305 ESTABLISHED - close the stock firmware backdoor:
# killall telnetd
(the backdoor will be automatically re-opened upon rebooting, until the "rootfs" default initrd squashfs flashed on the NAND memory is customized as per instructions below)
Debian root filesystem option 2: as a standalone ext2 partition within a re-partitioned hard-disk
The stock kernel has been compiled with no more modern filesystem capabilities than "ext2".
Advantages:
Advantages:
- faster;
- slightly safer from accidental erasure when using the system as a dumb USB external disk;
- The stock firmware Linux system is set up to assume that a (ex)VFAT or NTFS partition should be present as /dev/sda1, and be used for all the default standalone device services.
- Create a swap partition. Suggested size is just 64MiB, i.e. twice as big as the physical RAM; for better performances it is best to set it up as close as possible to hard disk cylinder 0, i.e. as /dev/sda2 just after the resized /dev/sda1;
- Create a ext2 partition for the new Debian MIPSEL installation. Suggested size is about 3GBi, as /dev/sda3;
- Create a ext2 partition with the rest of the unallocated space, i.e. as /dev/sda4.
Install the base system:
Same as for the method above. At the end of it, simply copy everything to the desired ext2 partition, such as /dev/sda3 in the scheme above (make sure not to unnecessarily copy bare devices themselves from /dev !).
The following "~/bin/autolog.sh" may be used to semi-automatically boot the Debian system after each device reboot. It assumes the "telnet" client and "expect" interpreter being available, and works through the default firmware ver. 1.1 backdoor:
#!/usr/bin/expect
# Script to deploy the Debian chroot and close the default telnet backdoor.
# Access the backdoor:
spawn "telnet" "10.10.10.254"
expect "M2M login:"
send "root\r"
expect "Password:"
send "20080826\r"
# expect "BusyBox"
expect "#"
# We are in. Switch from the VFAT -hosted swapfile to a swap partition (faster):
send "swapon /dev/sda2\r"
expect "#"
send "swapoff /data/UsbDisk1/Volume1/.vst/swapfile\r"
expect "#"
# Mount the Debian and leftover storage partition. Sync mode is used, even if slower (the SoC offers limited performances anyway, we are limited by it rather than the I/O subsystem) to afford a margin of safety against sudden switching off.
send "mount /dev/sda3 /mnt/ -o sync\r"
send "mount none /mnt/proc -t proc\r"
expect "#"
# Populate the virtual filesystem:
send "mount -t sysfs sysfs /mnt/sys/\r"
expect "#"
# send "mkdir /mnt/dev/pts\r"
send "mount -t devpts devpts /mnt/dev/pts/\r"
expect "#"
send "mount -t usbfs usbfs /mnt/proc/bus/usb/\r"
expect "#"
# Start the chroot. WARNING: no standard services are initialized, this saves resources but breaks some Debian available services assumptions.
send "chroot /mnt /bin/bash\r"
expect "#"
# Before mounting the leftover partition, the Debian fsck.ext2 tool is used to check it for errors in case it has not been properly unmounted before:
send "fsck.ext2 -p -v -C0 /dev/sda4\r"
expect "#"
send "mount /dev/sda4 /home/ -o sync\r"
expect "#"
# Mount everything else may have been configured:
send "mount -a\r"
expect "#"
# Launch the SSH server: either Dropbear (fewer resources) or OpenSSH:
send "/etc/init.d/dropbear start\r"
expect "Starting Dropbear SSH server: dropbear."
# send "/etc/init.d/ssh start\r"
# expect "Starting OpenBSD Secure Shell server: sshd."
# Close this telnet backdoor, leaving only SSH (and other stock firmware services such as UPnP i.e. minidlna, SAMBA i.e. smbd etc.) access:
send "killall telnetd\r"
# interact
Prepare a custom firmware:
Temporary notes, high risk of bricking the device. Proceed with caution! No kernel upgrade has been tried yet, only userspace modifications.Analysis of a stock firmware image and the flashing process:
The following notes apply to the stock firmware ver. 1.1:
$ unzip 1389341356.zip gives a license, and the actual firmware image fw-M2M-1.100.000
fw-M2M-1.100.000 is a peculiar UNIX self-extracting archive.
$ file fw-M2M-1.100.000 returns:
fw-M2M-1.100.000: POSIX shell script executable (binary data)
fw-M2M-1.100.000: POSIX shell script executable (binary data)
$ binwalk fw-M2M-1.100.000 returns:
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
4326 0x10E6 gzip compressed data, was "initrdup", from Unix, last modified: Mon Jul 1 09:44:07 2013, max compression
1539822 0x177EEE LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 65536 bytes
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
4326 0x10E6 gzip compressed data, was "initrdup", from Unix, last modified: Mon Jul 1 09:44:07 2013, max compression
1539822 0x177EEE LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 65536 bytes
[...]
In practice, the first 170 ASCII text lines are a shell script that instruct on how to unpack (and flash) the rest. Following these, we begin with:
tail -n +171 fw-M2M-1.100.000 > upfs.gz
which gives:
$ file upfs.gz
upfs.gz: gzip compressed data, was "initrdup", last modified: Mon Jul 1 09:44:07 2013, max compression, from Unix
upfs.gz: gzip compressed data, was "initrdup", last modified: Mon Jul 1 09:44:07 2013, max compression, from Unix
$ gunzip upfs.gz
gives a upfs file, which is a standard ext2 filesystem image:
$ file upfs
upfs: Linux rev 1.0 ext2 filesystem data, UUID=48ee846c-1fa2-4ad2-a3d0-692446b63b1f
upfs: Linux rev 1.0 ext2 filesystem data, UUID=48ee846c-1fa2-4ad2-a3d0-692446b63b1f
This can be mounted as loopback device for further analysis:
# mount upfs initdup/ -o loop
initdup# ls -l
total 15
drwxr-xr-x 2 root root 2048 Mar 21 2013 bin
drwxr-xr-x 3 root root 1024 Jul 15 2012 boot
drwxr-xr-x 3 root root 1024 Jul 15 2012 config
drwxr-xr-x 5 root root 1024 Jul 15 2012 dev
drwxr-xr-x 2 root root 1024 Jun 9 2013 etc
drwxr-xr-x 2 root root 1024 Jul 1 2013 firmware
drwxr-xr-x 5 root root 2048 Jul 15 2012 lib
drwxr-xr-x 3 root root 1024 Jul 15 2012 mnt
drwxr-xr-x 2 root root 1024 Jul 15 2012 proc
drwxr-xr-x 2 root root 1024 Jul 15 2012 sys
-rwxr-xr-x 1 root root 1151 Nov 21 2012 update.sh
drwxr-xr-x 5 root root 1024 Jul 15 2012 var
total 15
drwxr-xr-x 2 root root 2048 Mar 21 2013 bin
drwxr-xr-x 3 root root 1024 Jul 15 2012 boot
drwxr-xr-x 3 root root 1024 Jul 15 2012 config
drwxr-xr-x 5 root root 1024 Jul 15 2012 dev
drwxr-xr-x 2 root root 1024 Jun 9 2013 etc
drwxr-xr-x 2 root root 1024 Jul 1 2013 firmware
drwxr-xr-x 5 root root 2048 Jul 15 2012 lib
drwxr-xr-x 3 root root 1024 Jul 15 2012 mnt
drwxr-xr-x 2 root root 1024 Jul 15 2012 proc
drwxr-xr-x 2 root root 1024 Jul 15 2012 sys
-rwxr-xr-x 1 root root 1151 Nov 21 2012 update.sh
drwxr-xr-x 5 root root 1024 Jul 15 2012 var
The "update.sh" script does the flashing of the MTD NAND, as directed by its numerical argument. In particular, it takes versioning informations, the kernel binary, its rootfs and the U-Boot bootloader from the "firmware" subdirectory:
# cat firmware/firmware.conf
NEWFILE=M2M
NEWVER=1.100.000
NEWBUILD=7
NEWFILE=M2M
NEWVER=1.100.000
NEWBUILD=7
# file firmware/kernel
firmware/kernel: u-boot legacy uImage, Linux Kernel Image, Linux/MIPS, OS Kernel Image (lzma), 1439867 bytes, Thu Apr 25 03:35:52 2013, Load Address: 0x80000000, Entry Point: 0x8043F000, Header CRC: 0x6A7044ED, Data CRC: 0x652C3C28
firmware/kernel: u-boot legacy uImage, Linux Kernel Image, Linux/MIPS, OS Kernel Image (lzma), 1439867 bytes, Thu Apr 25 03:35:52 2013, Load Address: 0x80000000, Entry Point: 0x8043F000, Header CRC: 0x6A7044ED, Data CRC: 0x652C3C28
The first difficulty appears in interpreting the firmware/rootfs file. At first its magic is not recognized:
# file firmware/rootfs
firmware/rootfs: data
firmware/rootfs: data
but binwalk reveals:
# binwalk firmware/rootfs
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
0 0x0 Squashfs filesystem, little endian, non-standard signature, version 3.0, size: 5167458 bytes, 926 inodes, blocksize: 65536 bytes, created: Mon Jul 1 09:44:02 2013
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
0 0x0 Squashfs filesystem, little endian, non-standard signature, version 3.0, size: 5167458 bytes, 926 inodes, blocksize: 65536 bytes, created: Mon Jul 1 09:44:02 2013
As shown by hexedit, the file begins with "shsq" rather than the usual "hsqs", thus the "non-standard signature" statement. This denotes a LZMA compression scheme with SWAPPED fields, which is not yet supported by Debian "unstable" unsquashfs-tools ver. 1:4.0-8 :
# unsquashfs -h
[...]
Decompressors available:
gzip
lzo
xz
gzip
lzo
xz
To unpack this, a later version of the squashfs tools may be downloaded from SourceForge via GIT (apt-get install git may be needed):
$ git clone git://git.code.sf.net/p/squashfs/code squashfs-code
It must be compiled with the new compression scheme enabled, but also a patch to support this particular deployment.
$ git clone git://git.code.sf.net/p/squashfs/code squashfs-code
It must be compiled with the new compression scheme enabled, but also a patch to support this particular deployment.
- Download a patch from: http://sourceforge.net/p/squashfs/patches/20/, and apply it:
$ git apply --stat ~/Downloads/0001-unsquashfs-add-support-for-LZMA-magics.patch
...will show:
$ cd .. ; git apply --check ~/Downloads/0001-unsquashfs-add-support-for-LZMA-magics.patch
squashfs-tools/squashfs_fs.h | 6 ++++++
squashfs-tools/unsquashfs.c | 24 ++++++++++++++++++------
2 files changed, 24 insertions(+), 6 deletions(-)
... should show no output (i.e. no errors or conflicts, the patch may be applied cleanly);
- Actually apply the patch; either via git, or by hand (removing all lines before:
--- a/squashfs-tools/squashfs_fs.h
+++ b/squashfs-tools/squashfs_fs.h , and issuing a simple:
patch -p1 < 0001-unsquashfs-add-support-for-LZMA-magics.patch ) - Edit the squashfs-tools/Makefile and make sure that it reads (apt-get install liblzma-dev may be needed):
[...]
########### Building XZ support #############
#
# LZMA2 compression.
#
# XZ Utils liblzma (http://tukaani.org/xz/) is supported
#
# To build using XZ Utils liblzma - install the library and uncomment
# the XZ_SUPPORT line below.
#
XZ_SUPPORT = 1
[...]
and further below:
[...]
########### Building LZMA support #############
#
# LZMA1 compression.
#
# LZMA1 compression is deprecated, and the newer and better XZ (LZMA2)
# compression should be used in preference.
#
# Both XZ Utils liblzma (http://tukaani.org/xz/) and LZMA SDK
# (http://www.7-zip.org/sdk.html) are supported
#
# To build using XZ Utils liblzma - install the library and uncomment
# the LZMA_XZ_SUPPORT line below.
#
# To build using the LZMA SDK (4.65 used in development, other versions may
# work) - download and unpack it, uncomment and set LZMA_DIR to unpacked source,
# and uncomment the LZMA_SUPPORT line below.
#
LZMA_XZ_SUPPORT = 1
#LZMA_SUPPORT = 1
[...] - Alternatively, an archive of the patched & configured snapshot of the tools is made available here. Simply unpack and issue a:
make
# unsquashfs -li /tmp/initdup/firmware/rootfs
For instance, the default passwords for the "admin" user, and the "root" backdoor may be brute-forced via John the Ripper (apt-get install john may be needed):
# john etc/passwd
Created directory: /root/.john
Loaded 2 password hashes with 2 different salts (md5crypt [MD5 32/64 X2])
Press 'q' or Ctrl-C to abort, almost any other key for status
00000 (admin)
Created directory: /root/.john
Loaded 2 password hashes with 2 different salts (md5crypt [MD5 32/64 X2])
Press 'q' or Ctrl-C to abort, almost any other key for status
00000 (admin)
This will be the default configuration password for the stock firmware HTTP interface.
Some additional information for this firmware release can be found in the etc/versioninfo file:
[...]
uboot=5350/bootloader-mt5350-32M-2013-04-25-09-25.img
kernel=5350/kernel-rt5350-32M-2013-04-25-09-31
... which would point to a Ralink 5350 part running at 360MHz, and confirming availability of 32MiB RAM.
Customizing a stock firmware image:
When rootfs modifications are satisfactory, the new filesystem can be re-squashed via:mksquashfs . ../new_rootfs -comp lzma
The mksquashfs compiled above, or the default Debian "Jessie" ver. 4.0, will however not be suitable for re-compressing the image before flashing. Besides compressor support for other algorithms such as LZMA, the squashfs binary format has been changed before vanilla kernel inclusion, and is not backwards compatible with the patched support of stock firmware kernel ver. 2.6.21, which will not mount our new new_rootfs file with error message:
SQUASHFS error: Major/Minor mismatch, trying to mount newer 4.0 filesystem
SQUASHFS error: Please update your kernel
Upgrading kernel at the same time as the root filesystem on an embedded system is risky, we may lose all access to the device if something goes wrong.
We can however simply produce a vintage format of our modified rootfs, using obsolete versions of the mksquashfs as available from i.e. the Debian archive. After unpacking the original firmware rootfs through the patched, latest unsquashfs v4.0, it doesn't really matter if the new, modified rootfs will be compressed via gzip rather than the more space efficient LZMA method.
The mksquashfs utility compiled from squashfs_3.1r2.orig.tar.gz works:
# mksquashfs squashfs-root/ new_rootfs_v3.1_format
...gives a file in the older ver.3.0 format:
$ binwalk new_rootfs_v3.0_format
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
0 0x0 Squashfs filesystem, little endian, version 3.0, size: 6043973 bytes, 920 inodes, blocksize: 65536 bytes, created: Fri May 30 17:14:40 2014
...which the stock firmware kernel ver. 2.6.21 can mount without problems, for instance as loopback filesystem just for testing before flashing:
# mount /mnt/new_rootfs_v3.0_format /opt/ -o loop
M2M:/# ls /opt/
bin boot data dev etc etc_ro home lib media mnt opt proc sbin sys tmp usr var www
The standard magic "hsqs" header will now denote in particular reliance on the older, less efficient compression algorithm.
When all customizations are satisfactory, the "new_rootfs" can replace the original "firmware/rootfs":
$ mv new_rootfs_v3.0_format firmware/rootfs
The whole pre-flashing filesystem can then be unmounted:
# umount initdup
...and re-compressed via gzip:
# gzip initdup
As a last step a self-extracting firmware file has to be created. In particular, the modified ext2 initdup.gz payload will have a different CRCSUM, as computed by the standard 'cksum' utility after some file massaging by sed.
Following the original firmware file scripted lines, the checksum is computed as:
$ sed '1,3d' fw-M2M-1.100.000 |cksum|sed -e 's/ /Z/' -e 's/ /Z/'|cut -dZ -f1
3696346624
... which matches the expected value as listed within the self-extracting archive:
$ head fw-M2M-1.100.000
#!/bin/sh
# constant
CRCSUM=3696346624
[...]
The new self-extracting firmware can be assembled as follows:
- Extract the unpacking and flashing script lines:
$ head -n 170 fw-M2M-1.100.000 > self_extracting_fw_header.sh - Prepare a temporary firmware (complete payload, but still invalid CRCSUM) with:
$ cp self_extracting_fw_header.sh self_extracting_fw.sh
$ cat upfs.gz >> self_extracting_fw.sh - Compute the valid CRCSUM via:
$ sed '1,3d' self_extracting_fw.sh |cksum|sed -e 's/ /Z/' -e 's/ /Z/'|cut -dZ -f1
...and replace the resulting value inside the new self_extracting_fw.sh file.
Normally, more than a single iteration can be required: the CRCSUM field is also part of the file content, for which the CRC is calculated, hence it changes as the field is updated. Such CRC calculation procedure is however a sort of lossy compression scheme. As such, modification of a few bytes, like the CRCSUM=... constant, will not change the outcome dramatically. Recalculation a second time is typically sufficient; just repeat this step 3) until the check value is stable and matches the file content.
Building a complete alternative:
A custom embedded Linux image may be assembled ("backed", in Android jargon...) via the BuildRoot system. This allows a great amount of customization, as it provides a set of rules and Makefiles to download, configure and cross-compile only the needed package and specifically supporting the device hardware, for a more efficient usage of the available SoC resources.
Apparently, Ralink also provides a customized BuildRoot SDK. A mirror copy of ver. 4.0.1.0 (including a more recent, but patched for a later board, Linux kernel 2.6.36 besides an older, patched ver. 2.6.21) is available for download for instance here.
The SDK above still needs an external cross-compilation toolchain. The oldish kernel version provided looks in particular not compatible with later GCC developments, such as ver. 4.4 included in the above MIPS(el) toolchain.
It would fail with error:
CHK include/linux/version.h
CHK include/linux/utsrelease.h
CC arch/mips/kernel/asm-offsets.s
arch/mips/kernel/asm-offsets.c: In function 'output_mm_defines':
arch/mips/kernel/asm-offsets.c:233: error: invalid 'asm': invalid use of '%X'
arch/mips/kernel/asm-offsets.c:234: error: invalid 'asm': invalid use of '%X'
arch/mips/kernel/asm-offsets.c:235: error: invalid 'asm': invalid use of '%X'
/tmp/rt5350_GPL_source/kernel/linux-2.6.21.x/./Kbuild:42: recipe for target 'arch/mips/kernel/asm-offsets.s' failed
make[1]: *** [arch/mips/kernel/asm-offsets.s] Error 1
Makefile:863: recipe for target 'prepare0' failed
make: *** [prepare0] Error 2
It seems the SDK refers to a specific GCC version, gcc-3.4.2. This is available from a study of another Ralink -based product, the Coolcam NIP-09 NIP-02, also based on the RT5350 (in the F = FPU variant). And also, by the way, including a telnet backdoor! (username: root, password: 123456) and is mirrored here for convenience.
Instructions on how to use the SDK and toolchain are available from here, and have been also mirrored here for convenience. In practice, the content of buildroot-gcc342.tar.bz2 should be placed within /opt, and one may issue:
$ export MANPATH=$MANPATH:/opt/buildroot-gcc342/man
... to furthermore have access to the included manpages.
Another, slightly more up-to-date version of the SDK (ver. 4.1.1.0) has been also made available online, and is mirrored for convenience here (including compiler toolchain etc.).
Further packages which may require installation are, for instance:
# apt-get install flex bison
... and so on, as per list of dependencies.
LZMA compression:
- Beside that toolchain, a (patched up) standalone LZMA compressor is also needed, if one wants to follow the default SDK build process. It seems slightly different from this version, and should be provided as part of the RT288X_SDK for instance. The utility "lzma_alone" must be compiled and placed in /opt/buildroot-gcc342/bin/
- Alternatively, it seems possible to switch to the older, less space efficient but far more established gzip compression scheme. The crucial stage where the rootfs is compressed, as part of the kernel building process, is controlled by the scrip linux-2.6.21.x/scripts/gen_initramfs_list.sh, which can be modified not to use the (vendor -patched) lzma_alone compressor by changing interpretation of option use_lzma to "n":
[...]
"-l")
use_lzma="n"
;;
[...]
$ make menuconfig
... command (apt-get install libncurses5-dev may be needed) and press Enter on the "Select the Product you wish to target", then select "Ralink Products", and "RT5350". Then select "Default configuration file" and choose "4M/32M(AP+NAS), and exit repeteadly.
The item "Kernel/Library/Defaults Selection" allows to change what cross-compiler chain to use, which parts of the BuildRoot distribution will be included in the firmware, which libc will these linked with, and which Linux kernel should drive the whole.
Even if no parameters will at first be changed, it is crucial to let BuildRoot scripted process take care of setting up the right cross-compiler toolchain in all subdirectory. This can be achieved by selecting for customization all the fields:
- Customize Kernel Settings
- Customize Vendor/User Settings
- Customize Busybox Settings
- Customize uClibc Settings
- Customize uClibc++ Settings
Once happy with all selection, save and exit the main menuconfig interface, and issue a simple:
# make
The build will take a few minutes but succeed without errors. The (safer) default BuildRoot behaviour has been modified in the SDK version, so as to try and create device files too under /dev in the rootfs. This will fail if the user is not root.
The outcome is stored in the images/ subdirectory, and attempts are made to also copy it as a /tftboot file in the host root filesystem (!). In particular, even after swiching off usage of the lzma_alone utility, a images/zImage.lzma file gets created and may be decompressed via:
$ unlzma ralink_sdk-master/source/images/zImage.lzma
Again binwalk provides better insight on its content:
$ binwalk zImage
$ binwalk zImage
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
752777 0xB7C89 LZMA compressed data, properties: 0x88, dictionary size: 1048576 bytes, uncompressed size: 4608 bytes
940089 0xE5839 LZMA compressed data, properties: 0x38, dictionary size: 1048576 bytes, uncompressed size: 4160 bytes
950753 0xE81E1 LZMA compressed data, properties: 0x30, dictionary size: 524288 bytes, uncompressed size: 992 bytes
2261044 0x228034 Linux kernel version "2.6.21 (root@t420) (gcc version 3.4.2) #2 Sat May 31 21:56:45 C 3.4.2) #2 Sat May 31 21:56:45 CEST 2014CEST 2014"
2267836 0x229ABC LZMA compressed data, properties: 0x02, dictionary size: 16777216 bytes, uncompressed size: 50331648 bytes
2424580 0x24FF04 ASCII cpio archive (SVR4 with no CRC), file name: "sh entry"
2875460 0x2BE044 LZMA compressed data, properties: 0x02, dictionary size: 16777216 bytes, uncompressed size: 512 bytes
2875541 0x2BE095 LZMA compressed data, properties: 0x02, dictionary size: 131072 bytes, uncompressed size: 33620481 bytes
2887043 0x2C0D83 LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 32 bytes
2887067 0x2C0D9B LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887259 0x2C0E5B LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887283 0x2C0E73 LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887307 0x2C0E8B LZMA compressed data, properties: 0x31, dictionary size: 65536 bytes, uncompressed size: 32 bytes
2887331 0x2C0EA3 LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887355 0x2C0EBB LZMA compressed data, properties: 0x31, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887379 0x2C0ED3 LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887427 0x2C0F03 LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887451 0x2C0F1B LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887475 0x2C0F33 LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887499 0x2C0F4B LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887523 0x2C0F63 LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 256 bytes
2892036 0x2C2104 LZMA compressed data, properties: 0x01, dictionary size: 131072 bytes, uncompressed size: 2 bytes
2892136 0x2C2168 LZMA compressed data, properties: 0x09, dictionary size: 131072 bytes, uncompressed size: 2 bytes
2892156 0x2C217C LZMA compressed data, properties: 0x0A, dictionary size: 131072 bytes, uncompressed size: 2 bytes
2894087 0x2C2907 LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894107 0x2C291B LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894127 0x2C292F LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894147 0x2C2943 LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894167 0x2C2957 LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894187 0x2C296B LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2905944 0x2C5758 LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 16777473 bytes
3084288 0x2F1000 gzip compressed data, from Unix, last modified: Sat May 31 21:56:39 2014, max compression
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
752777 0xB7C89 LZMA compressed data, properties: 0x88, dictionary size: 1048576 bytes, uncompressed size: 4608 bytes
940089 0xE5839 LZMA compressed data, properties: 0x38, dictionary size: 1048576 bytes, uncompressed size: 4160 bytes
950753 0xE81E1 LZMA compressed data, properties: 0x30, dictionary size: 524288 bytes, uncompressed size: 992 bytes
2261044 0x228034 Linux kernel version "2.6.21 (root@t420) (gcc version 3.4.2) #2 Sat May 31 21:56:45 C 3.4.2) #2 Sat May 31 21:56:45 CEST 2014CEST 2014"
2267836 0x229ABC LZMA compressed data, properties: 0x02, dictionary size: 16777216 bytes, uncompressed size: 50331648 bytes
2424580 0x24FF04 ASCII cpio archive (SVR4 with no CRC), file name: "sh entry"
2875460 0x2BE044 LZMA compressed data, properties: 0x02, dictionary size: 16777216 bytes, uncompressed size: 512 bytes
2875541 0x2BE095 LZMA compressed data, properties: 0x02, dictionary size: 131072 bytes, uncompressed size: 33620481 bytes
2887043 0x2C0D83 LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 32 bytes
2887067 0x2C0D9B LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887259 0x2C0E5B LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887283 0x2C0E73 LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887307 0x2C0E8B LZMA compressed data, properties: 0x31, dictionary size: 65536 bytes, uncompressed size: 32 bytes
2887331 0x2C0EA3 LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887355 0x2C0EBB LZMA compressed data, properties: 0x31, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887379 0x2C0ED3 LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887427 0x2C0F03 LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887451 0x2C0F1B LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887475 0x2C0F33 LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887499 0x2C0F4B LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887523 0x2C0F63 LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 256 bytes
2892036 0x2C2104 LZMA compressed data, properties: 0x01, dictionary size: 131072 bytes, uncompressed size: 2 bytes
2892136 0x2C2168 LZMA compressed data, properties: 0x09, dictionary size: 131072 bytes, uncompressed size: 2 bytes
2892156 0x2C217C LZMA compressed data, properties: 0x0A, dictionary size: 131072 bytes, uncompressed size: 2 bytes
2894087 0x2C2907 LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894107 0x2C291B LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894127 0x2C292F LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894147 0x2C2943 LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894167 0x2C2957 LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894187 0x2C296B LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2905944 0x2C5758 LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 16777473 bytes
3084288 0x2F1000 gzip compressed data, from Unix, last modified: Sat May 31 21:56:39 2014, max compression
The crucial information is at the end. As a result of the gen_initramfs_list.sh script modification, the rootfs archive has been appended at the end of the file in gzip format. It can be extracted for verification by skipping all preceeding parts of the file:
$ dd if=zImage of=rootfs_recomp.gz seek=3084288 bs=1
and simply:
$ gunzip rootfs_recomp.gz
... to reveal a standard CPIO archive:
$ file rootfs_recomp
rootfs_recomp: ASCII cpio archive (SVR4 with no CRC)
rootfs_recomp: ASCII cpio archive (SVR4 with no CRC)
As per standard Linux kernel documentation, this can be opened via:
$ cpio -i -d -H newc -F rootfs_recomp --no-absolute-filenames
(again, attempts at creating special /dev files will fail, without root permission)
In other words, we should be able to check that this SDK -recompiled CPIO archive of a rootfs matches the stock firmware "firmware/rootfs" ext2 image, which is itself normally shipped within the initrdup.gz payload of a ready-to-flash self-extracting firmware file.
This allows to upgrade the userspace parts of the embedded Linux environment, without changing yet the default kernel. It is possible in particular to close the default telnet backdoor; add other packages such as i.e. like the Snort NIDS to better monitor the network; and provide i.e. a out-of-the-box dropbear SSH server for better local access security.
One problem with the old GCC toolchain that Ralink SDK would use by default is lack of support for better CPU optimization. Contrary to the more up-to-date compiler that even Debian "Lenny" ships, GCC ver. 3.4.2 supports at most a:
-mips32r2 -O3
... optimized build target, thereby not really exploiting more advanced capabilities of the SoC MIPS_24KEc processor.
Another alternative worthy considering would be plain adoption of an embedded Linux distribution such as OpenWRT, see for instance their useful explanation of the flash memory layout.
Support for the base mainboard was added with this commit, and compatibility with the hardware should only improve with time, as it is officially adopted for further deployments of Ralink RT5350 "router on a chip" such as this one.
Extra safety before flashing firmware from a completely different codebase would suggest first gaining access to the "Das U-Boot" bootloader serial console (and before that, the Linux getty login which appears running in the standard firmware), by opening the device as illustrated here, and connecting a TTL <-> 5V level converting serial cable to the appropriate pins. One suitable adapter should be for instance the very common, USB-ready CP2102 module, or clones.
[...continues...]
Cool tricks:
Access through SSH:
- SSH client for various Windows versions: try PuTTY;
- Konqueror "FISH" sshfs -lookalike access: just use fish://root@10.10.10.254/ address in the address bar;
- Automatic, incremental backup (Apple "Time Capsule" -alike functionality) via Back In Time, relying on the rsync protocol to reduce network traffic, SSH for data encryption during the transfer, and ext2 hard-links (as opposed to the cruder VFAT capabilities) to save disk space by only storing changes.
"Back In Time" and rsync in particular would also work, with the stock firmware and through the SAMBA interface, making the exported VFAT partition accessible on Linux via a CIFS mountpoint. This introduces however extra overhead.
Non-interactive, safe SSH access may be configured with public key authentication.
Non-interactive CIFS access from a Linux system to the default /dev/sda1 partition made available through the SMB daemon may be set up with the "/etc/fstab" line:
//10.10.10.254/WiFiDisk1_Volume1/ /mnt/M2M_Backup cifs credentials=/home/[USERNAME]/.smbcredentials,users,iocharset=utf8,sec=ntlm,noauto 0 0
... which points to the /home/[USERNAME]/.smbcredentials file (with Samba crentials in clear text!):
username=admin
password=[password chosen through the unit HTTP interface]
It is sufficient to include the appropriate APT source line in /etc/apt/sources.list:
[...]
deb-src http://archive.debian.org/debian-archive/debian/ lenny main contrib non-free
[...]
... getting sources (and build dependencies) via:
apt-get source [packagename]
The package compilation flags may be changed within its debian/rules file, and a customized version prepared via:
dpkg-buildpackage -b
therefore installing the resulting pacakgename.deb via:
dpkg -i packagename.deb
...as usual. Since the "Lenny" distribution suggested above is in "Archived" status, there will not be later package revisions from the central repository to overcome local preferences.
Alternatively, the more complete apt-build solution may also be used.
Even with these optimization, the choking point in network backups appears to be the SSH server. The embedded CPU is just not powerful enough to handle on-the-fly strong encryption at the speed otherwise supported by the WiFi network, or the local hard-disk.
Using "Back in Time" CLI interface shows:
$ backintime --benchmark-cipher 20
Back In Time
Version: 1.0.34
Back In Time comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type `backintime --license' for details.
create random data file
20+0 records in
20+0 records out
20971520 bytes (21 MB) copied, 1.61118 s, 13.0 MB/s
$ rsync --daemon --no-detach --port=2000 -vvv --config=rsyncd.conf
and benchmarked from the client with:
Non-interactive CIFS access from a Linux system to the default /dev/sda1 partition made available through the SMB daemon may be set up with the "/etc/fstab" line:
//10.10.10.254/WiFiDisk1_Volume1/ /mnt/M2M_Backup cifs credentials=/home/[USERNAME]/.smbcredentials,users,iocharset=utf8,sec=ntlm,noauto 0 0
... which points to the /home/[USERNAME]/.smbcredentials file (with Samba crentials in clear text!):
username=admin
password=[password chosen through the unit HTTP interface]
Package recompilation with enhanced CPU support:
Even without switching to a fully custom firmware via i.e. BuildRoot above, some critical Debian packages may easily be recompiled on the unit itself with optimization options better geared to the available hardware. Options:
-O3 -march=24kec -mdsp -mips32r2
... show some speedup.
It is sufficient to include the appropriate APT source line in /etc/apt/sources.list:
[...]
deb-src http://archive.debian.org/debian-archive/debian/ lenny main contrib non-free
[...]
... getting sources (and build dependencies) via:
apt-get source [packagename]
The package compilation flags may be changed within its debian/rules file, and a customized version prepared via:
dpkg-buildpackage -b
therefore installing the resulting pacakgename.deb via:
dpkg -i packagename.deb
...as usual. Since the "Lenny" distribution suggested above is in "Archived" status, there will not be later package revisions from the central repository to overcome local preferences.
Alternatively, the more complete apt-build solution may also be used.
Even with these optimization, the choking point in network backups appears to be the SSH server. The embedded CPU is just not powerful enough to handle on-the-fly strong encryption at the speed otherwise supported by the WiFi network, or the local hard-disk.
Using "Back in Time" CLI interface shows:
$ backintime --benchmark-cipher 20
Back In Time
Version: 1.0.34
Back In Time comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type `backintime --license' for details.
create random data file
20+0 records in
20+0 records out
20971520 bytes (21 MB) copied, 1.61118 s, 13.0 MB/s
- 3des-cbc: 20MB 585.1KB/s 00:35
20MB 640.0KB/s 00:32 - aes128-cbc: 20MB 1.1MB/s 00:19
20MB 1.1MB/s 00:18 - aes256-cbc: 20MB 1.1MB/s 00:18
20MB 1.1MB/s 00:19 - blowfish-cbc: 20MB 1.1MB/s 00:18
20MB 1.1MB/s 00:18
$ rsync --daemon --no-detach --port=2000 -vvv --config=rsyncd.conf
and benchmarked from the client with:
- Highest compression, no SSH:
$ time rsync -vvv -az --compress-level=9 /tmp/re rsync://m2m:2000/pub
sent 20,983,554 bytes received 34 bytes 1,678,687.04 bytes/sec
total size is 20,971,520 speedup is 1.00
[sender] _exit_cleanup(code=0, file=main.c, line=1183): about to call exit(0)
real 0m11.875s - No compression, no SSH:
$ time rsync -vvv -a /tmp/re rsync://m2m:2000/pub
sent 20,976,730 bytes received 34 bytes 1,824,066.43 bytes/sec
total size is 20,971,520 speedup is 1.00
[sender] _exit_cleanup(code=0, file=main.c, line=1183): about to call exit(0)
real 0m11.107s - No compression, SSH (twice as slow!):
$ time rsync -vvv -e ssh /tmp/re m2m:/tmp/testrsync
sent 20,976,707 bytes received 437 bytes 975,681.12 bytes/sec
total size is 20,971,520 speedup is 1.00
[sender] _exit_cleanup(code=0, file=main.c, line=1183): about to call exit(0)
real 0m21.642s
What a faschinating write down.
ReplyDeleteI bought this device by Chance two saturdays ago and have since then been looking for a way to open it up and "hack" it.
I also saw the same enclosing somewhere online without a disk and there it was mentioned that once you build in a disk and close it, you cannot open it again without damage.
So i was afraid i might never see and debug its UART-Interface without damaging it.
Your Blog Post gives me the hope that i might have fun tinkering with this nice litte Gadget.
Would you eventually help me if i had questions when trying to build the chroot stuff and using apt-get to install and run my favourite Debian CLI apps on it?
Did you actually work with the intenso Team that designed and implemented it or are you just a versatile binwalk-Soc-Firmware-Analyst-or-engineer?
Thanks for the comment; the writeup is unfortunately still rather messy.
ReplyDeleteI've only played a bit with the device; I haven't physically opened it yet, and can't comment on how hard to put it back together may be. I may proceed to do that in order to physically connect to the serial port, and really get U-Boot prompt menu for debugging when trying a new kernel.
On the software side things are a bit scattered around, and you should be careful not to mess up with basic functionality. However it can be fun to tinker, and the backdoor left by the company should really be closed. Keep in mind that Lenny is a retired Debian version, not receiving securty updates any more, while a more up-to-date kernel would allow to use a more recent, properly maintained release.
I can try to help if you have specific questions but I've only tried to understand a little how the device works on my own, as a hobby. I can't offer any guarantee things would work the same way for others too. But it can be instructive; have fun!
Wow... This is fantastic work. I have to try it out myself ... actually all that I wanted to do seems possible now. Bravo ;-)
ReplyDeleteThanks, just some tinkering and looking around. Somebody with real OpenWRT experience could probably help a lot.
ReplyDeleteI'm waiting for a TTL-to-serial levels converter over USB to arrive, then I'll try to open the case, and connect to the serial port which should be there: it would allow to follow the stock firmware boot process, and actually upgrade the kernel with some degree of fail-safe.
If you do carry on with your own tests, please do let us know how they go!
Hijo, .... looking forward to read about your progress with the fail-safe kernel upgrade . And as soon I manage to replicate what you did (which could take some time :-P), I will certainly share whatever i find out on the way.
DeleteGood trick!
ReplyDeleteThere is indeed a CRC check, be careful with new firmwares creation (see notes). However is pretty easy to get into a hash collision scenario, the payload is big with respect to small changes of few bytes.
When I reflash, I typically have to do a couple of CRC passes or so, to find a "stable" CRC that can be included inside the file for which it is itself computed, and still not be sensitive to the variation (think of it as if it were a sort of lossy compression scheme...). It also means however, that a slightly corrupted firmware also has high changes not to trigger the CRC validation, thus bricking the device.
Have fun, happy hacking!
I suppose one way to conceive checksumming is along lossy compression. Think of it like this: you could double check that a payload is not corrupted, by uploading it twice and asking both copies to be identical, before flashing one.
ReplyDeleteThen you could compress the second copy in a non-lossy way: it would occupy less space, but still give you full redundancy.
Then you could compress it in a lossy way: it would occupy arbitrarily less space, down to the handful of bytes used for the CRC string, and give correspondingly less and less redundancy. An extreme case would be using a single bit for validation, 0 or 1, corresponding to have an even or odd total number of bits set to 1 in the payload: in such example, two completely different payloads with the same bit parity would both pass the validation test, or in other terms generate a hash collision.
The CRC in use in not so crude, but not too advanced either. It has few bits alltogether to keep track of a relatively big payload. If you change it only a little bit, you can "get lucky". Or if you proceed with the checksum calculation a few times until stability as in the quick notes above, what you're actually doing is to crudely deploy dynamical systems theory to identify a fixed point, see for instance the quick notes here: http://www2.maths.ox.ac.uk/chebfun/examples/veccalc/html/DynamicalSystems.shtml
This should be a pretty general way to put the problem, in practice the solution is so easy to find because of the crude implementation adopted as hash function.
The checksum function in use is a combination of sed handling case etc., and the cksum UNIX utility, see above. In practice, you can compute it from a shell via:
ReplyDelete$ sed '1,3d' PAYLOAD |cksum|sed -e 's/ /Z/' -e 's/ /Z/'|cut -dZ -f1
I am still waiting for a USB TTL-to-serial interface to arrive, I'd like to really monitor the boot process. Have you ever tried to open the device case, can you comment perhaps on possible screws location / other interlock mechanisms?
Thanks for the tips on opening the case!
ReplyDeleteToday I've received the cheap CP2102 USB-to-TTL serial adapter I was waiting for (about 2 Eur via Amazon), and could indeed open the device, find the appropriate pads on the circuit board, solder some pins and gain serial access.
I'll put down some more notes when time allows to play a bit more. In practice, I can confirm there is a UART interface, easy to access through the 4 pads close to the battery, where +Vcc 3.3 Vdc is the square one, to its left lies Rxc, then Txc, then Gnd.
Here the booting process dumps all its debug informations, and at the end a standard "getty" is waiting for log in. The default root account and password works there too.
Happy hacking!
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHi,
ReplyDeleteI have Verbatim Mediashare device. It has one USB and one SDCARD slot. It has a web interface and Android interface to manage content via Wifi.
I have connected a usb splitter. When I connect only one Flashdisk it works fine (like without splitter).
When I connect two flash drives I see two drives but I see the last attached drive two times.
I logged into with telnet as root and have checked the mounting.
It looks like the following
/dev/sda1 /data/UsbDisk2/Volume1
/dev/sdb1 /data/USbDisk2/Volume1
I have remove the last mount and I have remounted a last one like:
/dev/sdb1 /data/UsbDisk3/Volume1
From command like the both mounting works well. I can copy from the one flash drive to the other the files with bash.
But the GUI does not lising well the two devices.
I have cheked the device /www folder and I have finded a index.js (and more).
for the copy I found the following snippet:
function qCopy(url,target,ov){
var head = {
"Destination":iHost + encodeURL(target),
"Depth":1
};
ov || (head.Overwrite = "F");
qExplor.flag = true;
$.Ajax.load({
ovTime:0,
url: encodeURL(url),
method:"COPY",
dataType:"text",
onCensor:"xx",
callBack:function(){
When I copy one file, the server communication is the following:
Request URL:http://10.10.10.254/data/UsbDisk3/Volume1/img_4121.jpg
Request Method:COPY
Status Code:201 Created
Remote Address:10.10.10.254:80
Response Headers
view source
Content-Length:0
Date:Sat, 31 Dec 2011 16:24:49 GMT
Server:lighttpd/1.4.28-devel-78M
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:hu,en-US;q=0.8,en;q=0.6,de;q=0.4
Connection:keep-alive
Content-Type:application/x-www-form-urlencoded
Cookie:Language=us; SESSID=SPf9Zx78rgWMMDU7AuWS6CwwpDeSftAYhG76d6dEd4iWH
Depth:1
Destination:http://10.10.10.254/data/UsbDisk3/Volume1/dcim/img_4121.jpg
Host:10.10.10.254
Method:COPY /data/UsbDisk3/Volume1/img_4121.jpg HTTP/1.1
Origin:http://10.10.10.254
Overwrite:F
Referer:http://10.10.10.254/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36
for listing the drives I found:
ReplyDelete#SD USB oMain
void function(H){
var iStorage;
function getStorage(){
$.Ajax.getXML("/protocol.csp?fname=storage&opt=listen_disk&function=get",function(flg,v,hq){
if(flg>0){
var storage = {
_text:hq.responseText
},csd,cusb;
var items = $.xjson(v,"item");
storage._items = items;
for(var i = 0,n;i<items.length;i+=1){
n = (items[i].type).toLowerCase().replace(/\s/g,"");
storage[n] = items[i];
}
if(iStorage && iStorage._text != storage._text){
var isd = iStorage.sdcard || iStorage.sdcard1 || iStorage.sdcard2 || iStorage.sdcard3,
sd = storage.sdcard || storage.sdcard1 || storage.sdcard2 || storage.sdcard3;
if(isd && sd){
//两次请求数据都存在,比较两项属性,有差异,说明换卡了
if(isd.name != sd.name || isd.type != sd.type ){
csd = 2;
Msg.prompt(Language.getHTMLValue("HotPlug_SDCard_in"));
}
}
else if(isd){
csd = -1;
Msg.prompt(Language.getHTMLValue("HotPlug_SDCard_out"));
}
else if(sd){
csd = 1;
Msg.prompt(Language.getHTMLValue("HotPlug_SDCard_in"));
}
var iusbmemory = iStorage.usbdisk1 || iStorage.usbdisk2 || iStorage.usbdisk3,
usbmemory = storage.usbdisk1 || storage.usbdisk2 || storage.usbdisk3;
if(iusbmemory && usbmemory){
//两次请求数据都存在,比较两项属性,有差异,说明换卡了
if(iusbmemory.name != usbmemory.name || iusbmemory.type != usbmemory.type ){
cusb = 2;
Msg.prompt(Language.getHTMLValue("HotPlug_USBDevice_in"));
}
}
else if(iusbmemory){
cusb = -1;
Msg.prompt(Language.getHTMLValue("HotPlug_USBDevice_out"));
}
else if(usbmemory){
cusb = 1;
Msg.prompt(Language.getHTMLValue("HotPlug_USBDevice_in"));
}
}
iStorage = storage;
if(csd || cusb){
try{
oMain.HotPlug.storageChange(iStorage,csd,cusb);
}catch(e){}
}
}
setTimeout(getStorage,5*1000);
});
}
H.getStorage = getStorage;
}(window.HotPlug = {});
Request URL:http://10.10.10.254/protocol.csp?fname=storage&opt=listen_disk&function=get
Request Method:GET
Status Code:200 OK
Remote Address:10.10.10.254:80
Response Headers
view source
Cache-Control:no-cache
Content-length:241
Content-type:text/xml;charset=UTF-8
Date:Mon, 10 Oct 2016 16:16:16 GMT
Expires:0
Pragma:no-cache
Server:vshttpd
Set-cookie:SESSID=SPf9Zx78rgWMMDU7AuWS6CwwpDeSftAYhG76d6dEd4iWH;
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:hu,en-US;q=0.8,en;q=0.6,de;q=0.4
Connection:keep-alive
Cookie:Language=us; SESSID=SPf9Zx78rgWMMDU7AuWS6CwwpDeSftAYhG76d6dEd4iWH
Host:10.10.10.254
Referer:http://10.10.10.254/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36
Query String Parameters
view source
view URL encoded
fname:storage
opt:listen_disk
function:get
payload:
<root>
<storage>
<listen_disk>
<item>
<name>sda</name>
<type>USBDisk1</type>
<plugflag>1</plugflag>
</item>
<item>
<name>sdb</name>
<type>USBDisk1</type>
<plugflag>1</plugflag>
</item>
<errno>0</errno>
</listen_disk>
</storage>
</root>
for both drives it is listing USBDisk1!!
And for the listing the content:
ReplyDeleteRequest URL:http://10.10.10.254/data/UsbDisk3/Volume1
Request Method:PROPFIND
Status Code:207 Multi-status
Remote Address:10.10.10.254:80
Response Headers
view source
Content-Length:3498
Content-Type:text/xml; charset="utf-8"
Date:Mon, 10 Oct 2016 16:17:58 GMT
Server:lighttpd/1.4.28-devel-185:188M
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:hu,en-US;q=0.8,en;q=0.6,de;q=0.4
Connection:keep-alive
Content-Type:text/xml; charset="utf-8"
Cookie:Language=us; SESSID=SPf9Zx78rgWMMDU7AuWS6CwwpDeSftAYhG76d6dEd4iWH
Depth:1
Host:10.10.10.254
Method:PROPFIND /data/UsbDisk3/Volume1 HTTP/1.1
Origin:http://10.10.10.254
Referer:http://10.10.10.254/apps/explorer/explorer.html
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36
<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:" xmlns:ns0="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/">
<D:response>
<D:href>http://10.10.10.254/data/UsbDisk3/Volume1/</D:href>
<D:propstat>
<D:prop>
<D:getcontentlength>16384</D:getcontentlength><D:getcontenttype>httpd/unix-directory</D:getcontenttype><D:getlastmodified ns0:dt="dateTime.rfc1123">Mon, 10 Oct 2016 18:17:58 GMT</D:getlastmodified><D:resourcetype><D:collection/></D:resourcetype><D:user>root</D:user></D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
<D:response>
<D:href>http://10.10.10.254/data/UsbDisk3/Volume1/ftptls%7e1.msu</D:href>
<D:propstat>
<D:prop>
<D:getcontentlength>2314805</D:getcontentlength><D:getcontenttype>application/octet-stream</D:getcontenttype><D:getlastmodified ns0:dt="dateTime.rfc1123">Fri, 05 Aug 2016 17:55:32 GMT</D:getlastmodified><D:user>root</D:user></D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
<D:response>
<D:href>http://10.10.10.254/data/UsbDisk3/Volume1/vst%7e1</D:href>
<D:propstat>
<D:prop>
<D:getcontentlength>32768</D:getcontentlength><D:getcontenttype>httpd/unix-directory</D:getcontenttype><D:getlastmodified ns0:dt="dateTime.rfc1123">Mon, 10 Oct 2016 17:40:36 GMT</D:getlastmodified><D:resourcetype><D:collection/></D:resourcetype><D:user>root</D:user></D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
<D:response>
..
On the device run: lighthttpd and vshttpd and more apps.
My questions are:
What kind of app replies that xmls? How the cgi works?
Can I modify somewhere to get the proper drive informations in the xml accoring to the current mounting?
I tried to modify one file in /www , but the whole /www is readonly. How can I modify it to rw?
I did not finded a mounting point for /www.
I has samba server support also. It is working. It shares the whole content of /data folder. When I try to http://10.10.10.254/data/UsbDisk3/Volume1/img_4121.jpg , I get it, but at sambe listing it does not list automaticaly the USBDisk3 folder. Or it is a different issue?
protocol.csp contains only:
ReplyDelete<%{%>
<%}%>
Whait is it , jsp?
Are there possibilities to use this device as a NAS drive? I bought one but I noticed that is not possible to write data over LAN to the device! Only over USB but I want to change the autorisations to Read/Write
ReplyDeleteHello,
ReplyDeleteGreat instructions for this interesting device. I recently bought a used device which was working fine until I flashed a firmware for the M2M Pro. Now the device is bricked, but I am planning to access the serial port and reflash the original firmware.
Is there a chance that you provide the original firmware or update the link in this post?
Thanks a lot in advance.
Olaf