一,如何取得EBP/EAX/ECX/ESI/EDI/这些寄存器的值首先一个程序中寄存器的功能是用来运算的,也就是
说它是总在变化的,而且我们平常写的应用程序是不太可能得到其它进程的寄存器的值的,除非你的程序
是调试程序例如OD,SoftICE,trw2000,或是CE中的调试状态。我们都知道大多游戏中的地址不是固定的,
每次重开游戏都是不一样的地址中存储数值,那我们怎么得到它呢?要取得这样的地址你必须得去分析
它的反汇编代码,一般游戏中的数值是通过一定的运算,最后保存在一个相对固定的地址,也就是这个相
对因定的地址是通过某种运算来取得的,下面有两种比较简单的方法来取得这些地址
1、你要做的就是分析它的运算过程,这样自己就可以写代码来计算你想取得的数值的地址了
例如 00456789 mov eax,dword ptr [esi]
你要分析这个语句之上的代码看看是什么东西来存放在ESI中,得到算法后在你的程序中用
ReadProcessMemory来读就行了
2、如果你的汇编底子不好,那就用这个方法,也就是所说的“代码注入”,到底为什么这样做呢?
数值地址是变化的,但是代码是不变的,如果我们把这个变化的地址写到一个不变的地址中,每次对
这个不变的地址进程读取不就可以了吗?
注入之前你要在目标进程中伸请一块内在用来保存你想要得到的数值的地址,这里假设已经伸请的地
址为0X7A5C62这样我们想要的数值的地址就保存在这个0X7A5C62中了,我们就可以在程序中用
ReadProcessMemory来得到这个地址中的数值了,注入代码用WriteProcessMemory,具体使用方法看帮助
(MSDN),下面是简单的演示00XXXXXX与00ZZZZZZ表示地址根据实际情况定(我身边没有调试程序也没
有游戏只能这样表示)
例如 00XXXXXX mov eax,dword ptr [esi]
00ZZZZZZ mov ecx,0xC <---你把这句改成jmp xxxxxx
00YYYYYY call,0x2a
这里要注意一个问题就是你插入指令的字节数与原来指令的字节数少了用nop占位,多了自然
就把下面的语句覆盖掉了,你要把被覆盖掉的的语句保存出来,改过之后如下
00XXXXXX mov eax,dword ptr [esi] <--想得到的数值保存在了eax中
00ZZZZZZ jmp xxxxxx <---原来的指令mov ecx,0xC
那么xxxxxx是什么呢,xxxxxx也是一个地址,这个地址是程序的空白位置,什么又是空白位
置呢?你可以找有很多行nop指令的地方,这里就是空白位置,你还在要这里插入代码,
我在这里设为xxxxxx
xxxxxx处代码如下
mov 0X7A5C62,eax <---eax中是我们想得到的数值,
<---但是这里是将eax的地址保存到0X7A5C62中
<--0X7A5C62中存放的只是地址
mov mov ecx,0xC <--还原原程序指令代码
jmp 00YYYYYY <--跳回原程序位置继续执行
以上就是两种解决方法,都有各自的好与坏,自己权衡。关键在于你要找到取值位置,然后注入实现跳
二、楼上这位老兄问的CE能找CALL吗?
游戏中的CALL就是调用一个过程,CE我没有细研究,但是我知道你在找一数值的时候在它的下面或
下面都会有CALL的代码,所以找CALL的方法就是:确定你找CALL的功能,在这个CALL执行的前后游戏的
哪些数值会发生变化,你对这些会变化的数值进行查找,你就会发现这个CALL了找CALL你要看反汇编代
码,能让你看到反汇编代码的工具都可以找到CALL
三、使用游戏中的CALL
远程线程可以实现
CreateRemoteThread与writeProcessMemory来注入实现对CALL调用的代码
具体代码不写了,这个不是一两句能说清楚的。
四、工具
CE:
虽然很好用,但是你要想写外挂你就要用OD一类的调试器来调试游戏代码,虽然CE也可以调试,但是这
个调试的功能它还比不上OD一类的调试器。具体的做法是结合所有的工具来帮助你分析游戏代码,
例如用CE来确定游戏内在地址,用OD在这个地址上下断点,中断游戏的执行来看其中的反汇编代码。
大家不要想着用一个CE就可以做出外挂来,那样你会很累,我想CCB老师也不会同意这样做吧。:)
下面列出一些API来,都是做外挂能用得上的。
GetWindowThreadProcessId
OpenProcess
CloseHandle
VirtualAllocEx
VirtualFreeEx
ReadProcessMemory
WriteProcessMemory
还有很多,但是有点不记得了,呵呵。。自己查一下MSDN吧