读取TlHelp32.h中MODULEENTRY32::modBaseAddr触发Access Violation错误
问题:获取游戏模块基址时出现访问违规及调试显示异常
我运行以下代码尝试获取Winquake进程的模块基址:
#include <iostream> // For general input and output #include <Windows.h> // Windows API for interacting with windows processes #include <TlHelp32.h> // For getting snapshots int main() { /* Get the process ID to attach later */ DWORD gameProcID = -1; // Variable to hold the process ID, has to be a DWORD because the windows API wants it that way. Starts as -1 (which is invald) so it is known if the process wasn't found HANDLE procSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS , 0); // Creates a "snapshot" of the current processes (Essentially a list of the processes) // Creates a placeholder process entry, that will hold each process for checking PROCESSENTRY32 currentProc; currentProc.dwSize = sizeof(PROCESSENTRY32); // Has to have it's "sizeof" member set, or else the loop fails. // Loops through each process in the snapshot until it finds Winquake.exe if (Process32First(procSnap, ¤tProc)) { // Starts by getting the first process do { if (!_wcsicmp(currentProc.szExeFile, L"Winquake.exe")) { // Checks if the process is Winquake, using a Wide Character String Compare function // If found, update the variable and break out the loop gameProcID = currentProc.th32ProcessID; break; } } while (Process32Next(procSnap, ¤tProc)); // While there are still more processes, keep checking } CloseHandle(procSnap); // Close the snapshot. Good memory management :) // If it can't find the process, print and then close if (gameProcID == -1) { std::cout << "Couldn't find process" << std::endl; exit(1); } /* Get the module inside the found process (Quite similar to finding the process) */ uintptr_t gameBaseAddr = -1; // Variable to hold the base memory address of the module we want to find, Starts as -1 (which is invalid) so it is known if the module wasn't found HANDLE modSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, gameProcID); // Creates a snapshot of all the modules inside the process // Creates a placeholder module entry, that will hold each module for checking MODULEENTRY32 currentMod; currentMod.dwSize = sizeof(currentMod); // Has to have it's "sizeof" member set, or else the loop fails. // Loops through each module in the snapshot until it finds Winquake.exe if (Module32First(modSnap, ¤tMod)) { // Starts by getting the first module do { if (!_wcsicmp(currentMod.szModule, L"Winquake.exe")) { // Checks if the module is Winquake, using a Wide Character String Compare fucntion // If found, update the variable and break out the loop gameBaseAddr = (uintptr_t)currentMod.modBaseAddr; } } while (Module32Next(modSnap, ¤tMod)); // While there are still more modules, keep checking } CloseHandle(modSnap); // Close the snapshot. Good memory management // If it can't find the module, print and then close if (gameBaseAddr == -1) { std::cout << "Couldn't find module inside game. Perhaps you have the wrong 'Winquake.exe' executable" << std::endl; exit(1); } // The final handle for the game process HANDLE gameProc = OpenProcess(PROCESS_ALL_ACCESS, NULL, gameProcID); // Opens a handle to attach to the Winquake process and module. With full access rights }
代码未抛出异常,但在第56行设置断点时,调试器显示currentMod的modBaseAddr字段内容为:
modBaseAddr 0x00007ffac7c00000
若尝试用std::cout将该字段值输出到控制台,会触发如下异常:
An exception was thrown at 0x00007FF9FAA77CC1 (ucrtbased.dll) in ProjectName.exe: 0xC0000005: Access violation reading from 0x00007FF7EF6C0000.
我已尝试读取不同游戏的数据,且Visual Studio及生成的Debug目录下的.exe均以管理员身份运行,但问题仍未解决。期望currentMod的modBaseAddr字段能正确存储模块基址,且该对象的其他所有字段数据均正常。
内容的提问来源于stack exchange,提问作者user30186722
相关产品推荐
相关产品推荐

