You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何调用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
    0x01
    
    微软官方文档说明:

    PAGE_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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 06:53:14