Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: reading memory of another process

Tags:

c++

memory

winapi

I'd like to have a function that allows me to read the memory of another process. I was thinking about something like this (pseudo code):

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)

Would that even be possible? Here is what I got so far:

#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;
}

As you can see form the question marks in the code I'm really unsure about the "buffer" and "size" parameters of ReadProcessMemory. I'd really appreciate it if someone could help me figuring this out.

like image 432
Forivin Avatar asked Dec 11 '22 10:12

Forivin


2 Answers

https://github.com/T-vK/Memory-Hacking-Class
Is a pretty simple class to do all that and even more.
Here is a list with all the methods it supports:

GetProcessId()
GetModuleBase()
SetPrivilege()
GetDebugPrivileges()
ReadInt()
GetPointerAddress()
ReadPointerInt()
ReadFloat()
ReadPointerFloat()
ReadText()
ReadPointerText()

Example usage:

#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;
}

In case you were wondering, yes, I'm the author.

like image 178
Forivin Avatar answered Dec 29 '22 13:12

Forivin


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; 
}

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.

like image 28
BeniBela Avatar answered Dec 29 '22 12:12

BeniBela