Unpacking encrypted router firmware

I’m having issues extracting the encrypted rootfs of this AGZHP 1.2.1 ZTE H388X firmware. I’m quite new to firmware reverse engineering and I’d appreciate any pointers. Here is what I got so far.

The header contains the firmware version (AGZH_1.2.1), the device model (ZXHN H388X) and length/offset for kernel/rootfs.

$ head -c 256 AGZHP_1.2.1_CLOSED.bin | hexdump -C
00000000  99 99 99 99 44 44 44 44  55 55 55 55 aa aa aa aa  |....DDDDUUUU....|
00000010  28 00 00 00 46 6d 2a 81  f6 57 24 e7 ba 84 d3 28  |(...Fm*..W$....(|
00000020  df 23 f9 96 34 19 67 b3  4a 7e d5 1c e7 63 29 a2  |.#..4.g.J~...c).|
00000030  2c 05 51 ca b5 89 cf df  c6 4d 15 eb 00 00 00 00  |,.Q......M......|
00000040  00 00 00 00 66 02 00 00  21 00 00 00 41 47 5a 48  |....f...!...AGZH|
00000050  50 5f 31 2e 32 2e 31 00  00 00 00 00 00 00 00 00  |P_1.2.1.........|
00000060  00 00 00 00 00 00 00 00  01 00 00 00 3c 02 9a 02  |............<...|

00000070  f7 08 3f 00 5c 02 10 00  04 63 d6 12 00 00 4a 02  |..?.\....c....J.| kernel: len, off, crc, rootfs: len
00000080  3c 02 50 00 83 4f ad 51  00 00 70 00 00 00 20 03  |<.P..O.Q..p... .| rootfs: off, crc, mtd kernel: addr, len
00000090  00 00 00 00 00 00 00 01  00 00 90 03 00 00 20 03  |.............. .|
000000a0  00 00 00 00 00 00 00 01  5a 58 48 4e 20 48 33 38  |........ZXHN H38|
000000b0  38 58 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |8X..............|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000d0  3c 02 00 00 5d 1d 48 06  01 00 00 00 01 00 00 00  |<...].H.........|
000000e0  a0 9b 06 28 32 30 32 31  30 38 32 34 31 36 32 36  |...(202108241626|
000000f0  31 31 00 00 00 00 00 00  ff ff ff ff ff ff ff ff  |11..............|

The firmware rootfs is encrypted with AES. By running binwalk I see a gzip compressed data section at 0x10025c, which corresponds to the kernel offset in the header.

$ binwalk AGZHP_1.2.1_CLOSED.bin
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
247812        0x3C804         CRC32 polynomial table, little endian
249788        0x3CFBC         AES Inverse S-Box
253572        0x3DE84         AES S-Box
1049180       0x10025C        Flattened device tree, size: 4131063 bytes, version: 17
1049428       0x100354        gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
5170620       0x4EE5BC        Flattened device tree, size: 8779 bytes, version: 17

To figure out where the decryption key is, I extract the kernel with dd if=AGZHP_1.2.1_CLOSED.bin bs=1 skip=$((16#10025c)) count=$((16#3f08f7)) of=kernel.img 2>/dev/null

Running binwalk on it I get:

$ binwalk parts/kernel.img
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Flattened device tree, size: 4131063 bytes, version: 17
248           0xF8            gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
4121440       0x3EE360        Flattened device tree, size: 8779 bytes, version: 17

There is a gzip image at offset 0xF8. I run dd if=kernel.img bs=1 skip=248 | zcat > Image to extract it. file Image reveal that it’s a Linux kernel ARM64 boot executable Image, little-endian. Here is where I get stuck. I’ve tried loading the image on IDA, disassembling as a ARM64 little-endian only the initial bytes seem to contain meaningful instructions. How to proceed?

I have run binwalk -Me (firmware) on my environment then found a Linux kernel at 0x100354, which wasn’t seemed to be encrypted. Most of the retrieved kernel binary was valid instructions and strings. There are some application softwares included before the gzipped kernel in the firmware, and I suppose those S-Boxes are just some parts of cryptographic libraries, not for firmware encryption.

$ strings AGZHP_1.2.1_CLOSED.bin -n 10 -tx | head -n 100
     4c AGZHP_1.2.1
     a8 ZXHN H388X
     e3 (20210824162611
   5634 FAILURE: 0x%x != 0x%x at physical address 0x%x.
   5674
   5694 setting %3u
   56a4 testing %3u
   56bf
...
  3bf2c zteboot_search_firmware
  3bf44 zteboot_compare_firmware
  3bf64 zteboot_select_firmware
  3bf7c zteboot_verify_uboot
  3bf94 zteboot_verify_kernel
  3bfac zteboot_verify_fs
  3bfc4 nand_select_chip
...
1 Like

This topic was automatically closed after 121 days. New replies are no longer allowed.