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_ENTRYpList=(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_ENTRYPLIST_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;
}

驱动中获取PsActiveProcessHead变量地址的五种方法相关推荐

  1. php获取ip几种方法区别,php获取客户端IP地址的几种方法

    php获取客户端IP地址的几种方法 阅读php获取客户端IP地址的几种方法, 1:来看看代码: echo "(1)浏览当前页面的用户的 IP 地址为:"; echo $_SERVE ...

  2. php获取客户端IP地址的几种方法(转)

    php获取客户端IP地址的几种方法方法一 <?php $iipp=$_SERVER["REMOTE_ADDR"]; echo $iipp; ?>方法二<?php ...

  3. php页面文件后缀名,PHP中获取文件扩展名的N种方法

    PHP中获取文件扩展名的N种方法 从网上收罗的,基本上就以下这几种方式: 第1种方法: function get_extension($file) { substr(strrchr($file, '. ...

  4. PHP中获取文件扩展名的N种方法

    PHP中获取文件扩展名的N种方法   从网上收罗的,基本上就以下这几种方式:      第1种方法:  function get_extension($file)  {  substr(strrchr ...

  5. JAVA中获取文件MD5值的四种方法

    JAVA中获取文件MD5值的四种方法其实都很类似,因为核心都是通过JAVA自带的MessageDigest类来实现.获取文件MD5值主要分为三个步骤,第一步获取文件的byte信息,第二步通过Messa ...

  6. 总结C++中取成员函数地址的几种方法

    这里, 我整理了4种C++中取成员函数地址的方法, 第1,2,4种整理于网上的方法, 第3种cdecl_cast是我自己想到的. 其中, 第4种(汇编)的方法不能在VC6上编译通过. 推荐使用第1,2 ...

  7. QT中获取选中的radioButton的两种方法

    QT中要获取radioButton组中被选中的那个按钮,可以采用两种如下两种办法进行: 方法一:采用对象名称进行获取 代码: 1 QRadioButton* pbtn = qobject_cast&l ...

  8. 在金蝶云星空中获取单据体信息的两种方法

    近日在学习星空产品的时候发现了两种获取单据体数据包方法,然后调试了一下,发现两种方法获取的信息都是一样的,特此记录一下. 第一种: Entity entity = this.View.BillBusi ...

  9. php获取访问者ip地址,PHP获取访问者IP地址的二种方法

    本节内容: PHP获取访问者IP地址 方法一:$_SERVER['HTTP_X_FORWARDED_FOR']来获取相应的地址 复制代码 代码示例: function get_onlineip() { ...

最新文章

  1. tomcat7修改内存 win_详解Windows下调整Tomcat启动参数的实现方法
  2. python操作Mysql基础
  3. 解决audio和video在手机端无法自动播放问题
  4. java可比较的和比较器的区别_Java中Compareable和Comparator两种比较器的区别
  5. 敏捷软件开发(Agile Software Development)简介之:什么是敏捷软件开发?
  6. npm打包前端项目太慢问题分析以及暂时解决方案
  7. DCASE 2013任务1(声学场景分类)参赛作品相关信息
  8. ajax请求相关问题
  9. Bootstrap 流式栅格系统
  10. import java文件,java 文件夹操作,java文件夹,import java.
  11. HDOJ-1272 小希的迷宫
  12. 英国云主机节点是欧美五大节点之一
  13. 用什么 软件测试无线频段,Wirelessmon无线频段与信号强度扫描工具软件使用技巧...
  14. word文档页码不连续怎么弄
  15. UE4 替换文件尝试解决 光照构建失败 Lighting build failed. Swarm failed to kick off
  16. 先将输入的一系列整数中的最小值与第一个数交换,然后将最大值与最后一个数交换,最后输出交换后的序列。
  17. idea列模式按列选取代码或按行选取代码快捷键
  18. kali-linux u盘便携性系统,暗组u盘怎么进入kali linux系统
  19. PHP 门面设计模式在laravel中的应用
  20. mysql8修改密码之后无法登陆_解决MySQL8.0安装第一次登陆修改密码时出现的问题...

热门文章

  1. 用Latex做介绍自己和团队科研的网页
  2. Visual Studio 2015 for Linux更好地支持Linux下的开发
  3. RedisTemplate
  4. 组件的高可用性 High Availability
  5. React Diff 算法
  6. c++11 字符串与int类型的转换
  7. 地球椭球体(Ellipsoid)、大地基准面(Datum)及地图投影(Projection)三者的基本概念
  8. 关于iOS7以后版本号企业公布问题
  9. 长城电脑或收购夏新电子笔记本业务
  10. ArcCore重构-Platform_Types.h实现辨析