NtQuerySystemInformation来遍历显示进程

NtQuerySystemInformation是未公开函数,可查询大量系统信息。本文介绍使用该函数查询进程名和对应PID,此函数在ntdll.dll中有导出,代码摘自网络并经大量修改,原程序用于查询特定进程下特定线程状态,核心代码被保留并注释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NtQuerySystemInformation属于未公开的函数,没有文档化,头文件中也不存在(winternl.h中有其及其部分数据结构的定义),该函数可以查询到非常大量的系统信息。这里来使用该函数来查询进程名和对应PID。

其在ntdll.dll中有导出

该代码摘自网络,我对其做了大量的修改,废弃掉了大部分不需要的内容并完善了程序, 其本来的用意是查询特定进程下的特定线程状态,我保留了原程序功能的核心代码仅将其注释掉。

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_SUCCESS ((NTSTATUS) 0x00000000)
#define SystemProcessInformation    5 // 功能号
#define NTAPI    __stdcall

//typedef enum _KWAIT_REASON
//{
//	Executive,
//	FreePage,
//	PageIn,
//	PoolAllocation,
//	DelayExecution,
//	Suspended,
//	UserRequest,
//	WrExecutive,
//	WrFreePage,
//	WrPageIn,
//	WrPoolAllocation,
//	WrDelayExecution,
//	WrSuspended,
//	WrUserRequest,
//	WrEventPair,
//	WrQueue,
//	WrLpcReceive,
//	WrLpcReply,
//	WrVirtualMemory,
//	WrPageOut,
//	WrRendezvous,
//	Spare2,
//	Spare3,
//	Spare4,
//	Spare5,
//	Spare6,
//	WrKernel,
//	MaximumWaitReason
//}KWAIT_REASON;


//typedef struct _SYSTEM_THREAD_INFORMATION
//{
//	LARGE_INTEGER   KernelTime;
//	LARGE_INTEGER   UserTime;
//	LARGE_INTEGER   CreateTime;
//	ULONG           WaitTime;
//	PVOID           StartAddress;
//	CLIENT_ID       ClientId;
//	KPRIORITY       Priority;
//	KPRIORITY       BasePriority;
//	ULONG           ContextSwitchCount;
//	LONG            State;// 状态,是THREAD_STATE枚举类型中的一个值
//	LONG            WaitReason;//等待原因, KWAIT_REASON中的一个值
//} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;


// 线程状态的枚举常量
//typedef enum _THREAD_STATE
//{
//	StateInitialized, // 初始化状态
//	StateReady, // 准备状态
//	StateRunning, // 运行状态
//	StateStandby, // 
//	StateTerminated,//关闭
//	StateWait, // 等待
//	StateTransition, // 切换
//	StateUnknown
//}THREAD_STATE;

typedef struct _UNICODE_STRING
{
	USHORT Length;
	USHORT MaximumLength;
	PWSTR  Buffer;
} UNICODE_STRING, * PUNICODE_STRING;

typedef LONG   NTSTATUS;
typedef LONG    KPRIORITY;

typedef struct _CLIENT_ID
{
	DWORD        UniqueProcess;
	DWORD        UniqueThread;
} CLIENT_ID, * PCLIENT_ID;


typedef struct _VM_COUNTERS
{
	SIZE_T        PeakVirtualSize;
	SIZE_T        VirtualSize;
	ULONG         PageFaultCount;
	SIZE_T        PeakWorkingSetSize;
	SIZE_T        WorkingSetSize;
	SIZE_T        QuotaPeakPagedPoolUsage;
	SIZE_T        QuotaPagedPoolUsage;
	SIZE_T        QuotaPeakNonPagedPoolUsage;
	SIZE_T        QuotaNonPagedPoolUsage;
	SIZE_T        PagefileUsage;
	SIZE_T        PeakPagefileUsage;
} VM_COUNTERS;

typedef struct _SYSTEM_PROCESS_INFORMATION
{
	ULONG            NextEntryDelta; // 指向下一个结构体的指针
	ULONG            ThreadCount; // 本进程的总线程数
	ULONG            Reserved1[6]; // 保留
	LARGE_INTEGER    CreateTime; // 进程的创建时间
	LARGE_INTEGER    UserTime; // 在用户层的使用时间
	LARGE_INTEGER    KernelTime; // 在内核层的使用时间
	UNICODE_STRING   ProcessName; // 进程名
	KPRIORITY        BasePriority; // 
	ULONG            ProcessId; // 进程ID
	ULONG            InheritedFromProcessId;
	ULONG            HandleCount; // 进程的句柄总数
	ULONG            Reserved2[2]; // 保留
	VM_COUNTERS      VmCounters;
	IO_COUNTERS      IoCounters;
	//SYSTEM_THREAD_INFORMATION Threads[5]; // 子线程信息数组
}SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;

typedef DWORD(WINAPI* NTQUERYSYSTEMINFORMATION)(UINT, PVOID, DWORD, PDWORD);

VOID EnumProcesses()
{
	int nRet = 0;
	NTSTATUS status = STATUS_SUCCESS;
	DWORD   dwSize = 0xFFFFF;
	NTQUERYSYSTEMINFORMATION NtQuerySystemInformation = NULL;
	PSYSTEM_PROCESS_INFORMATION pInfo = { 0 };
	LPTSTR pBuf = NULL;

	NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(
		LoadLibrary("ntdll.dll"), 
		"NtQuerySystemInformation"
	);

	do
	{
		pBuf = new TCHAR[dwSize];
		if (NULL == pBuf)
		{
			break;
		}
		pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuf;
		
		status = NtQuerySystemInformation(
			SystemProcessInformation,
			pInfo,
			dwSize,
			&dwSize
		);
		if (!NT_SUCCESS(status)) {/*如果函数执行失败*/
			break;
		}
		// 遍历结构体,找到对应的进程
		while (pInfo->NextEntryDelta) {
			if (0 != pInfo->ProcessId)
			{
				_tprintf(TEXT("进程名: %wZ, PID: %d\n"), &(pInfo->ProcessName), pInfo->ProcessId);
			}
			//// 这段代码用于查询对应线程是否挂起
			//if (pInfo->ProcessId == dwProcessID) {
			//	// 找到该进程下的对应的线程,也就是遍历所有线程
			//	for (DWORD i = 0; i < pInfo->ThreadCount; i++) {
			//		if (pInfo->Threads[i].ClientId.UniqueThread == dwThreadID) { //找到线程 
			//			//如果线程被挂起
			//			if (pInfo->Threads[i].State == StateWait
			//				&& pInfo->Threads[i].WaitReason == Suspended) {
			//				nRet = 1;
			//				break;
			//			}
			//		}
			//	}
			//	break;
			//}
			pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo) + pInfo->NextEntryDelta);
		}
	} while (0);

	if (NULL != pBuf)
	{
		delete[] pBuf;
		pBuf = NULL;
	}
}

int _tmain()
{
	EnumProcesses();
	system("pause");

	return(0);
}

//BOOL IsThreadAlive(DWORD dwThreadID)
//{
//	BOOL bRet = FALSE;
//	DWORD ExitCode = 0;
//
//	HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, dwThreadID);
//	if (hThread != NULL) {
//		if (GetExitCodeThread(hThread, &ExitCode)) {
//			if (ExitCode == STILL_ACTIVE)
//				bRet = TRUE;
//		}
//		CloseHandle(hThread);
//	}
//	return bRet;
//}

下面给出运行效果:

(完)

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值