欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]调试外挂经验记录[更新]

[原创]调试外挂经验记录[更新]


我目前遇到的外挂绕过保护有两种:
1. 将外挂代码写到系统进程中。
2. 将外挂dll注入到游戏进程中。
游戏是有保护的,调试外挂,想知道外挂功能执行,打开游戏进行调试是不现实的,因为你想用OD之类的,你首先要绕过游戏的保护。
有一个办法可以解决这个问题,那就是你写一个exe,伪装成游戏进程。伪装很简单,把自己写的exe的名字改成与游戏进程名一样就OK了。有些外挂即使你进程名和游戏进程名是一样的,还是会提示“请打开XXX游戏”,经过实际调试,原因是外挂使用FindWindow()函数,所以你要把你的程序的窗口名和窗口句柄改成和游戏一样的。这样就完全OK了。
伪装游戏的程序用易语言写最简单,直接生成一个窗口程序,在属性里面将窗口标题和窗口类名改了,然后静态编译,熟悉的话1分钟搞定,不熟悉的人10分钟也能搞定。
伪装进程还有一个好处,那就是游戏中存在的地址你的这个假进程不一定有,因为游戏是很大的,现在的游戏动辄1G+,而你的伪装程序可能就1M左右。所以当执行部分功能的时候会出现下图的消息框:

主要的是这句话:"XXXX1"指令引用的"XXXX2"内存。该内存不能为"written"。
XXXX2这个内存地址就是外挂写入游戏的内存地址,如果打开OD,将所有的异常忽略全部取消,OD就可以在这个错误发生的地方断下来,再根据调用堆栈,就可以定位这个功能执行的地方。
我所分析的外挂都是用易语言写的,发现了一个情况,易语言的组合框(就是下拉列表)中的功能可以用OD搜索到字符串,而复选框却不可以。经过分析,我认为组合框是要临时判断所选择的功能的,所以在执行功能的时候会用到组合框中的文字,所以OD搜索到相应的文字以后可以很快的定位功能实现地点,而复选框不用,所以无法根据复选框旁边的文字来定位功能实现的地点。
想要知道外挂进程向游戏进程写入数据的细节,可以自己写一个驱动级的监控软件。
///////////////////////////////////////////////////////////////////////////////////////////////////
2013/04/11更
易语言中定位事件的方法。
通过我写的一个易语言测试程序,比较调用堆栈,定位了一段汇编,只要易语言中产生外挂作者处理的事件就会运行到这个汇编中。比如,按钮被单击,选择框、单选框被选中等等。而由易语言处理的事件,比如窗口焦点等,都不会执行到这段汇编。
下面就是要提取特征码了。

0041A4C0  /$  55            push ebp
0041A4C1  |.  8BEC          mov ebp,esp
0041A4C3  |.  83EC 18       sub esp,0x18
0041A4C6  |.  53            push ebx
0041A4C7  |.  56            push esi
0041A4C8  |.  57            push edi
0041A4C9  |.  894D E8       mov [local.6],ecx
0041A4CC  |.  8B45 08       mov eax,[arg.1]
0041A4CF  |.  8B48 0C       mov ecx,dword ptr ds:[eax+0xC]
0041A4D2  |.  51            push ecx
0041A4D3  |.  8B55 08       mov edx,[arg.1]
0041A4D6  |.  8B42 08       mov eax,dword ptr ds:[edx+0x8]
0041A4D9  |.  50            push eax
0041A4DA  |.  8B4D 08       mov ecx,[arg.1]
0041A4DD  |.  8B51 04       mov edx,dword ptr ds:[ecx+0x4]
0041A4E0  |.  52            push edx
0041A4E1  |.  8B45 08       mov eax,[arg.1]
0041A4E4  |.  8B08          mov ecx,dword ptr ds:[eax]
0041A4E6  |.  51            push ecx
0041A4E7  |.  8B4D E8       mov ecx,[local.6]
0041A4EA  |.  E8 419CFFFF   call 易语言试.00414130
0041A4EF  |.  8945 FC       mov [local.1],eax
0041A4F2  |.  837D FC 00    cmp [local.1],0x0
0041A4F6  |.  75 04         jnz short 易语言试.0041A4FC
0041A4F8  |.  33C0          xor eax,eax
0041A4FA  |.  EB 67         jmp short 易语言试.0041A563
0041A4FC  |>  56            push esi
0041A4FD  |.  57            push edi
0041A4FE  |.  8B55 08       mov edx,[arg.1]
0041A501  |.  8B42 0C       mov eax,dword ptr ds:[edx+0xC]
0041A504  |.  83E8 01       sub eax,0x1
0041A507  |.  8945 EC       mov [local.5],eax
0041A50A  |.  EB 09         jmp short 易语言试.0041A515
0041A50C  |>  8B4D EC       /mov ecx,[local.5]
0041A50F  |.  83E9 01       |sub ecx,0x1
0041A512  |.  894D EC       |mov [local.5],ecx
0041A515  |>  837D EC 00     cmp [local.5],0x0
0041A519  |.  7C 12         |jl short 易语言试.0041A52D
0041A51B  |.  8B55 EC       |mov edx,[local.5]
0041A51E  |.  8B45 08       |mov eax,[arg.1]
0041A521  |.  8B4C90 10     |mov ecx,dword ptr ds:[eax+edx*4+0x10]
0041A525  |.  894D F0       |mov [local.4],ecx
0041A528  |.  FF75 F0       |push [local.4]
0041A52B  |.^ EB DF         \jmp short 易语言试.0041A50C
0041A52D  |>  FF55 FC       call [local.1]
0041A530  |.  5F            pop edi
0041A531  |.  5E            pop esi
0041A532  |.  895D F4       mov [local.3],ebx
0041A535  |.  8945 F8       mov [local.2],eax
0041A538  |.  8B55 E8       mov edx,[local.6]
0041A53B  |.  C782 F0010000>mov dword ptr ds:[edx+0x1F0],0x0
0041A545  |.  837D F4 00    cmp [local.3],0x0
0041A549  |.  74 13         je short 易语言试.0041A55E
0041A54B  |.  8B45 08       mov eax,[arg.1]
0041A54E  |.  C740 24 01000>mov dword ptr ds:[eax+0x24],0x1
0041A555  |.  8B4D 08       mov ecx,[arg.1]
0041A558  |.  8B55 F8       mov edx,[local.2]
0041A55B  |.  8951 28       mov dword ptr ds:[ecx+0x28],edx
0041A55E  |>  B8 01000000   mov eax,0x1
0041A563  |>  5F            pop edi
0041A564  |.  5E            pop esi
0041A565  |.  5B            pop ebx
0041A566  |.  8BE5          mov esp,ebp
0041A568  |.  5D            pop ebp
0041A569  \.  C2 0400       retn 0x4

我提取其中这么一段汇编。
0041A50C  |> /8B4D EC       /mov ecx,[local.5]
0041A50F  |. |83E9 01       |sub ecx,0x1
0041A512  |. |894D EC       |mov [local.5],ecx
0041A515  |> |837D EC 00     cmp [local.5],0x0
0041A519  |. |7C 12         |jl short 易语言试.0041A52D
0041A51B  |. |8B55 EC       |mov edx,[local.5]
0041A51E  |. |8B45 08       |mov eax,[arg.1]
0041A521  |. |8B4C90 10     |mov ecx,dword ptr ds:[eax+edx*4+0x10]
0041A525  |. |894D F0       |mov [local.4],ecx
0041A528  |. |FF75 F0       |push [local.4]
0041A52B  |.^\EB DF         \jmp short 易语言试.0041A50C
0041A52D  |>  FF55 FC       call [local.1]

因为有[local.1]、jl short 易语言试.0041A52D之类的OD翻译的汇编语句,所以不能直接用来查找命令序列,而且OD的命令序列只能查找8条指令,还有易语言所编译出来的汇编和OD所翻译的汇编有时会不一样,所以使用ctrl+s查找命令序列的方法是很不精确甚至查不到的。
那么最好是使用二进制来定位,虽然提取二进制很麻烦,但是只要易语言不做大的更新,这个二进制特征码可以用很长很长时间了。
将前面的汇编的二进制提取出来
8B4DEC83E901894DEC837DEC007C128B55EC8B45088B4C9010894DF0FF75F0EBDFFF55FC

那么如何进入外挂作者的事件当中哪?在上面的
0041A52D  |>  FF55 FC       call [local.1]

这个call中,按F7进入,就直接到了事件处理函数中。
当定位到这段汇编以后,要在
0041A52D  |>  FF55 FC       call [local.1]

这个语句下断点,因为只要定位的位置正确,这个call是必然会被调用的,而别的地方不一定。
如果外挂中使用了线程,那么就会频繁的进入这段代码,因为这段代码就是用来调用外挂作者自己的函数的(这个描述可能不太准确,因为在外挂作者自己的函数中调用了外挂作者自己写的函数,可能不会执行到这段汇编)。所以需要使用条件断点。
如果外挂注入的是伪造进程,而伪造进程是用易语言写的,那么就会有两段这样的代码,需要在内存窗口中去查看,定位到的内存地址是在哪个模块中。

上传的附件 1.jpg

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功