华为E586固件

逆向工程 文件格式 固件 嵌入式
2021-06-27 08:11:33

我正在解包 Hauwei E586 MiFi 固件。我下载了可用作 Windows EXE 的固件更新包,然后使用 Hauwei Modem Flasher 从安装程序中解压真实固件。

我有4个文件:

01.bin: data
02.bin: ELF 32-bit LSB executable, ARM, version 1, statically linked, not stripped
03.bin: data
04.bin: ELF 32-bit LSB executable, ARM, version 1, statically linked, not stripped

如我们所见0204是可执行文件。01可能是某种引导加载程序(我从字符串分析中假设它)。03是某种伪FS。

我从分析开始03(我把它贴在这里):

有标题部分

02 00 EE EE  50 BA 6E 00  20 00 00 00  D0 A2 02 00
7B 02 00 00  00 00 00 00  00 00 00 00  00 00 00 00

7B 02因为 16 位给出 635,这是二进制文件的数量(使用 验证strings)。然后有 635 个部分描述每个文件(称为目录),最后是文件的内容。

我找到的第一个 GIF 文件有目录条目。我选择 GIF 是因为它很容易识别(有页眉 GIF8X 和页脚 0x3B)。

77 77 77 5C  75 6D 5C 70  75 62 6C 69  63 5F 73 79
73 2D 72 65  73 6F 75 72  63 65 73 5C  42 75 74 74
75 6E 5F 43  75 72 72 65  6E 74 2E 67  69 66 00 00
lot of zeros
18 22 11 00  10 02 00 00  00 00 00 00  00 00 FF EE

我们可以看到它的名字:www\um\public_sys-resources\Buttun_Current.gif在最后一行有二进制和文件大小的文件偏移量,但我不确定如何解释这些值。

我在目录之后找到第一个 GIF 并手动提取它(从页眉到页脚),这给了我 528 字节大小的文件,因此读取10 02为 16 位无符号给了我这个数字。我试图将18 2216 位无符号视为获取偏移量,但它与我手动从文件中读取的偏移量不同。但是1286864. 所以我创建了解包这个二进制文件的脚本(我得到了偏移量并添加到它1286864)。

脚本仅部分起作用。它重新创建了目录结构,但只能提取一个特定目录(我用作参考的带有 GIF 的目录)中的文件。检查文件的不同部分后,不同子目录中的偏移量似乎是这个GIF目录中的另一个。所以,我的猜测是我解释偏移量是错误的(但将其视为 32 位没有任何用处)。

有解压脚本:

import sys, struct, os

def main(args):
    outdir = args[1]
    f = open(args[0], 'rb')
    f2 = open(args[0], 'rb')
    header = f.read(32)
    print(len(header[16:]))
    number_of_files = struct.unpack("h", header[16:18])[0]
    print(number_of_files)

    for i in range(number_of_files):
        body = f.read(272)
        file_, rest = body.split(b'\x00', 1)
        offset = struct.unpack("H", body[256:258])[0] + 1286864
        size = struct.unpack("H", body[260:262])[0]
        file_ = file_.decode(encoding='UTF-8').replace('\\', '/')
        dirname = os.path.join(outdir, os.path.dirname(file_))
        filename = os.path.basename(file_)
        print(filename, size, offset, dirname)
        try:
            os.makedirs(dirname)
        except OSError:
            pass

        outfile = open(os.path.join(dirname, filename), "wb")
        f2.seek(offset)
        outfile.write(f2.read(size))
        outfile.close()

if __name__=='__main__':
    sys.exit(main(sys.argv[1:]))

用法: ./script.py 03.bin output_directory

所以我的问题是:我做错了什么?也许我应该读取另一种数据类型作为偏移量/大小?哪一个?

3个回答

我设法解决了问题。

目录中的第一个文件是ZSP.bin. 这个文件的偏移量是 16 位还是 32 位并不重要,因为在这两种情况下都是 0。据我所知,目录在哪里结束,目录之后的第一个文件应该是 ZSP.bin。

下面是最后一个目录条目的最后两行,我怀疑应该是第一行ZSP.bin

00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00 
FC 94 6D 00  53 25 01 00  00 00 00 00  00 00 FF EE
11 00 10 00  30 00 00 00  10 00 00 00  00 00 00 00

每个目录条目FF EE都以ZSP.bin. 它的偏移量是0x2a2d0然后我检查了ZSP.bin.

我知道它在哪里,但我不知道它是 16 位还是 32 位(B4 C3B4 C3 0C 00)。当我将B4 C316 位无符号添加到我的已知偏移量时,0x2a2d0我到达的地址0x36684看起来不像 XML 文件的开头(这是目录中的第三个,但第二个长度为 0)。因此,我尝试将0xcc3b4(32 位值)添加到我的偏移量中,这给了我0xf6684并且在此地址处有 XML 文件的开头... :)

所以我修改了我的代码:

offset = struct.unpack("I", body[256:260])[0] + 172752
size = struct.unpack("I", body[260:264])[0]

在手动检查了一些随机的非二进制文件后,所有文件都没有问题(HTML 和 XML 的正确开头和结尾,GIF 被识别为 GIF)...

顺便说一句,我醒来后首先想到的是检查目录中的第一个文件而不是这个 GIF 的想法...... :)

我无法获得正确格式的评论..所以请原谅这是一个新回复。这是标题格式:

offset:length   description
-------------   -----------
0x00 : 4        unknown, probably 2 16-byte words for a version or file ID
0x04 : 4        size of the data block containing file data
0x08 : 4        unknown
0x0C : 4        offset to the data block
0x10 : 4        number of file entries
0x14 : 12       unknown / padding

可以使用以下方法读取文件头:

size_of_data, offset_to_data, number_of_files = struct.unpack("< 4x L 4x L L 12x", header)  

每个文件条目如下所示:

offset:length   description
-------------   -----------
0x000 : 256     file path
0x100 : 4       offset to file in data block
0x104 : 4       size of file data
0x108 : 8       unknown

然后对于每个文件条目:

filepath, offset, size = struct.unpack("< 256s L L 8x", body)  

文件的最终偏移量是:

offset = offset + offset_to_data

我知道这是一个旧线程,但我只想补充一点,您的 Hauwei E586 可能基于 HiSierrra 芯片组和固件。(即使用华为Modem Flasher时,华为固件以“21.”开头。)这是使用嵌入式linux服务器,与基于高通芯片的MiFi不同,固件以“11.”开头。是另一个关于在其中一个(E589)上反转固件的有趣线程。

我的问题是,您是否还必须处理整个二进制文件的校验和?(你知道如何计算它,以及它的位置吗?)

附注。这是作为评论的意思,但我仍然没有所需的代表来做到这一点。