Проблема с взаимодействием CreateToolhelp32Snapshot и OpenProcess в Windows 11.C++

Программы на C++. Форум разработчиков
Anonymous
Проблема с взаимодействием CreateToolhelp32Snapshot и OpenProcess в Windows 11.

Сообщение Anonymous »

Я столкнулся с необычной проблемой в моем приложении C++ в Windows 11, связанной с функциями CreateToolhelp32Snapshot и OpenProcess. Вот краткий обзор проблемы:
Когда мой код вызывает GetAllModulesInfoOfPID(второй блок), который внутренне вызывает CreateToolhelp32Snapshot (первый блок) для получения информации о модуле процесс, идентифицируемый его PID, CreateToolhelp32Snapshot возвращает INVALID_HANDLE_VALUE с кодом ошибки 0x5 (Доступ запрещен). Однако если я закомментирую вызов GetRDataSectionBaseAddress (последний блок), последующая функция GetAllModulesInfoOfPID (которая использует CreateToolhelp32Snapshot) выполнится без ошибок.

Код: Выделить всё

char** GetAllModulesInfoOfPID(DWORD PID, int* numModules) {
//CreateToolHelp32Snapshot is powerfull
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, PID);
if (hSnapshot == INVALID_HANDLE_VALUE) {
switch (GetLastError()){
case 5:
warn("PID: %-6d, Denied Access", PID);
break;
case 299:
warn("PID: %-6d, Error Memory Management", PID);
break;
default:
warn("PID: %-6d, [CreateToolhelp32Snapshot] failed to get handle, Error: %lx", GetLastError());
break;
}
*numModules = 0;
return nullptr;
}
//...

Код: Выделить всё

    if (processList) {
info("Writing in list_MODULES_imports:");
for (int i = 0; i < numProcesses; i++) {
int numModules = 0;
char** moduleNames = GetAllModulesInfoOfPID(processList[i].pid, &numModules);
if (moduleNames) {
// If you call get_all_modules_info_of_PID and GetRDataSectionBaseAddress it'll denies access magically
for (int j = 0; j < numModules; ++j) {
fprintf(outputFile, "%s (%d), %s\n", moduleNames[0], processList[i].pid, moduleNames[j]);
//get_exported_functions(processList[i].pid, processList[i].processName);
}
free_module_names(moduleNames, numModules);
} else {
//pass
}
}
} else { return false; }

Код: Выделить всё

LPVOID GetRDataSectionBaseAddress(DWORD PID, const char* moduleName) {
info("[GetRDataSectionBaseAddress] call");
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID);
if (hProcess == NULL) {
warn("[OpenProcess] failed to get handle to %d. Error: %lx", PID, GetLastError());
return nullptr;
}

HMODULE hModules[1024];
DWORD cbNeeded;
if (!EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded)) {
warn("[EnumProcessModules] failed to list modules. Error: %lx", GetLastError());
CloseHandle(hProcess);
return NULL;
}

HMODULE hModule = NULL;
for (unsigned int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
char szModuleName[MAX_PATH];
if (GetModuleBaseNameA(hProcess, hModules[i], szModuleName, sizeof(szModuleName))) {
if (_stricmp(szModuleName, moduleName) == 0) {
hModule = hModules[i];
break;
}
}
}

if (hModule == NULL) {
warn("[GetModuleBaseNameA] failed to get name of module. Error: %lx", GetLastError());
CloseHandle(hProcess);
return NULL;
}

MODULEINFO moduleInfo;
if (!GetModuleInformation(hProcess, hModule, &moduleInfo, sizeof(moduleInfo))) {
warn("[GetModuleInformation] failed to get info about module.  Error: %lx", GetLastError());
CloseHandle(hProcess);
return NULL;
}

BYTE* moduleBase = reinterpret_cast(moduleInfo.lpBaseOfDll);
PIMAGE_DOS_HEADER dosHeader = reinterpret_cast
(moduleBase);
PIMAGE_NT_HEADERS ntHeaders = reinterpret_cast(moduleBase + dosHeader->e_lfanew);

PIMAGE_SECTION_HEADER sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);
for (int i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
if (strncmp(reinterpret_cast(sectionHeader->Name), ".rdata", IMAGE_SIZEOF_SHORT_NAME) == 0) {
LPVOID rdataBaseAddress = moduleBase + sectionHeader->VirtualAddress;
CloseHandle(hProcess);
okay("Got base address of .rdata");
return rdataBaseAddress;
}
sectionHeader++;
}

warn("Failed to get .rdata base address");
CloseHandle(hProcess);
return NULL;
}

Код: Выделить всё

    if (processList) {
info("Writing in list_importExport_table:");
for (int i = 0; i < numProcesses; i++) {
if (contains_exe(processList[i].processName)){
//system("pause");
info("Base Address of .rdata of PID %d: %p", processList[i].pid, GetRDataSectionBaseAddress(processList[i].pid, processList[i].processName));
} else {
warn("Something went wrong with %s (%d)", processList[i].processName, processList[i].pid);
}
}
} else { return false; }

fclose(outputFile);
okay("Operation Success!");

return true;
Работа в Windows 11 с отключенным антивирусом для папки приложения.
Я экспериментировал с различными разрешениями для OpenProcess (например, PROCESS_ALL_ACCESS, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ), но проблема сохраняется.
Такое поведение происходит постоянно, и другой аналогичный код, использующий NtOpenProcess, не сталкивается с проблемами доступа.
Я убедился, что все дескрипторы закрыты правильно и нет утечек ресурсов.
Что может быть причиной сбоя CreateToolhelp32Snapshot с сообщением «Доступ запрещен» только при вызове GetRDataSectionBaseAddress? Как я могу решить или дополнительно диагностировать эту проблему?
Я ожидаю, что CreateToolhelp32Snapshot успешно получит информацию о модуле процесса, даже если GetRDataSectionBaseAddress вызывается до GetAllModulesInfoOfPID .

Подробнее здесь: https://stackoverflow.com/questions/787 ... windows-11

Вернуться в «C++»