Sunday, February 12, 2017

Reverse engineering Maginon smart plug firmware

My smart plugs are working ok, but I'm facing 2 problems:

  1. The network connectivity is flaky and sometimes drops
  2. The plug would disconnect the power consumption at (re)boot
Especially the 2nd point is annoying. So, I'll try to adapt that in the boot code of the plug. Below, I'll show how I can download the firmware from the plug and start analyzing the different binaries. 

Getting hold of the flash files

The plug is serving the firmware files through MTD. We can download these from the plug for further processing on a Linux box.
# cat /proc/mounts
rootfs / rootfs rw 0 0
proc /proc proc rw 0 0
none /var ramfs rw 0 0
none /etc ramfs rw 0 0
none /tmp ramfs rw 0 0
none /media ramfs rw 0 0
none /dev/pts devpts rw 0 0

# cat /proc/partitions
major minor  #blocks  name

  31     0       4096 mtdblock0
  31     1        192 mtdblock1
  31     2         64 mtdblock2
  31     3         64 mtdblock3
  31     4       3136 mtdblock4
  31     5        640 mtdblock5
  
# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00400000 00010000 "ALL"
mtd1: 00030000 00010000 "Bootloader"
mtd2: 00010000 00010000 "Config"
mtd3: 00010000 00010000 "Factory"
mtd4: 00310000 00010000 "Kernel"
mtd5: 000a0000 00010000 "STTflash"

# cd /dev
# tftp -p -r mtdblock0 192.168.0.187
Repeat this for all files as needed.

Analyzing the files

We have transfered these files now over to our Linux box for further processing.
Useful tool that we will be using: binwalk, strings and hexdump, so install if needed. I learned a lot from this excellent tutorial here.

Listing the binary files, we see that we have all firmware files under the all.blck0.bin, which is the same as the 5 others, pasted sequencially after each other.

root@osboxes:~# ls -l ori-files/
total 8192
-rw-r--r-- 1 root root 4194304 Feb  5 06:48 all.blck0.bin
-rw-r--r-- 1 root root  196608 Feb  5 06:49 bootloader.blck1.bin
-rw-r--r-- 1 root root   65536 Feb  5 06:48 config.blck2.bin
-rw-r--r-- 1 root root   65536 Feb  5 06:49 factory.blck3.bin
-rw-r--r-- 1 root root 3211264 Feb  5 06:49 kernel.blck4.bin
-rw-r--r-- 1 root root  655360 Feb  5 06:49 sttflash.blck5.bin

When running binwalk, we see that there are 4 relevant parts.

root@osboxes:~/ori-files# binwalk all.blck0.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0x3ABFB9EA, created: Tue Jul 30 08:28:14 2013, image size: 97004 bytes, Data Address: 0x80200000, Entry Point: 0x80200000, data CRC: 0x798C5A57, OS: Linux, CPU: MIPS, image type: Standalone Program, compression type: none, image name: "SPI Flash Image"
80080         0x138D0         U-Boot version string, "U-Boot 1.1.3 (Jul 30 2013 - 15:28:09)"
327680        0x50000         uImage header, header size: 64 bytes, header CRC: 0x132FA66C, created: Mon Aug 25 09:53:45 2014, image size: 1878075 bytes, Data Address: 0x80000000, Entry Point: 0x802FF000, data CRC: 0xBA5B6A2A, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image"
327744        0x50040         LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 4136529 bytes

Doing the same onto bootloader and kernel, we identify, these are the ones that contain these parts.

root@osboxes:~/ori-files# binwalk kernel.blck4.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0x132FA66C, created: Mon Aug 25 09:53:45 2014, image size: 1878075 bytes, Data Address: 0x80000000, Entry Point: 0x802FF000, data CRC: 0xBA5B6A2A, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image"
64            0x40            LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 4136529 bytes

root@osboxes:~/ori-files# binwalk bootloader.blck1.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0x3ABFB9EA, created: Tue Jul 30 08:28:14 2013, image size: 97004 bytes, Data Address: 0x80200000, Entry Point: 0x80200000, data CRC: 0x798C5A57, OS: Linux, CPU: MIPS, image type: Standalone Program, compression type: none, image name: "SPI Flash Image"
80080         0x138D0         U-Boot version string, "U-Boot 1.1.3 (Jul 30 2013 - 15:28:09)"

Now with the -Me options added to binwalk, the parts will be searched for recursively and also extracted whenever possible. Let's do this for the kernel.

root@osboxes:~/ori-files# binwalk -Me kernel.blck4.bin

Scan Time:     2017-02-12 10:00:34
Target File:   kernel.blck4.bin
MD5 Checksum:  1d2432cb866f6bb15629d16495bd0fed
Signatures:    285

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0x132FA66C, created: Mon Aug 25 09:53:45 2014, image size: 1878075 bytes, Data Address: 0x80000000, Entry Point: 0x802FF000, data CRC: 0xBA5B6A2A, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image"
64            0x40            LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 4136529 bytes


Scan Time:     2017-02-12 10:00:35
Target File:   _kernel.blck4.bin.extracted/40
MD5 Checksum:  f4c1b0c5c8f6c53d6ceb0f6b9b175dd8
Signatures:    285

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
752300        0xB7AAC         LZMA compressed data, properties: 0xC0, dictionary size: 16777216 bytes, uncompressed size: 525022 bytes
2332768       0x239860        LZMA compressed data, properties: 0xC0, dictionary size: 33554432 bytes, uncompressed size: 526566 bytes
2793528       0x2AA038        Linux kernel version "2.6.21 (root@RD-HP3000) (gcc version 3.4.2) #324 Mon Aug 25 16:rsion 3.4.2) #324 Mon Aug 25 16:53:40 CST 2014"
2996076       0x2DB76C        XML document, version: "1.0"
3272704       0x31F000        LZMA compressed data, properties: 0x5D, dictionary size: 1048576 bytes, uncompressed size: 4133888 bytes


Scan Time:     2017-02-12 10:00:37
Target File:   _kernel.blck4.bin.extracted/_40.extracted/239860
MD5 Checksum:  d41d8cd98f00b204e9800998ecf8427e
Signatures:    285

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------


Scan Time:     2017-02-12 10:00:37
Target File:   _kernel.blck4.bin.extracted/_40.extracted/31F000
MD5 Checksum:  3ca1eaaf5d89acfd97a43e677a926c05
Signatures:    285

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ASCII cpio archive (SVR4 with no CRC), file name: "/tmp", file name length: "0x00000005", file size: "0x00000000"
116           0x74            ASCII cpio archive (SVR4 with no CRC), file name: "/media", file name length: "0x00000007", file size: "0x00000000"
236           0xEC            ASCII cpio archive (SVR4 with no CRC), file name: "/bin", file name length: "0x00000005", file size: "0x00000000"
352           0x160           ASCII cpio archive (SVR4 with no CRC), file name: "/bin/iperf", file name length: "0x0000000B", file size: "0x00024314"
148720        0x244F0         ASCII cpio archive (SVR4 with no CRC), file name: "/bin/ntpclient", file name length: "0x0000000F", file size: "0x00005914"
171652        0x29E84         ASCII cpio archive (SVR4 with no CRC), file name: "/bin/rm", file name length: "0x00000008", file size: "0x00000008"
171780        0x29F04         ASCII cpio archive (SVR4 with no CRC), file name: "/bin/mkdir", file name length: "0x0000000B", file size: "0x00000008"
171912        0x29F88         ASCII cpio archive (SVR4 with no CRC), file name: "/bin/date", file name length: "0x0000000A", file size: "0x00000008"
172040        0x2A008         ASCII cpio archive (SVR4 with no CRC), file name: "/bin/erase", file name length: "0x0000000B", file size: "0x00001840"
...

Many more files are being listed, but this means we have found the read-only file system which is being loaded, each time the plug restarts.

When looking closer to the file called '40', we can start pulling data from there.

root@osboxes:~/ori-files/_kernel.blck4.bin.extracted# binwalk -M 40

Scan Time:     2017-02-12 10:21:11
Target File:   40
MD5 Checksum:  f4c1b0c5c8f6c53d6ceb0f6b9b175dd8
Signatures:    285

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
752300        0xB7AAC         LZMA compressed data, properties: 0xC0, dictionary size: 16777216 bytes, uncompressed size: 525022 bytes
2332768       0x239860        LZMA compressed data, properties: 0xC0, dictionary size: 33554432 bytes, uncompressed size: 526566 bytes
2793528       0x2AA038        Linux kernel version "2.6.21 (root@RD-HP3000) (gcc version 3.4.2) #324 Mon Aug 25 16:rsion 3.4.2) #324 Mon Aug 25 16:53:40 CST 2014"
2996076       0x2DB76C        XML document, version: "1.0"
3272704       0x31F000        LZMA compressed data, properties: 0x5D, dictionary size: 1048576 bytes, uncompressed size: 4133888 bytes

root@osboxes:~/ori-files/_kernel.blck4.bin.extracted# dd if=40 of=part0.bin bs=1 count=$((0xB7AAC))
752300+0 records in
752300+0 records out
752300 bytes (752 kB) copied, 1.96053 s, 384 kB/s

Or the Linux kernel

root@osboxes:~/ori-files/_kernel.blck4.bin.extracted# dd if=40 of=part2.bin bs=1 count=$((0x2AA038-0x239860)) skip=$((0x239860))
460760+0 records in
460760+0 records out
460760 bytes (461 kB) copied, 1.3339 s, 345 kB/s

When running hexdump, we can see that there's some empty data towards the end of the file.

Going further down the generated files, we saw before that the read-only file system is being stored there in a file. We can extract that.

root@osboxes:~/ori-files/_kernel.blck4.bin.extracted/_40.extracted/_31F000.extracted# ls -l
total 4040
-rw-r--r-- 1 root root 4133888 Feb 12 10:00 0.cpio
root@osboxes:~/ori-files/_kernel.blck4.bin.extracted/_40.extracted/_31F000.extracted# cpio -i --no-absolute-filenames -F ../31F000
cpio: Removing leading `/' from member names
8074 blocks
root@osboxes:~/ori-files/_kernel.blck4.bin.extracted/_40.extracted/_31F000.extracted# ls -l
total 4096
-rw-r--r-- 1 root root 4133888 Feb 12 10:00 0.cpio
drwxrwxrwx 2 root root    4096 Feb 12 10:41 bin
drwxrwxrwx 3 root root    4096 Feb 12 10:41 dev
drwxrwxrwx 2 root root    4096 Feb 12 10:41 etc
drwxrwxrwx 9 root root    4096 Feb 12 10:41 etc_ro
drwxrwxrwx 2 root root    4096 Feb 12 10:41 home
lrwxrwxrwx 1 root root      11 Feb 12 10:41 init -> bin/busybox
drwxr-xr-x 4 root root    4096 Feb 12 10:41 lib
drwxrwxrwx 2 root root    4096 Feb 12 10:41 media
drwxrwxrwx 3 root root    4096 Feb 12 10:41 mnt
drwxrwxrwx 2 root root    4096 Feb 12 10:41 proc
drwxrwxrwx 2 root root    4096 Feb 12 10:41 sbin
drwxrwxrwx 2 root root    4096 Feb 12 10:41 sys
drwxrwxrwx 2 root root    4096 Feb 12 10:41 tmp
drwxrwxrwx 5 root root    4096 Feb 12 10:41 usr
drwxrwxrwx 2 root root    4096 Feb 12 10:41 var
root@osboxes:~/ori-files/_kernel.blck4.bin.extracted/_40.extracted/_31F000.extracted#

We are now in control of the firmware of the plug and can start making tweaks to the files where needed.

2 comments:

  1. Next post? Did you succeed improving the plug?

    ReplyDelete
  2. Hi, would it be possible for you to upload your firmware dump? I have a Maginon SP-1E here with most likely corrupt firmware.

    ReplyDelete