windows平台游戏外挂实现原理

本文探讨了Windows游戏外挂泛滥的原因,重点讲解了如何利用exe文件的二进制结构、汇编指令以及内存操作(如CheatEngine、window32API)来修改游戏数据,实现游戏修改或外挂制作的过程。
摘要由CSDN通过智能技术生成

游戏开发


文章目录


前言

windows游戏外挂泛滥的根本原因就是太容易,只需要明白windows的原理。

我们都知道windows下的可执行文件的扩展名为exe(executable file)。

exe文件是一个二进制文件,是由0、1构成的数据流(stream),把这个数据流想象成一条有固定长度的纸带,纸带上有等分的格子,每个格子上有一个符号,要么是0,要么是1,然后按照一定的要求来读取上面的内容,比如每8个格子代表一个信息如:01000101。

我们并不清楚01000101意味着什么,但是我们有一本字典,这本字典记录了01000101对应的意思,这本字典就叫做汇编指令集。

汇编指令很容易看懂,但逻辑并不易懂,它看起来就像一本故事书,故事的内容并不是连续的,需要根据一定的信息来猜测它要表达的意义。

没错就是猜测,既然是猜测那么猜测的根据是什么?那就要根据想要做的事情来想办法,比如我要修改游戏里人物的血量,血量是一个整数并且知道血量的具体数值,那么问题就简单了,使用CE(Cheat Engine)就可以根据数值找到对应的汇编指令,改写汇编指令,然后再把汇编编译成exe可执行文件,这样我们就达到了修改目的,破解版软件可以使用这种方式。

以上的方法在软件执行之前通过修改逻辑达到目的,更容易的方法是通过修改内存(memory)来达到同样的目的。

下面举一个小例子,TargetApp002.exe为例,我们在内存当中修改它内部的数值:
在这里插入图片描述

TargetApp002内部有一个弹窗,弹窗里有一个自增长的值,当前值为1,我们现在将这个值修改为1050:
在这里插入图片描述

windows程序执行起来,程序就会加载到内存当中,内存中有软件的执行逻辑,也有数据。

windows首先会给程序分配一个pid(process id),然后把进程加载到内存中,映射内存地址。

我们只需要知道程序的映射内存的起始地址,就可以确定具体数值的位置,只要程序不变,数据在映射内存中的位置不变。

首先使用CE查找到弹窗当中值为1的数据在内存中的地址:
在这里插入图片描述

TargerApp002.exe+6788就是我们使用CE查找到的数值,TargetApp002.exe代表的就是程序的起始地址,+6788代表着该数据存放的位置,这个+6788就叫做偏移地址(offset address),可以理解成相对位置。

!!!每次启动程序都会给程序分配不同的pid,起始地址会变,但是这个偏移地址永远不会变。

OK,我们知道这个,按照这个思路就可以写对应的代码,代码使用python调用window32 API操作。

第一步:获取程序的映射起始地址。

第二步:写入内存地址+6788的值

第三步:读取内存地址+6488的值

#1
def imageBase(self):
pModules = win32process.EnumProcessModules(self.hProcess)
return pModules[0]
#1代码可以获取到程序所有模块的映射地址,第一个就是程序的起始地址。

#2
def write(self, memAddr, num, dataLen, dataType=‘’):
if dataType == ‘int’:
addr = ctypes.c_int32(num)
elif dataType == ‘float’:
addr = ctypes.c_float(num)
elif dataType == ‘double’:
addr = ctypes.c_double(num)
dataLen = 8
elif dataType == ‘long’:
addr = ctypes.c_ulong(num)
else:
addr = ctypes.c_int32(num)
return ctypes.windll.kernel32.WriteProcessMemory(int(self.hProcess), ctypes.c_void_p(memAddr), ctypes.byref(addr), dataLen, None)
#2代码写入内存。

#3
def read(self, memAddr, dataLen=4, dataType=‘’):
if dataType == ‘int’:
addr = ctypes.c_int32()
elif dataType == ‘float’:
addr = ctypes.c_float()
elif dataType == ‘double’:
addr = ctypes.c_double()
dataLen = 8
else:
addr = ctypes.c_ulong()

    ctypes.windll.kernel32.ReadProcessMemory(int(self.hProcess), ctypes.c_void_p(memAddr), ctypes.byref(addr), dataLen, None)
    return addr.value

#3代码读取内存地址。

#4
def main():
w32 = mem.MemOperation(“TargetApp002”, None)
image = w32.imageBase()
w32.write(image+0x6788,1050,4,int)
value = w32.read(image+0x6788,4,int)
print(“当前值为:{var}”.format(var=value))
根据程序标题名称查找到程序,然后获取到映射起始地址,向+6788内存写入数据,读取数据,我们将数据修改为1050,效果如下。

由于是自增长数据,所以执行弹窗的时候自加1,显示为1051。

OK明白了原理,代码就很简单。

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值