游戏外挂原理解析与制作

  本章意在批注怎么着运用高端语言依照变量数值搜索内部存款和储蓄器地址。涉及代码以C#为例。

  我用C#写了三个WinForm方式的德姆o,分界面如下:

  图片 1

  源代码:

 //血量初始值 private int value = 1000; public Form1() { InitializeComponent(); } /// <summary> /// 刷新界面:将最新的血量显示在界面 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_refresh_Click(object sender, EventArgs e) { this.label_display.Text = value.ToString(); } /// <summary> /// 更新血量:将自定义的数值写入血量变量 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_update_Click(object sender, EventArgs e) { int iVaule = -1; bool ParseResult = int.TryParse(this.textBox_value.Text,out iVaule); if (ParseResult) { value = iVaule; this.label_display.Text = this.textBox_value.Text; } } 

  很轻便的二个德姆o:一个名字为value的变量,整数型,赋予其开头值1000;多少个按键:修改按键点击后把文本框的数值赋值给value,并且修改标签文本=修改后value的值;另五个刷新开关,点下后更新标签文本=value的新式值。

  

  回看上一章节,大家讲到查询数值的内部存款和储蓄器地址必要用到多少个函数VirtualQueryEx和ReadProcessMemory:

  个中VirtualQueryEx的第七个参数是三个用以吸收接纳内部存储器音信的结构体指针,来看一下重组那几个结构体的积极分子

 //接收内存信息的结构体 public struct MEMORY_BASIC_INFORMATION { //区域基地址 public int BaseAddress; //分配基地址 public int AllocationBase; //区域被初次保留时赋予的保护属性 public int AllocationProtect; //区域大小 public int RegionSize; //状态 public int State; //保护属性 public int Protect; //类型 public int lType; }

  这么些注释是自身从百度健全上摘抄的,改进确的分解提出查阅MSDN的API,上面贴代码的时候自身也会据笔者的精晓去解释涉及到的分子,但要么提出中肯学习Computer的操作系统原理工夫当真调节这个术语与它们的意思。特意贴出这一段是自个儿以为那是整整外挂制作进程中最要害的贰个步骤。套用我们现有的沙盘可能应用三番五次小编也会波及的一三种帮助理工科程师具去实现外挂的炮制,是很难成才的,一些名扬四海的游艺靠工具寻觅基址千难万难,只有稳步的去领略那些API、领会存放器和汇编语言,能力走的更远。

 

  原归正传,小编就径直跟着实际测量试验来一步一步讲明:

  1). 张开测验程序

  图片 2

  程序的名目:WinMemory_Test

  图片 3

  2). 依照上一章节通过进度名称获取PID=7956

  图片 4

  3). 照旧上一章节事关的经过PID=7956得到进度句柄Handle=1072

  图片 5

  4). 通过Handle循环遍历可读写内存地址,获得字节数组。

 public void SearchAddress() { MEMORY_BASIC_INFORMATION MBInfo = new MEMORY_BASIC_INFORMATION(); //获取结构体大小[单次读取字节数] int MBSize = Marshal.SizeOf(MBInfo); //从0x00开始查询 StartAddress = 0x000000; //实际读取的字节数 int ReadSize = 0; //从0开始查询,直到查询到整形的最大值2147483647 while (StartAddress >= 0 && StartAddress <= 0x7fffffff && MBInfo.RegionSize >= 0) { //读取结果存入输出参数MBInfo MBSize = VirtualQueryEx(hProcess, (IntPtr)StartAddress, out MBInfo, Marshal.SizeOf(MBInfo)); //如果实际读取到的字节数等于结构体MEMORY_BASIC_INFORMATION字节数,表示读取成功 if (MBSize == Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))) { //PAGE_READWRITE:允许读写的内存区。 //MEM_COMMIT:已分配物理内存[要找的数值确定了,那么内存肯定提前分配了]。 if (MBInfo.Protect == PAGE_READWRITE && MBInfo.State == MEM_COMMIT) { byte[] FindArray = new byte[MBInfo.RegionSize]; //把读取到的字节写入上面定义的数组byData中 if (ReadProcessMemory(hProcess, (IntPtr)StartAddress, FindArray, MBInfo.RegionSize, out ReadSize)) //如果读取的字节数无误 if (ReadSize == MBInfo.RegionSize) { //处理数据[对比分析] DealData(DataArray, StartAddress); } } } else { break; } StartAddress += MBInfo.RegionSize; } }

   

  5).
将收获的字节数组转化整型与一千进展相比,将追寻到的持有结果保存到全局List.

public void DealData(byte[] DataArray, int StartAddress) { byte[] intBuff = new byte[4]; for (int i = 0; i < DataArray.Length - 4; i++) { Array.Copy(DataArray, i, intBuff, 0, 4); int num = BitConverter.ToInt32(intBuff, 0); if (num == 1000) { AddressList.Add(StartAddress + i); } } }

   看一下结实:

  图片 6

   至此,德姆o中整形数值等于一千的地址已经全副被大家找到了,下一章节疏解怎么着稳定大家所要查找的不胜“一千”以及修改其值。

 

  PS:转发请附带原版的书文路线: 。

相关文章

Comment ()
评论是一种美德,说点什么吧,否则我会恨你的。。。