If the ASLR isn't enabled for the module, and it's loaded at the address of 0x400000 this is as simply as
DWORD address = 0x427000;
ReadProcessMemory(handle, (void*)address, &value, sizeof(value), NULL);
However if the ASLR is enabled (or the process just isn't mapped to memory starting at 0x400000) you need to get base address of the module. I assume you aren't part of the process (because you want to use ReadProcessMemory
) therefore you can't call GetModuleHandle
, because the function allows to obtain the handle only for modules loaded in the calling process.
The easiest way to get external process module base that comes to my mind is via the TlHelp32
functions and could look like this:
DWORD GetModuleHandleExternal(DWORD pid, const wchar_t* module)
{
DWORD base = 0;
HANDLE handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
MODULEENTRY32 entry;
entry.dwSize = sizeof(MODULEENTRY32);
while(Module32First(handle, &entry))
{
if (!wcscmp(entry.szModule, module))
{
base = (DWORD)entry.modBaseAddr;
break;
}
}
CloseHandle(handle);
return base;
}
Then you can just simply call
HANDLE handle = OpenProcess(PROCESS_VM_READ, FALSE, pid);
DWORD base = GetModuleHandleExternal(pid, L"module.exe");
DWORD address = base + 0x27000;
DWORD value = 0;
ReadProcessMemory(handle, (void*)address, &value, sizeof(value), NULL);
CloseHandle(handle);