逆向工程第002篇:打造自己的仙剑奇侠
众所周知,在国产RPG游戏里面,《仙剑奇侠传》是永恒的经典。发布近二十年以来,依旧话题不断。但是鲜有人对其进行逆向分析,只是听说多年之前曾有人为了探究其是否有隐藏剧情,从而采取了某种逆向分析的手段。在此,我依旧以通过分析其存档文件的方式,从最简单的修改金钱出发,以主角李逍遥为研究对象,逆向追踪物品、人物状态以及法术的相对地址标志位,以无限制使用“酒神”为最终目标,从而实现打造自己的仙剑奇侠的目的。图1《仙剑奇侠传》游戏封面
一、观察游戏目录中的文件信息 《仙剑奇侠传》游戏目录中包含有两个文件夹以及35个文件。两个文件夹分别用于存储游戏说明文件(网页版)以及游戏音乐。剩下的35个文件,包含有6个AVI格式的视频文件,即游戏中的所有片头片尾及过场动画。包含6个以RPG为扩展名的存档文件,以0至5作为文件名,对应于游戏中的5个存档位置,其中0.RPG文件可能仅作备份之用,因此实际可用的存档文件为1.RPG、2.RPG、3.RPG、4.RPG以及5.RPG。只有在游戏中保存过进度,这五个存档文件才会依次出现,否则游戏文件夹中初始只有0.RPG。而存档文件也是本文重点分析的对象。然后,还有14个MKF格式的文件,1个ICO(图标)文件,4个DLL(动态链接库)文件,1个INI(配置)文件,1个DAT(数据)文件,1个MSG文件以及1个EXE(可执行)文件,因为这些文件不对我们的修改产生影响,因此不作深入讨论。但是需要注意的是,M.msg文件保存有游戏中的所有旁白以及对话信息,可通过修改这个文件的内容来达到修改游戏对话及旁白的目的。而Word.dat文件保存有游戏中所有的物品及法术等文字信息,稍后会用到这个文件的内容。图2《仙剑奇侠传》游戏目录
二、修改游戏金钱 游戏金钱的修改可以说是一切的根本,是我们逆向研究的起点。通过对金钱的修改,可以在游戏中的商店(武器铺、杂货铺及药铺等)随意购买任何物品,同时也可以无限制使用“乾坤一掷”。但由于游戏初始的金钱数为0,不好搜索,幸运的是很快苗人首领就给了我们500金钱。十进制的500等于十六进制的1F4,由于是小端显示,因此在游戏存档文件的十六进制代码中应该是以F401的方式显示的,通过这个就可以迅速定位。经过测试可以知道在相对地址0x00028至0x0002b这四个字节就是游戏中金钱的标志位。由于游戏中只能显示六位有效的金钱数字,而如果超出六位,要么会只保留低六位显示,要么就是彻底不显示。因此将金钱修改为999999即十六进制的F423F(小端显示为3F420F)就足够了。图3金钱标志位
三、逆向追踪并修改物品 一般来说,RPG游戏会有众多的各式各样的物品,那么我们的工作就是找到这些物品在游戏中的编号以及相对地址。如果能够找到,那么就无需在游戏中购买物品,金钱的作用也就仅仅是使用“铜钱镖”以及“乾坤一掷”了。游戏初始我们身上是没有任何物品的,但是在李逍遥自己的房间可以找到止血草、净衣符、木鞋以及皮帽,这就已经足够了。在取得物品前后分别存档,用文件二进制代码比较软件对这两个存档进行比较,那么就可以找到物品的标志位。它起始于相对地址为0x006c0的位置,以六个字节为一个单元表示一样物品(这点比较特殊,一般别的标志位都是以两个字节为一个单元)。在这六个字节中,前两个字节是物品的编号,第三个字节是物品的数量,之后再用三个字节的00作为填充对齐之用。图4物品标志位 通过分析可以得知,止血草的编号为63(十六进制),净衣符为40,木鞋为ec,皮帽为c9。有理由相信,游戏中的所有物品都是以某种顺序排列的,编号也是依次排列下来的。所以在此需要分析之前提到过的Word.dat文件。图5 Word.dat文件(部分内容) 可见游戏物品中排在第一位的是“观音符”,而“净衣符”排在第四位,那么依照顺序可以得知,“观音符”的编号为3d,以此可以类推到编号为126(十六进制)的最后一样物品,也就是芦苇漂。这些物品包括恢复类物品、剧情类物品以及武器防具等。至此所有物品的编号以及标志位都已经推断出,现在就可以通过修改获得任意物品了。表1《仙剑奇侠传》所有物品编号列表
四、逆向追踪并修改人物状态 在游戏中的人物状态界面中共有九项内容,它们分别是:Exp(经验值)、修行、体力、真气、武术、灵力、防御、身法以及吉运。由于Exp以及修行的修改没有意义,故不予论述。图6人物状态界面 体力的修改比较简单,可以直接搜索96(十六进制,李逍遥的初始体力值),之后对搜索出来的结果分别修改,然后进入游戏以进行查看。这里至少会搜索出两个正确的结果,即当前的体力值以及体力的最大值。于是可以知道: 李逍遥的体力最大值标志位的相对地址为0x00250以及0x00251, 李逍遥当前的体力值标志位的相对地址为0x00268以及0x00269。 同理可以检索到: 李逍遥的真气最大值标志位的相对地址为0x0025c以及0x0025d, 李逍遥当前的真气值标志位的相对地址为0x00274以及0x00275。图7李逍遥的体力与真气值标志位 这里需要特别说明的是,在李逍遥每一项体力或者真气标志位的后面都还有十个字节的数据,这些数据代表的是其他五位游戏中的可控人物的初始体力或者真气值。举个例子来说,游戏第二个可控出场人物是赵灵儿,那么她的这四项数值就是紧紧跟在李逍遥四项数值的后面。例如0x00252以及0x00253,这两个字节是赵灵儿的初始体力值上限,也就是十六进制的00f0,即十进制的240。以此类推,这里不再赘述。那么我们就可以对所有登场人物的体力值以及真气值进行修改,但是最大值不能超过十进制的999,即十六进制的03e7。 之后的五种状态属性比较特殊,基本不能通过直接搜索获得相对地址。比如搜索武术属性,李逍遥的初始值为十进制的35,即十六进制的23,可是即便将所有的搜索结果进行改动,游戏中李逍遥的武术值依旧无法改变,那么可以得知游戏中是以其他的数值来取代该项数据的。为了进行修改,可以首先修改出一定数量的金蚕王,通过在游戏中使用金蚕王来使李逍遥不断升级,那么这五个状态属性也就会随之改变。将改变前的存档与改变后的存档用二进制代码对比软件进行对比,就可以锁定这些状态属性的位置了。于是便得到: 李逍遥武术属性标志位的相对地址为0x002c8以及0x002c9; 李逍遥灵力属性标志位的相对地址为0x002d4以及0x002d5; 李逍遥防御属性标志位的相对地址为0x002e0以及0x002e1; 李逍遥身法属性标志位的相对地址为0x002ec以及0x002ed; 李逍遥吉运属性标志位的相对地址为0x002f8以及0x002f9。图8李逍遥的五种状态属性标志位 同理,李逍遥每种属性后面的五个字节分别对应于游戏中五个可控人物的属性值,此处也不再论述。 以武术属性为例,游戏中显示的值为35,而实际搜索出来的值为33。之所以会出现这样的情况,我认为是因为游戏中李逍遥在没有任何装备的前提下会有一个基础属性值,而进行装备之后的实际属性值则是游戏中显示的值,这里为35。游戏初始,李逍遥装备了武术加2的木剑,李逍遥的基础武术值33加上木剑的加成,得到35。那么可以得知,我们搜索出来的这五项属性值就是人物的基础属性值,它们的实际在游戏中的属性值还需加上相应的装备的加成。也正是因为这个原因,才会出现开始时搜不到属性值的情况。
五、逆向追踪并修改法术 其实法术的逆向追踪与修改的原理与之前的物品逆向的方法相同,同样要配合Word.dat文件进行。通过该文件可以得知各项法术的编号,因为法术是紧挨着物品依次排列下来的。而通过对比的手段则可以定位法术的相对地址。表2《仙剑奇侠传》所有法术编号列表 李逍遥最初只有“气疗术”这一招法术,在山神庙师从酒剑仙又可以学会“御剑术”,那么通过山神庙剧情前后的存档文件对比,搜索代表“气疗术”的0128(十六进制)以及代表“御剑术”的0159(十六进制)就可以锁定法术的相对地址,即0x0037c以及0x0037d为李逍遥第一个法术的位置,间隔十个字节,来到0x00388以及0x00389的位置,即为李逍遥第二个法术的位置(若没有法术则显示0000)。依此类推,每隔十个字节就是李逍遥下一个法术的位置。而同样地,李逍遥每两个法术之间,是其他可控人物的法术标志位,这里也不再进行讨论。图9李逍遥法术标志位 经过以上分析,就可以实现人物法术的修改,可以在游戏初期就拥有高级别的法术,但是“酒神”法术却比较特殊,需要另外详加论述。
六、通过修改达到无限制使用酒神的目的 在《仙剑奇侠传》游戏中,“酒神”作为终极法术,威力极大,因此在游戏中只能够使用九次。而之所以在这里研究“酒神”,是因为需要之前的成果,需要调出物品“酒”以及法术“酒神”。因此我将修改“酒神”的使用限制作为本篇研究的最终目标。 一般来说,在编写这样的程序时,无非是设立一个标志位,从0到9开始计数,每用一次“酒神”,标志位自加1,直至标志位达到9的时候,令“酒神”不能使用。或者反过来,从9开始计数,每次自减1,直至标志位为0。 经过实际研究,当“酒神”使用九次之后,李逍遥的法术标志位中本来属于“酒神”的位置被重新置为了0。而将“酒神”再次修改出来之后,进入游戏也只能再仅仅使用一次便显示法术已经用尽。当然确实可以每用完一次再修改一次,再用一次再修改一次的方法来达到无限次使用“酒神”的目的,但是这种笨拙的方法显然是我们不希望使用的,还是必须找到“酒神”的计数器才可以。可惜的是,存档文件中所有的09似乎并不是我们要找的标志位,也许使用了其它数字予以取代。那么只能通过对比存档文件之间的不同,采用“暴力”的方式来进行定位。 我取得了李逍遥在同一个野外场景中,“酒神”分别还能使用九次、八次、七次直到已经用尽的十份存档文件,这里的“酒神”不断用尽的过程也是在这一场景中,免得不同场景之间增加其它的不同的标志位。对比还能使用九次以及还能使用一次的两个存档文件,将不同之处进行分组,以组为单位,对“酒神”还能使用一次的存档进行修改。若某组修改之后进入游戏,“酒神”只能使用一次,说明要寻找的标志位不在这个组之中。反之则可定位到这个组之中,那么下一步就是对这个组中每个不同的字节分别进行修改,每修改完一处就进入游戏进行查看,直至定位到某一个或两个字节处,就是“酒神”计数器的位置。这里我找到的位置是0x02a60以及0x02a61。在我的系统中,这个值初始为76a8(小端显示),每用一次“酒神”,这个值就会自增1,直至用完九次,这个值变为7ea8,“酒神”便无法使用。图10“酒神”计数器标志位 在“酒神”还能使用一次以及用尽时,计数器位置的数值是完全一样的,而不同的是在“酒神”用尽的存档中,酒神法术的位置会被清空。所以之前在“酒神”用尽时,通过修改法术标志位将法术调出来,由于计数器标志位没有更改,因此游戏会认为只剩下一次“酒神”法术,所以每次修改完只能使用一次。因此只需把这个标志位两个字节的数据全部修改为00即可。经过测试发现,修改完之后,使用“酒神”不再改变这个标志位的数值,那么这个标志位的数值永远无法达到7ea8,于是我们的目的也就达到,“酒神”可以无限制地使用了。但是需要注意的是,必须要有充足的“酒”作为供应才可以。
七、总结 经过对《仙剑奇侠传》存档文件的分析可见,游戏中的某些可见数据(如之前的人物状态属性值)在逆向的过程中不见得能够出现,它可能是几个数字之和形成的,所以需要采用多种方式进行查询。而“暴力查找法”需要多次的文件对比(如查找“酒神”计数标志位),这也是最后的选择,毕竟“暴力查找法”非常耗费时间与精力。 至此,我们的目的已经达到,能够任意在仙剑的世界驰骋。逆向工程的第二个成功的尝试,也为以后的逆向工作积累了非常宝贵的经验。
吾爱-路人甲 发表于 2015-6-23 22:31
太厉害啊,我现在还在自学,乱七八糟什么都学,c++,c,mfc,php,html,最近在学滴水逆向,不知道学到什么程 ...
但是正规公司去做逆向的话,其实挣得不多,但是如果去那种专门搞破解,WG的公司,确实能赚非常多的钱 ioio_jy 发表于 2015-6-23 21:27
我闲人一个,没事就好研究这些东西
太厉害啊,我现在还在自学,乱七八糟什么都学,c++,c,mfc,php,html,最近在学滴水逆向,不知道学到什么程度才能去找工作,这些逆向分析的工资都很高。 这个厉害,膜拜了。。 大牛必须来学习下啊 这个蛮好.明天白天去玩玩这个游戏试试.嘿嘿. Hei,manyou are do good! 这游戏是经典了 牛人确实很多 谢谢楼主分享,支持一下 很给力.够详细