为何调用WriteProcessMemory无法写入目标进程内存?
摘要
尝试通过WinAPI的ReadProcessMemory和WriteProcessMemory函数对目标进程ConsoleApplication1.exe进行内存读写,目前能成功读取,但无法写入。
详情
使用GetBaseAddress进程执行内存读写操作。
代码(读写进程GetBaseAddress)
// GetBaseAddress.cpp : This file contains the 'main' function. Program execution begins and ends there. // #include <sstream> #include <iostream> #include <windows.h> #include <psapi.h> #include <processthreadsapi.h> #include <tlhelp32.h> #include <string.h> using namespace std; DWORD FindID(char *name ); void errExit(const char msg[50], HANDLE handle = 0); int main() { std::cout << "Hello World!\n"; /*Find Process ID by Name*/ char name[] = "ConsoleApplication1.exe"; DWORD processID = FindID(name); HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, processID); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID); if (snapshot == INVALID_HANDLE_VALUE || processHandle == NULL||processHandle == INVALID_HANDLE_VALUE) { errExit("Counldn't create snapshot exiting...", snapshot); } cout << "[+]Snapshot created for PID:" << processID << endl; cout << "[+]Retriving Module Info..." << endl; MODULEENTRY32 moduleEntry ; moduleEntry.dwSize = sizeof(MODULEENTRY32); if (Module32First(snapshot, &moduleEntry) == FALSE) { errExit("Counldn't retrive entry exiting...",processHandle); } //stringstream address; // char buff[12] = "Hello World"; DWORD offset = 0x19B44; //HelloWorld - [H] // //BYTE word = *moduleEntry.modBaseAddr; DWORD_PTR dwModuleBaseAddress = (DWORD_PTR)moduleEntry.modBaseAddr+offset; std::stringstream stream; stream << std::hex << dwModuleBaseAddress; std::string hexAddress = stream.str(); cout << "[+]Base Address of the module is:" << hexAddress << endl; cout << "[+]Reading Memory..." << endl; BOOL rslt = ReadProcessMemory(processHandle, moduleEntry.modBaseAddr + offset, buff, sizeof(buff) - 1, NULL); if (rslt == FALSE) { errExit("Couldn't read memory region exiting..."); } //char buff2[] = "Hacked "; cout << "[+]Memory Data:" << buff << endl; cout << endl; rslt= WriteProcessMemory(processHandle, moduleEntry.modBaseAddr + offset,buff,sizeof(buff)-1,NULL); if (rslt == FALSE) { errExit("Couldn't write to the Memory Address"); } } DWORD FindID(char *name) { cout << name << endl; DWORD procIDs[1024],needed=0; std::wstring str = L"ConsoleApplication1.exe"; int rslt = EnumProcesses(procIDs, sizeof(procIDs), &needed); if (rslt==0) { errExit("Procees IDs list couldn't be retrived exiting..."); } cout << "[+]Process IDs List Retrived..." << endl; cout << "[+]Bytes Returned:" << needed << endl; cout << "[+]sizeof(DWORD):" << sizeof(DWORD) << endl; cout << "[+]Number of Process Retrived:" << needed / sizeof(DWORD) << endl; for (int i = 0;i <= needed / sizeof(DWORD); i++) { HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, procIDs[i]); if (processHandle == NULL) { //CloseHandle(processHandle); continue; } wchar_t processFileName[MAX_PATH]; GetModuleBaseNameW(processHandle, NULL, processFileName, sizeof(processFileName)); if (std::wstring(processFileName) == str) { cout << "[+]Found:" << procIDs[i] << endl; cout << "[+]Process " <<":" << i << endl; wcout << "[+]Process Name" << ":" << processFileName << endl; return procIDs[i]; } CloseHandle(processHandle); } } void errExit(const char msg[50], HANDLE handle) { cout << "[-]"<<msg << endl; cout << "[-]Retriving Last Error:" << GetLastError() << endl; CloseHandle(handle); system("pause"); exit(1); }
通过modEntry.modBaseAddr + offset定位目标进程内存地址,其中modEntry.modBaseAddr是进程第一个模块的基地址,该计算结果指向目标进程中字符串“Hello World”的首字符。调用WriteProcessMemory时触发错误:
998 - ERROR_NOACCESS Invalid access to memory location.
已尝试的解决方法
- 调用
VirtualProtect修改内存保护属性失败,旧保护属性为:
微软官方文档说明:-PAGE_NOACCESS 0x01PAGE_NOACCESS
0x01
禁用对已提交页面区域的所有访问。尝试读取、写入或执行该区域会导致访问违规。此标志不受CreateFileMapping函数支持。 - 多次重试写入操作,仍报相同错误
- 使用硬编码地址
(LPVOID)0x619b44(即modEntry.modBaseAddr + offset的计算结果)写入,结果一致 - 关闭进程句柄后以
PROCESS_VM_WRITE权限重新打开,问题依旧
目标进程ConsoleApplication1.exe的代码
#include<Windows.h> //#include<unistd.h> #include <iostream> using namespace std; int main() { HANDLE d = GetModuleHandle(NULL); cout << "Module Handle:"<<d<<endl; int gold = 0; int* ptr = &gold; char buff[] = "Hello World\n"; std::cout << buff; system("title hackme"); std::cout << "Enter something:"; std::cin >> gold; for (;;) { std::cout << buff; //gold++; std::cout << "Address:"; std::cout << &gold<< std::endl; std::cout << gold << std::endl; Sleep(1000); } cout << "Congrats Pro!!!" << endl; }
输出信息
- GetBaseAddress的输出:显示找到目标进程PID、创建快照成功、获取模块基地址为
0x619b44、读取内存成功得到“Hello World”,最后提示无法写入内存地址,错误码998。 - ConsoleApplication1.exe的输出:显示模块句柄、打印“Hello World”、提示输入内容,之后循环打印“Hello World”、变量
gold的地址和值。
软件环境信息
- Microsoft Visual Studio Community 2019
- 版本:
16.11.23 - 优化选项:已禁用
- 操作系统:Windows 10
内容的提问来源于stack exchange,提问作者SUDO HERO
相关产品推荐
相关产品推荐

