这几天在玩剑三,突然兴趣来了,想要分析剑3的资源打包格式。在资源分析和逆向方面原来偶尔也干过,
不过总体来说还是处于菜鸟阶段,这篇文章希望和其他有兴趣的兄弟分享下这几天的经历,仅仅作为技术研究。
一、安全保护
一般来说,很少有游戏的资源格式可以直接通过分析资源文件本身得到答案,大部分难免要静态逆向、动态调试。
无论是静态逆向还是动态调试,首先需要知道当前exe和dll的保护情况,用peid查看,发现只有gameupdater.exe 用upx加壳了。不太明白金山为什么对客户端没有加壳。
其实我并不关心gameupdater.exe 是否加壳,毕竟要动态分析的目标是JX3Client.exe
,要动态调试JX3Client.exe,首先要解决启动参数问题。
二、启动参数
如果直接启动JX3Client.exe,JX3Client.exe会直接退出,并启动gameuodater.exe,然后通过gameupdater.exe启动JX3Client.exe。
这种启动方式会影响动态调试,所以首先我需要找出JX3Client.exe的启动参数。打开IDA逆向,转到启动处,汇编代码如下:
start proc near
call ___security_init_cookie
jmp ___tmainCRTStartup
start endp
这是一个典型的VC程序入口,在___tmainCRTStartup
里,crt会初始化全局变量、静态变量,然后进入main,我们需要做的是直接找到main,
跟进去,会发现IDA已经帮我们找到WinMain了,直接跟进去,
关键代码在WinMain的入口处:
从这个代码片段可以知道,WinMain开始就比较了命令行参数是否是"DOTNOTSTARTGAMEBYJX3CLIENT.EXE
",如果不是,
则转到启动更新程序了。这个好办,我们写一个run.bat,内容只有一行:
JX3Client.exe DOTNOTSTARTGAMEBYJX3CLIENT.EXE
运行,果然,直接看到加载界面了。
三、PAK文件管理
在剑3里,PAK目录下有很多PAK文件,剑3是通过package.ini 来加载和管理pak内部文件的。
这个文件内容如下:
[SO3Client]
10=data_5.pak
1=ui.pak
0=update_1.pak
3=maps.pak
2=settings.pak
5=scripts.pak
4=represent.pak
7=data_2.pak
6=data_1.pak
9=data_4.pak
Path=.\pak
8=data_3.pak
基本上PAK目录下所有的PAK文件都列出来了,其实剑3的资源文件打包方式基本上和新剑侠情缘类似(细节还是有比较大的差别)。
打开ollyDbg,带参数启动JX3Client.exe,在CreateFile设置断点,可以发现,package.ini
的读取和处理是在
Engine_Lua5.dll
的g_LoadPackageFiles
函数,熟悉新剑侠情缘资源管理方式的同学大概会猜到这个函数是做什么的,先看看函数内容吧,这个函数比较长
只能逐步的分析了,首先是打开ini文件
使用g_OpenIniFile打开前面提到的ini文件,如果打开失败,自然直接返回了。
打开成功后,循环读取ini配置的文件,读取的section是SO3Client 读取的key是0到0x20。
loc_1001119A: ; int
push 0Ah
lea ecx, [esp+1A0h+var_178]
push ecx ; char *
push ebx ; int
call ds:_itoa ; 这是根据数字生成key的代码
mov edx, [ebp+0]
mov edx, [edx+24h]
add esp, 0Ch
push 40h
lea eax, [esp+1A0h+var_168]
push eax
mov eax, [esp+1A4h+var_184]
push offset unk_10035B8C
lea ecx, [esp+1A8h+var_178]
push ecx
push eax
mov ecx, ebp
call edx ; 读取INI内容 readString(section, key)
test eax, eax
jz loc_1001127A
这段是通过readString("SO3Client", key)来获取pak文件名, key就是"0"~"32"的字符串,也就是最多能配置32个Pak文件。
获得了pak文件名后,下面就是打开和保存pak文件的索引数据了。
后面的注释是我分析的时候加上的,IDA这个功能不错!
首先new一个0x20字节的空间用来存储pak对象(我自己命名的类),接着调用构造函数,创建pak对象。
创建对象后,要用这个Pak对象打开对应的pak文件了,这是我们下面的代码:
首先通过
mov [edi+edx*4], eax
将对象保存,然后,调用这个类的成员函数打开pak文件,具体代码在sub_10010ca0。
这段代码的意思很明白了,打开文件,读取0x20的文件头,
这里做的是验证文件格式,和一些必要的验证。
这段是读取pak内部文件数目,读取索引数据,以备后面查询使用。
到此为止,所有pak文件的管理对象都已经加载和设置完毕了。
以上内容看起来很顺理成章,但是实际上凝聚了无数的失败和重试。
后面是pak内部文件的查找和读取了。
剩下的内容明天贴了~~~
posted on 2010-07-15 21:07
feixuwu 阅读(5110)
评论(10) 编辑 收藏 引用 所属分类:
逆向工程