动网论坛,站长建站首选,国内使用量最多的论坛软件 动网论坛官方技术讨论区 站长工具 申请属于您自己的免费论坛
首页 | 新闻资讯 | 网站运营 | 网络编程 | 数据库 | 服务器 | 网页设计 | 图像媒体 | 网络应用 | 搜索优化 | 资源下载 | 动网主机 | DVBOX
    本站内  互联网 ASP论坛  ASP.Net论坛  PHP论坛
   安全 → 阅读文章

 安全稳定的实现进线程监控

作者来源: 
阅读 数 560 人次 , 2006-4-25 9:50:00 

  

用PsSetCreateProcessNotifyRoutine,PsSetCreateThreadNotifyRoutine来进行进程线程监控我想大家已经都非常熟练了.sinister在<<编写进程/线程监视器>>一文中已经实现得很好了.前一段时间看到网上有人在研究监视远线程的文章,比较有意思.就写代码玩一玩.这之中就出现了一些问题.比方说直接用sinister的代码的话,是不能动态卸载的,因为他在安装了进线程监视函数后没有进行清除动作,造成在动态卸载时蓝屏,BUGCHECK为0x000000ce,错误码为:DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS.很显然,在驱动退出后,一些进线程操作仍然在访问原来的地址,造成出错.在XP后,微软给出了一个函数PsRemoveCreateThreadNotifyRoutine用来清除线程监视函数(清除进程监视的就是PsSetCreateProcessNotifyRoutine).我一直奇怪ICESWORD在2000中是怎么做到进线程监视的.后来才发现,在运行icesword后释放出一个detport.sys文件,然后一直在系统中存在着没有卸载掉.只是把它隐藏了而已^_^.这不是个好消息,难道我为了测试一个驱动,测试一次就得重启一次吗?呵呵,肯定不是啊,所以想办法搞定它.

我们来看一下进线程监视在底层是如何实现的,在win2000源代码中先找到创建线程的函数实现:
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// \win2k\private\ntos\ps\create.h
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS
PspCreateThread(
...
...
)
{
...
if (PspCreateProcessNotifyRoutineCount != 0) { //首先调用进程监控函数
ULONG i;
for (i=0; i<PSP_MAX_CREATE_PROCESS_NOTIFY; i++) {
if (PspCreateProcessNotifyRoutine[i] != NULL) {
(*PspCreateProcessNotifyRoutine[i])( Process->InheritedFromUniqueProcessId,
Process->UniqueProcessId,
TRUE
);
}
}
}

}
...
...
if (PspCreateThreadNotifyRoutineCount != 0) {
ULONG i;

for (i=0; i<PSP_MAX_CREATE_THREAD_NOTIFY; i++) { //再调用线程监控函数
if (PspCreateThreadNotifyRoutine[i] != NULL) {
(*PspCreateThreadNotifyRoutine[i])( Thread->Cid.UniqueProcess,
Thread->Cid.UniqueThread,
TRUE
);
}
}
}
...
...
}

从上面可以看到,在每创建一个线程后会调用PspCreateProcessNotifyRoutine[i]地址指向的函数.而PsSetCreateThreadNotifyRoutine的作用就是将PspCreateThreadNotifyRoutine[i]数组设置值,该值就是监视函数的地址.

NTSTATUS
PsSetCreateThreadNotifyRoutine(
IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
{
ULONG i;
NTSTATUS Status;

Status = STATUS_INSUFFICIENT_RESOURCES;
for (i = 0; i < PSP_MAX_CREATE_THREAD_NOTIFY; i += 1) {
if (PspCreateThreadNotifyRoutine[i] == NULL) {
PspCreateThreadNotifyRoutine[i] = NotifyRoutine;
PspCreateThreadNotifyRoutineCount += 1;
Status = STATUS_SUCCESS;
break;
}
}

return Status;
}
上面的一些结构如下:
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// \win2k\private\ntos\ps\psp.h
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
#define PSP_MAX_CREATE_THREAD_NOTIFY 8 //最大监视数目

ULONG PspCreateThreadNotifyRoutineCount; //用来记数
PCREATE_THREAD_NOTIFY_ROUTINE PspCreateThreadNotifyRoutine[ PSP_MAX_CREATE_THREAD_NOTIFY ]; //函数地址数组

而PCREATE_THREAD_NOTIFY_ROUTINE定义如下:
typedef
VOID
(*PCREATE_THREAD_NOTIFY_ROUTINE)(
IN HANDLE ProcessId,
IN HANDLE ThreadId,
IN BOOLEAN Create
);

相应的,进程的结构也是一样的.
通过上面,我们可以看到,只要我们找出该函数数组地址,在我们退出驱动时先将其全部清零,清零的大小为PSP_MAX_CREATE_THREAD_NOTIFY,
这样的话下一次的进线程操作就不会调用这个函数指针了.也就让系统回到正常,我们再通过PsSetCreateProcessNotifyRoutine来验证一下:

NTSTATUS
PsSetCreateProcessNotifyRoutine(
IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
IN BOOLEAN Remove
)
{
ULONG i;

for (i=0; i < PSP_MAX_CREATE_PROCESS_NOTIFY; i++) {
if (Remove) {
if (PspCreateProcessNotifyRoutine[i] == NotifyRoutine) { //清除时就是简单的赋植操作
PspCreateProcessNotifyRoutine[i] = NULL;
PspCreateProcessNotifyRoutineCount -= 1; //将计数器减一
return STATUS_SUCCESS;
}
} else {
if (PspCreateProcessNotifyRoutine[i] == NULL) { //设置时也是简单的赋值操作
PspCreateProcessNotifyRoutine[i] = NotifyRoutine;
PspCreateProcessNotifyRoutineCount += 1; //将计数器加一
return STATUS_SUCCESS;
}
}
}

return Remove ? STATUS_PROCEDURE_NOT_FOUND : STATUS_INVALID_PARAMETER;
}

  
 本文Tags安全  
 收藏本文  打印本文  论坛讨论  关闭窗口
· 上一篇:安全?Windows XP五秒钟内即可被病毒感染
· 下一篇:病毒防护: 焚烧木马 彻底教你防杀木马
· 入侵检测术语全接触
· 用 SSL 保护应用程序
· 安装配置SSH(Secure Shell)
· 浅析传统网络防火墙的五大不足之处
· 诺基亚手机杀毒软件使用指南


关于本站 | 联系我们 | 业务合作 | 客户案例 | 诚聘英才 | 广告合作 | 收藏本站
海口动网先锋网络科技有限公司版权所有
Copyright © 2000 - 2006 Cndw.Com
中华人民共和国电信与信息服务业务经营许可证编号 琼 ICP 020077