I'm new to reverse engineering, and quite new to C++. I'm trying to collect a player's character name in a game using ReadProcessMemory()
from the Win32 API, but it throws an exception whenever I try to read it:
if (procId != NULL) {
hprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procId);
ModuleBase = getModuleBaseAddr(procId, "ac_client.exe");
localPlayerptr = ModuleBase + 0x10f4f4;
healthaddr = findDMAaddy(hprocess, localPlayerptr, { 0xf8 });
//load to entitylist Array
ReadProcessMemory(hprocess, (BYTE*)localPlayerptr, &Entitylist[0], sizeof(Entitylist[0]), 0);
for (int i = 1; i < 10; ++i) {
ReadProcessMemory(hprocess, (BYTE*)ModuleBase + 0x10f4f8, &Entitylist[i], sizeof(Entitylist[i]), 0);
ReadProcessMemory(hprocess,(BYTE*) Entitylist[i]+(i*4), &Entitylist[i], sizeof(Entitylist[i]), 0);
std::cout << std::hex << Entitylist[i] << std::endl;
uintptr_t nameaddres;
std::string name;
nameaddres = Entitylist[i] + 0x225;
//ReadProcessMemory(hprocess, (BYTE*)nameaddres, &name, sizeof(name), 0);
/*--> ** This is where I have a problem. ***/
std::cout << name << std::endl;
}
First, you need to determine whether the string you want to read is a wide-byte (wchar) or multi-byte (char) version, then you could use std::string/char*
or std::wstring/wchar_t*
.
Second, do not use sizeof(std::string)
, you need to determine the length of the string you want to read.
For wide-byte:
&(std::string)name
is not a writable address, as comments pointed out, you could use a wchat_t array instead:
wchat_t name[100];
BOOL ret = ReadProcessMemory(hprocess, (BYTE*)nameaddres, name, sizeof(name), 0);
Or you could use &name[0]
(From @Remy):
std::wstring name;
name.reserve(100);
BOOL ret = ReadProcessMemory(hprocess, (BYTE*)nameaddres, &name[0], 100*sizeof(wchar_t), 0);
std::wcout << name << std::endl;
Then, std::cout
is not available for the wchar_t*
, it only prints the address value. It is a local variable in the for loop, so it will reallocate the address every time comes in. Due to certain rules, the system may prefer to choose the same address, so you've got the same address value.
Use the std::wcout << name
to out put the wchar_t string, and If the output is always only one character, then you may consider using the multi-byte version to read memory.