軒轅劍伍:一劍凌雲山海情

PEiD探壳:StarForce V3.X -> StarForce Copy Protection System [Overlay] *

軒轅劍伍繁体CD版是可以通过双机模拟iSCSI绕过STARFORCE的(参考游侠网上文章),脱壳前要先能双机进游戏,或者如果有正版也行

安装完后先观察目录,所有文件包括动画都有,而且只要一开始通过了StarForce验证后,即使拿出盘也可以玩,这就是说只要脱了壳就可免CD

OD加载swd5.exe,还没见到入口就挂了

注意游戏目录下有个文件binkw32.dll,这个显然是播放BIK动画的
STARFORCE再流氓总不能程序异常出错连个非法操作也不跳出来吧?抓住这个问题就可以把OD载进去
先修改binkw32.dll中有个函数_BinkOpen(从名字可以猜出来播放动画肯定要调用它),在此函数入口加个int3
运行游戏,一放开场动画果然非法,事先把OD设为默认调试器,这个时候点调试就可以乘虚而入了

大概调了一下发现F8,F7是不行的,会被SF发现,不过既然SF买int3的帐,当然就可以F2+F9,这样和F8也差不多,只是麻烦一点

利用binkw32.dll断下来后就可以DUMP了,抓下来IDA一看,没想到代码居然没有变过型,入口很清楚,就在0065D00E处,而且IDA还可以把VC库函数都识别出来,SF在这方面倒是挺安分的...

但这不是在OEP脱的,为什么非要在OEP呢?因为在OEP时全局变量没有被动过,这是非常重要的
举个例子,以上在binkw32.dll中断所DUMP的文件,即使把OEP,IAT修复还是会出错,这个错误出在EnterCriticalSection,因为VC的启动代码会初始化一个临界区全局变量,就是mlock.c中的PCRITICAL_SECTION _locktable[_TOTAL_LOCKS],而上面所DUMP文件中这个量并非为0,因此启动代码会认为已经初始化,从而跳过初始化过程,所以EnterCriticalSection时传递的就是无效临界区
程序一旦经历了后面的代码,全局变量也就不同了,人一旦经历了有些事,也就不再是原来那个人了,现在的尔玛再回山里放羊又焉能心境淡远如初?所以这么DUMP是不行的,就算可以把引起异常的变量都一一修复掉,那些不会引起异常的逻辑错误又怎么办?有些内在的东西一旦变了,不是那么容易就能变回去的

所以还是要在OEP处DUMP,OD根本无法在调试状态下运行游戏,怎么停在OEP呢?
别忘了SF发现没放光盘还会提醒放入后重试,乘此良机又可钻进去:
先拿出光盘,运行swd5.exe,此刻kernel32.dll等文件都已经加载到内存,用WinHex编辑内存,修改GetVersion最后一行ret为CC,我的机器上这个地址是7C8114DB,然后放入光盘,点重试,SF是很给CC面子的,于是乖乖的在GetVersion非法
此时DUMP的文件只要修正下入口点就算是在OEP处DUMP的了

然而IDA载入后却发现很多库函数都残废了,只有到运行时SF才会补上代码,想要精神和肉体都同时不受束缚怎么可能?现实总是充满矛盾
幸而在CPU里发生的事没有那么残酷,两全其美还是可能的
binkw32.dll处DUMP精神残废肉体健全,GetVersion处DUMP肉体残废精神正常,既然如此不妨各取其完好的地方重新拼装一个:
VC的全局变量段在IDA里很好识别的,swd5.exe的变量段就是006BD000处大小为297000的_brick段
将OEP处DUMP文件中的这个段保存下来并复制到binkw32.dll处DUMP的文件,这个文件就同时具有正确的代码和变量

但它仍然不健全,开两个OD加载DUMP的文件和在停在GetVersion的文件,打开内存镜像对比,会发现DUMP的文件少了很多快内存段
这些内存段是SF动态申请的,每次地址都不同,我脱壳时这种内存有57块,地址从1220000到02200000,大小各不相同,1000,10000,40000...
这些里面放的是SF初始化后的变量,大概是用了SDK的原因,因为全局变量中有指向这些动态内存的指针,试想在OEP时什么都没运行,怎么会有静态指针指向动态数据?可能的解释只能是一部分变量由SF初始化(这里面包括当前的游戏目录字符串)

这样的话只好写个loader修复了,内存段太多,不可能全保存到exe里,我写了个由ini配置文件载入段的loader,在附件中
在OEP处将57个段保存下来并DUMP修复全局变量段,同时保存IAT(addr=00697FFC size=340)这时用loader先载入内存段,加CC中断在OEP,再用OD载入调试,再载入IAT,这时F9已经可以免CD运行游戏了,SF所HOOK的IAT指向了那57个内存段,虽然没有识别出来,不过运行是没问题的

IAT没有识别毕竟遗憾,但这时的程序已经脱离了老流氓的魔抓,可以用OD正常调试,要修复IAT还会难吗?
imprec分析后大概有20多个函数未知,用OD载入一一修复,这些函数是SF模拟了部分系统代码,对比一下还是容易识别出来的
比如00698060这个IAT干脆没有调用任何API,不过其中有一行指令shrd eax,edx,18
只要在kernel32.dll模块中搜索这个指令很容易发现00698060就是kernel32.GetTickCount
再比如006980FC壳代码有一行mov eax,dword ptr ds:[7C88303C],搜索此行发现是IsBadReadPtr
后面有个把API指令不怎么特殊,搜索不管用了,可以让OD分析user32.dll,kernel32.dll,然后call到系统DLL里时根据交叉参考分析出来
比如006982D4这个IAT,壳代码先调用了77D184D0,进入user32.dll,OD中间的窗口显示有所有call到这里的来源,点开"显示全部跳转和局部调用"那个窗口,一一查看,因为壳代码调用完77D184D0接着就调用了77D1B65A,所以只要看哪一个下面有call 77D1B65A,很快就发现这是GetClientRect
比较邪的就是HeapAlloc/HeapFree这两个函数,如果系统是XP直接定向到ntdll里,在kernel32.dll里干脆没这个符号(感谢blackthink,DiKeN,Erika,bbbsl几位朋友的帮助)
另外,有好几个函数在IDA里可看到有库函数调用,这就更容易,只要打开VC6的库函数代码对比一下就发现了
附件中有一个完整的IAT

修完IAT后可以不用OD载入,直接用loader载入内存段就能运行,进一步处理懒得弄了(游戏目录被定死)

轩辕剑5是个好游戏,在大陆上市了我肯定会买正版的,如今象大宇这样还在做单机RPG的公司不多了,而且简体版马上要在大陆发行,各位朋友要是做出免CD补丁,烦请别放到网上,以保护正版

DonQuixote[CCG][iPB]
Email:DonQuixote@mail.nankai.edu.cn
2006/8/12

附件下载:loader.rar