I was asked by
@G33RT how the firmware could be extracted, so I said I'd put up an example to share with others.
Hopefully we'll see some refinement contributions.
This is an example of how you might take a first look at an embedded Linux firmware update file.
This 'first-cut' look is not aimed at a rigorous unpack/modify/repack but rather for getting an overview of the contents.
Create a couple of folders, to hold the contents, and a temporary mount point, and any files.
Useful for a first look is to use 'binwalk'. This can give some good clues, though it also can give lots of false indications, as well as miss lots of stuff.
In this case, the results are somewhat sparse.
The uImage signature should be reliable (as opposed to just a Linux copyright string), as should the jffs2 indication.
The gzip data looks like a false match, judging from the lack of date.
And there is nothing matched in the 131k bytes preceding the uImage, so we'll probably have to inspect that for clues with a hex editor.
But first, let's cut out the chunks that seem like a reasonable match. The sizes are taken directly from the binwalk numbers.
The 'file' command can be pretty useful in helping figure file types.
Code:
alastair@PC-I5 ~/ipcc $ ll
total 13076
drwxr-xr-x 2 alastair alastair 4096 Apr 23 11:50 ./
drwxr-xr-x 68 alastair alastair 4096 Apr 23 09:13 ../
-rw-r--r-- 1 alastair alastair 6296 Apr 23 10:22 readme.txt
-rw-r--r-- 1 alastair alastair 13369612 Apr 20 18:23 UPG_ipc3580ar-w7-M20-hi3518e-20150728_013643.ov
alastair@PC-I5 ~/ipcc $ mkdir tmp_mount
alastair@PC-I5 ~/ipcc $ mkdir fw_contents
alastair@PC-I5 ~/ipcc $ binwalk UPG_ipc3580ar-w7-M20-hi3518e-20150728_013643.ov
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
131340 0x2010C uImage header, header size: 64 bytes, header CRC: 0x6D151FDF, created: Wed Sep 17 18:14:06 2014, image size: 2519356 bytes, Data Address: 0x80008000, Entry Point: 0x80008000, data CRC: 0xC84C5528, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "Linux-3.0.8"
153948 0x2595C gzip compressed data, from Unix, NULL date: Thu Jan 1 01:00:00 1970, max compression
2687244 0x29010C JFFS2 filesystem, little endian
alastair@PC-I5 ~/ipcc $ tail -c +131341 UPG_ipc3580ar-w7-M20-hi3518e-20150728_013643.ov | head -c 2555904 > chunk_uImage
alastair@PC-I5 ~/ipcc $ tail -c +2687245 UPG_ipc3580ar-w7-M20-hi3518e-20150728_013643.ov > chunk_jffs2
alastair@PC-I5 ~/ipcc $ head -c 131340 UPG_ipc3580ar-w7-M20-hi3518e-20150728_013643.ov > chunk_header
alastair@PC-I5 ~/ipcc $ ll
total 26144
drwxr-xr-x 4 alastair alastair 4096 Apr 23 12:06 ./
drwxr-xr-x 68 alastair alastair 4096 Apr 23 09:13 ../
-rw-r--r-- 1 alastair alastair 131340 Apr 23 12:06 chunk_header
-rw-r--r-- 1 alastair alastair 10682368 Apr 23 12:02 chunk_jffs2
-rw-r--r-- 1 alastair alastair 2555904 Apr 23 12:02 chunk_uImage
drwxr-xr-x 2 alastair alastair 4096 Apr 23 11:58 fw_contents/
-rw-r--r-- 1 alastair alastair 6296 Apr 23 10:22 readme.txt
drwxr-xr-x 2 alastair alastair 4096 Apr 23 11:58 tmp_mount/
-rw-r--r-- 1 alastair alastair 13369612 Apr 20 18:23 UPG_ipc3580ar-w7-M20-hi3518e-20150728_013643.ov
alastair@PC-I5 ~/ipcc $ file *
chunk_header: data
chunk_jffs2: Linux jffs2 filesystem data little endian
chunk_uImage: u-boot legacy uImage, Linux-3.0.8, Linux/ARM, OS Kernel Image (Not compressed), 2519356 bytes, Wed Sep 17 18:14:06 2014, Load Address: 0x80008000, Entry Point: 0x80008000, Header CRC: 0x6D151FDF, Data CRC: 0xC84C5528
fw_contents: directory
readme.txt: ASCII text, with very long lines
tmp_mount: directory
UPG_ipc3580ar-w7-M20-hi3518e-20150728_013643.ov: data
alastair@PC-I5 ~/ipcc $
Now for the trickier stuff - extracting the jffs2 contents.
This requires creating a dummy block device to mount the jffs2 file system contents, copying the files to permanent storage, and tidying up after.
Code:
alastair@PC-I5 ~/ipcc $ ll /dev/mtd*
ls: cannot access /dev/mtd*: No such file or directory
alastair@PC-I5 ~/ipcc $ sudo modprobe mtdram total_size=32768
[sudo] password for alastair:
alastair@PC-I5 ~/ipcc $ sudo modprobe mtdblock
alastair@PC-I5 ~/ipcc $ ll /dev/mtd*
crw------- 1 root root 90, 0 Apr 23 12:10 /dev/mtd0
crw------- 1 root root 90, 1 Apr 23 12:10 /dev/mtd0ro
brw-rw---- 1 root disk 31, 0 Apr 23 12:10 /dev/mtdblock0
alastair@PC-I5 ~/ipcc $ sudo dd if=chunk_jffs2 of=/dev/mtdblock0
20864+0 records in
20864+0 records out
10682368 bytes (11 MB) copied, 0.0716073 s, 149 MB/s
alastair@PC-I5 ~/ipcc $ sudo mount -t jffs2 /dev/mtdblock0 ~/ipcc/tmp_mount
alastair@PC-I5 ~/ipcc $ ll tmp_mount
total 6
drwxr-xr-x 28 root root 0 Jan 1 1970 ./
drwxr-xr-x 4 alastair alastair 4096 Apr 23 12:06 ../
drwxr-xr-x 3 alastair wireshark 0 Sep 28 2013 bin/
drwxr-xr-x 2 alastair wireshark 0 Jul 27 2015 boot/
drwxr-xr-x 2 alastair wireshark 0 Jul 27 2015 cifs/
drwxr-xr-x 2 alastair wireshark 0 Jul 27 2015 cifstest/
drwxr-xr-x 2 alastair wireshark 0 Jul 9 2013 dev/
drwxr-xr-x 5 alastair wireshark 0 Jul 27 2015 etc/
drwxr-xr-x 2 alastair wireshark 0 Sep 28 2013 font/
drwxr-xr-x 2 alastair wireshark 0 Jul 9 2013 home/
lrwxrwxrwx 1 alastair wireshark 9 Feb 19 2014 init -> sbin/init*
drwxrwxr-x 3 alastair wireshark 0 Jul 1 2015 komod/
drwxr-xr-x 2 alastair wireshark 0 Apr 19 2012 lib/
lrwxrwxrwx 1 alastair wireshark 11 Feb 19 2014 linuxrc -> bin/busybox*
drwxr-xr-x 2 alastair wireshark 0 Jul 9 2013 lost+found/
drwxr-xr-x 3 alastair wireshark 0 Jul 27 2015 mnt/
drwxr-xr-x 2 alastair wireshark 0 Jul 27 2015 nfsroot/
drwxr-xr-x 2 alastair wireshark 0 Jul 9 2013 opt/
drwxr-xr-x 2 alastair wireshark 0 Jul 9 2013 proc/
drwxr-xr-x 2 alastair wireshark 0 Dec 10 2007 root/
lrwxrwxrwx 1 alastair wireshark 15 Dec 19 2014 rt -> /mnt/config/usr
drwxr-xr-x 2 alastair wireshark 0 Feb 19 2014 sbin/
drwxr-xr-x 2 alastair wireshark 0 Jul 9 2013 share/
drwxr-xr-x 2 alastair wireshark 0 Jul 9 2013 sys/
drwxr-xr-x 3 alastair wireshark 0 Jul 27 2015 system/
drwxr-xr-x 2 alastair wireshark 0 Jul 9 2013 tmp/
drwxr-xr-x 2 alastair wireshark 0 Jul 27 2015 tmpfs/
drwxr-xr-x 2 alastair wireshark 0 Jul 27 2015 tmpfs2/
drwxr-xr-x 6 alastair wireshark 0 Jul 27 2015 usr/
drwxr-xr-x 4 alastair wireshark 0 Jul 9 2013 var/
alastair@PC-I5 ~/ipcc $ cp -R tmp_mount/* fw_contents
alastair@PC-I5 ~/ipcc $ sudo umount ~/ipcc/tmp_mount
alastair@PC-I5 ~/ipcc $ sudo modprobe -r mtdram
alastair@PC-I5 ~/ipcc $ sudo modprobe -r mtdblock
alastair@PC-I5 ~/ipcc $
So far, so good.
But what about that chunk_header?
Well, another useful tool is 'strings'.
When this is run against the file, the result is a set of strings that's typical of u-boot. And the size is about right too.
Example : "U-Boot 2010.06-svn3738 (Jul 14 2015 - 18:33:44)"
There is more though, it looks like it may have built-in firmware update code:
Code:
do_upgrade now
upgradeAddr:0x%x
upgradeAddr erro
------------------Upgrade Version 1------------------
magic:%x
version:%x
UpgradeBitmap:%x
BootLen:%x
BootAddr:%x
BootPartitionLen:%x
KernelLen:%x
KernelAddr:%x
KernelPartitionLen:%x
RootfsLen:%x
RootfsAddr:%x
RootPartitionLen:%x
AppLen:%x
AppAddr:%x
AppPartitionLen%x
ConfigAddr:%x
ConfigLen:%x
ConfigPartitionLen:%x
ParaAddr:%x
ParaLen:%x
ParaPartitionLen:%x
upgrade fail magic error
------------------start check crc------------------
check crc success
check crc failure
------------------start upgrade boot------------------
------------------end upgrade boot------------------
------------------start upgrade kernel------------------
------------------end upgrade kernel------------------
------------------start upgrade rootfs------------------
------------------end upgrade rootfs------------------
------------------start upgrade app------------------
------------------end upgrade app------------------
------------------start upgrade config------------------
------------------end upgrade config------------------
------------------start upgrade para------------------
------------------end upgrade para------------------
------------------upgrade success------------------
------------------clean upgrade pos------------------
------------------Upgrade Version 2------------------
magic:%x
version:%x
UpgradeBitmap:%x
BootLen:%x
BootAddr:%x
BootFlashStartAddr:%x
BootPartitionLen:%x
KernelLen:%x
KernelAddr:%x
KernelFlashStartAddr:%x
KernelPartitionLen:%x
RootfsLen:%x
RootfsAddr:%x
RootfsFlashStartAddr:%x
RootPartitionLen:%x
AppLen:%x
AppAddr:%x
AppFlashStartAddr:%x
AppPartitionLen%x
ConfigAddr:%x
ConfigFlashStartAddr:%x
ConfigLen:%x
ConfigPartitionLen:%x
ParaFlashStartAddr:%x
ParaAddr:%x
ParaLen:%x
ParaPartitionLen:%x
upgrade fail magic11 error
magic:%08x
version:%08x
crc:%08x
envcnt:%08x
setenv %s %s
------------------set boot env success------------------
upgradepos
upgradePos null!!!
upgradePos %#x!!!
upgrade board
print monitor version
%-*s- %s
Unknown command '%s' - try 'help' without arguments for list of all known commands
runtop18e #
No input devices available!
No output devices available!
No error devices available!
*** Warning - bad CRC, using default environment
SPI Flash
Environment SPI flash not initialized
Warning: Erase size 0x%08x smaller than one erase block 0x%08x
Erasing 0x%08x instead
Erasing SPI flash, offset 0x%08x size %s ...
Writing to SPI flash, offset 0x%08x size %s ...
Comments / critique / extras / improvements welcome.