反向 LZSS 压缩算法的问题

逆向工程 固件 十六进制 解压
2021-07-07 11:31:53

我正在尝试对我的 HP 打印机的固件进行逆向工程,所以我从板上转储了 SPI 芯片,并且有很多字符串,但几乎总是看起来像这样: 在此处输入图片说明

我注意到一种模式,有时每 8 个字节后添加一个 FF 字节。然而,这并不是全部模式。有谁知道这可能是什么?这不是转储错误,因为我从未压缩的部分中提取了一些 JPEG 图像就好了,并且多次转储生成相同的文件。

更新: 我认为这可能是 LZSS 压缩,我设法解压缩了这部分并得到了这个. 但是,当我在具有相同模式另一部分尝试相同的脚本时,它无法正确解压缩。可能是什么原因?

我将 QuickBMS 脚本用于 LZSS 算法(代码如下)。理想情况下,我想用 python 来做,但我发现的脚本即使使用相同的 LZSS 参数也没有产生好的结果。我对 QuickBMS 脚本不是很熟悉。

# lzss decompression function written in 100% bms scripting

set NAME string "unpacked.dat"
get ZSIZE asize
math SIZE = ZSIZE
math SIZE *= 10
log MEMORY_FILE 0 ZSIZE
callfunction LZSS_BMS_DUMP

# you must set: MEMORY_FILE (input), ZSIZE (input size), MEMORY_FILE2 (output), SIZE (max size)
startfunction LZSS_BMS_DUMP
    set EI long 12
    set EJ long 4
    set P long 2
    set rless long P
    set init_chr long 0x00

    set N long 1
    math N <<= EI
    set F long 1
    math F <<= EJ

    # pre-allocate memory for faster performances
    putvarchr MEMORY_FILE3 N 0
    for i = 0 < N
        putvarchr MEMORY_FILE3 i init_chr
    next i
    putvarchr MEMORY_FILE2 SIZE 0

    math r = N
    math r -= F
    math r -= rless
    math N -= 1
    math F -= 1

    math src = 0
    math dst = 0
    math srcend = ZSIZE
    math dstend = SIZE

    math flags = 0
    for src = 0 < srcend
        if flags & 0x100
        else
            getvarchr flags MEMORY_FILE src
            math src += 1
            math flags |= 0xff00
        endif
        if flags & 1
            getvarchr c MEMORY_FILE src
            math src += 1
            putvarchr MEMORY_FILE2 dst c
            math dst += 1
            putvarchr MEMORY_FILE3 r c
            math r += 1
            math r &= N
        else
            getvarchr i MEMORY_FILE src
            math src += 1
            getvarchr j MEMORY_FILE src
            math src += 1
            math TMP = j
            math TMP >>= EJ
            math TMP <<= 8
            math i |= TMP
            math j &= F
            math j += P
            for k = 0 <= j
                math TMP = i
                math TMP += k
                math TMP &= N
                getvarchr c  MEMORY_FILE3 TMP
                putvarchr MEMORY_FILE2 dst c
                math dst += 1
                putvarchr MEMORY_FILE3 r c
                math r += 1
                math r &= N
            next k
        endif
        math flags >>= 1
    next
    math SIZE = dst
    log NAME 0 SIZE MEMORY_FILE2
endfunction
1个回答

几年后的经验,我重新审视了这个项目并弄清楚了!压缩实际上是 LZSS,我问题中的 QuickBMS 脚本能够正确解压缩它。我提到的第二部分有问题,因为芯片转储中的压缩块之间存在未压缩的块,因此,显然,它们需要单独提取和解压缩。

如果有人对正确理解 LZSS 感兴趣,我真的很喜欢“复古游戏考古学:探索旧电脑游戏”一书中的解释方式,第 104 页(可以在 Google 图书上免费查看)。

感谢所有人的帮助,如果这里没有一个了不起的社区,我无法弄清楚!:)