游戏找CALL练习实例ONE——入门篇

Home / Article MrLee 2016-4-12 10306

博主也是根据这样入门的。原理是一样的,所以贴出来。图文并茂的文章已经不多了。
目标:游戏找CALL练习实例ONE 记:看这篇找CALL文章,并不是说要学会它的操作步骤,而是学会找步骤的原理,只有懂得原理,才算真正会了.不要因为模拟器的简单 而忽略这篇文章,也不要因为曾经写过这个模拟器的挂 而忽略这篇文章.希望这篇文章能给你带来帮助.


这是一位大牛做的模拟器器,今天就来找这个 模拟器的CALL
用OD 加载 模拟器
然后按F9 运行
下bp send 断点


P:为什么要下 send 断点?
*send 是微软提供的一个API 函数,可以用来发送数据包. 绝大部分游戏都是用这个函数来发包的,其他还有 WSASend sendto WSASendto == send对应的收包函数是 recv WSASend对应的收包函数是 WSARecv
下段 后 这里按 ALT+B 会显示 已经下段的 地址


*当你暂时不想断下来 而又不想删掉 就可以 按 空格 来禁止.
断下来后,我们点下 模拟器的 加血 按钮 OD立马就断了下来


*标题显示 模块- ws2_32 表明 我们还在系统领空 *游戏发送数据包是调用send函数 发送的,掉用以后 程序告诉系统 我要发包了,然后系统就开发发送封包,这个时候断下来后 我们就在 系统发送完封包 后.
按 CTRL+F9 返回
P:为什么要用 CTRL+F9 返回?而不是 前进?
*程序是 一层套着一层的,就像一个箱子 里面 包含一个箱子 ,而里面的箱子里又有一个箱子.而我们断的send 就是在最里面的箱子,所以我们需要返回到 我们所需要的代码层.


我们来看下 堆栈窗口
这里 第一行是 CALL 第二行到第五行 是 CALL的 参数 写成函数就是 send(soket,data,datasize,flags)
这个就是 系统send所需要的参数 DATA 这里存放着 send发送的封包内容 DATASIZE 表示 封包的大小


从MSDN查看一下 函数的参数 我们会 发现 他的参数 跟我们刚刚反汇编的一样.


*按照 __cdecl调用约定 参数 是从 右边 开始压入堆栈
继续 返回
这里 我们已经到了 程序领空了 (标题显示 模拟器,而没有显示ws2_32) 在这里 OD已经 给我们标明了. 这是调用send 的汇编代码 因为这个模拟器并没有写接收 返回封包的 代码 所以 我们调用这个send 函数程序也是没有反应的
继续返回


这里有一个CALL 如果我们第一次找,我们并不能确认这个是否 是我们要找的
P:如何确认这个是否是我们需要的CALL呢?
我们先断下来 再说
继续返回


这里上面 有一个 retn
*retn 表示 一段程序的结束.
这里从 JMP 00403814 开始 到下面的retn 代表 这个是连续的一段代码
继续返回


这里 我们又发现一个CALL
先断下来再说
在返回 一层


这里也有一个CALL 也断下来
好了 我们现在已经返回了6层 找到了3个CALL
到底哪个是我们需要找的呢 我们先来测试下我们找的
把 send 断点 删了 暂时没用了
按下 加血 我们发现 所有断点 都会断, 这个时候 我们发现 第二个CALL 附近有 "血"这种文本
当然一般的除了喊话CALL 以外不会有很明确的数值当做依据 这个时候就要靠 你的经验 去猜了.
我们在 点下 吃蓝 发现 只断下 第一个. 好了,第一个先不要管了.为啥?猜的...
好了 我们来看看第二个CALL
mov edx,00453028 call 00452E98 retn
*要写一个CALL,我们就要模拟出他所需要的寄存器,还有堆栈的环境
P:如果看一个CALL所 需要的 寄存器?
我们进入 call 00452E98 的内部
选中 call 00452E98 那行 按 回车 就会 跳到下面
00452E98 /$ 55 push ebp 00452E99 |. 8BEC mov ebp, esp 00452E9B |. 83C4 F8 add esp, -8 00452E9E |. 53 push ebx 00452E9F |. 8955 FC mov dword ptr [ebp-4], edx 00452EA2 |. 8BD8 mov ebx, eax 00452EA4 |. 8B45 FC mov eax, dword ptr [ebp-4] 00452EA7 |. E8 1414FBFF call 004042C0 00452EAC |. 33C0 xor eax, eax 00452EAE |. 55 push ebp 00452EAF |. 68 7E2F4500 push 00452F7E 00452EB4 |. 64:FF30 push dword ptr fs:[eax] 00452EB7 |. 64:8920 mov dword ptr fs:[eax], esp 00452EBA |. 8B45 FC mov eax, dword ptr [ebp-4] 00452EBD |. BA 942F4500 mov edx, 00452F94 00452EC2 |. E8 5513FBFF call 0040421C
00452E98 /$ 55 push ebp 00452E99 |. 8BEC mov ebp, esp 00452E9B |. 83C4 F8 add esp, -8 00452E9E |. 53 push ebx
这里是 保存 堆栈环境 我们先不管他
00452E9F |. 8955 FC mov dword ptr [ebp-4], edx
将 EDX 保存到 [EBP-4] 我们来找下 EDX的值
这段汇编代码 前面 没有给 EDX赋值 我们返回上一层 按小键盘 -
上一层
mov edx,00453028
这句代码的意思是 将 453028赋值给EDX 也就是说EDX=00453028
找到EDX 的值后 继续往下面找
00452EA2 |. 8BD8 mov ebx, eax
这里需要EAX的值,但是 我们找了这一层和上一层 并没有发现有给EAX赋值的代码
我们这里 先直接给EAX赋值
其他没有了
好了 我们现在可以确认了 这个CALL 调用了 EDX 和EAX的寄存器的值


这个CALL的写法就是
mov edx,00453028 mov eax,00991FA8 call 00452E98
我们来测试下


CALL成功了
但是,我们拿到另外一台电脑 发现 居然不能用了? 调试了下 发现 EAX的值 跟刚刚的不一样~
P:如何取到 EAX的固定值呢?
答案很简单 用CE搜


看到那个绿色的值了么 那个就是 EAX的基址 ,无论 EAX的值 怎么变 都可以在这个地址读取到真正的值
代码如下
mov edx,00453028 mov eax,456d68 mov eax,[eax] call 00452E98
好了 现在 可以再任意一台电脑上运行了
=======================================================
好了 先不管这个CALL
我们现在来找下 EAX的值。
在 call 00452E98 下断 按下 加血 OD 断下来了
然后我们按 CTRL+F9 返回
好了 到了这里


mov edx,ebx mov eax,[ebx+124] call [ebx+120]
这个时候 我们发现 EAX的值
EAX=[ebx+124]
我们发现 CALL地址 并不是 是直接的地址。
在这个CALL 下断 点下 加血 按钮
我们发现 [EBX+124]=[0099493C]=00991FA8 EAX=991FA8 刚刚 我们找过 EAX的基址了
[ebx+120]=[00994938]=00453014
这里的CALL地址 写成代码是
mov eax,456d68 mov eax,[eax] call 453014


CALL成功了`
P:为什么2个不同地址的CALL都会成功呢?
经过不断测试(如何测试?点击不同的按钮 看看CALL的地址)
发现 不同按钮断下来的地址 都是不同的。


补魔的地址


冰系的地址
==========
我们来测试下第三个CALL


mov edx,[ebx+214] mov [eax+24c],edx mov eax,ebx call 4324d8
调试过程中 [EBX+214]=0 那么 edx的值 =0
[EAX+24C]=EDX=0 EAX=00991FA8
EAX=EBX=994818 CALL 4324d8
寄存器的值都搞清楚了 然后 我们看看 CALL还调用了哪个寄存器
跟进CALL (按 F7 进入CALL )
004324D8 /$ 53 push ebx 004324D9 |. 8BD8 mov ebx, eax 004324DB |. 66:83BB 22010>cmp word ptr [ebx+122], 0 004324E3 |. 74 2D je short 00432512 004324E5 |. 8BC3 mov eax, ebx 004324E7 |. 8B10 mov edx, dword ptr [eax] 004324E9 |. FF52 3C call dword ptr [edx+3C] 004324EC |. 85C0 test eax, eax 004324EE |. 74 22 je short 00432512 004324F0 |. 8BC3 mov eax, ebx 004324F2 |. 8B10 mov edx, dword ptr [eax]
004324E5 |. 8BC3 mov eax, ebx 这里有一行 调用了 EBX 我们往上找找 发现 有给EBX 赋值的代码 那么 我们就不必理会了
004324E7 |. 8B10 mov edx, dword ptr [eax] 这里调用了 EAX 在上一层 有给EAX赋值的 代码
下面就没了
好了 用代码注入器 写CALL
mov edx,[ebx+214] ,[EBX+214]=0
那么 第一句就是 mov edx,0
mov [eax+24c],edx ,edx的值 =0 EAX=00991FA8 那么 第二句 就是 MOV [EAX+24C],0 但是 注入器不通过 这个时候 我们换一种写法 首先给 EAX赋值 mov eax,991FA8 这里 我们刚刚找过 这个基址 456d68 是EAX的基址
首先放入 基址的值 mov eax,456d68 然后在读取 基址 mov eax,[eax] 然后 加上偏移 24C add [eax],24c
地址写好后 我们把 EDX放到 地址里去 mov [eax],edx
mov eax,ebx第三句 EBX=994818 因为 CALL没有调用EBX 所以我们不必给ebx 赋值 mov eax,994818
call 4324d8
放到一起 那么就是
mov edx,0 mov eax,456d68 mov eax,[eax] add eax,24c mov [eax],edx mov eax,994818 call 4324d8


好了 CALL成功了~
经过调试 发现 不同的 按钮 他的EBX里的值也不一样
好了 我们发现这也可以调用
提问:
P:为什么3个不同地址的CALL都会成功呢?
总结
*retn 表示 一段程序的结束 *send 是微软提供的一个API 函数,可以用来发送数据包. 绝大部分游戏都是用这个函数来发包的,其他还有 WSASend sendto WSASendto == send对应的收包函数是 recv WSASend对应的收包函数是 WSARecv *要写一个CALL,我们就要模拟出他所需要的寄存器,还有堆栈的环境

本文链接:https://www.it72.com/9124.htm

推荐阅读
最新回复 (0)
返回