RE 压缩备份文件,基于路由器 linux 那么它是用 zlib 压缩的吗?

逆向工程 linux
2021-06-21 20:32:43

所以我从我的路由器中备份了它的 zte zxv10h201l 和它的基于 linux 的,但我无法识别这个文件的压缩类型。这是它的前几行“行”


00000000  99 99 99 99 44 44 44 44  55 55 55 55 aa aa aa aa  |....DDDDUUUU....|
00000010  00 00 00 00 00 00 00 00  00 00 00 04 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 40  |...............@|
00000040  00 01 00 00 00 00 00 80  00 00 23 90 00 00 00 00  |..........#.....|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000080  04 03 02 01 00 00 00 00  00 00 00 0b 5a 58 56 31  |............ZXV1|
00000090  30 20 48 32 30 31 4c 01  02 03 04 00 00 00 00 00  |0 H201L.........|
000000a0  01 4c 54 00 00 23 78 00  00 20 00 40 34 b7 80 e9  |.LT..#x.. .@4...|
000000b0  80 47 c0 00 00 00 00 00  00 00 00 00 00 00 00 00  |.G..............|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000d0  00 00 00 00 00 20 00 00  00 03 d0 00 00 04 18 78  |..... .........x|
000000e0  da ed 58 61 53 da 30 18  fe be 5f c1 f1 03 b0 29  |..XaS.0..._....)|
000000f0  88 db 4e 77 07 6d d1 de  00 3b e8 64 b7 2f 5e 6c  |..Nw.m...;.d./^l|
00000100  23 e6 2c 49 2f 4d 11 f6  eb 97 da 56 0b da 34 45  |#.,I/M.....V..4E|
00000110  77 d3 13 94 2b 94 27 6f  9e be 79 f2 bc 6f 7b 6c  |w...+.'o..y..o{l|
00000120  f6 bf 7d 6a 88 d7 b1 7b  15 34 08 5c a0 93 a6 d9  |..}j...{.4.\....|
00000130  ef c3 08 35 1b 13 7a 67  d0 98 f0 93 26 68 a6 a0  |...5..zg....&h..|
00000140  7b a0 38 dd 18 d3 93 a6  56 38 79 ff 83 39 ca 02  |{.8.....V8y..9..|
00000150  d8 03 9b 5c d3 66 63 09  03 01 03 e2 4f 17 ef 8e  |...\.fc.....O...|
00000160  96 be 80 d6 d5 40 27 fd  a6 03 fd 30 3b 7d 98 fc  |.....@'....0;}..|
00000170  92 1e f5 ec d8 4e 8e cd  83 c2 dc 07 62 f2 8c ef  |.....N......b...|

在我将 ttl-rs232 连接到路由器之后,当在我的路由器 Web UI 上按下备份按钮时,这会显示在日志中


=~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2014.01.31 22:58:29 =~=~=~=~=~=~=~=~=~=~=~=
04:15:12 [webd][Info] [upload.c(1138)my_upload_file] Enter my_upload_file.
04:15:12 [webd][Info] [upload.c(1343)my_upload_file] Begin download file.(filetype : config)
04:15:12 [DB][Info] [dbc_mgr_file.c(1644)dbGetBinFile] DB get cfg start
04:15:12 [FLASHRW][Info] [proc_file_mod.c(1204)file_open] open file: /proc/cfg/db_user_cfg.xml
04:15:12 [FLASHRW][Info] [proc_file_mod.c(1334)file_close] close file: /proc/cfg/db_user_cfg.xml
04:15:12 [DB][Info] [dbc_mgr_file_en(570)dbcCfgFileIsEnc] FileIsEncry return 0
04:15:12 [FLASHRW][Info] [proc_file_mod.c(1204)file_open] open file: /proc/cfg/db_user_cfg.xml
04:15:12 [FLASHRW][Info] [proc_file_mod.c(1334)file_close] close file: /proc/cfg/db_user_cfg.xml
04:15:12 [DB][Info] [dbc_mgr_file_si(198)dbcCfgFileSign] SignFile return 0
04:15:12 [DB][Info] [dbc_mgr_file_ve(277)dbcCfgFileVersi] add FileVersion return 0
04:15:12 [DB][Warn] [dbc_mgr_file.c(1708)dbGetBinFile] DB download cfg(iRet:0)
04:15:12 [webd][Info] [upload.c(644)create_config_f] user cfg path:/var/tmp/version-cfg

所以我在路由器固件中搜索了像上面这样的文字串并找到了这一行

放气 1.1.4 jean loup gailly

在一些字符串附近,在快速谷歌之后,它接缝是 zlib 并且它用于压缩“某物”,之后我试图用我的小知识尝试用这样的命令解压缩它

printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - zlib.raw |gzip -dc

猫/tmp/数据| openssl zlib -d

但是运气不好,后来我在网上找到了类似的文件,没有压缩,所以我看了一下,发现文件头和更多的“字节”与我的压缩文件相同,我不知道我是怎么做的可以跳过这些第一个“字节”并尝试解压缩其余的“数据”,也可以从日志中看到某种类型的“标志”也需要跳过,这是未压缩的类似文件的样子


00000000  99 99 99 99 44 44 44 44  55 55 55 55 aa aa aa aa  |....DDDDUUUU....|
00000010  00 00 00 00 00 00 00 00  00 00 00 04 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 40  |...............@|
00000040  00 02 00 00 00 00 00 80  00 04 5e 85 00 00 00 00  |..........^.....|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000080  3c 44 42 3e 0a 3c 54 62  6c 20 6e 61 6d 65 3d 22  |<DB>.<Tbl name="|
00000090  44 42 42 61 73 65 22 20  52 6f 77 43 6f 75 6e 74  |DBBase" RowCount|
000000a0  3d 22 31 22 3e 0a 3c 52  6f 77 20 4e 6f 3d 22 30  |="1">.<Row No="0|
000000b0  22 3e 0a 3c 44 4d 20 6e  61 6d 65 3d 22 49 46 49  |">.<DM name="IFI|
000000c0  6e 66 6f 22 20 76 61 6c  3d 22 30 31 30 31 30 32  |nfo" val="010102|
000000d0  30 31 30 34 30 30 30 30  30 30 30 31 30 36 30 31  |0104000000010601|
000000e0  30 34 30 30 30 30 30 32  31 32 35 30 30 30 30 30  |0400000212500000|
000000f0  30 30 35 30 30 31 30 30  30 30 35 30 30 32 30 30  |0050010000500200|
00000100  30 30 35 30 30 33 30 30  30 30 22 2f 3e 0a 3c 2f  |0050030000"/>.</|
00000110  52 6f 77 3e 0a 3c 2f 54  62 6c 3e 0a 3c 54 62 6c  |Row>.</Tbl>.<Tbl|
00000120  20 6e 61 6d 65 3d 22 45  54 48 22 20 52 6f 77 43  | name="ETH" RowC|
00000130  6f 75 6e 74 3d 22 34 22  3e 0a 3c 52 6f 77 20 4e  |ount="4">.<Row N|
00000140  6f 3d 22 30 22 3e 0a 3c  44 4d 20 6e 61 6d 65 3d  |o="0">.<DM name=|
00000150  22 56 69 65 77 4e 61 6d  65 22 20 76 61 6c 3d 22  |"ViewName" val="|
00000160  49 47 44 2e 4c 44 31 2e  45 54 48 31 22 2f 3e 0a  |IGD.LD1.ETH1"/>.|
00000170  3c 44 4d 20 6e 61 6d 65  3d 22 4c 44 57 44 56 69  |<DM name="LDWDVi|

在这里你可以找到压缩备份。

编辑:在图片上,您可以看到(左侧)上的两个文件 db_user_cfg.xml(来自日志的文件)和“相同文件”的比较,但何时在右侧“备份”

中兴比较

3个回答

如果您查看备份文件的偏移量 0xDF,您将看到两个字节:

0x78 0xDA

这些通常分隔 zlib 压缩文件的开头。

事实上,原来的 XML 配置文件已经被拆分成多个 zlib 压缩块:

$ binwalk default-config.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------------------
223           0xDF            Zlib header, best compression, uncompressed size >= 8192
1211          0x4BB           Zlib header, best compression, uncompressed size >= 8192
2260          0x8D4           Zlib header, best compression, uncompressed size >= 8192
2901          0xB55           Zlib header, best compression, uncompressed size >= 8192
3796          0xED4           Zlib header, best compression, uncompressed size >= 8192
4306          0x10D2          Zlib header, best compression, uncompressed size >= 8192
5224          0x1468          Zlib header, best compression, uncompressed size >= 8192
6066          0x17B2          Zlib header, best compression, uncompressed size >= 8192
7084          0x1BAC          Zlib header, best compression, uncompressed size >= 8192
8058          0x1F7A          Zlib header, best compression, uncompressed size >= 8192
8981          0x2315          Zlib header, best compression, uncompressed size >= 3156

如果您解压缩每个块并将解压缩的数据连接在一起,您将获得原始 XML 配置文件。

好的,这是可行的小python脚本:)


import zlib

magic_numbers = ['\x78\xDA'] filename = 'config-marina.bin'

infile = open(filename, 'r') data = infile.read()

pos = 0 found = False

while pos < len(data): window = data[pos:pos+2] for marker in magic_numbers: if window == marker: found = True start = pos print "Start of zlib %s" % pos rest_of_data = data[start:] decomp_obj = zlib.decompressobj() uncompressed_msg = decomp_obj.decompress(rest_of_data) print "Content: %s" % uncompressed_msg break if pos == len(data): break pos += 1

if found: header = data[:start] footer = decomp_obj.unused_data

if not found: print "Sorry, no zlib found."

config.bin 文件中的每个压缩块都由一个包含以下信息的小 3-DWORD 标头开头:

  1. 未压缩的 xml 块的长度。对于除最后一个块之外的所有块,此值为 0x10000
  2. 压缩后的 zlib 块的长度
  3. 附加块后文件的累积长度。对于最后一个块,该值为 0x0。

这些标头可用于在块检测期间避免误报:有效块将在第一个字段上具有 0x10000 或在第三个字段上具有 0x0。标头还可用于验证未压缩的数据大小。

import re
import zlib
import struct


def extract_config_xml(config_bin):
    config_xml = b''
    for zlib_chunk in re.finditer('\x78\xda', config_bin):
        zlib_chunk_start = zlib_chunk.start()
        zlib_chunk_header = config_bin[zlib_chunk_start - 12: zlib_chunk_start]
        xml_chunk_length, zlib_chunk_length, config_bin_length = \
            struct.unpack('>LLL', zlib_chunk_header)
        if xml_chunk_length == 0x10000 or config_bin_length == 0:
            zlib_chunk_end = zlib_chunk_start + zlib_chunk_length
            zlib_chunk = config_bin[zlib_chunk_start: zlib_chunk_end]
            xml_chunk = zlib.decompress(zlib_chunk)
            assert xml_chunk_length == len(xml_chunk)
            config_xml += xml_chunk
    return config_xml


with open('config.bin', 'rb') as f:
    print extract_config_xml(f.read())