├── DLLFinder.sln ├── DLLFinder ├── DLLFinder.vcxproj ├── DLLFinder.vcxproj.filters ├── Process.cpp ├── Process.h └── Source.cpp └── README.md /DLLFinder.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30501.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLLFinder", "DLLFinder\DLLFinder.vcxproj", "{CA1A1CF9-9D0D-4EA7-9099-D82C6A081C6C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {CA1A1CF9-9D0D-4EA7-9099-D82C6A081C6C}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {CA1A1CF9-9D0D-4EA7-9099-D82C6A081C6C}.Debug|Win32.Build.0 = Debug|Win32 16 | {CA1A1CF9-9D0D-4EA7-9099-D82C6A081C6C}.Release|Win32.ActiveCfg = Release|Win32 17 | {CA1A1CF9-9D0D-4EA7-9099-D82C6A081C6C}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /DLLFinder/DLLFinder.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {CA1A1CF9-9D0D-4EA7-9099-D82C6A081C6C} 15 | Win32Proj 16 | DLLFinder 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 55 | 56 | 57 | Console 58 | true 59 | 60 | 61 | 62 | 63 | Level3 64 | 65 | 66 | MaxSpeed 67 | true 68 | true 69 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 70 | 71 | 72 | Console 73 | true 74 | true 75 | true 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /DLLFinder/DLLFinder.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /DLLFinder/Process.cpp: -------------------------------------------------------------------------------- 1 | #include "Process.h" 2 | #include 3 | 4 | Process::Process(std::string Proc) { 5 | Pinfo = GetProcessInfo(Proc); 6 | } 7 | 8 | Process::~Process(){ 9 | 10 | } 11 | 12 | #pragma optimize("", off) 13 | //Get the Process Information 14 | Process::Process_INFO Process::GetProcessInfo(std::string & PN){ 15 | PVOID buffer = NULL; 16 | PSYSTEM_PROCESS_INFO inf = NULL; 17 | LPWSTR ProcNAME; 18 | 19 | //convert CHAR to WCHAR 20 | /*int nChars = MultiByteToWideChar(CP_ACP, 0, PN, -1, NULL, 0); 21 | LPWSTR P1 = new WCHAR[nChars]; //Release this at some point 22 | MultiByteToWideChar(CP_ACP, 0, PN, -1, (LPWSTR)P1, nChars); 23 | //delete[] P1; 24 | */ 25 | 26 | ULONG buffer_size = 512 * 512; 27 | 28 | NTSTATUS Status = STATUS_INFO_LENGTH_MISMATCH; 29 | _ntQSI fpQSI = (_ntQSI)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtQuerySystemInformation"); 30 | 31 | 32 | buffer = VirtualAlloc(NULL, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 33 | 34 | if (buffer == NULL){ 35 | return Pinfo; 36 | } 37 | 38 | Status = fpQSI((SYSTEM_INFORMATION_CLASS)All_SYS::SystemExtendedProcessInformation, buffer, buffer_size, NULL); 39 | 40 | //if buffer is too small double size 41 | if (Status == STATUS_INFO_LENGTH_MISMATCH) { 42 | VirtualFree(buffer, NULL, MEM_RELEASE); 43 | buffer_size *= 2; 44 | } 45 | 46 | else if (!NT_SUCCESS(Status)) { 47 | VirtualFree(buffer, NULL, MEM_RELEASE); 48 | return Pinfo; 49 | } 50 | 51 | else{ 52 | inf = (PSYSTEM_PROCESS_INFO)buffer; 53 | 54 | while (inf) { 55 | ProcNAME = inf->ImageName.Buffer; 56 | 57 | if (inf->ImageName.Buffer != nullptr){ 58 | 59 | //List of all the process id on the current system 60 | if (inf->UniqueProcessId > 0){ 61 | //System_PID_List.push_back(inf->UniqueProcessId); 62 | } 63 | 64 | //WinAPI - Converts a Wide Char to multibyte 65 | int nLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ProcNAME, -1, NULL, NULL, NULL, NULL); 66 | LPSTR P1 = new CHAR[nLen]; 67 | WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ProcNAME, -1, P1, nLen, NULL, NULL); 68 | std::string ProcessName(P1); 69 | delete[] P1; 70 | //std::cout << P1 << std::endl; 71 | //if (strcmp(PN, ProcessName) == 0){ 72 | if (PN.compare(ProcessName) == 0){ 73 | Pinfo.Process_ID = (DWORD)inf->UniqueProcessId; 74 | 75 | Pinfo.Process_Name = ProcessName; 76 | CHAR szTemp[MAX_PATH] = { 0 }; 77 | sprintf(szTemp, "%I64d", (inf->CreateTime).QuadPart); 78 | Pinfo.Create_Time = szTemp; 79 | Pinfo.ThreadCount = inf->NumberOfThreads; 80 | Pinfo.HandleCount = inf->HandleCount; 81 | 82 | /*FILETIME ft; 83 | SYSTEMTIME st; 84 | GetSystemTime(&st); 85 | SystemTimeToFileTime(&st, &ft); 86 | LARGE_INTEGER CT = inf->CreateTime; 87 | CHAR szTemp[MAX_PATH] = { 0 }; 88 | CHAR szTemp1[MAX_PATH] = { 0 }; 89 | sprintf(szTemp, "%I64d", CT.QuadPart); 90 | sprintf(szTemp1, "%I64d", ft); 91 | std::cout << szTemp << std::endl; 92 | std::cout << szTemp1 << std::endl;*/ 93 | //std::cout << PID << std::endl; 94 | //delete[] P1; 95 | 96 | //return Pinfo; 97 | } 98 | //delete[] P1; 99 | 100 | 101 | /*//Testing stuff 102 | if (wcscmp(P1, ProcNAME) == 0){ 103 | PID = (DWORD)inf->UniqueProcessId; 104 | delete[] P1; 105 | std::cout << PID << std::endl; 106 | return PID; 107 | }*/ 108 | 109 | } 110 | 111 | if (!inf->NextEntryOffset) 112 | break; 113 | 114 | inf = (PSYSTEM_PROCESS_INFO)((LPBYTE)inf + inf->NextEntryOffset); 115 | } 116 | 117 | if (buffer) VirtualFree(buffer, NULL, MEM_RELEASE); 118 | } 119 | 120 | return Pinfo; 121 | } 122 | 123 | All_SYS::PLDR_DATA_TABLE_ENTRY Process::GetNextNode(PCHAR nNode, int Offset){ 124 | #ifdef _WIN64 125 | nNode -= sizeof(LIST_ENTRY64) * Offset; 126 | #else 127 | nNode -= sizeof(LIST_ENTRY) * Offset; 128 | #endif 129 | return (All_SYS::PLDR_DATA_TABLE_ENTRY)nNode; 130 | } 131 | 132 | //List Modules From PBI 133 | //ListType = 0 - InLoadOrderModuleList 134 | //ListType = 1 - InMemoryOrderModuleList 135 | //ListType = 2 - InInitializationOrderModuleList 136 | //Order = 0 - Flick through list (Forward Order) 137 | //Order = 1 - Blink through list (Backwards Order) 138 | void Process::ListModules(DWORD PID, int ListType, int Order){ 139 | pNtQueryInformationProcess NtQIP; 140 | NTSTATUS status; 141 | std::wstring BaseDllName; 142 | std::wstring FullDllName; 143 | 144 | //Check ListType in range 145 | if (ListType > 2 || ListType < 0){ 146 | return; 147 | } 148 | if (Order > 1 || Order < 0){ 149 | return; 150 | } 151 | 152 | PROCESS_BASIC_INFORMATION PBI = { 0 }; 153 | HANDLE ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, false, PID); 154 | NtQIP = (pNtQueryInformationProcess)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtQueryInformationProcess"); 155 | status = NT_SUCCESS(NtQIP(ProcessHandle, ProcessBasicInformation, &PBI, sizeof(PROCESS_BASIC_INFORMATION), NULL)); 156 | 157 | if (status){ 158 | All_SYS::PEB_LDR_DATA LdrData; 159 | All_SYS::LDR_DATA_TABLE_ENTRY LdrModule; 160 | All_SYS::PPEB_LDR_DATA pLdrData = nullptr; 161 | PBYTE address = nullptr; 162 | 163 | PBYTE LdrDataOffset = (PBYTE)(PBI.PebBaseAddress) + offsetof(struct All_SYS::_PEB, LoaderData); 164 | ReadProcessMemory(ProcessHandle, LdrDataOffset, &pLdrData, sizeof(All_SYS::PPEB_LDR_DATA), NULL); 165 | ReadProcessMemory(ProcessHandle, pLdrData, &LdrData, sizeof(All_SYS::PEB_LDR_DATA), NULL); 166 | 167 | if (Order == 0){ 168 | if (ListType == 0) 169 | address = (PBYTE)LdrData.InLoadOrderModuleList.Flink; 170 | else if (ListType == 1) 171 | address = (PBYTE)LdrData.InMemoryOrderModuleList.Flink; 172 | else if (ListType == 2) 173 | address = (PBYTE)LdrData.InInitializationOrderModuleList.Flink; 174 | } 175 | else{ 176 | if (ListType == 0) 177 | address = (PBYTE)LdrData.InLoadOrderModuleList.Blink; 178 | else if (ListType == 1) 179 | address = (PBYTE)LdrData.InMemoryOrderModuleList.Blink; 180 | else if (ListType == 2) 181 | address = (PBYTE)LdrData.InInitializationOrderModuleList.Blink; 182 | } 183 | 184 | #ifdef _WIN64 185 | address -= sizeof(LIST_ENTRY64)*ListType; 186 | #else 187 | address -= sizeof(LIST_ENTRY)*ListType; 188 | #endif 189 | 190 | All_SYS::PLDR_DATA_TABLE_ENTRY Head = (All_SYS::PLDR_DATA_TABLE_ENTRY)address; 191 | All_SYS::PLDR_DATA_TABLE_ENTRY Node = Head; 192 | 193 | do 194 | { 195 | BOOL status1 = ReadProcessMemory(ProcessHandle, Node, &LdrModule, sizeof(All_SYS::LDR_DATA_TABLE_ENTRY), NULL); 196 | if (status1) 197 | { 198 | if (LdrModule.BaseAddress == 0) 199 | break; 200 | 201 | BaseDllName = std::wstring(LdrModule.BaseDllName.Length / sizeof(WCHAR), 0); 202 | FullDllName = std::wstring(LdrModule.FullDllName.Length / sizeof(WCHAR), 0); 203 | ReadProcessMemory(ProcessHandle, LdrModule.BaseDllName.Buffer, &BaseDllName[0], LdrModule.BaseDllName.Length, NULL); 204 | ReadProcessMemory(ProcessHandle, LdrModule.FullDllName.Buffer, &FullDllName[0], LdrModule.FullDllName.Length, NULL); 205 | 206 | BaseDllName.push_back('\0'); 207 | FullDllName.push_back('\0'); 208 | 209 | std::wcout << BaseDllName << " \t" << LdrModule.BaseAddress << std::endl; 210 | } 211 | 212 | if (Order == 0){ 213 | if (ListType == 0) 214 | Node = GetNextNode((PCHAR)LdrModule.InLoadOrderModuleList.Flink, ListType); 215 | else if (ListType == 1) 216 | Node = GetNextNode((PCHAR)LdrModule.InMemoryOrderModuleList.Flink, ListType); 217 | else if (ListType == 2) 218 | Node = GetNextNode((PCHAR)LdrModule.InInitializationOrderModuleList.Flink, ListType); 219 | } 220 | else{ 221 | if (ListType == 0) 222 | Node = GetNextNode((PCHAR)LdrModule.InLoadOrderModuleList.Blink, ListType); 223 | else if (ListType == 1) 224 | Node = GetNextNode((PCHAR)LdrModule.InMemoryOrderModuleList.Blink, ListType); 225 | else if (ListType == 2) 226 | Node = GetNextNode((PCHAR)LdrModule.InInitializationOrderModuleList.Blink, ListType); 227 | } 228 | 229 | } while (Head != Node); 230 | } 231 | 232 | CloseHandle(ProcessHandle); 233 | } 234 | 235 | void Process::SuspendProcess(DWORD dwPID){ 236 | pNtSuspendProcess ntSP; 237 | HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); 238 | 239 | ntSP = (pNtSuspendProcess) GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtSuspendProcess"); 240 | 241 | if (NT_SUCCESS(ntSP(hProc))){ 242 | std::cout << "Process: " << Pinfo.Process_Name << " PID: " << Pinfo.Process_ID << " Has Been Suspended\n" << std::endl; 243 | } 244 | 245 | CloseHandle(hProc); 246 | return; 247 | } 248 | 249 | void Process::ResumeProcess(DWORD dwPID){ 250 | pNtResumeProcess ntSP; 251 | HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); 252 | 253 | ntSP = (pNtResumeProcess)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtResumeProcess"); 254 | 255 | if (NT_SUCCESS(ntSP(hProc))){ 256 | std::cout << "Process: " << Pinfo.Process_Name << " PID: " << Pinfo.Process_ID << " Has Been Resumeded\n" << std::endl; 257 | } 258 | 259 | CloseHandle(hProc); 260 | return; 261 | } 262 | 263 | //This is not really what you would do although it does work if the PE Header of the file still exists 264 | //You would most likely query the page against a set of blacklisted pages 265 | void Process::ListModulesVQ(DWORD dwPID){ 266 | pNtQueryVirtualMemory ntQVM; 267 | All_SYS::MEMORY_BASIC_INFORMATION mbi; 268 | 269 | ULONG sizeMSNBuffer = 512; 270 | PMEMORY_SECTION_NAME msnName = (PMEMORY_SECTION_NAME)VirtualAlloc(NULL, sizeMSNBuffer, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 271 | 272 | HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); 273 | 274 | ntQVM = (pNtQueryVirtualMemory)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtQueryVirtualMemory"); 275 | 276 | SYSTEM_INFO sysINFO; 277 | GetSystemInfo(&sysINFO); 278 | PBYTE pCurAddr = (PBYTE) sysINFO.lpMinimumApplicationAddress; 279 | PBYTE pMaxAddr = (PBYTE) sysINFO.lpMaximumApplicationAddress; 280 | 281 | while (pCurAddr < pMaxAddr){ 282 | //Get the MEMORY_BASIC_INFORMATION 283 | if (NT_SUCCESS(ntQVM(hProc, pCurAddr, MemoryBasicInformation, &mbi, sizeof(All_SYS::MEMORY_BASIC_INFORMATION), NULL))){ 284 | //For obvious reasons it is not a good idea to only look for MEM_IMAGE 285 | if (mbi.Type == MEM_IMAGE){ 286 | 287 | std::cout << "Addr: " << mbi.AllocationBase << " \t" << "Size: " << mbi.RegionSize 288 | << " \tProtect: " << mbi.Protect << std::endl; 289 | 290 | 291 | //Get the Memory Section Name 292 | if (NT_SUCCESS(ntQVM(hProc, pCurAddr, MemorySectionName, msnName, sizeMSNBuffer, NULL))){ 293 | printf("%S\n\n", msnName->SectionFileName.Buffer); 294 | } 295 | } 296 | } 297 | 298 | //Get the Next page 299 | pCurAddr += mbi.RegionSize; 300 | } 301 | 302 | if (msnName) VirtualFree(msnName, NULL, MEM_RELEASE); 303 | CloseHandle(hProc); 304 | 305 | return; 306 | } 307 | 308 | #pragma optimize("", on) -------------------------------------------------------------------------------- /DLLFinder/Process.h: -------------------------------------------------------------------------------- 1 | #ifndef __Process_H__ 2 | #define __Process_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 10 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 11 | 12 | namespace All_SYS{ 13 | typedef enum _SYSTEM_INFORMATION_CLASS 14 | { 15 | SystemBasicInformation = 0x0000, 16 | SystemProcessorInformation = 0x0001, 17 | SystemPerformanceInformation = 0x0002, 18 | SystemTimeOfDayInformation = 0x0003, 19 | SystemPathInformation = 0x0004, 20 | SystemProcessInformation = 0x0005, 21 | SystemCallCountInformation = 0x0006, 22 | SystemDeviceInformation = 0x0007, 23 | SystemProcessorPerformanceInformation = 0x0008, 24 | SystemFlagsInformation = 0x0009, 25 | SystemCallTimeInformation = 0x000A, 26 | SystemModuleInformation = 0x000B, 27 | SystemLocksInformation = 0x000C, 28 | SystemStackTraceInformation = 0x000D, 29 | SystemPagedPoolInformation = 0x000E, 30 | SystemNonPagedPoolInformation = 0x000F, 31 | SystemHandleInformation = 0x0010, 32 | SystemObjectInformation = 0x0011, 33 | SystemPageFileInformation = 0x0012, 34 | SystemVdmInstemulInformation = 0x0013, 35 | SystemVdmBopInformation = 0x0014, 36 | SystemFileCacheInformation = 0x0015, 37 | SystemPoolTagInformation = 0x0016, 38 | SystemInterruptInformation = 0x0017, 39 | SystemDpcBehaviorInformation = 0x0018, 40 | SystemFullMemoryInformation = 0x0019, 41 | SystemLoadGdiDriverInformation = 0x001A, 42 | SystemUnloadGdiDriverInformation = 0x001B, 43 | SystemTimeAdjustmentInformation = 0x001C, 44 | SystemSummaryMemoryInformation = 0x001D, 45 | SystemMirrorMemoryInformation = 0x001E, 46 | SystemPerformanceTraceInformation = 0x001F, 47 | SystemCrashDumpInformation = 0x0020, 48 | SystemExceptionInformation = 0x0021, 49 | SystemCrashDumpStateInformation = 0x0022, 50 | SystemKernelDebuggerInformation = 0x0023, 51 | SystemContextSwitchInformation = 0x0024, 52 | SystemRegistryQuotaInformation = 0x0025, 53 | SystemExtendServiceTableInformation = 0x0026, 54 | SystemPrioritySeperation = 0x0027, 55 | SystemVerifierAddDriverInformation = 0x0028, 56 | SystemVerifierRemoveDriverInformation = 0x0029, 57 | SystemProcessorIdleInformation = 0x002A, 58 | SystemLegacyDriverInformation = 0x002B, 59 | SystemCurrentTimeZoneInformation = 0x002C, 60 | SystemLookasideInformation = 0x002D, 61 | SystemTimeSlipNotification = 0x002E, 62 | SystemSessionCreate = 0x002F, 63 | SystemSessionDetach = 0x0030, 64 | SystemSessionInformation = 0x0031, 65 | SystemRangeStartInformation = 0x0032, 66 | SystemVerifierInformation = 0x0033, 67 | SystemVerifierThunkExtend = 0x0034, 68 | SystemSessionProcessInformation = 0x0035, 69 | SystemLoadGdiDriverInSystemSpace = 0x0036, 70 | SystemNumaProcessorMap = 0x0037, 71 | SystemPrefetcherInformation = 0x0038, 72 | SystemExtendedProcessInformation = 0x0039, 73 | SystemRecommendedSharedDataAlignment = 0x003A, 74 | SystemComPlusPackage = 0x003B, 75 | SystemNumaAvailableMemory = 0x003C, 76 | SystemProcessorPowerInformation = 0x003D, 77 | SystemEmulationBasicInformation = 0x003E, 78 | SystemEmulationProcessorInformation = 0x003F, 79 | SystemExtendedHandleInformation = 0x0040, 80 | SystemLostDelayedWriteInformation = 0x0041, 81 | SystemBigPoolInformation = 0x0042, 82 | SystemSessionPoolTagInformation = 0x0043, 83 | SystemSessionMappedViewInformation = 0x0044, 84 | SystemHotpatchInformation = 0x0045, 85 | SystemObjectSecurityMode = 0x0046, 86 | SystemWatchdogTimerHandler = 0x0047, 87 | SystemWatchdogTimerInformation = 0x0048, 88 | SystemLogicalProcessorInformation = 0x0049, 89 | SystemWow64SharedInformationObsolete = 0x004A, 90 | SystemRegisterFirmwareTableInformationHandler = 0x004B, 91 | SystemFirmwareTableInformation = 0x004C, 92 | SystemModuleInformationEx = 0x004D, 93 | SystemVerifierTriageInformation = 0x004E, 94 | SystemSuperfetchInformation = 0x004F, 95 | SystemMemoryListInformation = 0x0050, 96 | SystemFileCacheInformationEx = 0x0051, 97 | SystemThreadPriorityClientIdInformation = 0x0052, 98 | SystemProcessorIdleCycleTimeInformation = 0x0053, 99 | SystemVerifierCancellationInformation = 0x0054, 100 | SystemProcessorPowerInformationEx = 0x0055, 101 | SystemRefTraceInformation = 0x0056, 102 | SystemSpecialPoolInformation = 0x0057, 103 | SystemProcessIdInformation = 0x0058, 104 | SystemErrorPortInformation = 0x0059, 105 | SystemBootEnvironmentInformation = 0x005A, 106 | SystemHypervisorInformation = 0x005B, 107 | SystemVerifierInformationEx = 0x005C, 108 | SystemTimeZoneInformation = 0x005D, 109 | SystemImageFileExecutionOptionsInformation = 0x005E, 110 | SystemCoverageInformation = 0x005F, 111 | SystemPrefetchPatchInformation = 0x0060, 112 | SystemVerifierFaultsInformation = 0x0061, 113 | SystemSystemPartitionInformation = 0x0062, 114 | SystemSystemDiskInformation = 0x0063, 115 | SystemProcessorPerformanceDistribution = 0x0064, 116 | SystemNumaProximityNodeInformation = 0x0065, 117 | SystemDynamicTimeZoneInformation = 0x0066, 118 | SystemCodeIntegrityInformation = 0x0067, 119 | SystemProcessorMicrocodeUpdateInformation = 0x0068, 120 | SystemProcessorBrandString = 0x0069, 121 | SystemVirtualAddressInformation = 0x006A, 122 | SystemLogicalProcessorAndGroupInformation = 0x006B, 123 | SystemProcessorCycleTimeInformation = 0x006C, 124 | SystemStoreInformation = 0x006D, 125 | SystemRegistryAppendString = 0x006E, 126 | SystemAitSamplingValue = 0x006F, 127 | SystemVhdBootInformation = 0x0070, 128 | SystemCpuQuotaInformation = 0x0071, 129 | SystemNativeBasicInformation = 0x0072, 130 | SystemErrorPortTimeouts = 0x0073, 131 | SystemLowPriorityIoInformation = 0x0074, 132 | SystemBootEntropyInformation = 0x0075, 133 | SystemVerifierCountersInformation = 0x0076, 134 | SystemPagedPoolInformationEx = 0x0077, 135 | SystemSystemPtesInformationEx = 0x0078, 136 | SystemNodeDistanceInformation = 0x0079, 137 | SystemAcpiAuditInformation = 0x007A, 138 | SystemBasicPerformanceInformation = 0x007B, 139 | SystemQueryPerformanceCounterInformation = 0x007C, 140 | SystemSessionBigPoolInformation = 0x007D, 141 | SystemBootGraphicsInformation = 0x007E, 142 | SystemScrubPhysicalMemoryInformation = 0x007F, 143 | SystemBadPageInformation = 0x0080, 144 | SystemProcessorProfileControlArea = 0x0081, 145 | SystemCombinePhysicalMemoryInformation = 0x0082, 146 | SystemEntropyInterruptTimingInformation = 0x0083, 147 | SystemConsoleInformation = 0x0084, 148 | SystemPlatformBinaryInformation = 0x0085, 149 | SystemThrottleNotificationInformation = 0x0086, 150 | SystemHypervisorProcessorCountInformation = 0x0087, 151 | SystemDeviceDataInformation = 0x0088, 152 | SystemDeviceDataEnumerationInformation = 0x0089, 153 | SystemMemoryTopologyInformation = 0x008A, 154 | SystemMemoryChannelInformation = 0x008B, 155 | SystemBootLogoInformation = 0x008C, 156 | SystemProcessorPerformanceInformationEx = 0x008D, 157 | SystemSpare0 = 0x008E, 158 | SystemSecureBootPolicyInformation = 0x008F, 159 | SystemPageFileInformationEx = 0x0090, 160 | SystemSecureBootInformation = 0x0091, 161 | SystemEntropyInterruptTimingRawInformation = 0x0092, 162 | SystemPortableWorkspaceEfiLauncherInformation = 0x0093, 163 | SystemFullProcessInformation = 0x0094, 164 | MaxSystemInfoClass = 0x0095 165 | } SYSTEM_INFORMATION_CLASS; 166 | 167 | #ifdef _WIN64 168 | //redefine the struct in windows interal header to include undocumented values 169 | typedef struct _PEB_LDR_DATA { 170 | ULONG Length; 171 | UCHAR Initialized; 172 | ULONG64 SsHandle; 173 | LIST_ENTRY64 InLoadOrderModuleList; 174 | LIST_ENTRY64 InMemoryOrderModuleList; 175 | LIST_ENTRY64 InInitializationOrderModuleList; 176 | PVOID64 EntryInProgress; 177 | UCHAR ShutdownInProgress; 178 | PVOID64 ShutdownThreadId; 179 | } PEB_LDR_DATA, *PPEB_LDR_DATA; 180 | 181 | typedef struct _PEB{ 182 | UCHAR InheritedAddressSpace; 183 | UCHAR ReadImageFileExecOptions; 184 | UCHAR BeingDebugged; 185 | BYTE Reserved0; 186 | ULONG Reserved1; 187 | ULONG64 Reserved3; 188 | ULONG64 ImageBaseAddress; 189 | ULONG64 LoaderData; 190 | ULONG64 ProcessParameters; 191 | }PEB, *PPEB; 192 | 193 | /** A structure that holds information about a single module loaded by a process **/ 194 | /** LIST_ENTRY is a link list pointing to the prev/next Module loaded **/ 195 | typedef struct _LDR_DATA_TABLE_ENTRY 196 | { 197 | LIST_ENTRY64 InLoadOrderModuleList; 198 | LIST_ENTRY64 InMemoryOrderModuleList; 199 | LIST_ENTRY64 InInitializationOrderModuleList; 200 | ULONG64 BaseAddress; 201 | ULONG64 EntryPoint; 202 | ULONG SizeOfImage; //bytes 203 | UNICODE_STRING FullDllName; 204 | UNICODE_STRING BaseDllName; 205 | ULONG Flags; 206 | USHORT LoadCount; 207 | } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 208 | 209 | typedef struct DECLSPEC_ALIGN(16) _MEMORY_BASIC_INFORMATION{ 210 | ULONGLONG BaseAddress; 211 | ULONGLONG AllocationBase; 212 | DWORD AllocationProtect; 213 | DWORD __alignment1; 214 | ULONGLONG RegionSize; 215 | DWORD State; 216 | DWORD Protect; 217 | DWORD Type; 218 | DWORD __alignment2; 219 | } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; 220 | 221 | #else 222 | //redefine the struct in windows interal header to include undocumented values 223 | typedef struct _PEB_LDR_DATA { 224 | DWORD Length; 225 | UCHAR Initialized; 226 | PVOID SsHandle; 227 | LIST_ENTRY InLoadOrderModuleList; 228 | LIST_ENTRY InMemoryOrderModuleList; 229 | LIST_ENTRY InInitializationOrderModuleList; 230 | PVOID EntryInProgress; 231 | UCHAR ShutdownInProgress; 232 | PVOID ShutdownThreadId; 233 | } PEB_LDR_DATA, *PPEB_LDR_DATA; 234 | 235 | typedef struct _PEB{ 236 | UCHAR InheritedAddressSpace; 237 | UCHAR ReadImageFileExecOptions; 238 | UCHAR BeingDebugged; 239 | BYTE Reserved2[9]; 240 | PPEB_LDR_DATA LoaderData; 241 | PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 242 | BYTE Reserved3[448]; 243 | ULONG SessionId; 244 | }PEB, *PPEB; 245 | 246 | /** A structure that holds information about a single module loaded by a process **/ 247 | /** LIST_ENTRY is a link list pointing to the prev/next Module loaded **/ 248 | typedef struct _LDR_DATA_TABLE_ENTRY 249 | { 250 | LIST_ENTRY InLoadOrderModuleList; 251 | LIST_ENTRY InMemoryOrderModuleList; 252 | LIST_ENTRY InInitializationOrderModuleList; 253 | PVOID BaseAddress; 254 | PVOID EntryPoint; 255 | ULONG SizeOfImage; 256 | UNICODE_STRING FullDllName; 257 | UNICODE_STRING BaseDllName; 258 | ULONG Flags; 259 | USHORT LoadCount; 260 | USHORT TlsIndex; 261 | LIST_ENTRY HashTableEntry; 262 | union 263 | { 264 | LIST_ENTRY HashLinks; 265 | struct 266 | { 267 | PVOID SectionPointer; 268 | ULONG CheckSum; 269 | }; 270 | }; 271 | union 272 | { 273 | ULONG TimeDateStamp; 274 | PVOID LoadedImports; 275 | }; 276 | _ACTIVATION_CONTEXT * EntryPointActivationContext; 277 | PVOID PatchInformation; 278 | LIST_ENTRY ForwarderLinks; 279 | LIST_ENTRY ServiceTagLinks; 280 | LIST_ENTRY StaticLinks; 281 | PVOID ContextInformation; 282 | DWORD OriginalBase; 283 | LARGE_INTEGER LoadTime; 284 | } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 285 | 286 | typedef struct _MEMORY_BASIC_INFORMATION { 287 | DWORD BaseAddress; 288 | DWORD AllocationBase; 289 | DWORD AllocationProtect; 290 | DWORD RegionSize; 291 | DWORD State; 292 | DWORD Protect; 293 | DWORD Type; 294 | } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; 295 | 296 | #endif 297 | } 298 | 299 | typedef struct _SYSTEM_PROCESS_INFO 300 | { 301 | ULONG NextEntryOffset; 302 | ULONG NumberOfThreads; 303 | LARGE_INTEGER SpareLi1; 304 | LARGE_INTEGER SpareLi2; 305 | LARGE_INTEGER SpareLi3; 306 | LARGE_INTEGER CreateTime; 307 | LARGE_INTEGER UserTime; 308 | LARGE_INTEGER KernelTime; 309 | UNICODE_STRING ImageName; 310 | ULONG BasePriority; 311 | #ifdef _WIN64 312 | ULONG pad1; 313 | ULONG UniqueProcessId; 314 | ULONG pad2; 315 | ULONG InheritedFromUniqueProcessId; 316 | ULONG pad3, pad4, pad5; 317 | #else 318 | ULONG UniqueProcessId; 319 | ULONG InheritedFromUniqueProcessId; 320 | #endif 321 | ULONG HandleCount; 322 | ULONG SessionId; 323 | PVOID PageDirectoryBase; 324 | ULONG VirtualMemoryCounters; 325 | SIZE_T PrivatePageCount; 326 | IO_COUNTERS IoCounters; 327 | PVOID Reserved[1]; 328 | }SYSTEM_PROCESS_INFO, *PSYSTEM_PROCESS_INFO; 329 | 330 | typedef NTSTATUS(NTAPI *_ntQSI)( 331 | IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 332 | IN OUT PVOID SystemInformation, 333 | IN ULONG SystemInformationLength, 334 | OUT PULONG ReturnLength OPTIONAL 335 | ); 336 | 337 | typedef NTSTATUS(NTAPI * pNtQueryInformationProcess) 338 | ( 339 | HANDLE, 340 | PROCESSINFOCLASS, 341 | PVOID, 342 | ULONG, 343 | PULONG 344 | ); 345 | 346 | typedef enum _MEMORY_INFORMATION_CLASS 347 | { 348 | MemoryBasicInformation, 349 | MemoryWorkingSetList, 350 | MemorySectionName, 351 | MemoryBasicVlmInformation 352 | } MEMORY_INFORMATION_CLASS; 353 | 354 | typedef struct _MEMORY_SECTION_NAME 355 | { 356 | UNICODE_STRING SectionFileName; 357 | } MEMORY_SECTION_NAME, *PMEMORY_SECTION_NAME; 358 | 359 | typedef NTSTATUS(NTAPI * pNtQueryVirtualMemory)( 360 | IN HANDLE ProcessHandle, 361 | IN PVOID BaseAddress, 362 | IN MEMORY_INFORMATION_CLASS MemoryInformationClass, 363 | OUT PVOID MemoryInformation, 364 | IN ULONG MemoryInformationLength, 365 | OUT PULONG ReturnLength OPTIONAL 366 | ); 367 | 368 | typedef NTSTATUS(NTAPI * pNtSuspendProcess)( 369 | IN HANDLE ProcessHandle 370 | ); 371 | 372 | typedef NTSTATUS(NTAPI * pNtResumeProcess)( 373 | IN HANDLE ProcessHandle 374 | ); 375 | 376 | class Process{ 377 | private: 378 | All_SYS::PLDR_DATA_TABLE_ENTRY GetNextNode(PCHAR nNode, int Offset); 379 | 380 | public: 381 | Process(std::string Proc); 382 | ~Process(); 383 | 384 | struct Process_INFO{ 385 | DWORD Process_ID = 0; 386 | std::string Process_Name = ""; 387 | std::string Create_Time = ""; 388 | ULONG HandleCount = 0; 389 | ULONG ModuleCount = 0; 390 | ULONG ThreadCount = 0; 391 | }Pinfo; 392 | 393 | Process_INFO GetProcessInfo(std::string & PN); 394 | 395 | void SuspendProcess(DWORD dwPID); 396 | void ResumeProcess(DWORD dwPID); 397 | 398 | void ListModules(DWORD PID, int ListType, int Order); 399 | void ListModulesVQ(DWORD dwPID); 400 | }; 401 | 402 | #endif -------------------------------------------------------------------------------- /DLLFinder/Source.cpp: -------------------------------------------------------------------------------- 1 | #include "Process.h" 2 | #include 3 | 4 | int main(){ 5 | std::cout << "-----DLL Finder v1.0-----\n" << std::endl; 6 | 7 | Process * A = new Process("firefox.exe"); 8 | 9 | //You can do this without suspending in most cases just 10 | //be aware of the fact the more memory maybe allocated as 11 | //the process runs 12 | A->SuspendProcess(A->Pinfo.Process_ID); 13 | 14 | //Listing the modules using the process' PEB 15 | //A->ListModules(A->Pinfo.Process_ID, 1, 0); 16 | 17 | //Listing the Modules using NtQueryVirtualMemory 18 | A->ListModulesVQ(A->Pinfo.Process_ID); 19 | 20 | //Resume the process after enum finishes 21 | A->ResumeProcess(A->Pinfo.Process_ID); 22 | 23 | delete A; 24 | 25 | system("pause"); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DLLFinder 2 | Enumerate the DLLs/Modules using NtQueryVirtualMemory 3 | 4 | ##Summary 5 | A basic application showing the use of NtQueryVirtualMemory to enumerate the memory to list the Modules and DLLs in an application. All in all you would most likely not use this to enumerate modules as opposed to scan the memory pages in the real world. 6 | 7 | ##Limitations 8 | The only real limitation is that if the PE Header of the DLL has been stripped it may fail. The only other limitation is that if NtQueryVirtualMemory is hooked in the SSDT the obvious outcome will result. 9 | --------------------------------------------------------------------------------