Windows开发——内存读写API
我们知道数据都是写在内存中的,通过一些API我们可以访问并修改内存中的数据,达到修改游戏数据的功能。
通过一个小项目,了解windos读写内存API,以及进程id获取相关API。
大体思路如下:
(1)先找到进程:(API:CreateToolhelp32Snapshot、Process32First、Process32Next)
void ShowProcessList() //功能1显示进程
{PROCESSENTRY32 pc;//定义一个32接收变量pc.dwSize = sizeof(pc);int count = 0; //进程计数HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//进程状态“快照”BOOL bMore = Process32First(hProcessSnap, &pc); //“快照”中获取第一个进程while (bMore){cout << "\n---------------------------------------\n";cout << "id: " << pc.th32ProcessID << endl; //.th32ProcessID获取进程idwprintf(L"name:%s\n", pc.szExeFile); bMore = Process32Next(hProcessSnap, &pc); //转向下一进程count++;}CloseHandle(hProcessSnap);cout << "目前进程数:" << count << endl;}
涉及API:
CreateToolhelp32Snapshot
Process32First
Process32Next
(2)编辑进程 (设计两轮查找,API: OpenProcess、WriteProcessMemory)
void EditProcessData() //功能2 编辑进程
{DWORD dwId = 0;DWORD dwSearchValue = 0;DWORD dwAddrList[4 * KONEK] = { 0 };DWORD dwAddrCount = 0;BOOL bRet = false;scanf_s("%d", &dwId); //输入需要编辑的进程idHANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);//获取进程句柄(打开进程)system("pause");printf("Please input the value which you want search first round:");scanf_s("%u", &dwSearchValue);//输入修改的进程内数据的当前值//首轮查找 待修改进程 查找目标值 存放数组 找到目标计数 空间FirstRound(hProcess, dwSearchValue, dwAddrList, &dwAddrCount, 4 * KONEK);ShowAddrList(dwAddrList, dwAddrCount);//显示搜索结果(目标数为):if (dwAddrCount == 0) //无目标:返回{return;}else if (dwAddrCount == 1) //一个目标:直接修改{DWORD value;printf("input the value which you want to set");scanf_s("%u", &value); //修改唯一值//改写内存数据bRet = WriteProcessMemory(hProcess, (LPVOID)dwAddrList[0], (LPVOID)&value, sizeof(DWORD), NULL);}else //多个目标:二轮查找{DWORD dwSecondRoundSearchValue = 0;DWORD dwTargetList[KONEK] = { 0 };DWORD dwTargetCounter = 0;scanf_s("%u", &dwSecondRoundSearchValue); //二次查找(需对数据进行修改)//二轮查找 进程 二轮查找目标值 原(1轮)地址 原(1轮)目标计数 新目标地址 新目标计数 SecondRound(hProcess, dwSecondRoundSearchValue, dwAddrList, dwAddrCount, dwTargetList, &dwTargetCounter);ShowAddrList(dwTargetList, dwTargetCounter);DWORD value;scanf_s("%u", &value); //想要改成的数值for (DWORD i = 0; i < dwTargetCounter; i++)//对二轮查找的所有值进行修改{bRet = WriteProcessMemory(hProcess, (LPVOID)dwTargetList[i], (LPCVOID)&value, sizeof(DWORD), NULL);}}}CloseHandle(hProcess);
}
涉及API:
OpenProcess
WriteProcessMemory
(3)结束进程 (API:OpenProcess、TerminateProcess)
void KillProcess() //功能3 结束进程
{BOOL bRet = FALSE; //进程结束是否成功标志DWORD dwId = 0; //需结束的进程IDcout << "Please input process id which you want to kill...\n";while (!scanf_s("%d", &dwId)){/*fflush(stdin);*/rewind(stdin);cout << "Please input process id which you want to kill";}HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId); //打开进程if (hProcess != NULL){bRet = TerminateProcess(hProcess, 0); //结束进程}CloseHandle(hProcess);if (bRet){cout << "kill process success\n";}else{cout << "kill process filed\n";}return;
}
涉及的API:
OpenProcess
TerminateProcess
ReadProcessMemory:读取进程内存
WriteProcessMemory:写入进程内存
void FirstRound(HANDLE hProcess, DWORD dwValue, DWORD *pAddrList, DWORD *pAddrListCounter, const DWORD addrListMax) //首轮内存查找
{DWORD dwBaseAddr = 64 * KONEK; //查找首地址DWORD dwPageCount = (2 * KONEG - 64 * KONEK * 2) / KPAGE; //查找计数 用以确定合法范围 | | 。。。 | | |// |前64k |用户程序区 |64k禁区 | 2G内核区 |// |NULL指针区 | | | |printf("%u pages\n", dwPageCount); printf("Start searching...\n");DWORD dwBeginAddr = dwBaseAddr;for (; dwBaseAddr< 2 * KONEG - 64 * KONEK; dwBaseAddr += KPAGE){if (!CompareOnePage(hProcess, dwBaseAddr, dwValue, pAddrList, pAddrListCounter, addrListMax)){return;}//计算进度百分比DWORD page = (dwBaseAddr - dwBeginAddr) / KPAGE + 1;printf("current is %u page\n", page);double temp = ((double)page / dwPageCount) * 100;printf("-----------%%%f---------\n", temp);}printf("\nSearch finished...\n");system("pause");
}
bool CompareOnePage(HANDLE hProcess, DWORD dwBaseAddr, DWORD dwValue, DWORD *pAddrList, DWORD *pAddrListCounter, const DWORD addrListMax) //对单页内数据进行遍历 比对
{BYTE byPage[KPAGE] = { 0 };if (!ReadProcessMemory(hProcess, (LPCVOID)dwBaseAddr, (LPVOID)byPage, KPAGE, NULL)){printf("Read Memory error!!!\n");return true;}DWORD *pdwPointer = NULL;pdwPointer = (DWORD*)byPage;for (DWORD i = 0; i < KONEK; i++){if (*pAddrListCounter >= addrListMax){printf("Too many data, can not save...\n");return false;}if (pdwPointer[i] == dwValue){pAddrList[*pAddrListCounter] = dwBaseAddr + i*sizeof(DWORD);(*pAddrListCounter)++;}}return true;
}void ShowAddrList(DWORD *pDwAddrList, DWORD dwAddrListCount)
{printf("\n--------------Address list begin---------------\n");for (DWORD i = 0; i < dwAddrListCount; i++){printf("%X\n", pDwAddrList[i]);}printf("\n--------------Address list end---------------\n");
}void SecondRound(HANDLE hProcess, DWORD dwValue, DWORD *pAddrList, DWORD dwAddrListCounter, DWORD *pTargetList, DWORD *pTargetCounter)
{DWORD dwTemp = 0;for (DWORD i = 0; i < dwAddrListCounter; i++){if (ReadProcessMemory(hProcess, (LPVOID)pAddrList[i], &dwTemp, sizeof(dwTemp), NULL)){if (dwTemp == dwValue){pTargetList[*pTargetCounter] = pAddrList[i];(*pTargetCounter)++;}}}
}
完整代码:
https://github.com/zjq4688/Myproject.git
Windows开发——内存读写API相关推荐
- Linux 字符设备驱动开发--内存读写操作
学习Linux的累计时间已经有两年多了,工作关系,学习的过程总是断断续续的,现在整理一下,下面要分享的是一个简单的linux驱动程序,将内存当作一个虚拟的设备去读写,没有什么实际的用处,像hello ...
- 【笔记】Windows Phone 8开发笔记之API
Windows Phone 8 API一览 Windows Phone 7平台不支持Native语言的开发,这困扰了许多游戏和底层应用的开发者.Windows Phone 8 SDK的推出,改善了这个 ...
- Android开发笔记(二十八)利用Application实现内存读写
全局变量 C/C++有所谓的全局变量,因为全局变量保存在内存中,所以操作全局变量就是操作内存,其速度远比操作数据库或者操作文件快得多,而且工程里的任何代码都可以引用全局变量,因此很多时候全局变量是共享 ...
- 【线程池】自行准备linux环境,带你手写线程池,只需仅仅150行代码|内存池|API|连接池|应用协议丨C/C++Linux服务器开发
[线程池]自行准备linux环境,带你手写线程池,只需仅仅150行代码 视频讲解如下,点击观看: [线程池]自行准备linux环境,带你手写线程池,只需仅仅150行代码|内存池|API|连接池|应用协 ...
- Windows下Libvirt Java API使用教程(二)- 接口使用说明
介绍完libvirt Java API的部署工作: <Windows下Libvirt Java API使用教程(一)- 开发环境部署> 接下来我们就介绍一下接口的使用和代码样例. libv ...
- 转载:Windows CE内存管理
内存管理 如果你在写Windows CE 程序中遇到的最重要的问题,那一定是内存问题.一个WinCE 系统可能只有4MB 的RAM,这相对于个人电脑来说是十分少的,因为个人电脑的标准配置已经到了128 ...
- 使用 dotnet core 和 Azure PaaS服务进行devOps开发(Web API 实例)
引子 这一篇文章将用一个完整的实例,给大家介绍如何基于dotnet core(微软.NET的最新版本,支持跨平台,跨设备的应用开发,详情请参考 https://www.microsoft.com/ne ...
- 为了分析WebRTC, 重学Windows开发
N多年没有写过 Window 程序了.为了研究 WebRTC 源码,这两天重新学习一下.还记得上大学的时候看过 <Windows95 程式设计>台湾版,对那本书印象极为深刻.一是当时国内确 ...
- DirectX游戏开发之一个API玩转音乐
DirectX游戏开发之一个API玩转音乐 当你闭上眼睛,打开一款游戏,如刺客信条,英雄联盟,DNF,或者是当有一个人坐在你背后玩一款新游戏,第一时间吸引你的是什么? 没错,就是各种游戏的音效,包括背 ...
- Windows的内存管理机制
Windows下的内存是如何管理的? Windows内存的管理可以分为两个层面:物理内存和虚拟内存 其中物理内存由系统管理,不允许应用程序直接访问,应用程序可见的只有一个2G的地址空间,而内存分配是通 ...
最新文章
- iis7 php oracle,PHP+IIS7配置OCI8链接Oracle 10G的方法
- hibernate加载持久化对象的两种方式---------------load方式和get方式
- 每日冲刺报告——Day4(Java-Team)
- Lucene学习之——停用词
- soapui返回值类型都有哪些_法兰的类型都有哪些以及法兰的设计
- 《天天数学》连载05:一月五日
- php5.4 升级,centos上PHP5.3升级到PHP5.4及更高版本方法
- Flask + Vue 搭建简易系统步骤总结
- 李迟2022年4月工作生活总结
- U盘修复“系统找不到指定文件”问题解决方法
- Word 只读模式修改
- 【GitHub上传文件夹:bug】 ! [rejected] master - master (non-fast-forward)
- POJ 3373 模运算 + 折半枚举
- Excel中的LEN和LENB,VBA中的Len和LenB
- Java反射获取类,方法
- linux查看tomcat 控制台,linux 下查看Tomcat的状态,以及开启停止服务命令
- 开源Linux面板-1Panel
- 区块链技术的概念及作用
- Angluar WARNING System.import() is deprecated and will be removed soon. Use import() instead
- 爬虫实例:每日一文和豆瓣电影
热门文章
- 2021-1-28Linux学习纪要
- gvim 命令行粘贴_vim基本命令之剪切复制粘贴替换
- linux用megacli看raid信息,Linux中使用MegaCli工具查看、管理Raid卡信息
- css两张图片怎么合在一起_PhotoShop怎么把两张图片合成一张?怎么用ps把两张图片合成一张?...
- php中is upload,PHP中,文件上传
- jQuery特效:实现简易轮播图
- Javascript特效:瀑布流
- PM_我们是怎么做Code Review的
- 论文笔记_S2D.43_2018-CVPR_单张RGB-D图像的深度补全
- 从零开始搭二维激光SLAM --- Karto的后端优化与回环检测的实现解读