Skip to content

HowTo: Extract parts out of firmware upgrade executable (0.elf)

Meow edited this page Nov 3, 2017 · 19 revisions

In this howto i describe the steps needed to extract the various parts out of the 0.elf firmware update executable which can be intercepted during download. I've based this howto on the Xiaomi 3.0.3.56 firmware file. When you execute the 0.elf firmware it will flash the firmware and give the following output:

    image table size:0x0000003c
    index:0
    reservations:0x12345678
    offset:0x00005e84
    size:0x00001000
    flash start address:0x00001000
    flash end address:0x00001fff


    index:20
    reservations:0x12345678
    offset:0x00006e84
    size:0x002e5c54
    flash start address:0x000c0000
    flash end address:0x003bffff

I've used this output to base the method to use for extracting the firmware parts.

Preparations

  1. Extract the firmware file (upd_isa.camera.isc5.bin) using 7zip
  2. Take the 0.elf file as this contains all the firmware parts (f.i. kernel, rootfs, nvram, uboot)
  3. Try to get hold of the Sonix SN986xx SDK OVA file

Structure of the 0.elf file

  1. Use arm-linux-objdump from the toolchain to view the file structure of 0.elf:
    /home/dev/SN986_1.50_037a_20151022_1049/snx_sdk/toolchain/crosstool-4.5.2/bin/arm-linux-objdump -h 0.elf

This is the output of the objdump:

0.elf:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .interp       00000014  000080f4  000080f4  000000f4  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .hash         000000c0  00008108  00008108  00000108  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .dynsym       000001d0  000081c8  000081c8  000001c8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .dynstr       000000d9  00008398  00008398  00000398  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .rel.plt      000000a0  00008474  00008474  00000474  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .init         00000010  00008514  00008514  00000514  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  6 .plt          00000104  00008524  00008524  00000524  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  7 .text         00000d84  00008628  00008628  00000628  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  8 .fini         00000010  000093ac  000093ac  000013ac  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  9 .rodata       00000200  000093bc  000093bc  000013bc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .image.table  009bfd70  000095c0  000095c0  000015c0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 11 .eh_frame     00000004  009c9330  009c9330  009c1330  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 12 .init_array   00000004  009d1334  009d1334  009c1334  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 13 .fini_array   00000004  009d1338  009d1338  009c1338  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 14 .jcr          00000004  009d133c  009d133c  009c133c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 15 .dynamic      000000b8  009d1340  009d1340  009c1340  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 16 .got          0000005c  009d13f8  009d13f8  009c13f8  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 17 .data         00000008  009d1454  009d1454  009c1454  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 18 .bss          0000001c  009d145c  009d145c  009c145c  2**2
                  ALLOC
 19 .comment      0000005e  00000000  00000000  009c145c  2**0
                  CONTENTS, READONLY
 20 .ARM.attributes 00000029  00000000  00000000  009c14ba  2**0
                  CONTENTS, READONLY
 21 .debug_aranges 00000040  00000000  00000000  009c14e8  2**3
                  CONTENTS, READONLY, DEBUGGING
 22 .debug_info   00000258  00000000  00000000  009c1528  2**0
                  CONTENTS, READONLY, DEBUGGING
 23 .debug_abbrev 00000028  00000000  00000000  009c1780  2**0
                  CONTENTS, READONLY, DEBUGGING
 24 .debug_line   0000018a  00000000  00000000  009c17a8  2**0
                  CONTENTS, READONLY, DEBUGGING
 25 .debug_frame  00000020  00000000  00000000  009c1934  2**2
                  CONTENTS, READONLY, DEBUGGING

This one stands out, because of it's size:

 10 .image.table  009bfd70  000095c0  000095c0  000015c0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

Use objcopy from the toolchain to extract this ".image.table" section to file "imagetable.bin":

   /home/dev/SN986_1.50_037a_20151022_1049/snx_sdk/toolchain/crosstool-4.5.2/bin/arm-linux-objcopy -O binary --only-section=.image.table 0.elf imagetable.bin

View the extracted section using an hex editor. This are the hexcodes of the first 68 bytes:

3C 00 00 00 78 56 34 12 84 5e 00 00 00 10 00 00 
00 10 00 00 FF 1F 00 00 78 56 34 12 84 6e 00 00 
54 5c 2e 00 00 00 0c 00 ff ff 3b 00 78 56 34 12
d8 ca 2e 00 70 30 6d 00 00 00 3c 00 ff ff ab 00 
00 00 00 00 

Using the output during the flashing process we can recognize certain numbers:

 bytes      | Hex value  | Dev value | Description 
------------|------------|-----------|---------------------
3C 00 00 00 | 0x0000003c | 60        | The size of the image table 
78 56 34 12 | 0x12345678 |           | Reservations 
84 5e 00 00 | 0x00005e84 | 24196     | Offset of the image 
00 10 00 00 | 0x00001000 | 4096      | Size of the image 
00 10 00 00 | 0x00001000 |           | Flash Start address 
FF 1F 00 00 | 0x00001fff |           | Flash End address 

78 56 34 12 | 0x12345678 |           | Reservations 
84 6e 00 00 | 0x00006e84 |  28292    | Offset of the image 
54 5c 2e 00 | 0x002e5c54 | 3038292   | Size of the image 
00 00 0c 00 |            |           | Flash Start address
ff ff 3b 00 |            |           | Flash End address

78 56 34 12 |            |           | Reservations
d8 ca 2e 00 | 0x002ecad8 | 3066584   | Offset of the image
70 30 6d 00 | 0x006D3070 | 7155824   | Size of the image
00 00 3c 00 |            |           | Flash Start address
ff ff ab 00 |            |           | Flash End address

00 00 00 00 |

Apparently there are 3 images in this firmware file. We have 3 image offset:

  • 0x00005e84 (= 24196)
  • 0x00006e84 (= 28292)
  • 0x002ecad8 (=3066584) The imagetable above has a reserved space of 512 bytes, this needs to be added to the offsets given in the imagetable.
  1. Use DD to extract the parts from the section:
dd iflag=skip_bytes,count_bytes skip=24708 count=4096 if=imagetable.bin of=unknown.bin
dd iflag=skip_bytes,count_bytes skip=28804 count=3038292 if=imagetable.bin of=KERNEL.bin
dd iflag=skip_bytes,count_bytes skip=3067096 count=7155824 if=imagetable.bin of=ROOTFS-R.bin

Both the KERNEL.bin and ROOTFS-R.bin file are wrapped. Here we unwrap these files.

dd iflag=skip_bytes,count_bytes skip=4 count=3038176 if=KERNEL.bin of=uImage
dd iflag=skip_bytes,count_bytes skip=0 count=7155820 if=ROOTFS-R.bin of=rootfs.cramfs

Let's try to mount the CramFS filesystem image.

mkdir -p /media/cramfs
sudo mount -t cramfs -o loop /tmp/rootfs.cramfs /media/cramfs
cd /media/cramfs
ls

Let's try to make some changes....

  1. Create a new directory: mkdir /media/newcramfs
  2. find /media/cramfs > /tmp/filelist.txt
  3. cat /tmp/filelist.txt | cpio -pdm /media/newcramfs
  • Replacing chinese audio files in directory: /media/cramfs/usr/share/notify

  • Remove MacOs finder cache file: rm /media/cramfs/usr/share/notify/.DS_Store

  • vi /media/cramfs/usr/share/hostapd.conf

  • vi /media/cramfs/usr/share/udhcpd_wpa2.conf

  • Modify files in: /media/cramfs/root/etc_default

  • Change timezone in: vi /media/cramfs/root/etc_default/TZ

  • Stop autostarting of "iSC3S" (Xiaomi Cloud) vi /media/cramfs/root/etc_default/init.d

  • vi /media/newcramfs/media/cramfs/linuxrc Comment out the last line: #exec /sbin/init

  • vi /media/newcramfs/media/cramfs/root/etc_default/init.d/rcS Comment out the line: #modprobe snx_wdt Comment out the last line: #/usr/bin/iSC3S/iSC3S &

    Add at the end of the file:

/usr/sbin/telnetd &
hostapd -B -P /var/run/hostapd.pid /etc/hostapd.conf 
udhcpd -f /etc/udhcpd.conf &

Place file in: /etc/wpa_supplicant.conf

ctrl_interface=/var/run/wpa_supplicant

ctrl_interface_group=0

ap_scan=1

network={
	ssid="TP-LINK_5EE504"
	key_mgmt=WPA-PSK 
	pairwise=CCMP TKIP
	group=CCMP TKIP WEP104 WEP40
	scan_ssid=1
	psk="sonix123"
	priority=2
}

Place file in: /etc/udhcpd.conf Place content from: https://github.com/raw/samtap/fang-hacks/0d2913f11b6bcf471f97e7bb29e6d4b5777c1dbf/etc/udhcpd.conf

Place file in /etc/hostapd.conf Place content from: https://github.com/raw/samtap/fang-hacks/master/bootstrap/hostapd.conf.tmpl

  • vi /media/newcramfs/media/cramfs/root/etc_default/TZ Modify to: GMT+1:00
  1. Once the changes are done, use mkcramfs to create the cramfs image again: /home/dev/SN986_1.60_QR_Scan_019a_20160606_0951/snx_sdk/toolchain/crosstool-4.5.2/bin/mkcramfs /media/newcramfs/media/cramfs/ /home/dev/SN986_1.60_QR_Scan_019a_20160606_0951/snx_sdk/image/rootfs.cramfs

cp /media/sf_Temp/uImage /home/dev/SN986_1.60_QR_Scan_019a_20160606_0951/snx_sdk/image/uImage yum install ncurses-dev

make menuconfig deselect both options in Uboot Partition Size deselect NVRAM Partion > NVRAM Factory Partition deselect NVRAM Partition > NVRAM User Partition select Kernel Partition > Put Kernel into FIRMWARE.BIN select Kernel Patition > Put Kernel into FIRMWARE_F.bin select Root File System Partition > Put Rootfs into FIRMWARE.bin select Root File System Partition > Put Rootfs into FIRMWARE_F.bin deselect Rescue System Partition select Configure File Partition > (both) erase

make firmware

xxxxxxx1. You can flash the resulting file from Uboot with: fatupdate mmc 0x000C0000 0elfkernel.bin kernel verify