使用 ReadProcessMemory 获取字符串值的访问冲突
Access Violation using ReadProcessMemory to get a string value
我是逆向工程的新手,也是 C++ 的新手。我正在尝试使用来自 Win32 API 的 ReadProcessMemory()
在游戏中收集玩家的角色名称,但每当我尝试读取它时它都会抛出异常:
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;
}
首先要判断要读取的字符串是宽字节(wchar)还是多字节(char)版本,然后可以使用std::string/char*
或std::wstring/wchar_t*
.
其次,不要使用sizeof(std::string)
,你需要确定你要读取的字符串的长度。
对于宽字节:
&(std::string)name
不是可写地址,正如评论所指出的,您可以使用 wchat_t 数组代替:
wchat_t name[100];
BOOL ret = ReadProcessMemory(hprocess, (BYTE*)nameaddres, name, sizeof(name), 0);
或者你可以使用&name[0]
(来自@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;
那么,std::cout
对于wchar_t*
是不可用的,它只打印地址值。在for循环中是一个局部变量,所以每次进来都会重新分配地址。由于某些规则,系统可能更愿意选择相同的地址,所以你得到了相同的地址值。
使用std::wcout << name
输出wchar_t字符串,如果输出总是只有一个字符,那么可以考虑使用多字节版本读取内存。
我是逆向工程的新手,也是 C++ 的新手。我正在尝试使用来自 Win32 API 的 ReadProcessMemory()
在游戏中收集玩家的角色名称,但每当我尝试读取它时它都会抛出异常:
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;
}
首先要判断要读取的字符串是宽字节(wchar)还是多字节(char)版本,然后可以使用std::string/char*
或std::wstring/wchar_t*
.
其次,不要使用sizeof(std::string)
,你需要确定你要读取的字符串的长度。
对于宽字节:
&(std::string)name
不是可写地址,正如评论所指出的,您可以使用 wchat_t 数组代替:
wchat_t name[100];
BOOL ret = ReadProcessMemory(hprocess, (BYTE*)nameaddres, name, sizeof(name), 0);
或者你可以使用&name[0]
(来自@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;
那么,std::cout
对于wchar_t*
是不可用的,它只打印地址值。在for循环中是一个局部变量,所以每次进来都会重新分配地址。由于某些规则,系统可能更愿意选择相同的地址,所以你得到了相同的地址值。
使用std::wcout << name
输出wchar_t字符串,如果输出总是只有一个字符,那么可以考虑使用多字节版本读取内存。