use OD debug GVOnline

original url : http://blog.sina.com.cn/s/blog_9a8bde1401013tfs.html


预备知识:NProtect实际上也是一个单独的程序,由航海自动载入。NP的主程序是航海根目录下的GameGuard.des文件,这个文件实际上是exe程序,不信你可以把扩展名des改成exe试试。因此——


第一步:将根目录下的GameGuard.des文件改名或者删掉。让航海程序无法载入NP。

 

弄掉根目录下的GameGuard.des文件以后,航海无法载入NP就报错,会弹出一个对话框”GameGuard.des filedoes not exist or is modified. This can be resolved by installingGameGuard setupfile..(00000099)”。处理方法就是修改航海程序流程,让航海即使知道有错误仍然继续运行。

 

第二步:用OD载入航海,程序停在入口点。下bpMessageBoxA断点。这样当航海弹出所有对话框的时候,都会被中断。下断点以后,按F9继续运行航海。接着一下子就到错误代码处了。

右下角堆栈一目了然。

按F8返回retn,OD停在加灰行(下同)

00ABBB7F  |> \FFB5 A4000000 pushdword ptr ss:[ebp+0xA4]                  ; /Style

00ABBB85  |.  53          push ebx                                  ; |Title

00ABBB86  |.  FFB5 A0000000push dword ptr ss:[ebp+0xA0]                  ; |Text

00ABBB8C  |.  FF75 80      push[local.32]                             ; |hOwner

00ABBB8F  |.  FF15 98C5AF00call dword ptrds:[<&USER32.MessageBoxA>]      ; \MessageBoxA

00ABBB95 |.  85FF        test edi,edi

这时候,程序已经检测过GameGuard.des文件被弄掉了。所以我们要返回上一层CALL看看是在什么地方检测的。继续F8到retn处,OD停在

00494F34  |> \8D4C24 08    lea ecx,dword ptrss:[esp+0x8]

00494F38  |.  50          pusheax

00494F39  |.  E8 423BF9FF  call duokai50.00428A80

00494F3E  |> 57          push edi

00494F3F  |.  56          pushesi

00494F40  |.  8D5424 10    lea edx,dword ptrss:[esp+0x10]

00494F44  |.  68 D825B000  push duokai50.00B025D8                       ; ASCII "(x)"

00494F49  |.  52          pushedx

00494F4A  |.  E8 4142F9FF  call duokai50.00429190

00494F4F  |.  8B7424 18    mov esi,dword ptrss:[esp+0x18]

00494F53  |.  8B46 F4      moveax,dword ptr ds:[esi-0xC]

00494F56  |.  83C4 0C      addesp,0xC

00494F59  |.  50          pusheax

00494F5A  |.  56          pushesi

00494F5B  |.  8D4C24 10    lea ecx,dword ptrss:[esp+0x10]

00494F5F  |.  E8 5C3EF9FF  call duokai50.00428DC0

00494F64  |.  8B7C24 08    mov edi,dword ptrss:[esp+0x8]

00494F68  |.  6A 00       push 0x0

00494F6A  |.  6A 10       push 0x10

00494F6C  |.  57          pushedi

00494F6D  |.  E8 626C6200  call duokai50.00ABBBD4

00494F72 |.  8D46 F0      lea eax,dword ptrds:[esi-0x10]

往上翻翻看。很明显这是一个case选择条件代码段。看起来还挺复杂。别急着下断点试。让我们分析一下程序思想:我们刚返回的地方是显示错误对话框,然后随便点几个上面的跳转,发现最后都会到显示错误这里来。而上面这么多case条件,应该都是错误A、错误B、错误C……。那么程序流程应该是:判断是否有错误,如果有错误,判断是哪个错误,最后显示错误对话框。s所以我们要找的不是某一个case事件,而是找判断是否有错误代码。因此我们继续往上翻,找

00494DDA  |.  83FE 7C      cmpesi,0x7C                                ; Switch (cases 6E..17C)

这句。这句是选择条件起始句。找到这句后继续往上看,找找最靠近的跳转语句。不远处就有一个

00494DA6     /0F84 1A020000 jeduokai50.00494FC6

这句跳的还挺远,甚至retn都不一样。有戏!让我们测试一下,直接将je00494FC6改成jmp 00494FC6。然后CTRL+F2重新载入航海,按CTRL+P,在第一行上点右键选择应用补丁,这样我们的修改就生效了。顺便按ALT+B把前几次的断点都删了。

继续按F9运行。航海成功运行!说明我们改对了。让我们把成果保存到文件:在随便一行代码上点右键,选择复制到可执行文件→全部修改,跳出来的对话框选全部复制,在跳出的窗口点右键选择保存文件,然后看你想保存到哪里都行。

不过这样有个小BUG,退出航海的时候会弹出来一个网页。处理方法:

第三步:将航海目录里的GameGuard子目录里的ggerror.des改名或删除,就不弹出网页了。

至此过NP搞定。

 

多开:

预备知识:台服默认能开3个航海。所以我们先正常打开3个航海窗口,无需登录。再打开第4个窗口,没任何反应。看来是程序检测了已知窗口,如果超过3个就自动退出了。

第一步:还是OD载入航海,停在入口点。下bpExitProcess断点。将会在程序退出时中断。F9运行。

程序中断下来以后,不能再F8单步了。因为没F8几次,程序直接OVER了。我们直接看堆栈。在堆栈第三行右键,选反汇编窗口跟随。

这么做的原因是,程序执行的流程肯定是:判断是否要退出→如果要退出,执行退出代码。所以如果我们回到堆栈第一行0018FE28那个,肯定是在执行退出代码段。我们应该到判断是否退出代码,所以要回到堆栈第三行那。

现在我们到了这里

00A8CEFF  |.  8935 34C3D400mov dword ptr ds:[0xD4C334],esi

00A8CF05  |.  FF75 08      push[arg.1]

00A8CF08  |.  E8 92FEFFFF  call duokai50.00A8CD9F

00A8CF0D |.  33FF        xor edi,edi

00A8CF08这个CALL就是执行退出代码的。我们已经知道只能开3个窗口,所以我们往上找找有没有个3比较的(汇编代码类似cmp XXX,0x3)。结果很遗憾没找到……不过这段代码也不长,我们干脆从头开始分析,看看两个变量里有没有和3比较的。在

00A8CE63  /$  6A 08       push 0x8

处下断。CTRL+F2重新载入,F9运行。程序停住了,F8分析,重点看cmp比较语句和回跳循环判断。找了一圈没收获……换个思路:程序是靠什么得知已经开了几个窗口呢?不会是通过进程名(你可以自己实验)。不会是通过窗口标题“大航海时代online"(还是自己实验,用很多软件可以随意更改程序标题)。那只能是通过窗口的类名了(这个类,大概就是大窗口里可以套小窗口的意思。类名是小窗口的标题名字)。所以

第二步:下BP GetClassNameA断点。CTRL+F2重新载入,F9运行。

中断下来了,F8继续走,返回到游戏代码

0049376E  |.  FF15 DCC6AF00call dword ptrds:[<&USER32.GetClassName>;\GetClassNameA

00493774 |.  A1 401DCD00  mov eax,dword ptr ds:[0xCD1D40]

然后F8继续往下走。

0049377E  |.  FF90 DC010000call dword ptr ds:[eax+0x1DC]

00493784  |.  50          push eax                           ; /String2 = "Greate Voyages Online GameMainFrame"

00493785  |.  8D4C24 14    lea ecx,dword ptrss:[esp+0x14]         ; |

00493789  |.  51          push ecx                           ; |String1 = "TaskListThumbnailWnd"

0049378A  |.  FF15 A0C3AF00call dword ptrds:[<&KERNEL32.lstrcmpA>]; \lstrcmpA

00493790  |.  85C0        test eax,eax

00493792  |.  75 03       jnz Xduokai50.00493797

00493794  |.  43          inc ebx

00493795  |.  891E        mov dword ptr ds:[esi],ebx

00493797  |> 5F          pop edi

 

这一眼就看出来了,航海的类名是"Greate Voyages Online GameMainFrame",string1是其他窗口的类名,然后用lstrcmpA函数比较,lstrcmpA函数返回的结果保存在EAX,然后testeax,eax(判断EAX值,结果会影响下面的jnz跳转),如果EAX是0,就inc ebx(ebx=ebx+1)。所以ebx保存的就是已经打开的航海窗口数。

所以第一种修改方法就是将jnz 00493797改成jmp 00493797强制跳转。让ebx永远是0。就可以实现无限开。

我们还不满足,想找出来判断3个窗口的地方。所以我们继续F8到retn处

00493794  |.  43           incebx

00493795  |.  891E         mov dword ptrds:[esi],ebx

00493797  |> 5F           pop edi

00493798  |.  5E           popesi

00493799  |.  B8 01000000   mov eax,0x1

0049379E  |.  5B           popebx

0049379F  |.  8BE5         mov esp,ebp

004937A1  |.  5D           popebp

004937A2 \.  C2 0800       retn0x8

这时我们再F8,发现跳回到系统DLL里去了(注意看OD标题),然后又跳回来,再跳回系统DLL……好累,让我们走个捷径,F8走到004937A2 retn这,看右下角堆栈,往下找第一个返回到上一层CALL的地址(duokai50是我自己的航海程序名,相应的你得知道你自己航海程序名是什么)。这句

0018FD54   0049539A  返回到duokai50.0049539A 来自 USER32.EnumWindows

在上面右击,反汇编窗口跟随,来到

00495394   .  FF15 C0C6AF00 call dword ptrds:[<&USER32.EnumWindows>>;\EnumWindows

0049539A  .  85C0         test eax,eax

我们看到EnumWindows这个函数是遍历所有窗口的。所以我们没来错地方。在0049539A   . 85C0          testeax,eax行上下断,F9运行断到这里,F8继续。下一行就是个jnz跳转,跳到了

004953F4   > \837C24 14 03  cmp dword ptr ss:[esp+0x14],0x3

注意看[esp+0x14]是4,这不就是4和3比较吗?这应该就是判断窗口数量的语句了。为了验证我们可以按空格,把03改成05理论上能开5个航海窗口,再按上面应用补丁的方法验证一下。最后发现我们找的没错,这句就是判断窗口数量的地方。

所以我们又一种修改方法就是把cmp dword ptr ss:[esp+0x14],0x3改成cmp dwordptr ss:[esp+0x14],0x64。就成了100开(64是16进制,换成10进制就是100)。

改完以后,还是按照上面应用补丁的方法保存结果就OK了。


你可能感兴趣的:(use OD debug GVOnline)