PsActiveProcessHead的定义:
在windows系统中,所有的活动进程都是连在一起的,构成一个双链表,表头是全局变量PsActiveProcessHead,当一个进程被创建时,其ActiveProcessList域将被作为节点加入到此链表中;当进程被删除时,则从此链表中移除,如果windows需要枚举所有的进程,直接操纵此链表即可。
方法一:从KdInitSystem函数地址处硬编码搜索
方法二:从System进程(pid=4)的PEPROCESS地址获取
方法三:从ntoskrnl.exe的导出变量PsInitialSystemProcess中获取
方法四:从KPCR中获取
方法五:调用NtSystemDebugControl函数获取
注:操作系统 Windows XP SP3
方法一:
系统内核变量KdDebuggerDataBlock是一个KDDEBUGGER_DATA64类型的结构体,结构成员PsActiveProcessHead正是我们所找的地址。可在WinDDK的\inc\api\WDBGEXTS.H文件中查看到此结构的定义。
KdInitSystem函数中引用了KdDebuggerDataBlock,而ntoskrnl.exe的导出函数KdEnableDebugger调用了KdInitSystem函数。
代码:
ULONG FindPsActiveProcessHead1() { //1.从KdEnableDebugger地址找到KdInitSystem地址 //nt!KdEnableDebugger 804f7810 //804f7837 6a00 push 0 //804f7839 6a00 push 0 //804f783b c605ecab558001 mov byte ptr [nt!PoHiberInProgress (8055abec)],1 //804f7842 e8f7951600 call nt!KdInitSystem (80660e3e) //804f7847 e8649a1600 call nt!KdpRestoreAllBreakpoints (806612b0) ULONG i; PCALL_CODE pCall; PUCHAR pKdInitSystem=NULL; PUCHAR p=(PUCHAR)GetExportFuncAddress(L"KdEnableDebugger"); KdPrint(("KdEnableDebugger地址=%x\n",p)); if (!p) { KdPrint(("获取KdEnableDebugger地址失败\n")); return 0; } for (i=0;i<100;i++,p++) { if ((*p==0x6a)&& (*(p+1)==0x00)&& (*(p+2)==0x6a)&& (*(p+3)==0x00)&& (*(p+4)==0xc6)&& (*(p+5)==0x05)&& (*(p+0xb)==0xe8)&& (*(p+0x10)==0xe8) ) { pCall=(PCALL_CODE)(p+0xb); pKdInitSystem=p+0xb+pCall->address+5; KdPrint(("KdInitSystem地址=%x\n",pKdInitSystem)); break; } } if (!pKdInitSystem) { KdPrint(("获取KdInitSystem地址失败\n")); return 0; } //2.从KdInitSystem地址找到KdDebuggerDataBlock地址 //nt!KdInitSystem 80660e3e //80660e8e 6890020000 push 290h //80660e93 68606b5480 push offset nt!KdDebuggerDataBlock (80546b60) //80660e98 be74926780 mov esi,offset nt!KdpDebuggerDataListHead (80679274) p=pKdInitSystem; for (i=0;i<100;i++,p++) { if ((*p==0x68)&& (*(p+5)==0x68)&& (*(p+0xA)==0xbe)) { pCall=(PCALL_CODE)(p+5); KdPrint(("KdDebuggerDataBlock地址=%x\n",pCall->address)); KdPrint(("PsActiveProcessHead地址=%x\n",((PKDDEBUGGER_DATA64)pCall->address)->PsActiveProcessHead)); return ((PKDDEBUGGER_DATA64)pCall->address)->PsActiveProcessHead; } } KdPrint(("获取KdDebuggerDataBlock地址失败\n")); return 0; }
方法二:PsActiveProcessHead是活动进程链表头,理论上是第二个进程的EPROCESS结构成员ActiveProcessLinks的Blink,最后一个进程的EPROCESS结构成员ActiveProcessLinks的Flink。第二个进程即System进程,进程ID等于4。
代码:
NTSTATUS FindPsActiveProcessHead(ULONG *pPsActiveProcessHead) { PEPROCESS process; PLIST_ENTRY pList=NULL; NTSTATUS status=PsLookupProcessByProcessId((HANDLE)4,&process); if (!NT_SUCCESS(status)) { KdPrint(("获取process失败\n")); return status; } //xp _EPROCESS +0x088 ActiveProcessLinks : _LIST_ENTRY pList=(PLIST_ENTRY)((PUCHAR)process+0x88); KdPrint(("PsActiveProcessHead地址=%x\n",pList->Blink)); *pPsActiveProcessHead=(ULONG)pList->Blink; ObDereferenceObject(process); return status; }
方法三:ntoskrnl.exe导出了一个类型为PEPROCESS结构的变量PsInitialSystemProcess,它指向system进程(PID=4)的EPROCESS。这个方法与上一个方法类似。使用PsInitialSystemProcess在WinDDK中编译的话有链接ntoskrnl.lib。
代码:
ULONG FindPsActiveProcessHead3() { ULONG addr=*(PULONG)PsInitialSystemProcess; //xp _EPROCESS +0x088 ActiveProcessLinks : _LIST_ENTRY PLIST_ENTRY pList=(PLIST_ENTRY)(addr+0x88); KdPrint(("PsActiveProcessHead地址=%x\n",pList->Blink)); return (ULONG)pList->Blink; }
方法四:每个CPU都有个KPCR结构,第一个KPCR结构的地址是固定的0xffdff000。KPCR结构偏移0x034位置的结构成员KdVersionBlock是一个DBGKD_GET_VERSION64类型的指针。此结构同样在WDBGEXTS.H中有定义。DBGKD_GET_VERSION64结构成员DebuggerDataList其实是KdpDebuggerDataListHead。而KdpDebuggerDataListHead.Flink=KdpDebuggerDataListHead.Blink=KdDebuggerDataBlock。
代码:
ULONG FindPsActiveProcessHead4() { PLIST_ENTRY pList; PKDDEBUGGER_DATA64 pKdDebuggerData; PDBGKD_GET_VERSION64 pKdVersionBlock=(PDBGKD_GET_VERSION64)(*(PULONG)(0xffdff000+0x34)); KdPrint(("获取到DebuggerDataList地址=%x\n",pKdVersionBlock->DebuggerDataList)); pList=(PLIST_ENTRY)pKdVersionBlock->DebuggerDataList; KdPrint(("pList->Flink=%x,pList->Blink地址=%x\n",pList->Flink,pList->Blink)); pKdDebuggerData=(PKDDEBUGGER_DATA64)pList->Flink; KdPrint(("PsActiveProcessHead地址=%x\n",pKdDebuggerData->PsActiveProcessHead)); return pKdDebuggerData->PsActiveProcessHead; }
方法五:调用SSDT表中的NtSystemDebugControl函数。
代码:
ULONG FindPsActiveProcessHead5() { PLIST_ENTRY pList; DBGKD_GET_VERSION64 KdVersionBlock; PKDDEBUGGER_DATA64 pKdDebuggerData; ZwSystemDebugControl NtSystemDebugControl; NtSystemDebugControl=(ZwSystemDebugControl)GetSSDTAddrFromIndex(255); KdPrint(("NtSystemDebugControl函数地址=%x\n",NtSystemDebugControl)); NtSystemDebugControl(SysDbgSysGetVersion,NULL,0,&KdVersionBlock,sizeof(DBGKD_GET_VERSION64),NULL); KdPrint(("DebuggerDataList=%x\n",KdVersionBlock.DebuggerDataList)); pList=(PLIST_ENTRY)KdVersionBlock.DebuggerDataList; KdPrint(("获取到KdDebuggerDataBlock地址=%x\n",pList->Flink)); pKdDebuggerData=(PKDDEBUGGER_DATA64)pList->Flink; KdPrint(("PsActiveProcessHead地址=%x\n",pKdDebuggerData->PsActiveProcessHead)); return pKdDebuggerData->PsActiveProcessHead; }
jpg 改 rar