剑3资源格式分析(仅用于学习和技术研究)(二)

本文解析了剑网3游戏中的pak文件格式及其内部文件的查询与解压过程。介绍了pak文件通过hash值进行快速查询的方法,以及如何利用C++技巧定位到文件解压函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   继续未完成的内容,声明本文仅用于学习研究,不提供解压工具和实际代码
由 于时间仓促,剑3资源格式分析(仅用于学习和技术研究)(一) 大部分只是贴出了分析的结果,并没有详细的分析过程,比如:如何知道那是一个pak文件处理对象,
如何根据虚表偏移获取实际函数地址等等,这就需 要读者对c++对象在内存中的layout有一定基础。
开始正文了~~,先整理下前面的分析结果:
1、剑3是通过package.ini 来管理pak文件的,最多可配置key从 0-32(0x20)的32个文件。
2、每个pak文件都用一个独立对象来管理,所有的pak对象指 针存储在一个数组里(这个后面会用到)。
3、pak文件格式:[pak标记(Uint32)] + [文件数目(Uint32)]+[索引数据偏移(Uint32)]+未知内容。另外,每个文件的索引数据是16个字节。

一、路径名哈希

  剑3的pak的内部文件是通过hash值来查找的,这样有利于加快查询速度。这就需要有一个函数通过传入 路径名返回hash值。
这个函数居 然是导出的。。。g_FileNameHash  这个函数代码比较少,可以逆向出来用C重写,也可以直接使用引擎函数(LoadLibrary,GetProceAddress来使用)。
熟悉剑 侠系列的朋友会发现,这个函数从新剑侠情缘(可能历史更久)开始就没有变过(确实没必要变),具体细节就不逐个分析了,我是写了一个单独的命令行工具
来 测试的。

二、查询过程

查询函数在sub_10010E00 里,也就是(0x10010E00)的位置,我是通过简单分析g_IsFileExist 得知这个函数功能的。下面
来分析这个函数过程:

从前文可知,pak文件对象是存储在一个数组的这个数组是类似 KPakFile* m_szPakFile[0x21];
前面0x20个存储的都是KPakFile对象指针,最后一个存储的是数组长度。
这个搜索结构比较 简单,就是遍历所有的KPakFile对象,逐个查询,找到了就返回。想知道具体怎么查询的吗,
接下来要看sub_100108B0了。

这 个函数稍微有点长,分几个部分来分析吧:

首先,验证下Hash值是否是0,如果是0,肯定是错了:)
然后接着开始根据这个 hash值进行查找了,经过分析,我发现这个函数其实是一个二分查找,代码贴出来如下 sub_10010320 :



从上面的代码还是比较容易可以知道,每个文件的16个索引数据中,前4个字节是hash值, 这个函数返回的是这个文件是pak包的第几个。

接着前面的sub_100108B0 来看吧

这一段是保存查询到的数据到对象里。分析到这里,我只知道16个索引数据前4个字节是 hash值,那么剩下的12个字节呢,
剩下的数据基本可以确定是:文件偏移、文件长度。我是个懒人,接下来的分析我是通过在fseek、 fread下断点来得到的,为什么不是在SetFilePointer和ReadFile呢,
这是根据前面的分析得到的,因为pak文件管理对象 使用的是C标准库函数。
根据fread和fseek的结果,可以得到如下结果:
索引数据构成是:
[哈希数值(Uint32)] + [文件偏移(Uint32)]+[未知数据(Uint32)] + 2(文件长度)+2(未知数据)。
剩下的,就是看看单独内部文件的解压方式 了,
在fread的缓冲区上设置内存断点,就可以找到解压函数了:
sub_10018020
这个函数不算太长,一开始我也想逆向 成C语言,后来看到如此多的分支就放弃了,转而用了一个偷懒的办法解决了:
从汇编代码可知这个函数的原型:
typedef int (*PUNPACK_FUN)(void* psrcData, int nSrcLen, void* pDstData, int* pDstLen);
直接加载剑3的dll,设置函数地址:
PUNPACK_FUN pEngineUnpack = (PUNPACK_FUN)((unsigned int)hEngineModule + 0x18020);
hEngineModule 是引擎dll的基址,大家看到了吧,dll的函数即使不导出,我们也是可以调用的:)

三、尾声

到这里,已经可以写出一个pak文件的解压包了,但是,我们还是没有还原真实的文件名,
下面是我解压的script.pak的文件的部分内容:

 终于看到大侠们的签名了。当然,对着一堆hash值为名字的文件,阅读起来确实很困难,
那 么有办法还原真实的文件名吗,办法还是有一些的,可以通过各种办法改写g_OpenFileInPak记录参数名,来获取游戏中用到的pak内部文件名, 相信这难不倒各位了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值