前言

在数个月之前,完成了OjoDnfExtractor的开发,该软件用于提取Dnf的资源包文件。

在做Dnf这些资源包文件的解析过程中,我明白了文件结构该如何设计。(也尝试了去设计文件结构)

经过多番观察、推测,成功解析了NPK以及IMG-Ver1、2、4、5、6的文件结构(支持读写)。

正文

npk文件是dnf用于模拟文件目录结构所使用的,结构相对简单。

为了直观的展示其结构,直接插图。

NPK头部结构图
Color Name Type Remark
红色 magic char[16] 文件标识
橙色 count int 文件数量
黄色 offset int 文件偏移
绿色 size int 文件尺寸
青色 name char[256] 文件名,加密过
蓝色 hash byte[32] 文件头哈希值(sha256)
# magic值
FILE_MAGIC = 'NeoplePack_Bill'
# 文件名加解密密钥
C_DECORD_FLAG = bytes('puchikon@neople dungeon and fighter %s\x00' % ('DNF' * 73), encoding='ascii')

由此可见,npk首先是由头部的magic进行验证是否为npk文件。

  • 然后通过count取得文件数量,循环加载offset、size、name这些信息(三位一体)。

    • 文件名加解密:使用密钥对文件名数据每一位进行位异或运算。(euc-kr编码)
  • 加载完成后,通过hash可以对文件头部进行验证(毕竟都是关键信息)。

    • hash计算:取文件头数据左边,长度为整除17位再乘17位的部分,进行sha256运算。

      hashlib.sha256(head_data[:len(head_data) // 17 * 17]).digest()
      

一般读取完成头部信息+hash值之后,当前位置就是文件数据了(file[0]['offset']),如前面的图所示,后面就是IMG文件的magic了。

当得到这些信息之后,即可通过offset以及size读取对应img/ogg文件了。

结语

有以上的信息,要实现npk的读写,已经是轻而易举了。

原来是打算一次写完的,不过当我写完NPK篇就已经花了不少时间,所以有空再更新IMG篇。