// VOID ListModuleThread(PVOID Context) { NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; ULONG StepAddress; ULONG Step2Address; ULONG BufferSize = 0x200; ULONG ReturnLength = 0; WCHAR LastImageName[260] = { 0 }; HANDLE HandleProcess; PMEMORY_SECTION_NAME SectionName = NULL; MEMORY_BASIC_INFORMATION BasicInformation; PTHREAD_CONTEXT ThreadContext = Context; PMODULE_INFO FoundModule = NULL; pFnZwQueryVirtualMemory ZwQueryVirtualMemory = NULL; ZwQueryVirtualMemory = (pFnZwQueryVirtualMemory) KeServiceDescriptorTable.ServiceTableBase[ServiceId_NtQueryVirtualMemory]; ntStatus = ObOpenObjectByPointer(ThreadContext->Process, OBJ_INHERIT, NULL, 0, *PsProcessType, ExGetPreviousMode(), &HandleProcess); if (!NT_SUCCESS(ntStatus)) { ExFreePoolWithTag(g_ModuleListHead, MEM_TAG); g_ModuleListHead = NULL; goto _End; } SectionName = ExAllocatePoolWithTag(PagedPool, BufferSize, MEM_TAG); for (StepAddress = 0; StepAddress <= 0x7FFFFFFF; StepAddress += 0x10000) { ntStatus = ZwQueryVirtualMemory(HandleProcess, (PVOID)StepAddress, MemoryBasicInformation, &BasicInformation, sizeof(MEMORY_BASIC_INFORMATION), &ReturnLength); if (!NT_SUCCESS(ntStatus) || BasicInformation.Type != SEC_IMAGE) continue; _Retry: ntStatus = ZwQueryVirtualMemory(HandleProcess, (PVOID)StepAddress, MemorySectionName, SectionName, BufferSize, &ReturnLength); if (!NT_SUCCESS(ntStatus)) { if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) { ExFreePoolWithTag(SectionName, MEM_TAG); SectionName = ExAllocatePoolWithTag(PagedPool, ReturnLength, MEM_TAG); goto _Retry; } continue; } __try { if (memcmp(LastImageName, SectionName->SectionFileName.Buffer, SectionName->SectionFileName.Length) && SectionName->SectionFileName.Length < 520) { memcpy(LastImageName, SectionName->SectionFileName.Buffer, SectionName->SectionFileName.Length); LastImageName[SectionName->SectionFileName.Length / 2] = L'/0'; // // Step into and get the image size // for (Step2Address = StepAddress + BasicInformation.RegionSize; Step2Address < 0x7FFFFFFF; Step2Address += BasicInformation.RegionSize) { ntStatus = ZwQueryVirtualMemory(HandleProcess, (PVOID)Step2Address, MemoryBasicInformation, &BasicInformation, sizeof(MEMORY_BASIC_INFORMATION), &ReturnLength); if (NT_SUCCESS(ntStatus) && BasicInformation.Type != SEC_IMAGE) break; } FoundModule = ExAllocatePoolWithTag(NonPagedPool, sizeof(MODULE_INFO), MEM_TAG); FoundModule->BaseAddress = StepAddress; FoundModule->ImageSize = Step2Address - StepAddress; RtlStringCbPrintfW(FoundModule->ImagePath, 520, L"%s", LastImageName); InsertTailList(&g_ModuleListHead->ModuleListHead, &FoundModule->ModuleLink); g_ModuleListHead->NumberOfModules ++; } } __except (EXCEPTION_EXECUTE_HANDLER) { continue; } } ExFreePoolWithTag(SectionName, MEM_TAG); ObCloseHandle(HandleProcess, ExGetPreviousMode()); _End: KeSetEvent(&ThreadContext->SynEvent, IO_NO_INCREMENT, FALSE); PsTerminateSystemThread(STATUS_SUCCESS); } 不知道大家看着代码风格咋样,另外一种枚举方法就是解析二叉树,效率高,但是不通用