内核级进程遍历
原理
windows中,每个进程都有一个属于自己的EPROCESS
结构,这个结构中包含了本程序的基本信息,并且数据中存在进程链表,通过该进程链表(双向链表)可以找到其他进程的EPROCESS
结构,所以可以借此遍历系统中的进程。
使用windbg
可以看到eprocess
的结构体,现摘录重要结构如下:
lkd> dt _eprocess -r1
nt!_EPROCESS
...
+0x084 UniqueProcessId : Ptr32 Void PID
+0x088 ActiveProcessLinks : _LIST_ENTRY 活动进程链表(双向链表)
+0x000 Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRY
...
+0x174 ImageFileName : [16] UChar //进程名
...
+0x1b0 Peb : Ptr32 _PEB //PEB,本节用不到
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 SpareBool : UChar
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA //指向模块结点表头
...
...
+0x258 Cookie : Uint4B
demo
用的vs2008sp1 on xp sp3,visual ddk。
其中工程选项中没有使用了visual studio,而部没有用ddk compiler,即使这样,用默认的结构去生成解决方案,还是无法加载。于是我全删掉,自己写,好在有ddk的sdk可以用vax智能提示。注意生成debug(chunk)版,否则debugview
无法显示输出。
#include "stdafx.h"
VOID OnUnload(IN PDRIVER_OBJECT pDriverObject)
{
KdPrint(("OnUnload called"));
}
NTSTATUS enum_services()
{
PEPROCESS pEprocess = NULL;
PEPROCESS pFirstEprocess = NULL;
ULONG ulProcessName = 0;
ULONG ulProcessId = 0;
pEprocess = PsGetCurrentProcess(); //get system process _eprocess_address
if (pEprocess == 0)
{
KdPrint(("PsGetcurrentProcess Error! \r\n"));
return STATUS_SUCCESS;
}
KdPrint(("pEprocess addr is:%08x\r\n",pEprocess));
pFirstEprocess = pEprocess;
//lkd> !process 0 0
//lkd> dt _eprocess xxxxxxxx
//+0x174 ImageFileName : [16] "smss.exe"
//+0x084 UniqueProcessId : 0x00000224 Void
//lkd> db 864bb0a8-0x88+0x174
//864bb194 73 6d 73 73 2e 65 78 65-00 00 00 00 00 00 00 00 smss.exe........ ascii
while (pEprocess )
{
ulProcessName = (ULONG)pEprocess+0x174;
ulProcessId = *(ULONG *) ((ULONG)pEprocess+0x84);
KdPrint(("PID=%d,process_name=%s",ulProcessId,ulProcessName));
// +0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x862669a8 - 0x865b76e8 ]
// +0x000 Flink : 0x862669a8 _LIST_ENTRY [ 0x863570a8 - 0x864bb0a8 ]
// +0x004 Blink : 0x865b76e8 _LIST_ENTRY [ 0x864bb0a8 - 0x8055b158 ]
pEprocess = (PEPROCESS)(*(ULONG*)((ULONG)pEprocess+0x88)-0x88); //pointer to the list ,not the eprocess_start,SO -0x88
//双向链表,到最末尾向指向头结点,表示结束。要么就是PID不大于0,这个不知道从哪里得来的
if (pEprocess == pFirstEprocess || ( *(LONG*)( (LONG)pEprocess+0x84 ) <= 0 ))
{
KdPrint(("enum over !\r\n"));
break;
}
}
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING registeryPath)
{
KdPrint(("Driver loaded"));
KdPrint(("just a test."));
pDriverObject->DriverUnload = OnUnload;
enum_services();
return STATUS_SUCCESS;
}
注意:
pEprocess = (PEPROCESS)(*(ULONG*)((ULONG)pEprocess+0x88)-0x88);
//pointer to the list ,not the eprocess_start,SO -0x88
- 不能看到两个0x88相减,就以为是0.因为一个前0x88要当指针取值,取完之后才减去0x88.(即取地址,得到结果,结果-0x88)。
- 和PEB中的
—ldr_data_table_entry
一样,链表指向的是下一个相同链表结构的地址,而不是下一个进程eprocess节点的头地址。所以需要-0x88。
DEBUG_VIEW输出:
00000001 0.00000000 OnUnload called
00000002 2.50107551 Driver loaded
00000003 2.50109267 just a test.
00000004 2.50110865 pEprocess addr is:865b7660
00000005 2.50112438 PID=4,process_name=System
00000006 2.50113988 PID=548,process_name=smss.exe
00000007 2.50115538 PID=612,process_name=csrss.exe
00000008 2.50117064 PID=636,process_name=winlogon.exe
00000009 2.50118613 PID=688,process_name=services.exe
00000010 2.50120139 PID=700,process_name=lsass.exe
00000011 2.50121689 PID=856,process_name=vmacthlp.exe
00000012 2.50123215 PID=868,process_name=svchost.exe
00000013 2.50124717 PID=952,process_name=svchost.exe
00000014 2.50126266 PID=1044,process_name=svchost.exe
00000015 2.50127792 PID=1100,process_name=svchost.exe
00000016 2.50129294 PID=1160,process_name=svchost.exe
00000017 2.50130844 PID=1416,process_name=spoolsv.exe
00000018 2.50132370 PID=1664,process_name=vmtoolsd.exe
00000019 2.50133944 PID=1956,process_name=explorer.exe
00000020 2.50135541 PID=496,process_name=vmtoolsd.exe
00000021 2.50137067 PID=536,process_name=ctfmon.exe
00000022 2.50138617 PID=1256,process_name=alg.exe
00000023 2.50140166 PID=1772,process_name=wscntfy.exe
00000024 2.50141716 PID=448,process_name=devenv.exe
00000025 2.50143218 PID=524,process_name=conime.exe
00000026 2.50144792 PID=184,process_name=Kernel Detectiv
00000027 2.50146341 PID=1284,process_name=windbg.exe
00000028 2.50147891 PID=1700,process_name=OSRLOADER.exe
00000029 2.50149441 PID=1880,process_name=Dbgview.exe
00000030 2.50150990 PID=428,process_name=mspdbsrv.exe
00000031 2.50152516 PID=1788,process_name=procexp.exe
00000032 2.50154066 PID=1656,process_name=wmiprvse.exe
00000033 2.50155592 PID=244,process_name=calc.exe
00000034 2.50157094 PID=1812,process_name=cmd.exe
00000035 2.50158644 PID=1588,process_name=notepad.exe
00000036 2.50160122 enum over !
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。