文章目录
进程遍历-NtQuerySystemInformation枚举
1. 相关函数及结构体
1.1 NtQuerySystemInformation
检索指定的系统信息
__kernel_entry NTSTATUS NtQuerySystemInformation(
[in] SYSTEM_INFORMATION_CLASS SystemInformationClass,
[in, out] PVOID SystemInformation,
[in] ULONG SystemInformationLength,
[out, optional] PULONG ReturnLength
);
SystemInformationClass SYSTEM_INFORMATION_CLASS中枚举的值之一,指示要检索的系统信息类型。
SystemInformation 指向接收请求信息的缓冲区的指针。 此信息的大小和结构因 SystemInformationClass 参数的值而异
SystemInformationLength SystemInformation 参数指向的缓冲区的大小(以字节为单位)
ReturnLength 写入所请求信息的实际大小的位置的可选指针
1.2 SYSTEM_PROCESS_INFORMATION
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
BYTE Reserved1[48];
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
PVOID Reserved2;
ULONG HandleCount;
ULONG SessionId;
PVOID Reserved3;
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG Reserved4;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
PVOID Reserved5;
SIZE_T QuotaPagedPoolUsage;
PVOID Reserved6;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved7[6];
} SYSTEM_PROCESS_INFORMATION;
数组中下一项的开头是上一项的地址加上 NextEntryOffset 成员中的值。 对于数组中的最后一项, NextEntryOffset 为 0
NumberOfThreads 成员包含进程中的线程数
ImageName 成员包含进程的映像名称
BasePriority 成员包含进程的基优先级,即在关联进程中创建的线程的起始优先级
UniqueProcessId 成员包含进程的唯一进程 ID
HandleCount 成员包含有问题的进程正在使用的句柄总数;改用 GetProcessHandleCount 检索此信息
SessionId 成员包含进程会话的会话标识符
PeakVirtualSize 成员包含进程使用的虚拟内存的峰值大小(以字节为单位)
VirtualSize 成员包含进程使用的虚拟内存的当前大小(以字节为单位)
PeakWorkingSetSize 成员包含进程的工作集的峰值大小(以 KB 为单位)
QuotaPagedPoolUsage 成员包含按分页池使用对进程收费的当前配额
QuotaNonPagedPoolUsage 成员包含针对非分页池使用向进程收费的当前配额
PagefileUsage 成员包含进程正在使用的页面文件存储的字节数
PeakPagefileUsage 成员包含进程使用的页面文件存储的最大字节数
PrivatePageCount 成员包含为使用此过程而分配的内存页数
2. 遍历进程
2.1 遍历进程思路分析
- 定义函数原型 pNtQuerySystemInfomation
- 通过GetProcAddress 获取NtQuerySystemInfomation函数地址(pNtQuerySystemInfomation)
- 通过NtQuerySystemInformation返回 SYSTEM_PROCESS_INFORMATION 结构的数组(每个结构对应系统中运行的进程)并初始化相应的空间
- 通过NtQuerySystemInformation获取数组的详细内容
- 处理进程信息结构体
2.2 遍历进程具体实现
#include <stdio.h>
#include <Windows.h>
#include <winternl.h>
#include <tchar.h>
#include <locale.h>
typedef NTSTATUS(NTAPI* pNtQuerySystemInfomation)(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SsystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
int main()
{
setlocale(LC_ALL, "zh_CN.UTF-8");
pNtQuerySystemInfomation fnNtQuerySystemInformation = NULL;
fnNtQuerySystemInformation = (pNtQuerySystemInfomation)GetProcAddress(GetModuleHandle(L"NTDLL.dll"), "NtQuerySystemInformation");
ULONG ulen1 = NULL;
fnNtQuerySystemInformation(SystemProcessInformation, NULL, NULL, &ulen1);
PSYSTEM_PROCESS_INFORMATION SystemProcInfo = NULL;
SystemProcInfo = (PSYSTEM_PROCESS_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)ulen1);
if (SystemProcInfo == NULL) {
return 0;
}
PVOID pValueToFree = NULL;
pValueToFree = SystemProcInfo;
NTSTATUS sts = NULL;
ULONG ulen2 = NULL;
sts = fnNtQuerySystemInformation(SystemProcessInformation, SystemProcInfo, ulen1, &ulen2);
if (sts != 0X0) {
return 0;
}
while (TRUE) {
_tprintf(TEXT("%d \t%ws\n"), (DWORD)SystemProcInfo->UniqueProcessId, SystemProcInfo->ImageName.Buffer);
if (!SystemProcInfo->NextEntryOffset) {
break;
}
SystemProcInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)SystemProcInfo + SystemProcInfo->NextEntryOffset);
}
HeapFree(GetProcessHeap(), 0, pValueToFree);
return 1;
}
关注我们,咱们在安全的路上,扬帆起航
参考文献
[1] https://learn.microsoft.com/zh-cn/windows/win32/api/winternl/nf-winternl-ntquerysysteminformation