C++:读取另一个进程的内存

For*_*vin 3 c++ memory winapi

我想要一个允许我读取另一个进程的内存的函数.我在考虑这样的事情(伪代码):

staticAddress = 0x026E0DC4
processId = GetProcessIdByName(processName)
processHandle = GetProcessHandle(processId)
processBaseAddress = GetBaseAddress(processHandle)
addressToRead = processBaseAddress+staticAddress
readValueAsInt = ReadMemoryInt(processHandle, addressToRead)
readValueAsFloat = ReadMemoryFloat(processHandle, addressToRead)
readValueAsString = ReadMemoryString(processHandle, addressToRead)
Run Code Online (Sandbox Code Playgroud)

这甚至可能吗?这是我到目前为止所得到的:

#include <Windows.h>
#include <conio.h>
#include <tlhelp32.h>
#include <string>
#include <psapi.h>
#pragma comment( lib, "psapi" )

int GetProcessId(char* ProcName) {
    PROCESSENTRY32 pe32;
    HANDLE hSnapshot = NULL;
    pe32.dwSize = sizeof( PROCESSENTRY32 );
    hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );

    if( Process32First( hSnapshot, &pe32 ) ) {
        do {
            if( strcmp( pe32.szExeFile, ProcName ) == 0 )
                break;
        } while( Process32Next( hSnapshot, &pe32 ) );
    }

    if( hSnapshot != INVALID_HANDLE_VALUE )
        CloseHandle( hSnapshot );

    return pe32.th32ProcessID;  
}

int GetModuleBase(HANDLE processHandle, string &sModuleName) 
{ 
   HMODULE *hModules; 
   char szBuf[50]; 
   DWORD cModules; 
   DWORD dwBase = -1; 
   //------ 

   EnumProcessModules(processHandle, hModules, 0, &cModules); 
   hModules = new HMODULE[cModules/sizeof(HMODULE)]; 

   if(EnumProcessModules(processHandle, hModules, cModules/sizeof(HMODULE), &cModules)) { 
      for(int i = 0; i < cModules/sizeof(HMODULE); i++) { 
         if(GetModuleBaseName(processHandle, hModules[i], szBuf, sizeof(szBuf))) { 
            if(sModuleName.compare(szBuf) == 0) { 
               dwBase = (DWORD)hModules[i]; 
               break; 
            } 
         } 
      } 
   } 

   delete[] hModules; 

   return dwBase; 
}


int ReadMemoryInt(HANDLE processHandle, LPCVOID address) {
    //LPVOID buffer = ??;
    //SIZE_T size = ??;
    SIZE_T NumberOfBytesToRead = 4; //??
    ReadProcessMemory(processHandle, address, buffer, size, NumberOfBytesToRead)
    return buffer; //??
}

int ReadMemoryFloat(HANDLE processHandle, LPCVOID address) {
    //LPVOID buffer = ??;
    //SIZE_T size = ??;
    SIZE_T NumberOfBytesToRead = 8; //??
    ReadProcessMemory(processHandle, address, buffer, size, NumberOfBytesToRead)
    return buffer; //??
}

int ReadMemoryString(HANDLE processHandle, LPCVOID address) {
    //LPVOID buffer = ??;
    //SIZE_T size = ??;
    SIZE_T NumberOfBytesToRead = 999; //??
    ReadProcessMemory(processHandle, address, buffer, size, NumberOfBytesToRead)
    return buffer; //??
}

int main()
{
    //read an integer from "Program.exe"+0x05D8A3C4
    int address = 0x05D8A3C4;
    char* processName = "Program.exe";
    int processId = GetProcessId(processName);
    HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
    int processBaseAddress = GetModuleBase(processHandle, (string)"Program.exe";
    LPCVOID actualAddress = processBaseAddress+address;
    int readValue = ReadMemory(processHandle, actualAddress);
    std::cout << readValue << std::endl;
    CloseHandle(processHandle);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

正如您在代码中看到的那样,问题我不确定ReadProcessMemory的"缓冲区"和"大小"参数.如果有人能帮助我解决这个问题,我真的很感激.

Ben*_*ela 7

Here is an example for your ReadMemoryInt() function:

int ReadMemoryInt(HANDLE processHandle, LPCVOID address) {
    int buffer = 0;
    SIZE_T NumberOfBytesToRead = sizeof(buffer); //this is equal to 4
    SIZE_T NumberOfBytesActuallyRead;
    BOOL err = ReadProcessMemory(processHandle, address, &buffer, NumberOfBytesToRead, &NumberOfBytesActuallyRead);
    if (err || NumberOfBytesActuallyRead != NumberOfBytesToRead)
      /*an error occured*/ ;
    return buffer; 
}
Run Code Online (Sandbox Code Playgroud)

The & mean that the address of the variable is passed instead its value.

And in ReadMemoryString() you cannot know the actual size you need to read, you could either read a big block (size 999) or read many little blocks till you get one containing \0.

And if you want to know if it works, you can start it in a debugger and look if the values you expect are returned.


For*_*vin 6

https://github.com/T-vK/Memory-Hacking-Class
是一个非常简单的类,可以完成所有这些甚至更多。
这是一个包含它支持的所有方法的列表:

GetProcessId()
GetModuleBase()
SetPrivilege()
GetDebugPrivileges()
ReadInt()
GetPointerAddress()
ReadPointerInt()
ReadFloat()
ReadPointerFloat()
ReadText()
ReadPointerText()
Run Code Online (Sandbox Code Playgroud)

用法示例:

#include "Memory.hpp"
using std::string;

int main() {
    char* TARGET_PROCESS_NAME = "League of Legends.exe";

    int GAME_VERSION_MODULE_OFFSET = 0x2A1D738; // [Base address of 'League of Legends.exe']+0x2A1D738 (address of a string containing a version number)

    Memory Memory;
    Memory.GetDebugPrivileges();
    int processId = Memory.GetProcessId(TARGET_PROCESS_NAME);
    HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, processId);

    int baseAddress = Memory.GetModuleBase(processHandle, (string)TARGET_PROCESS_NAME);

    int gameVersionAddress = baseAddress + GAME_VERSION_MODULE_OFFSET;

    string gameVersion = Memory.ReadText(processHandle, gameVersionAddress);

    std::cout << "Game version: " << gameVersionAddress << std::endl;

    cin.get();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果你想知道,是的,我是作者。

  • 2020 年的那一刻,你意识到你在 2017 年回答了你在 2013 年提出的问题。 (11认同)
  • 进程的基地址总是不同的。偏移量只是相对于基地址,因此永远不会改变(除非游戏已更新并运行新代码)。 (3认同)