先说下call是什么。
call就是程序调用。熟悉VB的朋友,应该熟悉调用函数call add(a, b)的方法。
在任何程序的编写中都有很多call。如何找到正确的call是比较难的事情。
列一个调用过程:
call 鼠标点击
{
call 判断是点到怪、物品、地面
{
select
case 怪 : call 选怪
case 物品 : call 捡取物品
case 地面 : call 走路
case 墙壁 : call ...
case ...
}
}
call 选怪(怪物ID或标识)
{
push 明文包
call 加密
}
call 捡取物品(物品ID或标识)
{
push 明文包
call 加密
}
call 加密1级
{
call 加密n级
{
w32_send()
//发送给服务器
}
}
游戏的大概流程就是这样子的了。
对于找call来说,重要的是在n层嵌套中找到正确的call。这方面只能靠经验或猜测,看那个
push比较有戏。具体的方法也很简单,在N层嵌套的call中,看那个参数我们比较熟悉,比如观
察是否有怪物ID等。在多个call中找到一个我们熟悉的,然后调用,观看效果,如果不对,再试
别的。
上次讲过,在找周围怪物列表的时候,通过call 选怪(怪物ID或标识),向上跟踪找到怪物ID的
来源。这个怪物ID肯定是在周围所有怪物中的其中一个,所以通过这种方法,可以找到怪物周围
列表。
基本的原理和方法都已经讲出来了。对于初次找CALL的朋友,可能对操作系统和编译器生成的原
理不是很熟悉。我这里大概说一下,也是重点。
首先要明白,windows是多进程、多线程的操作系统。CPU轮流切换时间片给每个线程。而每个进
程都有自己独立的地址空间。具个例子,一排的牢房,CPU是送餐的,从左到右一直送过去。
每个牢房都是独立的,不会影响其他的牢房。
而DOS操作系统是单进程的,每次只能运行一个程序。这里我要说的是,当你面对一个进程的时
候,就不要考虑其他进程怎么样怎么样了,因为其他的进程和你自己的进程是没有关系的。这也
是在大学里讲c或者汇编只考虑一个进程的原因。
我们继续。
而在一个进程里的多个线程是共享当前进程空间的,如果你写过多线程的程序,就比较容易理解
call是怎么回事。我们看代码:
function add(a, b) as long
{
add = a + b
}
这是一个加法的call。
在我们的程序里有2个线程。
function thread1()
{
while 1
{
text1 = add(1, 2)
}
}
function thread2()
{
while 1
{
text2 = add(2, 3)
}
}
2个线程都可以调用add函数,都可以得到正确的结果。同样的概念套到游戏里就是游戏的线程和
我们自己的线程都可以调用“选怪”这个函数,并且得到正确的结果。call的原理就是让我们自
己的程序,去调用游戏里的函数。当然,必须存在我们这个“线程”。注意,这里线程是非常关
键的。如果不是一个新的线程,就无法得到CPU时间片。所以,一定是一个线程在调用1个或者多
个call。
明白概念之后,我们就可以考试动手了。首先找到call的地址,然后想办法调用他。
这里又需要考虑,我们如何才能调用它。首先第一个概念是要在游戏进程开辟一个线程,在这个
线程中做我们想要的操作。
那么首先要做的是,把这个线程放在游戏进程中。目前流行的方式有2中,编写钩子dll。或者远
程注入一个dll。
因为dll没有自己的独立空间,只能依附在一个exe的进程当中。而且windows帮我做了很多dll在
exe空间中定位的问题。所以dll就是我们的不二选择。
鉴于钩子和远线程的资料非常多,我就不写了。
我习惯用远线程来注入dll。按我的习惯,我们继续说。
被注入的dll,一定要是个标准dll。不能是activex dll。两者的调用方式不同,所以不能用
activex,这也决定了vb做的dll是不能被注入的。能被注入游戏地址空间中的dll,几乎都是用c
或者delphi写的。所以这个dll,还需要大家去学习这两种语言中的一种。
然后在dll里,直接调用。比如我们找到的call汇编如下:
push 1
push 2
call 123456
这里传递1和2做加法操作。我们在自己的dll写下:
__asm
{
push 2
push 5
call 123456
}
这样,这个call中就实现了2+5的操作。如果在123456这个call中,输出一个和的消息框,我们
就能看到结果了。在后面我会给出一个可操作的exe和注入dll的代码。
我要说的最后一个概念,也是很多人的疑问。已经注入的dll,我们如何调用它。
可以很明确的告诉你,不能调用(其实也不是不能调用,只是很麻烦,也非常占用资源,就是利
用远线程调用)。因为你的dll已经生存在对方进程中了。你自己的exe又是另外一个独立的进程
。想像一下,如果你能调用对方进程里dll中的函数,那不是也可以直接调用游戏call了么:)
这样的话,也就不需要注入了。
然后你肯定又会问,如果不能调用dll里的函数,我们让他执行。
这里有2种方法,
1.全部代码都在dll中写,包括界面、流程等这些内容。
2.采用进程间交互的方法。windows虽然不同意你调用其他进程中的数据,但是允许不同的进程
间做数据通讯。进程间通讯的方法很多,比如消息,共享内存区,映射文件等。百度上资料很多
。
如果有朋友用过readProcessMemory API的话,一定会奇怪,我们可以读写其他进程中的函数,
为什么你又说windows不允许呢。如果你有跟踪过readProcessMemory函数的话,你会发现,该
API用的是共享内存区的方式获得对方内存中的数据。
就先写这么多吧,打这么点字也用了半个多小时。
- 幻觉公式 2007.06.19 13:29
欢迎转载,但请保留所有内容。
也欢迎朋友们,接着这个话题继续说下去,或者对未说明的地方进行补充。
阅读(507) | 评论(0) | 转发(0) |