[Win32] 实现内存修改器
0. 实现原理
- 在游戏运行中启动修改器, 输入游戏当前想要修改的金币/矿石/木材/…的数值
- 找到程序运行时的进程ID, Windows为每个进程都分配4GB的虚拟地址空间, 我们只需要在虚拟地址空间去遍历保存数值与游戏中数值相同的地址, 去修改它即可, 但需要注意仅搜索一次得到的保存此数值的地址极可能不唯一, 故在得到多个地址时就再在游戏中花费一点金币/…的值, 再到刚刚保存的多个地址中搜索. 直到获得唯一的地址.
- 修改此地址上的数值, 完成目标 !
直接使用CUI操作, 没有GUI美丽的外衣.(加上GUI不就成了金山某侠了吗?)
1. 找到目标进程
首先将游戏运行起来, Windows为每个进程分配4GB的地址空间, 前2GB归应用程序所有, 后2GB属于整个操作系统共用. 我们要向在指定的进程地址空间中修改数据就先要得到此进程的操作句柄.
实现原理: 输出当前所有运行中的进程及进程ID, 主动输入指定的进程ID, 返回目标进程的操作句柄. 通过句柄就能在找到指定的空间修改数据了.
实现输出和查找进程ID的demo
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>using namespace std;int main()
{PROCESSENTRY32 pe32;pe32.dwSize = sizeof(pe32);PROCESSENTRY32 _pe32;_pe32.dwSize = sizeof(_pe32);HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (hProcessSnap == INVALID_HANDLE_VALUE){cout << "调用失败" << endl;return -1;}BOOL bMore = Process32First(hProcessSnap, &pe32);while (bMore){cout << "进程名称: " << pe32.szExeFile << endl;cout << "进程ID: " << pe32.th32ProcessID << endl;bMore = Process32Next(hProcessSnap, &pe32);}bMore = Process32First(hProcessSnap, &_pe32);DWORD ProcessID;cout << "Input ProcessID: ";cin >> ProcessID;while (bMore){if (_pe32.th32ProcessID == ProcessID){cout << "find ID: " << ProcessID << " 进程名称: " << _pe32.szExeFile << endl;break;}bMore = Process32Next(hProcessSnap, &_pe32);}CloseHandle(hProcessSnap);system("pause");return 0;
}
这样就能将所有正在运行中的进程名与进程ID打印出来, 得到ID即可使用函数得到句柄
2. 找到指定数据所在的地址
Windows采用分页机制来管理数据, 以4KB为单位搜索可以提高搜索速率. 下面的CompareAPage函数的功能就是比较目标进程内存1页大小的内存. 得到的地址可能不止一个, 故将符合的所有地址保存在一个set中, 接下来会在这些地址中再筛选.
BOOL CompareAPage(DWORD dwBaseAddr, DWORD dwValue)
{// 读取1页内存BYTE arBytes[4096];if (!ReadProcessMemory(g_hProcess, (LPVOID)dwBaseAddr, arBytes, 4096, NULL)){return FALSE;}// 在这1页中查找DWORD* pdw;for (int i = 0; i < 4 * 1024 - 3; i++){pdw = (DWORD*)&arBytes[i];if (pdw[0] == dwValue){if (g_HashMap.size() >= 1024){return FALSE;}else{g_HashMap.insert(dwBaseAddr + i);}}}return TRUE;
}
使用FindFirst函数来在2GB的内存中搜索
BOOL FindFirst(DWORD dwValue)
{const DWORD dwOneGB = 1024 * 1024 * 1024;const DWORD dwOnewPage = 4 * 1024;if (g_hProcess == NULL){return FALSE;}// 在用户地址空间进行搜索, Win98为应用地址预留地址为4MB至2GB// Win2000预留地址为64KB至2GB// 故需判断操作系统类型, 用以决定开始地址DWORD dwBase;OSVERSIONINFO vi = { sizeof(vi) };GetVersionEx(&vi);if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS){dwBase = 4 * 1024 * 1024; // Win98系列, 4MB起}else{dwBase = 64 * 1024;}// 从开始地址到2GB的地址空间进行查找for (; dwBase < 2 * dwOneGB; dwBase += dwOnewPage){CompareAPage(dwBase, dwValue);}return TRUE;
}
3. 在所得到的地址中筛选得到正确的地址
数值改变后再到之前保存的地址中查找数据变化相同的数据, 直到满足结果
BOOL FindNext(DWORD dwValue)
{// 在g_HashMap中查找BOOL bRet = FALSE;DWORD dwReadValue;unordered_set<DWORD> newSet;for (auto& e : g_HashMap){if (ReadProcessMemory(g_hProcess, (LPVOID)e, &dwReadValue, sizeof(DWORD), NULL)){if (dwReadValue == dwValue){newSet.insert(e);bRet = TRUE;}}}g_HashMap.swap(newSet);return bRet;
}
4. 修改数值
BOOL WriteMemory(DWORD dwAddr, DWORD dwValue)
{return WriteProcessMemory(g_hProcess, (LPVOID)dwAddr, &dwValue, sizeof(DWORD), NULL);
}
5. 主函数
#include "MemRepair.h"HANDLE g_hProcess; // 保存游戏进程句柄
unordered_set<DWORD> g_HashMap; // 保存数据地址int main()
{ShowProcess();DWORD ProcessID;cout << "Input ProcessID: ";cin >> ProcessID;g_hProcess = FindProcess(ProcessID);cout << endl << "-----------------------------" << endl;int val;cout << "Input val = ";cin >> val;FindFirst(val);ShowHash();cout << endl << "----------------" << endl;size_t countAddr = 0;// 若地址数量不再减少, 则将所有的数据都修改了!while (g_HashMap.size() > 1 && countAddr != g_HashMap.size()){countAddr = g_HashMap.size();cout << "Input val = ";cin >> val;FindNext(val);if (FindNext == false){cout << "找不到此数据! " << endl;return -1;}ShowHash();cout << "----------------" << endl;}cout << "Input new val = ";cin >> val;auto it = g_HashMap.begin();while (it != g_HashMap.end()){if (WriteMemory(*it, val)){cout << "Write data success!" << endl;}else{cout << "Write data fail!" << endl;}it++;}return 0;
}
6. 测试
本来想使用红警2测试, 由于游戏版本过低原因我无法切回桌面, 故使用红警3
打开游戏, 开始游戏, 这个时候只有15000很少.
打开修改器程序. 输入指定游戏进程ID
输入5692, 等待输入金额
输入15000的金额, 程序进行搜索, 将保存此数值的地址打印并保存起来
发现多个地址, 我们在游戏中建一个电厂花费点钱, 金钱变为14200, 再在窗口输入这个数
这时在刚刚保存的地址中仅有两个地址存储的数据为14200, 再重复上一步花点钱. 再输入进去
最后, 输入你想要的数字, 回车, 返回游戏查看ohhhhhhhhhhhhhhhhhhhhhhhh, 让我们使用先锋轰炸机轰平Tokyo吧 !
需要原码可以联系作者哦
参考文献:
Windows程序设计(第三版) 张铮 孙宝山 周天立
[Win32] 实现内存修改器相关推荐
- andorid平台游戏内存修改器的开发思路
实现一个linux下的命令行内存修改器,然后安卓程序调用这个外置命令 1. 对指定andorid程序的内存进行扫描,把符合条件的数据都列表显现. 这个研究下/proc/pid/maps文件结构,主要分 ...
- 手机html5游戏内存修改,一种防止游戏被内存修改器修改的方法
一种防止游戏被内存修改器修改的方法 [技术领域] [0001]本发明涉及游戏数据处理领域,尤其涉及一种防止游戏被内存修改器修改的方法. [背景技术] [0002]目前,电子游戏越来越受到大家的喜爱,丰 ...
- 给初学者:用VB写外挂 ———— 实战六:幽城幻剑录-幽城幻劍錄内存修改器
先起个头,有时间再写,今天病的,到现在也没睡着...本来写了好几天了,哎. 前几天下了这个游戏看了看,感觉还可以吧,发现有诸多存盘修改器.随时存档补丁.穿墙等补丁,很乱,玩家打上一个免CD还要打其他补 ...
- 【术】游戏内存修改器原理及游戏敏感数值加密建议
介绍市面上主流游戏内存修改器的原理,对症下药,让游戏从数据加密层面上更好的抵御这类内存修改器. 主流游戏内存修改器有三大内存搜索功能: 1. 基础数值搜索 2. 模糊搜索 3. 反加密搜索 基础数值搜 ...
- 内存修改器对游戏的危害
内存修改器是游戏外挂里面的一个大类,通过修改器可实现很多魔幻且具有很大破坏性的功能. 下面几张图是使用修改器实现的游戏破解效果. 内存修改器实现的透视功能 内存修改器实现的遁地功能 修改器实现的飞天功 ...
- Java外挂开发之内存修改器(类似CE)
最近闲着蛋疼,无聊之中用CE耍了一哈游戏,发现挺好用的,于是就想,我自己能不能写个内存修改器呢?于是乎,这个软件就诞生了! 当然我只会Java,C++嘛,了解了解,嘿嘿,所以这个工具也是用Java写的 ...
- Windows编程_Lesson008_内存_内存修改器
内存修改器 修改指定进程名字中的指定值所在的地址,进而改变这个值. 单线程版本 #include <Windows.h> #include <stdio.h> #include ...
- 超漂亮的内存修改器,可以媲美某类似软件,UI界面反复调整 功能更加人性化,更多隐藏功能待您发现
内存修改器:(有个比较有名的Cheat Engine修改器,功能十分相似,可能没ce专业,界面UI是反复调整后的) 对比图 一般是修改某应用在变化的某值,确定其内存地址(通过2次搜索锁定目标)然后写入 ...
- 使用VC2008制作简单大航海外传内存修改器
作者 :小草 日期 :2010/7/4 始发于 http://bbs.evewind.net/read.php?tid=2815 程序源代码下载地址: http://code.google.com/p ...
- Android For JNI(二)——C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器
Android For JNI(二)--C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器 当我们把Hello World写完之后,我们就可以迈入C的大门了,今天就来讲讲基本的一些数据类型 ...
最新文章
- 7个面向对象常用原则的中英文名、别名、定义及显著特点
- NLPer,是时候重视因果推理了!这有一份杨笛一等撰写的综述
- 欢迎进入Node.js世界
- 通过Web.config实现301重定向
- 文本编辑器实现跳转到指定行的功能
- Android API Level对应Android版本一览表
- Popush任务之linux配置篇
- 关于在asp.net中textbox文本输入框中的汉语标点符号显示位置的问题
- LeetCode(463)——岛屿的周长(JavaScript)
- 远程办公、游戏迅猛增长,旅行、汽车业遭重创!疫期移动互联网行业报告解读...
- 相信大家看了这篇文章对Oracle如何工作有一个形象的了解!
- 无线网卡在使用过程突然不好使的解决方法,Deepin Linux 15.9与Windows 10双系统
- 2017年前端该学些什么(译)
- linux系统调用使用方法,Linux系统的使用以及系统调用的开发方法OS.ppt
- 阿里中间件首席架构师钟华:《企业IT架构转型之道:阿里巴巴中台战略思想与架构实战》新书出版(含试读PDF)!...
- 基于java的企业人事管理系统的设计与实现(含源文件)
- RuntimeError: Exporting the operator affine_grid_generator to ONNX opset version 9 is not supported.
- oracle rman list,Oracle RMAN的show,list,crosscheck,delete
- 5寸android智能手机,5寸刚入门 六款巨屏安卓智能手机盘点
- 入门 - 01- Java帝国的诞生
热门文章
- 武大女硕士面试被拒,改简历冒充本科生找工作的感想(原创)
- Python绘制中国地图
- 6.1.3. Mentor: Design Not Just for Usability, but Learnability
- 渗透实战(周三):Ettercap·ARP毒化MITM中间人攻击
- 用python解决放苹果问题_[18/11/24] 递归解决-放置苹果问题
- 清蒸野猪佩奇自带LastDance
- pacman安装ubuntu_pacman命令 – 软件包管理器
- 深入理解计算机系统(第三版)家庭作业 第九章
- dns备用服务器信息,dns服务器地址(dns首选和备用填多少)
- MM 移动类型-入门篇