前一段时间做了个在驱动中列举进程信息的东西,其实也是自己在网上看了别人的部分代码后自己试着改了一下,现在拿过来分享罢了。
原理比较简单,就是调用函数ZwQuerySystemInformation请求信息SystemProcessesAndThreadsInformation,然后会返回一个SYSTEM_PROCESSES链表,其中所有进程的信息便存储在这个链表中。不过这里有几个注意的地方:
(1)ZwQuerySystemInformation需要调用两次,第一次调用时是为了获取存放SYSTEM_PROCESSES链表内存空间的大小,然后申请对应的内存空间,第二次将申请的内存空间作为参数就可以获取最后的链表;
(2)链表虽然都是连续存放在上面申请的内存空间中,但是每个进程节点所占用的大小不是确定的,这个看下面的SYSTEM_PROCESSES结构就可以知道。因此下个节点的位置为当前节点的pProcess->NextEntryDelta中。
(3)这种方法获取的信息有限,能获取进程的pid,进程名,但无法获取进程的完整路径。
关键代码如下:
#define SystemProcessesAndThreadsInformation 5
typedef struct _SYSTEM_THREADS {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientIs;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
ULONG ThreadState;
KWAIT_REASON WaitReason;
}SYSTEM_THREADS;
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; //windows 2000 only
struct _SYSTEM_THREADS Threads[1];
}SYSTEM_PROCESSES;
VOID GetExistedProcess()
{
SYSTEM_PROCESSES *pProcess;
PVOID buf;
ULONG n = 0;
ULONG num = 0;
ULONG i = 0;
NTSTATUS status;
CHAR packet[MAX_PKT_LEN] = {0};
ULONG sessionId = 0;
ANSI_STRING processName;
status = ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, &buf, n, &n );
if ( !NT_SUCCESS(status) )
{
buf = ExAllocatePool(NonPagedPool, n);
if ( NULL == buf )
{
return STATUS_UNSUCCESSFUL;
}
}
status = ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, buf, n, NULL );
{
if ( !NT_SUCCESS(status) )
{
return STATUS_UNSUCCESSFUL;
}
}
for ( pProcess = buf; NULL != pProcess && NULL != pProcess->NextEntryDelta; pProcess = (SYSTEM_PROCESSES*)((unsigned char*)pProcess + pProcess->NextEntryDelta) )
{
KdPrint(("process: pid = %d, process name = %ws\n", pProcess->ProcessId, pProcess->ProcessName.Buffer));
}
RtlFreeAnsiString(&processName);
}
ExFreePool(buf);
}
原理比较简单,就是调用函数ZwQuerySystemInformation请求信息SystemProcessesAndThreadsInformation,然后会返回一个SYSTEM_PROCESSES链表,其中所有进程的信息便存储在这个链表中。不过这里有几个注意的地方:
(1)ZwQuerySystemInformation需要调用两次,第一次调用时是为了获取存放SYSTEM_PROCESSES链表内存空间的大小,然后申请对应的内存空间,第二次将申请的内存空间作为参数就可以获取最后的链表;
(2)链表虽然都是连续存放在上面申请的内存空间中,但是每个进程节点所占用的大小不是确定的,这个看下面的SYSTEM_PROCESSES结构就可以知道。因此下个节点的位置为当前节点的pProcess->NextEntryDelta中。
(3)这种方法获取的信息有限,能获取进程的pid,进程名,但无法获取进程的完整路径。
关键代码如下:
#define SystemProcessesAndThreadsInformation 5
typedef struct _SYSTEM_THREADS {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientIs;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
ULONG ThreadState;
KWAIT_REASON WaitReason;
}SYSTEM_THREADS;
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; //windows 2000 only
struct _SYSTEM_THREADS Threads[1];
}SYSTEM_PROCESSES;
VOID GetExistedProcess()
{
SYSTEM_PROCESSES *pProcess;
PVOID buf;
ULONG n = 0;
ULONG num = 0;
ULONG i = 0;
NTSTATUS status;
CHAR packet[MAX_PKT_LEN] = {0};
ULONG sessionId = 0;
ANSI_STRING processName;
status = ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, &buf, n, &n );
if ( !NT_SUCCESS(status) )
{
buf = ExAllocatePool(NonPagedPool, n);
if ( NULL == buf )
{
return STATUS_UNSUCCESSFUL;
}
}
status = ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, buf, n, NULL );
{
if ( !NT_SUCCESS(status) )
{
return STATUS_UNSUCCESSFUL;
}
}
for ( pProcess = buf; NULL != pProcess && NULL != pProcess->NextEntryDelta; pProcess = (SYSTEM_PROCESSES*)((unsigned char*)pProcess + pProcess->NextEntryDelta) )
{
KdPrint(("process: pid = %d, process name = %ws\n", pProcess->ProcessId, pProcess->ProcessName.Buffer));
}
RtlFreeAnsiString(&processName);
}
ExFreePool(buf);
}
No comments:
Post a Comment