DNF的SPK文件解析笔记

  欢迎参与讨论,转载请注明出处。
  本文转载自https://musoucrow.github.io/2017/07/21/spk_analysis/

前言

  SPK文件是DNF的一种更新时所用的压缩包(国服除外),在更新时会从服务器下载这种SPK文件然后于本地解压。有时候为了获得更快的速度,以及突破墙的限制,我们通过获取到更新服务器的网址直接下载。但是此刻对于如何将SPK文件解压便是个问题了,本文遂由此而生。

详解

  SPK文件的本质上是将原文件按照一定规则进行分割成多个片段,然后对这些片段使用bzip2算法进行压缩。以下是文件结构图:1

  由于信息的不对称,导致不少地方是处于盲区的,不过这并不影响获取到关键数据。这种被压缩的片段开头标识为”BZh91AY&SY”,所以只需要以此为关键字进行分割就能得出关键数据了,不过实际操作时发现除了压缩数据之外还有非压缩数据,并且会用一段48字节的数据进行分隔。且拥有非压缩数据的片段结尾也会有一段意味不明的数据,好在它们都有对应的开头标识,进行分割即可。
  在得出压缩数据后使用bzip2算法进行解压缩,然后将所有解压后的数据与非压缩数据按顺序进行拼接,每个片段如此类推最后总体拼接起来即可得到完整的原文件。本次解析使用的环境是Python3.6,以下是过程代码:

import sys
import bz2
import struct


HEADER = b"BZh91AY&SY"
MARK = b"\x00\x00\x00\x00\x00\x10\x0e\x00\xff\xff\xff\xff\xff\xef\xf1\xff"
# 00 00 00 00 00 10 0E 00 FF FF FF FF FF EF F1 FF
TAIL = b"\x01\x00\x00\x00"  # 01 00 00 00


def decompress_spk(path):
    f = open(path, "rb")

    f.read(4)  # unknown, all files are same.
    f.read(260)  # total 260 bits, contain name and buffer.
    f.read(4)  # unknown, all files are same.
    struct.unpack('i', f.read(4))[0]  # decompress_size

    content = f.read()
    parts = content.split(HEADER)
    f.close()

    new_content = b""

    for n in range(1, len(parts)):
        lst = parts[n].split(MARK)
        length = len(lst)
        new_content = new_content + bz2.decompress(HEADER + lst[0])

        if length > 1:
            for m in range(1, length - 1):
                new_content = new_content + lst[m][32:]

            pos = lst[length - 1].rfind(TAIL)
            new_content = new_content + lst[length - 1][32:pos]

    f2 = open(path[:-4], "wb")
    f2.write(new_content)
    f2.close()

if __name__ == "__main__" and len(sys.argv) > 1:
    decompress_spk(sys.argv[1])

后记

  事实上这种SPK的压缩机制效果根本是微乎其微,我完全不明白Neople这么做的用意。以及片段的划分机制和诸多盲区都没搞懂,看来我得考虑学下逆向方面的知识了。不过无论如何,最终要达到的目标还是做到了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值