驱动中获取PsActiveProcessHead变量地址的五种方法也可以获取KdpDebuggerDataListHead
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
驱动中获取PsActiveProcessHead变量地址的五种方法也可以获取KdpDebuggerDataListHead的更多相关文章
- php获取客户端IP地址的几种方法(转)
[php] view plain copy php获取客户端IP地址的几种方法 方法一 <?php $iipp=$_SERVER["REMOTE_ADDR"]; echo $ ...
- 获取函数的地址(三种方法,分别是@,Addr,MethodAddress)
问题来源: http://www.cnblogs.com/del/archive/2008/07/30/1039045.html#1272783 在编译器看来, 重载函数根本就是完全不同的几个函数, ...
- 总结C++中取成员函数地址的几种方法
这里, 我整理了4种C++中取成员函数地址的方法, 第1,2,4种整理于网上的方法, 第3种cdecl_cast是我自己想到的. 其中, 第4种(汇编)的方法不能在VC6上编译通过. 推荐使用第1,2 ...
- 【转】总结C++中取成员函数地址的几种方法
转自:“http://www.cnblogs.com/nbsofer/p/get_member_function_address_cpp.html” 这里, 我整理了4种C++中取成员函数地址的方法, ...
- 让块元素在div中水平居中,并且垂直居中的五种方法
在写代码前,先做下准备工作,写两个div,设置下div的大小,把小的div放在大的div里面.可以给小的div设置下颜色,方便观看. 方法一:写一个伪元素,将它设置为行内块元素,高度与父元素相同,写一 ...
- C#程序读取MAC地址的五种方法(转)
public class GetMac { ///<summary> /// 根据截取ipconfig /all命令的输出流获取网卡Mac ///</summary> ///& ...
- 转载:(Mac)在bash和zsh配置环境变量path的几种方法
参考文献 老习惯,列出本文参考或引用或转载的文档和博客,致以崇高的敬意,感兴趣的可以去看看 1.http://postgresapp.com/ 2.http://postgresapp.com/doc ...
- html table表格导出excel的方法 html5 table导出Excel HTML用JS导出Excel的五种方法 html中table导出Excel 前端开发 将table内容导出到excel HTML table导出到Excel中的解决办法 js实现table导出Excel,保留table样式
先上代码 <script type="text/javascript" language="javascript"> var idTmr; ...
- windows下获取IP地址的两种方法
windows下获取IP地址的两种方法: 一种可以获取IPv4和IPv6,但是需要WSAStartup: 一种只能取到IPv4,但是不需要WSAStartup: 如下: 方法一:(可以获取IPv4和I ...
随机推荐
- Unity3d《Shader篇》漫反射
Unity3d<Shader篇>漫反射 Shader "Custom/Ambient" { Properties { _MainTex ("Base (RGB ...
- SolrCloud环境配置
Solr是一个企业级搜索服务器,对外提供Web-Service接口,用户可以通过http请求,向搜索引擎提交xml或者json格式的数据,生成索引:然后可以通过http get请求查找,获取返回的xm ...
- nyoj756_重建二叉树_先序遍历
重建二叉树 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 题目很简单,给你一棵二叉树的后序和中序序列,求出它的前序序列(So easy!). 输入 输入有多组数 ...
- 如何将.il、.res文件封装成dll文件
将你的.il..res文件保存在你的硬盘上,如下图: 我存放的路径在E盘的test文件夹中,我们开始封装了咯.进入DOS命令,如下图: 我们通过DOS命令先进入.il..res文件目录,如下图: 然后 ...
- JavaScript数组排序
JavaScript的sort方法排序是有问题的,我们可以给sort方法传一个参数 function Compare(value1, value2) { //数字排序的函数参数 if (value1 ...
- javaWeb四大域对象
servletContext Request HttpSession pageContext 详细参考:http://www.tuicool.com/articles/NJfyMrn
- Android WebView 支持H5的定位Js
//启用数据库 webSettings.setDatabaseEnabled(true); String dir = this.getApplicationContext().getDir(" ...
- 浅谈 switch和if
1.所有的switch 都可以用if 替换,但所有的if不一定能被switch替换 2.:switch case直接跳到对应的case值里面执行相应代码.而if语句会执行一条一条判断语句,直到匹配到对 ...
- Android Tab -- 使用ViewPager、Fragment、FragmentPagerAdapter来实现
原文地址:http://blog.csdn.net/crazy1235/article/details/42678877 效果:滑动切换:点击标签切换. 代码:https://github.com/l ...
- Clr Via C#读书笔记---I/O限制的异步操作
widows如何执行I/O操作 构造调用一个FileStream对象打开一个磁盘文件-----FileStream.Read方法从文件中读取数据(此时线程从托管代码转为本地/用户模式代码)- ...