双星物语是个老游戏了,看游戏配置选项竟然是DX2,OTZ
老游戏要跳光盘验证一般是很简单的,我也就会点简单的,献丑了:)
打开ollydbg,载入zweipet.exe

右键菜单的“搜索”->“所有模块间调用”

找到“kernel32.GetDriveTypeA”,一般光盘验证都会用到这个函数,用来判断磁盘是硬盘还是光盘。选中,按F2,或者右键选“开关断点”,然后按F9运行

点“开始”,会断下来:

00408843 . FF15 FC304200 call dword ptr ds:[<&KERNEL32.GetDriveTypeA>] ; \GetDriveTypeA
00408849 83F8 05 cmp eax,5 //如果是光驱的话返回5
0040884C . 75 65 jnz short zweipet.004088B3 //不是光驱就跳走继续判断下一个盘
按F8一步一步跟踪,一开始一般是从A盘或者C盘开始的,都会执行0040884C这一行跳走继续,等到判断到光驱了,就继续,看代码:
0040884E . 6A 00 push 0
00408850 . 8D4C24 1C lea ecx,dword ptr ss:[esp+1C]
00408854 . 6A 00 push 0
00408856 . 8D5424 24 lea edx,dword ptr ss:[esp+24]
0040885A . 51 push ecx
0040885B . 52 push edx
0040885C . 6A 00 push 0
0040885E . 8D8424 340200>lea eax,dword ptr ss:[esp+234]
00408865 . 68 04010000 push 104
0040886A . 8D4C24 38 lea ecx,dword ptr ss:[esp+38]
0040886E . 50 push eax
0040886F . 51 push ecx
00408870 . FFD5 call ebp
按F8到00408870那一行的时候,olly在代码右边的注释区会显示出
00408870 . FFD5 call ebp ; kernel32.GetVolumeInformationA
可以看出,前面的一堆PUSH都是为了调用GetVolumeInformation函数而入栈的参数,不用特别注意,只要注意结果就好了。我这时候光驱里没有放盘,所以得到的肯定是个空字符串。继续按F8看代码:
00408872 . BE 3C894200 mov esi,zweipet.0042893C ; 把程序内部的字符串放到esi中,地址0042893C指向的是ASCII字符串 "ZWEI!!"
00408877 . 8D8424 200200>lea eax,dword ptr ss:[esp+220] ;把前面函数得到的字符串的地址放到eax中
0040887E > 8A10 mov dl,byte ptr ds:[eax] ;把eax指向的字符串的第一个字节放到dl中
00408880 . 8ACA mov cl,dl ;转存到cl里
00408882 . 3A16 cmp dl,byte ptr ds:[esi] ;和esi的第一个字符和dl里的字符比较
00408884 75 1C jnz short zweipet.004088A2 ;不一样的话跳走继续判断下一个盘
00408886 . 84C9 test cl,cl ;如果cl为空,这里需要说明一下,程序中的字符串都是以\0结尾的,这里就是判断是否字符串结束
00408888 . 74 14 je short zweipet.0040889E ;结束的话跳走,没必要进行下面的判断
0040888A . 8A50 01 mov dl,byte ptr ds:[eax+1] ;eax+1就是第二个字符了
0040888D . 8ACA mov cl,dl ;还是转存到cl里
0040888F . 3A56 01 cmp dl,byte ptr ds:[esi+1] ;同上的判断
00408892 75 0E jnz short zweipet.004088A2 ;不一样跳走
00408894 . 83C0 02 add eax,2 ;字符串指针+2,作用是前两个字符被pass掉了,第三个字符现在成为第一个
00408897 . 83C6 02 add esi,2 ;程序中用于比较的字符串指针也+2
0040889A . 84C9 test cl,cl ;同上,判断字符串是否结束
0040889C .^ 75 E0 jnz short zweipet.0040887E ;结束的话跳走
从上面的注释可以看出,这个光盘验证很简单,就是判断光盘的卷标是否是"ZWEI!!",解决办法应该有不少,常用的两种:1。做一个空镜象文件,卷标是"ZWEI!!",然后载入到虚拟光驱里;2。把验证光驱的代码nop掉。第一种很简单,但是我懒,就不演示了。下面讲第二种。
根据上面的注释,可以看出来,这段代码是2个字节为一次的比较,所以有两次的跳转,都pass掉就好了。也就是说,把00408884和00408892这两行的代码跳掉。都是jnz语句,一行代码是75 1C,另一行是75 0E,都改成90 90 就好了。多废话一句:用两个90是因为这连个jnz语句都是2个字节的,75是一个字节,1C是一个字节。75 0E也是一样。
按F9看看,成功进游戏了,这是在本次游戏执行的内存中修改的,并不保存到程序文件上,下次执行还是要问你要光盘的,下面讲怎么把文件中的代码也跳掉。
用ultraEdit打开程序文件,就是zweipet.exe。然后记下来刚才修改内存代码的时候附近的代码,因为如果只根据一两个字节的代码来查找的话可能会出现重复的,这里只有一个是我们需要的,其他的就是其他的代码,乱改的话该出错了,所以要多记一些。比如查找8A CA 3A 16 75 1C 84 C9,如果只找到一个那就对了,找到多个的话就多记几个字节的代码再来找。找到之后,把75 1C改成90 90 。再查找第二处,查找8A 50 01 8A CA 3A 56 01 75 0E,找到了把 75 0E改成90 90 ,保存。
就这样就OK了,很简单就搞定了,毕竟是老游戏,现在的游戏动不动就是starforce的。。。我搞不来。。。不过反正这也是入门教程,想找高级的去bbs.pediy.com,那里有很多高级的:)
这样的话自己的就是免CD了,但是如果想把发布免CD补丁怎么办呢?有两种方式:1。把改好的zweipet.exe发布出去;2。写一个程序,用来修改zweipet.exe。
懒人都是用第一种方法,这方法也没什么好讲了。第二种方法,等下一篇吧-_-~~,有空再来发,木哈哈哈哈
多谢大家捧场~