免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
内容参考于:易道云信息技术研究院
上一个内容:102.游戏安全项目-显示人物属性
102.游戏安全项目-显示人物属性它的代码写完之后存在一个问题,人物对象的地址(0x4CEF08)是写死的,当切换进度人物对象地址会变,所以这里的人物对象的地址不能给写死了。
如下图,内容显示的是灰狼并不是人物的数据了,0x4CEF08这个起点变成了怪物的起点了
人物血量地址变成了0x4B6CC4了
内存地址变了,数据的结构没有变
这种内存地址变化很常见,这个问题就需要通过基址来解决,血量在写代码时就是一个变量然后变量本质上是内存地址,内存地址是需要操作系统分配的,所以知道变量怎么分配的也就指定如何解决了,变量的声明有局部变量,全局变量。
局部变量内存地址分配的方式是通过函数一开始的压栈来实现的,栈是一段提前设置好的内存空间,然后栈是在线程里的每个线程都有不同的栈,也就是一个进程有几个线程就有几个栈,也就是同一个变量因为调用函数的线程不同会导致变量的地址不同,所以局部变量的内存地址是不固定的,几个线程有几个栈的原因是保证多线程的运行,调用函数时它会有一个 sub esp,一个数字,也就是调用函数时会进行压栈操作,局部变量的地址一样不一样是取决于压栈的,,下图调用两次a函数内存地址都是一样的,原因是当main调用的第一个a函数时进行压栈,第一个a函数执行完它里面的变量就消失了也就是把栈里的数据pop回去了(或者其它恢复栈的操作),然后再调用a函数就会用的也是第一个a函数的那块栈空间了
然后一个递归函数可以看出局部变量的地址都是不一样的,也就是它不还原栈就再次压栈导致了局部变量内存地址不一样,然后栈上分配内存出了内存地址不固定之外还有一个函数的栈控件是有限的默认1mb,虽然栈空间是可以调的但是基本上也没人调,它本身的设计就是用来存放临时的东西
分配局部变量的空间,往往通过函数头的 sub esp, XXX 这样的代码就可以知道这个函数大概有多少个变量了
全局变量
全局变量因为很多函数都会用所以,编译器一定会在编译时把全局变量的位置给写死,写死的这个值是一个偏移,通过基址 + 偏移就可以找到
全局变量的地址
a函数
b函数,也可以看出直接把地址从汇编层面写死了
然后有一点pe的内容,pe是一个文件的格式比如exe,dll等文件,pe与jpg,zip,ini这种性质一样是一种格式一种规范,然后一个exe文件也就是一个数据在双击的时候操作系统会把数据加载到内存中的某个位置假设这个位置是x,然后硬盘讲究的是节约而内存讲究的是对齐,也就是一个文件在硬盘里显示是9kb当加载到内存中之后会大于9kb的,然后它就有一段代码是 mov eax, HP的内存地址,这样的代码,然后exe文件在硬盘中的时候它是不知道hp的地址的因为它不知道x是什么,所以编译的时候编译器是不会把hp的地址给写死的只会写一个偏移(比如把hp放在0x200这个位置),当加载到内存时通过x + 0x200这样的方式来访问hp这个变量。
在 Cheat Engine 中显示为绿色的就说明这个值是全局的,判断一个值是不是全局的就看 这个内存地址是不是 大于基址 小于基址+文件大小,如果在这个范围那么它就是全局变量。