运行环境:
windows 10
涉及工具:
vs2019
编程语言:
C
以下为主题内容:没太了解过Cheat engine,但是感觉写出来的这个估计也Ce的机理差不多
所用到的Api CreateProcess、ReadProcessMemory、WriteProcessMemory流程是先用CreateProcess()打开目标进程,以获取hProcess(进程句柄),然后ReadProcessMemory...找地址
WirteProcessMemory该地址的数据
里面还有很多细节 比如我只枚举了进程低2Gb的空间 因为高2Gb是内核。而且基质要是64kb以后,前64kb的物理页无法写入和读取。Windows系统的规定。
贴出Msdn给的这三个Api的解释,加上代码 估计能了解各个参数的含义。难懂的参数我都会注释。(其实也已经英文注释了 看不懂的可以自己去翻译)
这三个Api都是很基础的了,纯纯菜鸟做,目前刚学windows核心编程。大佬还请点击右上角
这是CreateProcess ApiCsdn的解释
[C++] 纯文本查看 复制代码 BOOL CreateProcess(
LPCTSTR lpApplicationName, // name of executable module
LPTSTR lpCommandLine, // command line string
LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD 安全属性
LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD 安全属性 无用 填Null
BOOL bInheritHandles, // handle inheritance option
DWORD dwCreationFlags, // creation flags
LPVOID lpEnvironment, // new environment block
LPCTSTR lpCurrentDirectory, // current directory name
LPSTARTUPINFO lpStartupInfo, // startup information
LPPROCESS_INFORMATION lpProcessInformation // process information);
下面是WriteProcessMemory和ReadProcessMemory;
[C++] 纯文本查看 复制代码 BOOL WriteProcessMemory( HANDLE hProcess, // handle to process
LPVOID lpBaseAddress, // base of memory area
LPVOID lpBuffer, // data buffer
DWORD nSize, // number of bytes to write
LPDWORD lpNumberOfBytesWritten // number of bytes written);
[C++] 纯文本查看 复制代码 BOOL ReadProcessMemory( HANDLE hProcess, // handle to the process
LPCVOID lpBaseAddress, // base of memory area
LPVOID lpBuffer, // data buffer
DWORD nSize, // number of bytes to read
LPDWORD lpNumberOfBytesRead // number of bytes read);
效果图:
输入要找的值
可以看到
有很多 那我们next search
现在只有一个值了 修改吧
因为我修改的值太大了 所以只能(32-bit) 这个值就是int的最大值 应该是有符号的最大值
代码下面 只有一个cpp 没有什么别的
[C++] 纯文本查看 复制代码
/////////////////////By Oxygen1a1///////////////////////////
////////////通过暴力枚举实现修改进程内存////////////////
////////////作者邮箱[email]304914289@qq.com[/email] 欢迎反馈///////
#include <stdio.h>
#include <Windows.h>
BOOL FindFirst(DWORD dwVaule);//对目标进程空间进行查找
BOOL FindNext(DWORD dwValue);//对目标空间以后的查找
//把查找的东西放在列表里面
DWORD g_arList[1024];
int g_nListCnt;//有效的地址个数
HANDLE g_hProcess;//目标进程句柄
void ShowList();//用来显示查找到的地址
BOOL WriteMemory(DWORD dwAddr, DWORD dwVaule);//最后用来改东西的
int main() {
//1.首先用CreateProcess 把目标进程Testor拉起来
//获取句柄就可以了
char szFileName[] = "Target.exe";//目标程序 注意工作路径
STARTUPINFO si;
memset(&si, 0, sizeof(si));
PROCESS_INFORMATION pi;
BOOL bRet = CreateProcess(
NULL,
szFileName,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi
);
if (bRet) {
g_hProcess = pi.hProcess;//获取进程句柄
}
//2.然后 我们需要将memchange接受一个目标值 并比对
int iVal;
printf("first search:");
scanf_s("%d", &iVal);
FindFirst(iVal);
//交互显示
ShowList();
while (g_nListCnt > 1) {
printf("next search:");
scanf_s("%d", &iVal);
FindNext(iVal);
ShowList();
}
//得到唯一地址的值
printf("new vaule:");
scanf_s("%d", &iVal);
if (WriteMemory(g_arList[0], iVal)) {
printf("ok!!");
}
}
BOOL ComPareAPage(DWORD dwBaseAddr, DWORD dwValue) {
BYTE arBytes[4096];//4kb
if (!ReadProcessMemory(g_hProcess, (LPVOID)dwBaseAddr, arBytes, 4096, NULL)) {
return false;
}
DWORD* pdw;
for (int i = 0; i < 4 * 1024 - 3; i++) {
pdw = (DWORD*)&arBytes[i];
if (*pdw == dwValue) {
if (g_nListCnt >= 1024) return false;//太多了
g_arList[g_nListCnt++] = dwBaseAddr + i;
}
}
return TRUE;
}
BOOL FindFirst(DWORD dwVaule) {
const DWORD dwOneGB = 1024 * 1024 * 1024;
const DWORD dwOnePage = 4 * 1024;//4kb
if (g_hProcess == nullptr) return false;
DWORD dwBase = 640 * 1024;
//BOOL bRet = FALSE;
for (; dwBase < 2 * dwOneGB; dwBase += dwOnePage) {//在低2Gb的内核态进行查找
ComPareAPage(dwBase, dwVaule);
}
return TRUE;
}
BOOL FindNext(DWORD dwVaule) {
BOOL bRet = FALSE;
//这个时候只需要在g_arList中查找即可,
int nOrgCnt = g_nListCnt;
g_nListCnt = 0;//清空上一次找到的地址 下面在慢慢加 也是节省变量
DWORD dwReadVaule;
for (int i = 0; i < nOrgCnt; i++) {
if (ReadProcessMemory(g_hProcess, (LPVOID)g_arList[i]
, &dwReadVaule, sizeof(DWORD), NULL)) {
//读取成功后
if (dwReadVaule == dwVaule) {
//值还一样
g_arList[g_nListCnt++] = g_arList[i];
}
}
bRet = TRUE;
}
return bRet;
}
void ShowList() {
printf("全部地址:\n");
for (int i = 0; i < g_nListCnt; i++) {
printf("%p ", g_arList[i]);
}
printf("\n");//换行 美观
}
BOOL WriteMemory(DWORD dwAddr, DWORD dwVaule) {
return WriteProcessMemory(g_hProcess, (LPVOID)dwAddr, &dwVaule
, sizeof(DWORD), NULL);
}
|