binwalk zlib 数据

逆向工程 二元分析 工具 固件
2021-06-20 10:10:09

我正在反转固件,但遇到了一些问题。我使用 binwalk 来逆向固件,但是 binwalk 产生了与我朋友不同的结果。我的朋友找到了一些 zlib 数据(参见1),但我找不到这些 zlib 数据项(参见2)。

我不明白有什么问题,但我binwak -e以同样的方式使用。我好糊涂

我的问题是:如何找到 zlib 数据?

谢谢。

1个回答

binwalk 结果之间的差异可能是由于您使用的 binwalk 版本不同造成的。因此,只需运行不带任何参数的 binwalk 即可检查 binwalk 的版本。关于固件,您无法使用 binwalk 解压缩内容。要了解原因,请检查固件的启动。您会发现一个0x20DLA50字符串开头字节标头这个魔法字符串和标题在 offset 处重复0x40200x8040依此类推。要查看标头的结构,请检查固件文件中间的以下一项:

在此处输入图片说明

我用黄色标记魔法字符串(DLA50),用绿色标记片段的位置,用蓝色标记片段的大小。

以下脚本可以跟随标题并从图像中提取部分:

import struct
import binascii
import sys

if (len(sys.argv) < 2):
    print 'firm.py filename'
    sys.exit(0)

id = 0
last = 0
idh = None

bf = open(sys.argv[1], 'rb')
while(True):
    h = bf.read(0x20)
    if (len(h) < 0x20 or h[0:5] != 'DLA50'):
        break
    dpos = struct.unpack('L', h[0x14:0x18])[0]
    dsize = struct.unpack('L', h[0x18:0x1c])[0]
    print '%s, pos: %x, size: %x'%(binascii.hexlify(h), dpos, dsize)
    d = bf.read(dsize)

    if (last != 0x4000):
        if (idh != None):
            idh.close()
        idh = open('%d.bin'%(id), 'wb')
        id += 1

    idh.write(d)
    last = dsize

idh.close()

上述脚本将提取以下部分:

  • 0-0x2865b: 可执行代码,可以用 LZMA、LZO 或类似的东西压缩
  • 0x286d7-0x56f60: 文件系统,单个文件也被压缩
  • 0x56f60-0x5bdc0: 可能是配置区

第一部分以0x10字节头开始,后跟高熵数据。标题包含一些标志或魔术字节和数据大小,我在下一张图片中用蓝色标记。我可以根据第一部分的大小来识别大小数据项,即0x28555 = header size + 0x28545.

在此处输入图片说明

下一部分以以下字节开始:

在此处输入图片说明

开始于的区域0x60似乎包含文件名,例如501h1_uk.js等等,以及其他二进制数据。因此,该区域可能包含文件条目。如果为真,则前面的数据 ( 0x00- 0x60) 是目录条目或标题。在这个头部区域,你可以找到一些小端字节序的有趣值。0x0002e709(标有蓝色)是与文件大小相等。0x00000060(标记为黄色)可能指向文件条目的开始。0x00000d48(用红色标出)后的文件入口偏移可以在文件内部彼此偏移。因此,在检查文件中的偏移量后,它看到它正好指向目录条目之后,因此它可能是数据区的起始偏移量。

我们对头的结构有一些猜测,所以让我们检查文件条目。如果我们假设文件名总是在文件条目内的相同位置开始,那么我们可以通过减去两个连续文件名的偏移量来计算一个条目的大小。根据此计算,文件条目大小将为0x16字节。

与前面的步骤类似,经过多一点研究,我们可以得出结论,文件入口区从文件的计数开始,每个文件入口包含文件名、文件标志、文件数据的相对位置和文件大小。

总而言之,以下脚本可以从固件文件的第二部分提取文件:

import struct
import sys

if (len(sys.argv) < 2):
    print 'parse_fs.py filename'
    sys.exit(0)

fh = open(sys.argv[1],'rb')
h = fh.read(0x60)
fs_size = struct.unpack('L', h[0x08:0x0c])[0]
offset = struct.unpack('L', h[0x20:0x24])[0]
data_start = struct.unpack('L', h[0x24:0x28])[0]

print 'fs size: %x, dir offset: %x, data start: %x'%(fs_size, offset, data_start)

fh.seek(offset)
ds = data_start-offset
d = fh.read(ds)
count = struct.unpack('H', d[0:2])[0]
for i in xrange(count):
    o = i*0x16+2
    unk1 = struct.unpack('H', d[o+0x00:o+0x02])[0]
    fname = d[o+0x02:o+0x0e]+'\x00'
    fname = fname[0:fname.find('\x00')]
    unk2 = struct.unpack('H', d[o+0x0e:o+0x10])[0]
    pos = struct.unpack('L', d[o+0x10:o+0x14])[0]+data_start
    size = struct.unpack('H', d[o+0x14:o+0x16])[0]
    print '  %s, pos: %x, size: %x, unk1: %x, unk2: %x'%(fname, pos, size, unk1, unk2)

    fh.seek(pos)
    open('fs_%s'%(fname), 'wb').write(fh.read(size))