[转]关于内存地址的个人理解和操作原理

来源:互联网 发布:卡西·阿弗莱克 知乎 编辑:程序博客网 时间:2024/04/29 12:54
 

[转]关于内存地址的个人理解和操作原理

发表于:2007年3月22日 15时55分13秒阅读(0)评论(0)本文链接:http://user.qzone.qq.com/185591848/blog/52
关于内存地址的个人理解和操作原理

最近看见太多人询问内存地址的作用和使用方法,我来做个大概的解释吧
     内存地址,其实电脑的每个操作都会在内存中先存储,然后经CPU处理后返回内存最终显现出来,而内存里有个内存地址,是为了区分各种不同数据的,而每个地址则相对应一个数据。
    网络游戏中,数据也会先存放到内存中,然后进行处理,包括坐标、血量、MANA等,其实所有信息都是在内存中一一存放并等待处理。处理完毕后结果将会返回原来的地址中(当然也有返回到其他的)。
    通过以上的解释,大家可以明白一个道理,其实任何数据都是会下载到本地电脑上然后经过处理后再返回的(至于返回到网络和返回到本地就看数据的重要性了)包括网页的浏览等,任何在你电脑上可以看见的东西必定先存放到本地内存中或硬盘中等待处理后才会显现出来的。
内存和外挂:
    说到这里当然要给大家举个例子了,就拿网络游戏来说吧。以前的网络游戏很多数据都是在本地电脑上进行处理和比对的,例如曾经的精灵,它的游戏币是在本地电脑上进行处理的,处理后的结果再返回服务器,这样就导致了当时的刷钱外挂,因为大家可以修改本地电脑上的内存地址中的数值,然后再返回给服务器。从以上可以知道单机游戏锁血锁蓝是多么简单的事了吧。因为所有的数据操作都是在本地运行计算的。
    当然,还有的外挂是通过改变封包数据来达到效果的。例如魔兽世界加速外挂,比如我现在人物的坐标是0  0然后按照正常速度走的话下一秒坐标是1  1。因为魔兽世界是在本地对人物坐标进行处理,如果只是单一的改变本地游戏坐标的位置,或许你在自己电脑上会看见自己一下跑到 3  3的位置了,但实际游戏服务器上的人物还在1  1这个位置,那就毫无意义。我们可以截取发送坐标的封包,修改我们下一秒跨度的数值,向服务器发送我下一秒会在3  3的位置,这时服务器处理后你的人物就在3  3的位置了。当然,整个过程只是改变封包内的数据值,并没有向服务器多发送封包,所以有的人说是加速外挂给游戏带来了压力的说法是错误的。当然,运营商也可以通过检查你的日常数据来判断你是否使用外挂,所以是没有查不出的外挂,只有不愿意查的外挂。
    而现在的网络游戏血、经验、等级、金钱等重要数据都是由服务器计算然后返回给客户端(就是我们),而且每次存放血、蓝等信息的内存地址在每次游戏的启动都会变化,在现在来说,修改其数值已经没有任何意义了,因为那只能让你在本地读取的数值不同而已,而真正的数据被存储在了服务器上,你无法修改。但是我们可以通过读取内存地址中的数值来精确我们脚本的计算。
脚本与读取内存地址:
    例如我要做一个脚本,需要在血或蓝少于一个具体的值的时候加血加蓝,这时候我们就可以采用内存地址的读取,因为这种做法可以让脚本以最精确的方式去加血加蓝,而不是去看血条蓝条(其实血条蓝条这时候已经根本不重要)。在按键精灵里
有这么一个脚本。
VBSCall ReadMemory(内存地址:整数(16进制),类型:0-字节 1-整数 2-长整数,输出值-所读取的内容:长整型变量)
实际应用(中间的内存地址为假设):
VBSCall ReadMemory( &H400000,2,xue)
这句脚本的意思为,&H400000为读取内存地址400000中数值;2为读取类型,为长整数;xue则把读取出来的数值保存到xue这个变量中去。
如果这个400000的地址是用来储存血量的。那我们就可以对xue这个变量来进行判断计算。实际应用如下
If xue<500
    //放入加血的脚本
EndIf
也就是当血量少于500的时候我们开始加血。这个500你可以随意改变

实际应用2挂机打怪,然后人物回到挂机点(中间的内存地址为假设):
vbs dim x,y,a,b
//申明变量(其实在按键精灵里不用这么做)
VBSCall ReadMemory( &H400000,2,x)
//读取地址中的纵坐标保存到x
VBSCall ReadMemory( &H800000,2,y)
//读取地址中的横坐标保存到y
vbs a=100
vbs b=100
//也就是原始坐标或者是你想定点的坐标
if x>a and y>b
   moveto 300  500
  //以上坐标为虚拟,根据游戏不同自己更改,以下放入这个游戏里移动的移动方式的脚本
endif
//如果两个坐标都大于我们希望保存的地方,我们就开始向另一个方向移动
由此我们可以生成
if x<a and y<b
if x>a and y<b
if x<a and y>b
if x=a and y=b
一共5种不同的处理方法,这样让人物回到原来的点继续开始打怪就可以轻松制作原点挂机的脚本
说了那么多,一定会产生一个很大的问题,如何查找游戏内的内存地址。
内存地址的查找
     我一般用金山游侠 例如我要找红,先在自己满血的时候输入上限,然后搜索,这时候会搜索出很多地址,一些是代表你当前的红,和你的上限,还有一些正好是搜索时碰巧一样的。
     OK,在结果里再搜索一次,会去掉一些,这样搜索3次基本上结果已经很少了,但还不准确。
     现在,你要做的是就是让自己死了,不同游戏可能不同,死的时候血是0,那就去自杀吧(如果掉经验用小号)。
     在结果里用0搜索一次。
     别以为这样就结束了,这次要让自己不死,那就让自己少点血,我一般采用脱掉加血上限的装备,让自己的血减少。
     依照以上方法反复尝试,最后确定一个地址。
     地址出现以后别高兴太早,现在很多游戏内存地址是变动的(至少每次开游戏时就变动),所以可能这次管用,到下次还要重新搜索。

以上这些都是我个人的经验之谈,可能有不精确之处,但我想基本上可以解决大部分问题,如果还有不懂的下面跟贴。
PS:这里的人看贴不回的习惯太不好了

以下发文观点皆以 "您已经会使用金山游侠、FPE2000、GameMaster等辅助软体来找寻资料"

相信不少玩家都经歷过那段记忆体只有 1M 时代,常常為為了挤那1,2k出来
跟OS争的你死我,再看看现在的电脑规格...,科技真一日千里 XD~

切入我们的主题,找到某游戏的内存位址数值后该怎麼用。

第一先从按精提供的函数来看
VBSCall ReadMemory(v1,v2,v3)
        v1:内存地址:整数(16进制)
        v2:类型:0-字节 1-整数 2-长整数
        v3:输出值-所读取的内容:长整型变量

我想很多人一开始就算你找到了数值,却卡在这边不知道要输入什麼,包括我第一次使用也
遇到这个问题,所以我觉得有必要就这个部份说明一下。
VBSCall ReadMemory(&HFAC8EA,1,HP)
上面这行您一定常用
&HFAC8EA 是内存地址 , 1 是读取一个整数然再后再存进 HP 变量裡面
不管您用过几次,下面这三个参数说明您一定要看完。
-------------------------------------------------------------------------------------------
ReadMemory()第一个参数 内存地址:整数(16进制)
-------------------------------------------------------------------------------------------
&HFAC8EA 是什麼东西,為什麼可以代表一个内存地址?
来测试一下,在按精脚本输入
[Copy to clipboard]
CODE:
VBSCall MessageBox(a)
VBSCall MessageBox(typename(a))
结果:
 第一次显示 16435434
 第二次显示 Long
没错,&HFAC8EA 是一个长整数,&H就是用来将一个10进制的数字转成16进制的表示法,
他的反函数是HEX(),按精测试 VBSCall MessageBox(HEX(16435434))会显示 FAC8EA。

*因為我没有 ReadMemory() 这个函数的原形,所以我并不知道為什麼说明文件上面写整数(16进位)
 也许是很早之前的按精版本确实只能使用整数,只是说明文件没改,也许是他确实是传入一个整数
 ,只是我误会他的意思,有时间我会把函数dump出来看看再上来加註,或是总版老大来龙去脉可以
 说明一下。

不过他是什麼型态无所谓,至少用到现在没有出错过(不过还是有必要瞭解一下),我们只要确定一点
a = &HFAC8EA,变量 a 的型态确实是一个长整数!! 就算你把他强制转形,他还是一个长整数。且看
以下。
[Copy to clipboard]
CODE:
VBSCall MessageBox(typename(a))

//强制转形為整数
a = CINT(a)
VBSCall MessageBox(typename(a))

嗯,二次都是显示 Long,这是因為VBS的特性会根据变量内容来决定他是什麼型态如同以下程式


[Copy to clipboard]
CODE:
b = 3
VBSCall MessageBox(a + b)

得到 8,因為VBS变数宣告的不定型特性,相对VBS也调整了一些运算子的自动转换,这样是好还是不好,
好处就是乱乱写也通,坏处就是在脚本裡做判断时很容易出错,因為你不知道他什麼时候偷偷帮你转形,
或是你以為他有帮你转形,事实上并没有,下就这段就不能执行了。


[Copy to clipboard]
CODE:

b = 3
VBSCall MessageBox(a + b)

这种情况其实常常发生从文字档裡读出使用者界面参数做判断时,有时应该要HP=30自动吃补药,但是没吃,
不是按精有问题,而是你的判断式不正确,避免这种情况发生,读取文字档裡的变数出来后一律强制转形一
次(一个被变数型态搞到失眠的人留),微软出了一个VBS不知道该说造大眾还是害死一堆入门设计师。

偏主题有点久了,这部份详细请参考拙作(其实是写给我自已看的)。
按键精灵与 VBScript 的基础观念(一)http://bbs.vrbrothers.com/viewth ... &extra=page%3D2
按键精灵与 VBScript 的基础观念(二)http://bbs.vrbrothers.com/viewth ... &extra=page%3D2

-------------------------------------------------------------------------------------------
ReadMemory()第二个参数 类型:0-字节 1-整数 2-长整数
-------------------------------------------------------------------------------------------
為什麼我这麼在意变量是整数还是长整数,原因就在这,第二个参数型态直接就影响到输出的结果,
字节跟整数跟长整数有什麼不同,最大就差别就在范围值
字节 = 1 Byte (-127 ~ 128) 或不带正负号 (0 ~ 255)  = 256
整数 = 2 Byte (-32,768 ~ 32,767) 或 (0 ~ 65535) =  65536(256 ^ 2)
长整数 = 4 Byte (-2,147,483,648 ~ 2,147,483,647) 或 (0 ~ 4294967296) = 256 ^ 4

上面的范围很重要在,超过原本型态的范围就会產生溢位(overflow)的错误。

整数一定是 2Byte ? 不一定,要看你用的是哪一套程式语言,像 .NET Framework 中的整数就是
4个 Byte,Long 是 8 个 Byte,有一种叫 短整数 才是 2 Byte。那你怎麼知道按精是什麼语言开
发的,对!我不知道...,那你怎麼知道上面字节要用1 Byte 整数要用 2 Byte,对!我猜的 =.=

呵呵,好啦,不要玩文字游戏了,没有特别的情况下一定是上面那种范围,我实测过的确第二个参数
是这个范围值没错,只是按精应该在指令说明上应该註明一下范围(ps.我的印像中好像
按精有一个地方有特别註明这个参数佔的Byte数,因為我看了5.9x简体版的说明文件还有繁体版的说明
文件还有官网上的按精宝典,都没有特别说明,我一时也想不起来在哪看过的,还是哪位高人po的帖子
有提及过,有版友可以提供我官方文件说明文件连结我就会回来编帖註解一下。)

这个跟我游戏中 血量是285 昇级经验值是 20000 有什麼关係?

所以重点就是如果你的血量是在 0~255内,你就要设 1(字节),0~65535就要设2(整数)

有时你现在的血量是124第二个参数你设1(字节),但可能你会昇级血量会超过255(字节的范围),读出来
的值最大就到255而己,所以你要先确定游戏中血量到底佔了几个Byte。
原创粉丝点击