├── Process Info.sln ├── Process Info ├── NT Stuff.h ├── Process Info.cpp ├── Process Info.h ├── Process Info.vcxproj ├── Process Info.vcxproj.filters ├── Process Info.vcxproj.user └── main.cpp └── README.md /Process Info.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29806.167 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Process Info", "Process Info\Process Info.vcxproj", "{93D3A791-F95B-431E-9C6E-296252B58FE3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {93D3A791-F95B-431E-9C6E-296252B58FE3}.Debug|x64.ActiveCfg = Debug|x64 17 | {93D3A791-F95B-431E-9C6E-296252B58FE3}.Debug|x64.Build.0 = Debug|x64 18 | {93D3A791-F95B-431E-9C6E-296252B58FE3}.Debug|x86.ActiveCfg = Debug|Win32 19 | {93D3A791-F95B-431E-9C6E-296252B58FE3}.Debug|x86.Build.0 = Debug|Win32 20 | {93D3A791-F95B-431E-9C6E-296252B58FE3}.Release|x64.ActiveCfg = Release|x64 21 | {93D3A791-F95B-431E-9C6E-296252B58FE3}.Release|x64.Build.0 = Release|x64 22 | {93D3A791-F95B-431E-9C6E-296252B58FE3}.Release|x86.ActiveCfg = Release|Win32 23 | {93D3A791-F95B-431E-9C6E-296252B58FE3}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {94CA935D-AE75-4735-B464-DBAAECA7E9BF} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Process Info/NT Stuff.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Windows.h" 4 | 5 | #ifndef NT_FAIL 6 | #define NT_FAIL(status) (status < 0) 7 | #endif 8 | 9 | #ifndef NT_SUCCESS 10 | #define NT_SUCCESS(status) (status >= 0) 11 | #endif 12 | 13 | #define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001 14 | #define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002 15 | #define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004 16 | 17 | #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 18 | 19 | struct UNICODE_STRING 20 | { 21 | WORD Length; 22 | WORD MaxLength; 23 | wchar_t * szBuffer; 24 | }; 25 | 26 | typedef struct _RTL_BALANCED_NODE 27 | { 28 | union 29 | { 30 | struct _RTL_BALANCED_NODE * Children[2]; 31 | struct 32 | { 33 | struct _RTL_BALANCED_NODE * Left; 34 | struct _RTL_BALANCED_NODE * Right; 35 | }; 36 | }; 37 | 38 | union 39 | { 40 | UCHAR Red : 1; 41 | UCHAR Balance : 2; 42 | ULONG_PTR ParentValue; 43 | }; 44 | } RTL_BALANCED_NODE, *PRTL_BALANCED_NODE; 45 | 46 | struct LDR_DATA_TABLE_ENTRY 47 | { 48 | LIST_ENTRY InLoadOrderLinks; 49 | LIST_ENTRY InMemoryOrderLinks; 50 | union 51 | { 52 | LIST_ENTRY InInitializationOrderLinks; 53 | LIST_ENTRY InProgressLinks; 54 | }; 55 | 56 | PVOID DllBase; 57 | PVOID EntryPoint; 58 | ULONG SizeOfImage; 59 | 60 | UNICODE_STRING FullDllName; 61 | UNICODE_STRING BaseDllName; 62 | 63 | ULONG Flags; 64 | WORD LoadCount; 65 | WORD TlsIndex; 66 | 67 | LIST_ENTRY HashLinks; 68 | }; 69 | 70 | struct PEB_LDR_DATA 71 | { 72 | ULONG Length; 73 | BYTE Initialized; 74 | HANDLE SsHandle; 75 | LIST_ENTRY InLoadOrderModuleListHead; 76 | LIST_ENTRY InMemoryOrderModuleListHead; 77 | LIST_ENTRY InInitializationOrderModuleListHead; 78 | void * EntryInProgress; 79 | BYTE ShutdownInProgress; 80 | HANDLE ShutdownThreadId; 81 | }; 82 | 83 | struct PEB 84 | { 85 | void * Reserved[3]; 86 | PEB_LDR_DATA * Ldr; 87 | }; 88 | 89 | typedef struct _CLIENT_ID 90 | { 91 | HANDLE UniqueProcess; 92 | HANDLE UniqueThread; 93 | } CLIENT_ID, * PCLIENT_ID; 94 | 95 | typedef LONG KPRIORITY; 96 | 97 | struct PROCESS_BASIC_INFORMATION 98 | { 99 | NTSTATUS ExitStatus; 100 | PEB * pPEB; 101 | ULONG_PTR AffinityMask; 102 | LONG BasePriority; 103 | HANDLE UniqueProcessId; 104 | HANDLE InheritedFromUniqueProcessId; 105 | }; 106 | 107 | struct PROCESS_SESSION_INFORMATION 108 | { 109 | ULONG SessionId; 110 | }; 111 | 112 | struct THREAD_BASIC_INFORMATION 113 | { 114 | NTSTATUS ExitStatus; 115 | PVOID TebBaseAddress; 116 | CLIENT_ID ClientId; 117 | KAFFINITY AffinityMask; 118 | KPRIORITY Priority; 119 | KPRIORITY BasePriority; 120 | }; 121 | 122 | enum _PROCESSINFOCLASS 123 | { 124 | ProcessBasicInformation = 0, 125 | ProcessSessionInformation = 24, 126 | ProcessWow64Information = 26 127 | }; 128 | typedef _PROCESSINFOCLASS PROCESSINFOCLASS; 129 | 130 | enum _SYSTEM_INFORMATION_CLASS 131 | { 132 | SystemProcessInformation = 5, 133 | SystemHandleInformation = 16 134 | }; 135 | typedef _SYSTEM_INFORMATION_CLASS SYSTEM_INFORMATION_CLASS; 136 | 137 | enum _THREADINFOCLASS 138 | { 139 | ThreadBasicInformation = 0, 140 | ThreadQuerySetWin32StartAddress = 9 141 | }; 142 | typedef _THREADINFOCLASS THREADINFOCLASS; 143 | 144 | struct SYSTEM_HANDLE_TABLE_ENTRY_INFO 145 | { 146 | WORD UniqueProcessId; 147 | WORD CreateBackTraceIndex; 148 | BYTE ObjectTypeIndex; 149 | BYTE HandleAttributes; 150 | WORD HandleValue; 151 | void * Object; 152 | ULONG GrantedAccess; 153 | }; 154 | typedef SYSTEM_HANDLE_TABLE_ENTRY_INFO SYSTEM_HANDLE_TABLE_ENTRY_INFO; 155 | 156 | struct _SYSTEM_HANDLE_INFORMATION 157 | { 158 | ULONG NumberOfHandles; 159 | SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1]; 160 | }; 161 | typedef _SYSTEM_HANDLE_INFORMATION SYSTEM_HANDLE_INFORMATION; 162 | 163 | enum _OBEJECT_TYPE_INDEX : BYTE 164 | { 165 | OTI_Unknown00 = 0x00, 166 | OTI_Unknown01 = 0x01, 167 | OTI_Unknown02 = 0x00, 168 | OTI_Directory = 0x03, 169 | OTI_Unknown04 = 0x04, 170 | OTI_Token = 0x05, 171 | OTI_Job = 0x06, 172 | OTI_Process = 0x07, 173 | OTI_Thread = 0x08, 174 | OTI_Unknown09 = 0x09, 175 | OTI_IoCompletionReserve = 0x0A, 176 | OTI_Unknown0B = 0x0B, 177 | OTI_Unknown0C = 0x0C, 178 | OTI_Unknown0D = 0x0D, 179 | OTI_DebugObject = 0x0E, 180 | OTI_Event = 0x0F, 181 | OTI_Mutant = 0x10, 182 | OTI_Unknown11 = 0x11, 183 | OTI_Semaphore = 0x12, 184 | OTI_Timer = 0x13, 185 | OTI_IRTimer = 0x14, 186 | OTI_Unknown15 = 0x15, 187 | OTI_Unknown16 = 0x16, 188 | OTI_WindowStation = 0x17, 189 | OTI_Desktop = 0x18, 190 | OTI_Composition = 0x19, 191 | OTI_RawInputManager = 0x1A, 192 | OTI_Unknown1B = 0x1B, 193 | OTI_TpWorkerFactory = 0x1C, 194 | OTI_Unknown1D = 0x1D, 195 | OTI_Unknown1E = 0x1E, 196 | OTI_Unknown1F = 0x1F, 197 | OTI_Unknown20 = 0x20, 198 | OTI_IoCompletion = 0x21, 199 | OTI_WaitCompletionPacket = 0x22, 200 | OTI_File = 0x23, 201 | OTI_Unknown24 = 0x24, 202 | OTI_Unknown25 = 0x25, 203 | OTI_Unknown26 = 0x26, 204 | OTI_Unknown27 = 0x27, 205 | OTI_Section = 0x28, 206 | OTI_Session = 0x29, 207 | OTI_Partition = 0x2A, 208 | OTI_Key = 0x2B, 209 | OTI_Unknown2C = 0x2C, 210 | OTI_ALPC_Port = 0x2D, 211 | OTI_Unknown2E = 0x2E, 212 | OTI_WmiGuid = 0x2F, 213 | OTI_Unknown30 = 0x30, 214 | OTI_Unknown31 = 0x31, 215 | OTI_Unknown32 = 0x32, 216 | OTI_Unknown33 = 0x33, 217 | OTI_Unknown34 = 0x34, 218 | OTI_Unknown35 = 0x35, 219 | }; 220 | typedef _OBEJECT_TYPE_INDEX OBJECT_TYPE_INDEX; 221 | 222 | enum class THREAD_STATE 223 | { 224 | Running = 0x02, 225 | Waiting = 0x05 226 | }; 227 | 228 | typedef enum class _KWAIT_REASON 229 | { 230 | Executive = 0x00, 231 | FreePage = 0x01, 232 | PageIn = 0x02, 233 | PoolAllocation = 0x03, 234 | DelayExecution = 0x04, 235 | Suspended = 0x05, 236 | UserRequest = 0x06, 237 | WrExecutive = 0x07, 238 | WrFreePage = 0x08, 239 | WrPageIn = 0x09, 240 | WrPoolAllocation = 0x0A, 241 | WrDelayExecution = 0x0B, 242 | WrSuspended = 0x0C, 243 | WrUserRequest = 0x0D, 244 | WrEventPair = 0x0E, 245 | WrQueue = 0x0F, 246 | WrLpcReceive = 0x10, 247 | WrLpcReply = 0x11, 248 | WrVirtualMemory = 0x12, 249 | WrPageOut = 0x13, 250 | WrRendezvous = 0x14, 251 | WrCalloutStack = 0x19, 252 | WrKernel = 0x1A, 253 | WrResource = 0x1B, 254 | WrPushLock = 0x1C, 255 | WrMutex = 0x1D, 256 | WrQuantumEnd = 0x1E, 257 | WrDispatchInt = 0x1F, 258 | WrPreempted = 0x20, 259 | WrYieldExecution = 0x21, 260 | WrFastMutex = 0x22, 261 | WrGuardedMutex = 0x23, 262 | WrRundown = 0x24, 263 | MaximumWaitReason = 0x25 264 | } KWAIT_REASON; 265 | 266 | typedef struct _SYSTEM_THREAD_INFORMATION 267 | { 268 | LARGE_INTEGER KernelTime; 269 | LARGE_INTEGER UserTime; 270 | LARGE_INTEGER CreateTime; 271 | ULONG WaitTime; 272 | PVOID StartAddress; 273 | CLIENT_ID ClientId; 274 | KPRIORITY Priority; 275 | LONG BasePriority; 276 | ULONG ContextSwitches; 277 | THREAD_STATE ThreadState; 278 | KWAIT_REASON WaitReason; 279 | } SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; 280 | 281 | typedef struct _SYSTEM_PROCESS_INFORMATION 282 | { 283 | ULONG NextEntryOffset; 284 | ULONG NumberOfThreads; 285 | LARGE_INTEGER WorkingSetPrivateSize; 286 | ULONG HardFaultCount; 287 | ULONG NumberOfThreadsHighWatermark; 288 | ULONGLONG CycleTime; 289 | LARGE_INTEGER CreateTime; 290 | LARGE_INTEGER UserTime; 291 | LARGE_INTEGER KernelTime; 292 | UNICODE_STRING ImageName; 293 | KPRIORITY BasePriority; 294 | HANDLE UniqueProcessId; 295 | HANDLE InheritedFromUniqueProcessId; 296 | ULONG HandleCount; 297 | ULONG SessionId; 298 | ULONG_PTR UniqueProcessKey; 299 | SIZE_T PeakVirtualSize; 300 | SIZE_T VirtualSize; 301 | ULONG PageFaultCount; 302 | SIZE_T PeakWorkingSetSize; 303 | SIZE_T WorkingSetSize; 304 | SIZE_T QuotaPeakPagedPoolUsage; 305 | SIZE_T QuotaPagedPoolUsage; 306 | SIZE_T QuotaPeakNonPagedPoolUsage; 307 | SIZE_T QuotaNonPagedPoolUsage; 308 | SIZE_T PagefileUsage; 309 | SIZE_T PeakPagefileUsage; 310 | SIZE_T PrivatePageCount; 311 | LARGE_INTEGER ReadOperationCount; 312 | LARGE_INTEGER WriteOperationCount; 313 | LARGE_INTEGER OtherOperationCount; 314 | LARGE_INTEGER ReadTransferCount; 315 | LARGE_INTEGER WriteTransferCount; 316 | LARGE_INTEGER OtherTransferCount; 317 | SYSTEM_THREAD_INFORMATION Threads[1]; 318 | } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; 319 | 320 | typedef union _LDRP_PATH_SEARCH_OPTIONS 321 | { 322 | ULONG32 Flags; 323 | 324 | struct 325 | { 326 | ULONG32 Unknown; 327 | }; 328 | } LDRP_PATH_SEARCH_OPTIONS, * PLDRP_PATH_SEARCH_OPTIONS; 329 | 330 | typedef struct _LDRP_PATH_SEARCH_CONTEXT 331 | { 332 | UNICODE_STRING DllSearchPath; 333 | BOOLEAN AllocatedOnLdrpHeap; 334 | LDRP_PATH_SEARCH_OPTIONS SearchOptions; 335 | UNICODE_STRING OriginalFullDllName; 336 | } LDRP_PATH_SEARCH_CONTEXT, * PLDRP_PATH_SEARCH_CONTEXT; 337 | 338 | #ifdef _WIN64 339 | 340 | struct UNICODE_STRING32 341 | { 342 | WORD Length; 343 | WORD MaxLength; 344 | DWORD szBuffer; 345 | }; 346 | 347 | typedef struct _LDRP_PATH_SEARCH_CONTEXT32 348 | { 349 | UNICODE_STRING32 DllSearchPath; 350 | BOOLEAN AllocatedOnLdrpHeap; 351 | LDRP_PATH_SEARCH_OPTIONS SearchOptions; 352 | UNICODE_STRING32 OriginalFullDllName; 353 | } LDRP_PATH_SEARCH_CONTEXT32, * PLDRP_PATH_SEARCH_CONTEXT32; 354 | 355 | struct LDR_DATA_TABLE_ENTRY32 356 | { 357 | LIST_ENTRY32 InLoadOrderLinks; 358 | LIST_ENTRY32 InMemoryOrderLinks; 359 | LIST_ENTRY32 InInitializationOrderLinks; 360 | DWORD DllBase; 361 | DWORD EntryPoint; 362 | ULONG SizeOfImage; 363 | UNICODE_STRING32 FullDllName; 364 | UNICODE_STRING32 BaseDllName; 365 | ULONG Flags; 366 | WORD LoadCount; 367 | WORD TlsIndex; 368 | union 369 | { 370 | LIST_ENTRY32 HashLinks; 371 | struct 372 | { 373 | ULONG SectionPointer; 374 | ULONG CheckSum; 375 | }; 376 | }; 377 | union 378 | { 379 | ULONG TimeDateStamp; 380 | ULONG LoadedImports; 381 | }; 382 | ULONG EntryPointActivationContext; 383 | ULONG PatchInformation; 384 | LIST_ENTRY32 ForwarderLinks; 385 | LIST_ENTRY32 ServiceTagLinks; 386 | LIST_ENTRY32 StaticLinks; 387 | }; 388 | 389 | struct PEB_LDR_DATA32 390 | { 391 | ULONG Length; 392 | BYTE Initialized; 393 | DWORD SsHandle; 394 | LIST_ENTRY32 InLoadOrderModuleListHead; 395 | LIST_ENTRY32 InMemoryOrderModuleListHead; 396 | LIST_ENTRY32 InInitializationOrderModuleListHead; 397 | DWORD EntryInProgress; 398 | BYTE ShutdownInProgress; 399 | DWORD ShutdownThreadId; 400 | }; 401 | 402 | struct PEB32 403 | { 404 | DWORD Reserved[3]; 405 | DWORD Ldr; 406 | }; 407 | 408 | #endif 409 | 410 | using f_NtCreateThreadEx = NTSTATUS (__stdcall*) 411 | ( 412 | HANDLE * pHandle, 413 | ACCESS_MASK DesiredAccess, 414 | void * pAttr, 415 | HANDLE hTargetProc, 416 | void * pFunc, 417 | void * pArg, 418 | ULONG Flags, 419 | SIZE_T ZeroBits, 420 | SIZE_T StackSize, 421 | SIZE_T MaxStackSize, 422 | void * pAttrListOut 423 | ); 424 | 425 | using f_LdrLoadDll = NTSTATUS (__stdcall*) 426 | ( 427 | wchar_t * szOptPath, 428 | ULONG ulFlags, 429 | UNICODE_STRING * pModuleFileName, 430 | HANDLE * pOut 431 | ); 432 | 433 | using f_LdrpLoadDll = NTSTATUS (__fastcall*) 434 | ( 435 | UNICODE_STRING * dll_path, 436 | LDRP_PATH_SEARCH_CONTEXT * search_path, 437 | ULONG32 Flags, 438 | LDR_DATA_TABLE_ENTRY ** ldr_out 439 | ); 440 | 441 | using f_LdrpPreprocessDllName = NTSTATUS (__fastcall*) 442 | ( 443 | UNICODE_STRING * dll_path_in, 444 | UNICODE_STRING * dll_path_out, 445 | uintptr_t * unknown_out_1, 446 | uintptr_t * unknown_out_2 447 | ); 448 | 449 | using f_RtlInsertInvertedFunctionTable = BOOL (__fastcall*) 450 | ( 451 | void * hDll, 452 | DWORD SizeOfImage 453 | ); 454 | 455 | using f_NtQueryInformationProcess = NTSTATUS (__stdcall*) 456 | ( 457 | HANDLE hTargetProc, 458 | PROCESSINFOCLASS PIC, 459 | void * pBuffer, 460 | ULONG BufferSize, 461 | ULONG * SizeOut 462 | ); 463 | 464 | using f_NtQuerySystemInformation = NTSTATUS (__stdcall*) 465 | ( 466 | SYSTEM_INFORMATION_CLASS SIC, 467 | void * pBuffer, 468 | ULONG BufferSize, 469 | ULONG * SizeOut 470 | ); 471 | 472 | using f_NtQueryInformationThread = NTSTATUS (__stdcall*) 473 | ( 474 | HANDLE hThread, 475 | THREADINFOCLASS TIC, 476 | void * pBuffer, 477 | ULONG BufferSize, 478 | ULONG * SizeOut 479 | ); 480 | 481 | using f_RtlQueueApcWow64Thread = NTSTATUS (__stdcall*) 482 | ( 483 | HANDLE hThread, 484 | void * pRoutine, 485 | void * pArg1, 486 | void * pArg2, 487 | void * pArg3 488 | ); -------------------------------------------------------------------------------- /Process Info/Process Info.cpp: -------------------------------------------------------------------------------- 1 | #include "Process Info.h" 2 | 3 | #pragma comment(lib, "Psapi.lib") 4 | 5 | #define NEXT_SYSTEM_PROCESS_ENTRY(pCurrent) reinterpret_cast(reinterpret_cast(pCurrent) + pCurrent->NextEntryOffset) 6 | 7 | PEB * ProcessInfo::GetPEB_Native() 8 | { 9 | if (!m_pFirstProcess) 10 | { 11 | return nullptr; 12 | } 13 | 14 | PROCESS_BASIC_INFORMATION PBI{ 0 }; 15 | ULONG size_out = 0; 16 | NTSTATUS ntRet = m_pNtQueryInformationProcess(m_hCurrentProcess, ProcessBasicInformation, &PBI, sizeof(PROCESS_BASIC_INFORMATION), &size_out); 17 | 18 | if (NT_FAIL(ntRet)) 19 | { 20 | return nullptr; 21 | } 22 | 23 | return PBI.pPEB; 24 | } 25 | 26 | LDR_DATA_TABLE_ENTRY * ProcessInfo::GetLdrEntry_Native(HINSTANCE hMod) 27 | { 28 | if (!m_pFirstProcess) 29 | { 30 | return nullptr; 31 | } 32 | 33 | PEB * ppeb = GetPEB(); 34 | if (!ppeb) 35 | { 36 | return nullptr; 37 | } 38 | 39 | PEB peb{ 0 }; 40 | if (!ReadProcessMemory(m_hCurrentProcess, ppeb, &peb, sizeof(PEB), nullptr)) 41 | { 42 | return nullptr; 43 | } 44 | 45 | PEB_LDR_DATA ldrdata{ 0 }; 46 | if (!ReadProcessMemory(m_hCurrentProcess, peb.Ldr, &ldrdata, sizeof(PEB_LDR_DATA), nullptr)) 47 | { 48 | return nullptr; 49 | } 50 | 51 | LIST_ENTRY * pCurrentEntry = ldrdata.InLoadOrderModuleListHead.Flink; 52 | LIST_ENTRY * pLastEntry = ldrdata.InLoadOrderModuleListHead.Blink; 53 | 54 | while (true) 55 | { 56 | LDR_DATA_TABLE_ENTRY CurrentEntry{ 0 }; 57 | ReadProcessMemory(m_hCurrentProcess, pCurrentEntry, &CurrentEntry, sizeof(LDR_DATA_TABLE_ENTRY), nullptr); 58 | 59 | if (CurrentEntry.DllBase == hMod) 60 | { 61 | return reinterpret_cast(pCurrentEntry); 62 | } 63 | else if (pCurrentEntry == pLastEntry) 64 | { 65 | break; 66 | } 67 | 68 | pCurrentEntry = CurrentEntry.InLoadOrderLinks.Flink; 69 | } 70 | 71 | return nullptr; 72 | } 73 | 74 | ProcessInfo::ProcessInfo() 75 | { 76 | HINSTANCE hNTDLL = GetModuleHandle(TEXT("ntdll.dll")); 77 | if (!hNTDLL) 78 | { 79 | return; 80 | } 81 | 82 | m_pNtQueryInformationProcess = reinterpret_cast (GetProcAddress(hNTDLL, "NtQueryInformationProcess")); 83 | m_pNtQuerySystemInformation = reinterpret_cast (GetProcAddress(hNTDLL, "NtQuerySystemInformation")); 84 | m_pNtQueryInformationThread = reinterpret_cast (GetProcAddress(hNTDLL, "NtQueryInformationThread")); 85 | 86 | if (!m_pNtQueryInformationProcess || !m_pNtQuerySystemInformation || !m_pNtQueryInformationThread) 87 | { 88 | return; 89 | } 90 | 91 | m_BufferSize = 0x10000; 92 | m_pFirstProcess = nullptr; 93 | 94 | m_WaitFunctionReturnAddress[0] = reinterpret_cast(GetProcAddress(hNTDLL, "NtDelayExecution" )) + NT_RET_OFFSET; 95 | m_WaitFunctionReturnAddress[1] = reinterpret_cast(GetProcAddress(hNTDLL, "NtWaitForSingleObject" )) + NT_RET_OFFSET; 96 | m_WaitFunctionReturnAddress[2] = reinterpret_cast(GetProcAddress(hNTDLL, "NtWaitForMultipleObjects" )) + NT_RET_OFFSET; 97 | m_WaitFunctionReturnAddress[3] = reinterpret_cast(GetProcAddress(hNTDLL, "NtSignalAndWaitForSingleObject" )) + NT_RET_OFFSET; 98 | m_WaitFunctionReturnAddress[4] = reinterpret_cast(GetProcAddress(hNTDLL, "NtRemoveIoCompletionEx" )) + NT_RET_OFFSET; 99 | 100 | HINSTANCE hWIN32U = LoadLibrary(TEXT("win32u.dll")); 101 | if (hWIN32U) 102 | { 103 | m_WaitFunctionReturnAddress[5] = reinterpret_cast(GetProcAddress(hWIN32U, "NtUserMsgWaitForMultipleObjectsEx")) + NT_RET_OFFSET; 104 | } 105 | } 106 | 107 | ProcessInfo::~ProcessInfo() 108 | { 109 | if (m_pFirstProcess) 110 | { 111 | delete[] m_pFirstProcess; 112 | } 113 | } 114 | 115 | bool ProcessInfo::SetProcess(HANDLE hTargetProc) 116 | { 117 | DWORD dwHandleInfo = 0; 118 | if (!hTargetProc || hTargetProc == INVALID_HANDLE_VALUE || !GetHandleInformation(hTargetProc, &dwHandleInfo)) 119 | { 120 | return false; 121 | } 122 | 123 | if (!m_pFirstProcess) 124 | { 125 | if (!RefreshInformation()) 126 | { 127 | return false; 128 | } 129 | } 130 | 131 | m_hCurrentProcess = hTargetProc; 132 | 133 | ULONG_PTR PID = GetProcessId(m_hCurrentProcess); 134 | 135 | while (NEXT_SYSTEM_PROCESS_ENTRY(m_pCurrentProcess) != m_pCurrentProcess) 136 | { 137 | if (m_pCurrentProcess->UniqueProcessId == reinterpret_cast(PID)) 138 | { 139 | break; 140 | } 141 | 142 | m_pCurrentProcess = NEXT_SYSTEM_PROCESS_ENTRY(m_pCurrentProcess); 143 | } 144 | 145 | if (m_pCurrentProcess->UniqueProcessId != reinterpret_cast(PID)) 146 | { 147 | m_pCurrentProcess = m_pFirstProcess; 148 | return false; 149 | } 150 | 151 | m_CurrentThreadIndex = 0; 152 | m_pCurrentThread = &m_pCurrentProcess->Threads[0]; 153 | 154 | return true; 155 | } 156 | 157 | bool ProcessInfo::SetThread(DWORD TID) 158 | { 159 | if (!m_pFirstProcess) 160 | { 161 | return false; 162 | } 163 | 164 | m_pCurrentThread = nullptr; 165 | 166 | for (UINT i = 0; i != m_pCurrentProcess->NumberOfThreads; ++i) 167 | { 168 | if (m_pCurrentProcess->Threads[i].ClientId.UniqueThread == reinterpret_cast(ULONG_PTR(TID))) 169 | { 170 | m_CurrentThreadIndex = i; 171 | m_pCurrentThread = &m_pCurrentProcess->Threads[i]; 172 | break; 173 | } 174 | } 175 | 176 | if (m_pCurrentThread == nullptr) 177 | { 178 | m_CurrentThreadIndex = 0; 179 | m_pCurrentThread = &m_pCurrentProcess->Threads[0]; 180 | return false; 181 | } 182 | 183 | return true; 184 | } 185 | 186 | bool ProcessInfo::FirstThread() 187 | { 188 | if (!m_pFirstProcess) 189 | { 190 | return false; 191 | } 192 | 193 | m_CurrentThreadIndex = 0; 194 | m_pCurrentThread = &m_pCurrentProcess->Threads[0]; 195 | 196 | return true; 197 | } 198 | 199 | bool ProcessInfo::NextThread() 200 | { 201 | if (!m_pFirstProcess) 202 | { 203 | return false; 204 | } 205 | 206 | if (m_CurrentThreadIndex == m_pCurrentProcess->NumberOfThreads - 1) 207 | { 208 | return false; 209 | } 210 | 211 | m_pCurrentThread = &m_pCurrentProcess->Threads[++m_CurrentThreadIndex]; 212 | 213 | return true; 214 | } 215 | 216 | bool ProcessInfo::RefreshInformation() 217 | { 218 | if (!m_pFirstProcess) 219 | { 220 | m_pFirstProcess = reinterpret_cast(new BYTE[m_BufferSize]); 221 | if (!m_pFirstProcess) 222 | { 223 | return false; 224 | } 225 | } 226 | else 227 | { 228 | delete[] m_pFirstProcess; 229 | m_pFirstProcess = nullptr; 230 | 231 | return RefreshInformation(); 232 | } 233 | 234 | ULONG size_out = 0; 235 | NTSTATUS ntRet = m_pNtQuerySystemInformation(SystemProcessInformation, m_pFirstProcess, m_BufferSize, &size_out); 236 | 237 | while (ntRet == STATUS_INFO_LENGTH_MISMATCH) 238 | { 239 | delete[] m_pFirstProcess; 240 | 241 | m_BufferSize = size_out + 0x1000; 242 | m_pFirstProcess = reinterpret_cast(new BYTE[m_BufferSize]); 243 | if (!m_pFirstProcess) 244 | { 245 | return false; 246 | } 247 | 248 | ntRet = m_pNtQuerySystemInformation(SystemProcessInformation, m_pFirstProcess, m_BufferSize, &size_out); 249 | } 250 | 251 | if (NT_FAIL(ntRet)) 252 | { 253 | delete[] m_pFirstProcess; 254 | m_pFirstProcess = nullptr; 255 | 256 | return false; 257 | } 258 | 259 | m_pCurrentProcess = m_pFirstProcess; 260 | m_pCurrentThread = &m_pCurrentProcess->Threads[0]; 261 | 262 | return true; 263 | } 264 | 265 | PEB * ProcessInfo::GetPEB() 266 | { 267 | return GetPEB_Native(); 268 | } 269 | 270 | LDR_DATA_TABLE_ENTRY * ProcessInfo::GetLdrEntry(HINSTANCE hMod) 271 | { 272 | return GetLdrEntry_Native(hMod); 273 | } 274 | 275 | DWORD ProcessInfo::GetPID() 276 | { 277 | return GetProcessId(m_hCurrentProcess); 278 | } 279 | 280 | bool ProcessInfo::IsNative() 281 | { 282 | BOOL bOut = FALSE; 283 | IsWow64Process(m_hCurrentProcess, &bOut); 284 | return (bOut == FALSE); 285 | } 286 | 287 | void * ProcessInfo::GetEntrypoint() 288 | { 289 | if (!m_pFirstProcess) 290 | { 291 | return nullptr; 292 | } 293 | 294 | PEB * ppeb = GetPEB(); 295 | if (!ppeb) 296 | { 297 | return nullptr; 298 | } 299 | 300 | PEB peb; 301 | if (!ReadProcessMemory(m_hCurrentProcess, ppeb, &peb, sizeof(PEB), nullptr)) 302 | { 303 | return nullptr; 304 | } 305 | 306 | PEB_LDR_DATA ldrdata; 307 | if (!ReadProcessMemory(m_hCurrentProcess, peb.Ldr, &ldrdata, sizeof(PEB_LDR_DATA), nullptr)) 308 | { 309 | return nullptr; 310 | } 311 | 312 | LIST_ENTRY * pCurrentEntry = ldrdata.InLoadOrderModuleListHead.Flink; 313 | LIST_ENTRY * pLastEntry = ldrdata.InLoadOrderModuleListHead.Blink; 314 | 315 | wchar_t NameBuffer[MAX_PATH]{ 0 }; 316 | while (true) 317 | { 318 | LDR_DATA_TABLE_ENTRY CurrentEntry; 319 | if (ReadProcessMemory(m_hCurrentProcess, pCurrentEntry, &CurrentEntry, sizeof(LDR_DATA_TABLE_ENTRY), nullptr)) 320 | { 321 | if (ReadProcessMemory(m_hCurrentProcess, CurrentEntry.BaseDllName.szBuffer, NameBuffer, CurrentEntry.BaseDllName.Length, nullptr)) 322 | { 323 | if (NameBuffer[CurrentEntry.BaseDllName.Length / 2 - 1] == 'e') 324 | { 325 | return CurrentEntry.EntryPoint; 326 | } 327 | } 328 | } 329 | 330 | if (pCurrentEntry == pLastEntry) 331 | { 332 | break; 333 | } 334 | 335 | pCurrentEntry = CurrentEntry.InLoadOrderLinks.Flink; 336 | } 337 | 338 | return nullptr; 339 | } 340 | 341 | DWORD ProcessInfo::GetTID() 342 | { 343 | if (!m_pCurrentThread) 344 | { 345 | return 0; 346 | } 347 | 348 | return DWORD(reinterpret_cast(m_pCurrentThread->ClientId.UniqueThread) & 0xFFFFFFFF); 349 | } 350 | 351 | DWORD ProcessInfo::GetThreadId() 352 | { 353 | if (!m_pCurrentThread) 354 | { 355 | return 0; 356 | } 357 | 358 | return DWORD(reinterpret_cast(m_pCurrentThread->ClientId.UniqueThread) & 0xFFFFFFFF); 359 | } 360 | 361 | bool ProcessInfo::GetThreadState(THREAD_STATE & state, KWAIT_REASON & reason) 362 | { 363 | if (!m_pCurrentThread) 364 | { 365 | return 0; 366 | } 367 | 368 | state = m_pCurrentThread->ThreadState; 369 | reason = m_pCurrentThread->WaitReason; 370 | 371 | return true; 372 | } 373 | 374 | bool ProcessInfo::GetThreadStartAddress(void *& start_address) 375 | { 376 | if (!m_pCurrentThread) 377 | { 378 | return false; 379 | } 380 | 381 | if (!IsNative()) 382 | { 383 | return GetThreadStartAddress_WOW64(start_address); 384 | } 385 | 386 | start_address = m_pCurrentThread->StartAddress; 387 | 388 | return true; 389 | } 390 | 391 | bool ProcessInfo::GetThreadStartAddress_WOW64(void *& start_address) 392 | { 393 | if (!m_pCurrentThread) 394 | { 395 | return false; 396 | } 397 | 398 | HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION, FALSE, (DWORD)(UINT_PTR)(m_pCurrentThread->ClientId.UniqueThread)); 399 | if (!hThread) 400 | { 401 | return false; 402 | } 403 | 404 | if (NT_SUCCESS(m_pNtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, &start_address, sizeof(start_address), nullptr))) 405 | { 406 | CloseHandle(hThread); 407 | 408 | return true; 409 | } 410 | 411 | CloseHandle(hThread); 412 | 413 | return false; 414 | } 415 | 416 | bool ProcessInfo::IsThreadInAlertableState() 417 | { 418 | if (!m_pCurrentThread) 419 | { 420 | return false; 421 | } 422 | 423 | HANDLE hThread = OpenThread(THREAD_GET_CONTEXT, FALSE, (DWORD)(UINT_PTR)(m_pCurrentThread->ClientId.UniqueThread)); 424 | if (!hThread) 425 | { 426 | return false; 427 | } 428 | 429 | CONTEXT ctx{ 0 }; 430 | ctx.ContextFlags = CONTEXT_ALL; 431 | 432 | if (!GetThreadContext(hThread, &ctx)) 433 | { 434 | CloseHandle(hThread); 435 | 436 | return false; 437 | } 438 | 439 | CloseHandle(hThread); 440 | 441 | #ifdef _WIN64 442 | 443 | if (ctx.Rip == m_WaitFunctionReturnAddress[0]) 444 | { 445 | return (ctx.Rcx == TRUE); 446 | } 447 | else if (ctx.Rip == m_WaitFunctionReturnAddress[1]) 448 | { 449 | return (ctx.Rdx == TRUE); 450 | } 451 | else if (ctx.Rip == m_WaitFunctionReturnAddress[2]) 452 | { 453 | return (ctx.Rsi == TRUE); 454 | } 455 | else if (ctx.Rip == m_WaitFunctionReturnAddress[3]) 456 | { 457 | return (ctx.Rsi == TRUE); 458 | } 459 | else if (ctx.Rip == m_WaitFunctionReturnAddress[4] && ctx.Rsp) 460 | { 461 | UINT_PTR buffer = 0; 462 | if (ReadProcessMemory(m_hCurrentProcess, reinterpret_cast(ctx.Rsp + 0x30), &buffer, sizeof(buffer), nullptr)) 463 | { 464 | return (buffer == TRUE); 465 | } 466 | } 467 | else if (ctx.Rip == m_WaitFunctionReturnAddress[5] && ctx.Rsp) 468 | { 469 | UINT_PTR buffer = 0; 470 | if (ReadProcessMemory(m_hCurrentProcess, reinterpret_cast(ctx.Rsp + 0x28), &buffer, sizeof(buffer), nullptr)) 471 | { 472 | return ((buffer & MWMO_ALERTABLE) != 0); 473 | } 474 | } 475 | 476 | #else 477 | 478 | if (!ctx.Esp) 479 | { 480 | return false; 481 | } 482 | 483 | DWORD stack_buffer[6] = { 0 }; 484 | if (!ReadProcessMemory(m_hCurrentProcess, reinterpret_cast(ctx.Esp), stack_buffer, sizeof(stack_buffer), nullptr)) 485 | { 486 | return false; 487 | } 488 | 489 | if (ctx.Eip == m_WaitFunctionReturnAddress[0]) 490 | { 491 | return (stack_buffer[1] == TRUE); 492 | } 493 | else if (ctx.Eip == m_WaitFunctionReturnAddress[1]) 494 | { 495 | return (stack_buffer[2] == TRUE); 496 | } 497 | else if (ctx.Eip == m_WaitFunctionReturnAddress[2]) 498 | { 499 | return (stack_buffer[4] == TRUE); 500 | } 501 | else if (ctx.Eip == m_WaitFunctionReturnAddress[3]) 502 | { 503 | return (stack_buffer[3] == TRUE); 504 | } 505 | else if (ctx.Eip == m_WaitFunctionReturnAddress[4]) 506 | { 507 | return (stack_buffer[4] == TRUE); 508 | } 509 | else if (ctx.Eip == m_WaitFunctionReturnAddress[5]) 510 | { 511 | return ((stack_buffer[5] & MWMO_ALERTABLE) != 0); 512 | } 513 | 514 | #endif 515 | 516 | return false; 517 | } 518 | 519 | bool ProcessInfo::IsThreadWorkerThread() 520 | { 521 | if (!m_pCurrentThread) 522 | { 523 | return false; 524 | } 525 | 526 | HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION, FALSE, (DWORD)(UINT_PTR)(m_pCurrentThread->ClientId.UniqueThread)); 527 | if (!hThread) 528 | { 529 | return false; 530 | } 531 | 532 | THREAD_BASIC_INFORMATION tbi{ 0 }; 533 | if (FAILED(m_pNtQueryInformationThread(hThread, ThreadBasicInformation, &tbi, sizeof(tbi), nullptr)) || !tbi.TebBaseAddress) 534 | { 535 | return false; 536 | } 537 | 538 | CloseHandle(hThread); 539 | 540 | USHORT TebInfo = NULL; 541 | if (ReadProcessMemory(m_hCurrentProcess, reinterpret_cast(tbi.TebBaseAddress) + TEB_SAMETEBFLAGS, &TebInfo, sizeof(TebInfo), nullptr)) 542 | { 543 | return ((TebInfo & 0x2000) != 0); 544 | } 545 | 546 | return false; 547 | } 548 | 549 | const SYSTEM_PROCESS_INFORMATION * ProcessInfo::GetProcessInfo() 550 | { 551 | return m_pFirstProcess ? m_pCurrentProcess : nullptr; 552 | } 553 | 554 | const SYSTEM_THREAD_INFORMATION * ProcessInfo::GetThreadInfo() 555 | { 556 | return m_pFirstProcess ? m_pCurrentThread : nullptr; 557 | } 558 | 559 | #ifdef _WIN64 560 | 561 | PEB32 * ProcessInfo::GetPEB_WOW64() 562 | { 563 | if (!m_pFirstProcess) 564 | { 565 | return 0; 566 | } 567 | 568 | ULONG_PTR pPEB; 569 | ULONG size_out = 0; 570 | NTSTATUS ntRet = m_pNtQueryInformationProcess(m_hCurrentProcess, ProcessWow64Information, &pPEB, sizeof(pPEB), &size_out); 571 | 572 | if (NT_FAIL(ntRet)) 573 | { 574 | return nullptr; 575 | } 576 | 577 | return reinterpret_cast(pPEB); 578 | } 579 | 580 | LDR_DATA_TABLE_ENTRY32 * ProcessInfo::GetLdrEntry_WOW64(HINSTANCE hMod) 581 | { 582 | if (!m_pFirstProcess) 583 | { 584 | return nullptr; 585 | } 586 | 587 | PEB32 * ppeb = GetPEB_WOW64(); 588 | if (!ppeb) 589 | { 590 | return nullptr; 591 | } 592 | 593 | PEB32 peb{ 0 }; 594 | if (!ReadProcessMemory(m_hCurrentProcess, ppeb, &peb, sizeof(PEB32), nullptr)) 595 | { 596 | return nullptr; 597 | } 598 | 599 | PEB_LDR_DATA32 ldrdata{ 0 }; 600 | if (!ReadProcessMemory(m_hCurrentProcess, (void*)(UINT_PTR)(peb.Ldr), &ldrdata, sizeof(PEB_LDR_DATA32), nullptr)) 601 | { 602 | return nullptr; 603 | } 604 | 605 | LIST_ENTRY32 * pCurrentEntry = reinterpret_cast((ULONG_PTR)ldrdata.InLoadOrderModuleListHead.Flink); 606 | LIST_ENTRY32 * pLastEntry = reinterpret_cast((ULONG_PTR)ldrdata.InLoadOrderModuleListHead.Blink); 607 | 608 | while (true) 609 | { 610 | LDR_DATA_TABLE_ENTRY32 CurrentEntry{ 0 }; 611 | ReadProcessMemory(m_hCurrentProcess, pCurrentEntry, &CurrentEntry, sizeof(LDR_DATA_TABLE_ENTRY32), nullptr); 612 | 613 | if (CurrentEntry.DllBase == (DWORD)(UINT_PTR)(hMod)) 614 | { 615 | return reinterpret_cast(pCurrentEntry); 616 | } 617 | else if (pCurrentEntry == pLastEntry) 618 | { 619 | break; 620 | } 621 | 622 | pCurrentEntry = reinterpret_cast((ULONG_PTR)CurrentEntry.InLoadOrderLinks.Flink); 623 | } 624 | 625 | return nullptr; 626 | } 627 | 628 | #endif -------------------------------------------------------------------------------- /Process Info/Process Info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "NT Stuff.h" 4 | 5 | #define NT_RET_OFFSET_64 0x14 6 | #define NT_RET_OFFSET_86 0x0C 7 | 8 | #define TEB_SAMETEBFLAGS_64 0x17EE 9 | #define TEB_SAMETEBFLAGS_86 0xFCA 10 | 11 | #ifdef _WIN64 12 | #define NT_RET_OFFSET NT_RET_OFFSET_64 13 | #define TEB_SAMETEBFLAGS TEB_SAMETEBFLAGS_64 14 | #else 15 | #define NT_RET_OFFSET NT_RET_OFFSET_86 16 | #define TEB_SAMETEBFLAGS TEB_SAMETEBFLAGS_86 17 | #endif 18 | 19 | class ProcessInfo 20 | { 21 | SYSTEM_PROCESS_INFORMATION * m_pCurrentProcess = nullptr; 22 | SYSTEM_PROCESS_INFORMATION * m_pFirstProcess = nullptr; 23 | SYSTEM_THREAD_INFORMATION * m_pCurrentThread = nullptr; 24 | 25 | ULONG m_BufferSize = 0; 26 | 27 | HANDLE m_hCurrentProcess = nullptr; 28 | 29 | DWORD m_CurrentThreadIndex = 0; 30 | 31 | f_NtQueryInformationProcess m_pNtQueryInformationProcess = nullptr; 32 | f_NtQuerySystemInformation m_pNtQuerySystemInformation = nullptr; 33 | f_NtQueryInformationThread m_pNtQueryInformationThread = nullptr; 34 | 35 | PEB * GetPEB_Native(); 36 | LDR_DATA_TABLE_ENTRY * GetLdrEntry_Native(HINSTANCE hMod); 37 | 38 | UINT_PTR m_WaitFunctionReturnAddress[6] = { 0 }; 39 | 40 | public: 41 | 42 | ProcessInfo(); 43 | ~ProcessInfo(); 44 | 45 | bool SetProcess(HANDLE hTargetProc); 46 | bool SetThread(DWORD TID); 47 | 48 | bool FirstThread(); 49 | bool NextThread(); 50 | 51 | bool RefreshInformation(); 52 | 53 | PEB * GetPEB(); 54 | LDR_DATA_TABLE_ENTRY * GetLdrEntry(HINSTANCE hMod); 55 | 56 | DWORD GetPID(); 57 | 58 | bool IsNative(); 59 | 60 | void * GetEntrypoint(); 61 | 62 | DWORD GetTID(); 63 | DWORD GetThreadId(); 64 | bool GetThreadState(THREAD_STATE & state, KWAIT_REASON & reason); 65 | bool GetThreadStartAddress(void *& start_address); 66 | bool GetThreadStartAddress_WOW64(void *& start_address); 67 | bool IsThreadInAlertableState(); 68 | bool IsThreadWorkerThread(); 69 | 70 | const SYSTEM_PROCESS_INFORMATION * GetProcessInfo(); 71 | const SYSTEM_THREAD_INFORMATION * GetThreadInfo(); 72 | 73 | #ifdef _WIN64 74 | 75 | PEB32 * GetPEB_WOW64(); 76 | LDR_DATA_TABLE_ENTRY32 * GetLdrEntry_WOW64(HINSTANCE hMod); 77 | 78 | #endif 79 | }; -------------------------------------------------------------------------------- /Process Info/Process Info.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {93D3A791-F95B-431E-9C6E-296252B58FE3} 24 | ProcessInfo 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v142 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | Level3 87 | true 88 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 89 | true 90 | 91 | 92 | Console 93 | true 94 | 95 | 96 | 97 | 98 | Level3 99 | true 100 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 101 | true 102 | 103 | 104 | Console 105 | true 106 | 107 | 108 | 109 | 110 | Level3 111 | true 112 | true 113 | true 114 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 115 | true 116 | 117 | 118 | Console 119 | true 120 | true 121 | true 122 | 123 | 124 | 125 | 126 | Level3 127 | true 128 | true 129 | true 130 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 131 | true 132 | 133 | 134 | Console 135 | true 136 | true 137 | true 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /Process Info/Process Info.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;ipp;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 | Headerdateien 20 | 21 | 22 | Headerdateien 23 | 24 | 25 | 26 | 27 | Quelldateien 28 | 29 | 30 | Quelldateien 31 | 32 | 33 | -------------------------------------------------------------------------------- /Process Info/Process Info.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Process Info/main.cpp: -------------------------------------------------------------------------------- 1 | #include "Process Info.h" 2 | #include 3 | 4 | int main() 5 | { 6 | HANDLE hProc = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentProcessId()); 7 | 8 | ProcessInfo info; 9 | if (!info.SetProcess(hProc)) 10 | { 11 | printf("ProcessInfo::SetProcess failed\n"); 12 | 13 | return 0; 14 | } 15 | 16 | printf("Process (%08d)\n", info.GetPID()); 17 | printf("\tPEB : %p\n", info.GetPEB()); 18 | printf("\tPEB entry : %p\n", info.GetLdrEntry(GetModuleHandle(NULL))); 19 | printf("\tEntrypoint : %p\n", info.GetEntrypoint()); 20 | printf("\tPlatform : %s\n", info.IsNative() ? "native" : "wow64"); 21 | 22 | printf("\n"); 23 | 24 | if (info.FirstThread()) 25 | { 26 | do 27 | { 28 | printf("Thread (%08d)\n", info.GetThreadId()); 29 | 30 | void * start_address = nullptr; 31 | if (!info.GetThreadStartAddress(start_address)) 32 | { 33 | printf("\tStartaddress : failed to query startaddress\n"); 34 | } 35 | else 36 | { 37 | printf("\tStartaddress : %p\n", start_address); 38 | } 39 | 40 | THREAD_STATE state; 41 | KWAIT_REASON reason; 42 | if (!info.GetThreadState(state, reason)) 43 | { 44 | printf("\tThread state : failed to query thread state\n"); 45 | printf("\tWait reason : failed to query wait reason\n"); 46 | } 47 | else 48 | { 49 | printf("\tThread state : %s\n", state == THREAD_STATE::Running ? "Running" : "Waiting"); 50 | printf("\tWait reason : %02d\n", (int)reason); 51 | } 52 | 53 | bool bAlertable = info.IsThreadInAlertableState(); 54 | printf("\tIs alertable : %s\n", bAlertable ? "Yes" : "No"); 55 | 56 | bool bWoker = info.IsThreadWorkerThread(); 57 | printf("\tIs worker : %s\n", bWoker ? "Yes" : "No"); 58 | 59 | printf("\n"); 60 | 61 | } while (info.NextThread()); 62 | } 63 | else 64 | { 65 | printf("ProcessInfo::FirstThread failed\n"); 66 | } 67 | 68 | return 0; 69 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ProcessInfo 2 | 3 | A small class to gather information about a Windows process, its threads and modules. 4 | It supports both x86 and x64. Gathering information from a x64 process of a WOW64 process works aswell. 5 | 6 | It gathers information using NtQuerySystemInformation, NtQueryInformationProcess and NtQueryInformationThread. 7 | 8 | --- 9 | 10 | Use SetProcess to specifie a process. The handle needs PROCESS_VM_READ | PROCESS_QUERY_INFORMATION | PROCESS_QUERY_INFORMATION_LIMITED access rights. 11 | It's recommended but not mandatory to call RefreshInformation when specifying a new process. 12 | 13 | The following process related functions are available: 14 | - GetPID 15 | - GetPEB 16 | - GetEntrypoint 17 | - IsNative 18 | - GetProcessInfo 19 | 20 | --- 21 | 22 | Use FirstThread and NextThread to enumerate through all threads of the process. This works similar to Thread32First and Thread32Next. 23 | Alternatively use SetThread to specify a thread by its identifier. 24 | 25 | The following thread related functions are available and will return information about the current thread: 26 | - GetThreadState 27 | - GetThreadStartAddress 28 | - IsThreadWorkerThread 29 | - IsThreadInAlertableState (this function doesn't support x64 to wow64) 30 | - GetThreadInfo 31 | 32 | --- 33 | 34 | GetLdrEntry returns a pointer to the LDR_DATA_TABLE_ENTRY structure of the specified module in the PEB. 35 | --------------------------------------------------------------------------------