c++readprocessmemory

How to read a process' memory using code compiled with g++?


I want to read the process memory of notepad.exe and find the string Hello World! inside it (it's typed inside a Notepad window).

I want to use g++.exe, not cl.exe, because it's too much of a hassle to try to figure out how to set the proper environment variables to be able to use it from the command line instead of from inside Visual Studio. There are other reasons as well, but the thing is I need to use g++.exe.

Trying to compile the following code gives the following errors (I know the code, even if run, would do nothing as-is. But this is a first step):

wstring was not declared in this scope

szModName was not declared in this scope

expected ; before wstrModContain

wstrModContain was not declared in this scope

string has not been declared

#include <windows.h>
#include <psapi.h>

HMODULE GetModule();

int main() {
    return 0;
}

HMODULE GetModule() {
    HMODULE hMods[1024];
    HWND hWnd = FindWindowA(0, "Untitled - Notepad");
    DWORD pID;
    GetWindowThreadProcessId(hWnd, &pID);
    HANDLE pHandle = OpenProcess(PROCESS_VM_READ, FALSE, pID);
    DWORD cbNeeded;
    unsigned int i;
    if (EnumProcessModules(pHandle, hMods, sizeof(hMods), &cbNeeded)) {
        for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
            wstring szModName[MAX_PATH];
            if (GetModuleFileNameEx(pHandle, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR))) {
                TCHAR* wstrModName = szModName;
                wstring wstrModContain = "notepad.exe";
                if (wstrModName.find(wstrModContain) != string::npos) {
                    CloseHandle(pHandle);
                    return hMods[i];
                }
            }
        }
    }
    return nullptr;
}

Solution

  • Here is a better answer than my last, since the previous only searched the executable image which only contains what's in the .exe file and not it's dynamic memory.

    Compile with: g++ filename.cpp -lpsapi

    The order of the #includes is important; <Windows.h> must come before <psapi.h>.

    #include <Windows.h>
    #include <psapi.h>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    int main() {
        DWORD pID;
        HWND hwnd = FindWindowA(NULL, "Untitled - Notepad"); // the window title
    
        if (!hwnd)
            std::cout << "FindWindowA Error: " << GetLastError() << std::endl;
    
        if (!GetWindowThreadProcessId(hwnd, &pID))
            std::cout << "GetWindowThreadProcessId Error: " << GetLastError() << std::endl;
    
        HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
        if (!pHandle)
            std::cout << "OpenProcess Error:" << GetLastError() << std::endl;
    
        unsigned char *p = NULL;
        MEMORY_BASIC_INFORMATION info;
    
        for (p = NULL; VirtualQueryEx(pHandle, p, &info, sizeof(info)) == sizeof(info); p += info.RegionSize) {
            std::vector<char> buffer;
    
            if (info.State == MEM_COMMIT && (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE)) {
                SIZE_T bytes_read;
                buffer.resize(info.RegionSize);
                ReadProcessMemory(pHandle, p, &buffer[0], info.RegionSize, &bytes_read);
                buffer.resize(bytes_read);
    
                for (int i = 0; i < buffer.size(); i++) {
                    char value = buffer.at(i);
                    std::cout << value;
                }
            }
        }
    }
    

    Amusingly my last answer was deleted for calling comments "imbecilic". Comments which were unhelpful, wrong, patronizing, did not answer the question, yet which were not themselves deleted.