之前转载过一点rootkit的内容;其中有提到ZwQuerySystemInformation函数,Zw开头的是在驱动程序中调用的函数,根据资料,Windows任务管理器枚举进程信息是通过NtQuerySystemInformation函数,NtQuerySystemInformation应该是调用的ZwQuerySystemInformation。
下面单独看一下ZwQuerySystemInformation,
内核下枚举进程
说明: SYSTEM_INFORMATION_CLASS 的5号功能枚举进程信息。其是这个函数对应着ring3下的 NtQuerySystemInformation,但msdn上说win8以后ZwQuerySystemInformation函数已经不可用,本人也没有在win8下测试过。顺便罗嗦一下,不像ring3下使用此函数是要先LoadLibrary,然后GetProcAddress。内核下,直接声明一下就可以用了(就是这个宏:NTSYSAPI),下面直接附上代码:
#include <ntddk.h>
#define SystemProcessesAndThreadsInformation 5
typedef struct _SYSTEM_PROCESSES
{
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters;
} _SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
NTSTATUS EnumSystemProcess( );
NTSYSAPI
NTSTATUS
NTAPI ZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength
);
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(DriverObject);
UNREFERENCED_PARAMETER(RegistryPath);
NTSTATUS status = STATUS_SUCCESS;
status = EnumSystemProcess( );
return status;
}
NTSTATUS EnumSystemProcess( )
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
*pRet = FALSE;
PSYSTEM_PROCESSES pProcessInfo = NULL;
PSYSTEM_PROCESSES pTemp = NULL;//这个留作以后释放指针的时候用。
ULONG ulNeededSize;
ULONG ulNextOffset;
if (NULL == pProcess)
{
return status;
}
//第一次使用肯定是缓冲区不够,不过本人在极少数的情况下第二次也会出现不够,所以用while循环
status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation , pProcessInfo, 0, &ulNeededSize);
while (STATUS_INFO_LENGTH_MISMATCH == status)
{
pProcessInfo = ExAllocatePoolWithTag(NonPagedPool, ulNeededSize, '1aes');
pTemp = pProcessInfo;
if (NULL == pProcessInfo)
{
KdPrint(("[allocatePoolWithTag] failed"));
return status;
}
status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation , pProcessInfo, ulNeededSize, &ulNeededSize);
}
if (NT_SUCCESS(status))
{
KdPrint(("[ZwQuerySystemInformation]success bufferSize:%x", ulNeededSize));
}
else
{
KdPrint(("[error]:++++%d", status));
return status;
}
do
{
KdPrint(("[imageName Buffer]:%08x", pProcessInfo->ProcessName.Buffer));
if (MmIsAddressValid(pProcessInfo->ProcessName.Buffer) && NULL != pProcessInfo)
{
KdPrint(("[ProcessID]:%d , [imageName]:%ws", pProcessInfo->ProcessId, pProcessInfo->ProcessName.Buffer));
}
ulNextOffset = pProcessInfo->NextEntryDelta;
pProcessInfo = (PSYSTEM_PROCESSES)((PUCHAR)pProcessInfo + pProcessInfo->NextEntryDelta);
} while (ulNextOffset != 0);
ExFreePoolWithTag(pTemp, '1aes');
return status;
}
是一个驱动程序,
此函数在Win8以后已不可用,见此,
https://learn.microsoft.com/zh-cn/windows/win32/sysinfo/zwquerysysteminformation