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

上传人:b****6 文档编号:7751183 上传时间:2023-01-26 格式:DOCX 页数:21 大小:20.69KB
下载 相关 举报
安全稳定的实现进线程监控.docx_第1页
第1页 / 共21页
安全稳定的实现进线程监控.docx_第2页
第2页 / 共21页
安全稳定的实现进线程监控.docx_第3页
第3页 / 共21页
安全稳定的实现进线程监控.docx_第4页
第4页 / 共21页
安全稳定的实现进线程监控.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

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

《安全稳定的实现进线程监控.docx》由会员分享,可在线阅读,更多相关《安全稳定的实现进线程监控.docx(21页珍藏版)》请在冰豆网上搜索。

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

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

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

用PsSetCreateProcessNotifyRoutine,PsSetCreateThreadNotifyRoutine来进行进程线程监控我想大家已经都非常熟练了。

前一段时间看到网上有人在研究监视远线程的文章,比较有意思。

就写代码玩一玩。

这之中就出现了一些问题,比方说直接用sinister的代码的话,是不能动态卸载的,因为他在安装了进线程监视函数后没有进行清除动作,造成在动态卸载时蓝屏。

BUGCHECK为0x000000ce,错误码为:

DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS

很显然,在驱动退出后,一些进线程操作仍然在访问原来的地址,造成出错。

在XP后,微软给出了一个函数PsRemoveCreateThreadNotifyRoutine用来清除线程监视函数(清除进程监视的就是PsSetCreateProcessNotifyRoutine)。

我一直奇怪ICESWORD在Windows2000中是怎么做到进线程监视的。

后来才发现,在运行icesword后释放出一个detport.sys文件,然后一直在系统中存在着没有卸载掉。

只是把它隐藏了而已。

这不是个好消息,难道我为了测试一个驱动,测试一次就得重启一次吗?

呵呵,肯定不是啊,所以想办法搞定它。

我们来看一下进线程监视在底层是如何实现的,在Windows2000源代码中先找到创建线程的函数实现:

//////////////////////////////////////////////////////////////////////////////////////////

//

//\win2k\private\ntos\ps\create.h

//

//////////////////////////////////////////////////////////////////////////////////////////

NTSTATUS

PspCreateThread(

...

...

{

...

if(PspCreateProcessNotifyRoutineCount!

=0){//首先调用进程监控函数

ULONGi;

for(i=0;iInheritedFromUniqueProcessId,

Process->UniqueProcessId,

TRUE

);

}

}

}

}

...

...

if(PspCreateThreadNotifyRoutineCount!

=0){

ULONGi;

for(i=0;iCid.UniqueProcess,

Thread->Cid.UniqueThread,

TRUE

);

}

}

}

...

...

}

从上面可以看到,在每创建一个线程后会调用PspCreateProcessNotifyRoutine[i]地址指向的函数。

而PsSetCreateThreadNotifyRoutine的作用就是将PspCreateThreadNotifyRoutine[i]数组设置值,该值就是监视函数的地址。

NTSTATUS

PsSetCreateThreadNotifyRoutine(

INPCREATE_THREAD_NOTIFY_ROUTINENotifyRoutine

{

ULONGi;

NTSTATUSStatus;

Status=STATUS_INSUFFICIENT_RESOURCES;

for(i=0;i

上面的一些结构如下:

//////////////////////////////////////////////////////////////////////////////////////////

//

//\win2k\private\ntos\ps\psp.h

//

//////////////////////////////////////////////////////////////////////////////////////////

#definePSP_MAX_CREATE_THREAD_NOTIFY8//最大监视数目

ULONGPspCreateThreadNotifyRoutineCount;//用来记数

PCREATE_THREAD_NOTIFY_ROUTINEPspCreateThreadNotifyRoutine[

PSP_MAX_CREATE_THREAD_NOTIFY];//函数地址数组

而PCREATE_THREAD_NOTIFY_ROUTINE定义如下:

typedef

VOID

(*PCREATE_THREAD_NOTIFY_ROUTINE)(

INHANDLEProcessId,

INHANDLEThreadId,

INBOOLEANCreate

);

相应的,进程的结构也是一样的。

通过上面,我们可以看到,只要我们找出该函数数组地址,在我们退出驱动时先将其全部清零,清零的大小为PSP_MAX_CREATE_THREAD_NOTIFY。

这样的话下一次的进线程操作就不会调用这个函数指针了,也就让系统回到正常。

我们再通过PsSetCreateProcessNotifyRoutine来验证一下:

NTSTATUS

PsSetCreateProcessNotifyRoutine(

INPCREATE_PROCESS_NOTIFY_ROUTINENotifyRoutine,

INBOOLEANRemove

{

ULONGi;

for(i=0;i

好了,方法已经知道了,只要找出地址,我们就能够“全身而退”了。

看一下Windows2003下面的PsRemoveCreateThreadNotifyRoutine实现:

lkd>uPsRemoveCreateThreadNotifyRoutinel20

nt!

PsRemoveCreateThreadNotifyRoutine:

80651d7b53pushebx

80651d7c56pushesi

80651d7d57pushedi

80651d7e33dbxorebx,ebx

80651d80bf400f5780movedi,0x80570f40//起始地址

80651d8557pushedi

80651d86e8a7500100callnt!

ExWaitForRundownProtectionRelease+0x5cf(80666e32)

80651d8b8bf0movesi,eax

80651d8d85f6testesi,esi

80651d8f7420jznt!

PsRemoveCreateThreadNotifyRoutine+0x36(80651db1)

80651d9156pushesi

80651d92e8ba1bffffcallnt!

IoReportTargetDeviceChange+0x7aa0(80643951)

80651d973b442410cmpeax,[esp+0x10]

80651d9b750djnznt!

PsRemoveCreateThreadNotifyRoutine+0x2f(80651daa)

80651d9d56pushesi

80651d9e6a00push0x0

80651da057pushedi

80651da1e8c54f0100callnt!

ExWaitForRundownProtectionRelease+0x508(80666d6b)

80651da684c0testal,al

80651da8751bjnznt!

PsRemoveCreateThreadNotifyRoutine+0x4a(80651dc5)

80651daa56pushesi

80651dab57pushedi

80651dace892510100callnt!

ExWaitForRundownProtectionRelease+0x6e0(80666f43)

80651db143incebx

80651db283c704addedi,0x4

80651db583fb08cmpebx,0x8//看是否到了最大数(8)

80651db872cbjbnt!

PsRemoveCreateThreadNotifyRoutine+0xa(80651d85)

80651dbab87a0000c0moveax,0xc000007a

80651dbf5fpopedi

80651dc05epopesi

80651dc15bpopebx

80651dc2c20400ret0x4

lkd>dd0x80570f40//设置了监视函数后

80570f40e316e557000000000000000000000000

.............................

lkd>dd0x80570f40//清除了监视函数后

80570f4000000000000000000000000000000000

哈哈,下面是实现代码,代码中实现了进线的的监视,并且实现了远线程的监视:

Drivers.c

//////////////////////////////////////////////////////////////////////////////////////////

//

//MadeByZwelL

#include“ntddk.h”

#include“windef.h”

#include“define.h”

#defineSYSNAME“System”

#defineVERSIONLEN100

constWCHARdevLink[]=L”\\?

?

\\MyEvent”;

constWCHARdevName[]=L”\\Device\\MyEvent”;

UNICODE_STRINGdevNameUnicd;

UNICODE_STRINGdevLinkUnicd;

PVOIDgpEventObject=NULL;//与应用程序通信的Event对象

ULONGProcessNameOffset=0;

PVOIDoutBuf[255];

BOOLg_bMainThread;

ULONGg_dwParentId;

CHECKLISTCheckList;

ULONGBuildNumber;//系统版本号

ULONGSYSTEMID;//System进程的ID

PWCHARVersion[VERSIONLEN];

NTSTATUSPsLookupProcessByProcessId(INULONGulProcId,OUTPEPROCESS*pEProcess);

ULONGGetProcessNameOffset()

{

PEPROCESScurproc;

inti;

curproc=PsGetCurrentProcess();

for(i=0;iData,valueInfoP->DataLength);

ReturnValue=1;

}

if(!

valueInfoP);

ExFreePool(valueInfoP);

ZwClose(KeyHandle);

returnReturnValue;

}

VOIDMyRemoveCraeteThreadNotifyRoutine(

INPCREATE_THREAD_NOTIFY_ROUTINENotifyRoutine

{

//PsRemoveCreateThreadNotifyRoutine(ThreadCreateMon);

PVOIDptr=NULL;

if(BuildNumber==2195)//Windows2000Sp4,2195

//低于sp4的我没有调试

{

ptr=0x80484520;

}

elseif(BuildNumber==2600)

{

if(wcscmp(Version,L”ServicePack1”)==0)//WindowsXpSp1,2600

ptr=0x8054efc0;

elseif(wcscmp(Version,L”ServicePack2”)==0)//WindowsXpSp2,2600

ptr=0x80561d20;

}

elseif(BuildNumber==3790)//Windows2003server,3790

{

ptr=0x80570f40;

}

if(ptr!

=NULL)

memset(ptr,0,sizeof(ULONG)*8);

}

VOIDThreadCreateMon(INHANDLEPId,INHANDLETId,INBOOLEANbCreate)

{

PEPROCESSEProcess,PEProcess;

NTSTATUSstatus;

HANDLEdwParentPID;

status=PsLookupProcessByProcessId((ULONG)PId,&EProcess);

if(!

NT_SUCCESS(status))

{

DbgPrint(“PsLookupProcessByProcessId()\n”);

return;

}

if(bCreate)

{

dwParentPID=PsGetCurrentProcessId();

status=PsLookupProcessByProcessId(

(ULONG)dwParentPID,

&PEProcess);

if(!

NT_SUCCESS(status))

{

DbgPrint(“PsLookupProcessByProcessId()\n”);

return;

}

if(PId==4)//System进程创建的东东我们不管

//在2000下是0,在XP后是4

return;

if((g_bMainThread==TRUE)

&&(g_dwParentId!

=dwParentPID)

&&(dwParentPID!

=PId)

{

g_bMainThread=FALSE;

sprintf(outBuf,“==============================“

“RemoteThread:

“==============================“

“\nT:

%18s%9d%9d%25s%9d\n”

“======================================“

“======================================\n”,

(char*)((char*)EProcess+ProcessNameOffset),

PId,TId,

(char*)((char*)PEProcess+ProcessNameOffset),dwParentPID);

if(gpEventObject!

=NULL)

KeSetEvent((PRKEVENT)gpEventObject,0,FALSE);

}

if(CheckList.ONLYSHOWREMOTETHREAD)//只显示远线程

return;

DbgPrint(“T:

%18s%9d%9d%25s%9d\n”,

(char*)((char*)EProcess+ProcessNameOffset),

PId,TId,

(char*)((char*)PEProcess+ProcessNameOffset),dwParentPID);

sprintf(outBuf,“T:

%18s%9d%9d%25s%9d\n”,

(char*)((char*)EProcess+ProcessNameOffset),

PId,TId,

(char*)((char*)PEProcess+ProcessNameOffset),dwParentPID);

if(gpEventObject!

=NULL)

KeSetEvent((PRKEVENT)gpEventObject,0,FALSE);

}

elseif(CheckList.SHOWTERMINATETHREAD)

{

DbgPrint(“TERMINATED==THREADID:

%d\n”,TId);

sprintf(outBuf,”TERMINATED==THREADID:

%d\n”,TId);

if(gpEventObject!

=NULL)

KeSetEvent((PRKEVENT)gpEventObject,0,FALSE);

}

}

VOIDProcessCreateMon(HANDLEhParentId,HANDLEPId,BOOLEANbCreate)

{

PEPROCESSEProcess,PProcess;

NTSTATUSstatus;

HANDLETId;

g_dwParentId=hParentId;

status=PsLookupProcessByProcessId((ULONG)PId,&EProcess);

if(!

NT_SUCCESS(status))

{

DbgPrint(“PsLookupProcessByProcessId()\n”);

return;

}

status=PsLookupProcessByProcessId((ULONG)hParentId,&PProcess);

if(!

NT_SUCCESS(status))

{

DbgPrint(“PsLookupProcessByProcessId()\n”);

return;

}

if(bCreate)

{

g_bMainThread=TRUE;

DbgPrint(“P:

%18s%9d%9d%25s%9d\n”,

(char*)((char*)EProcess+ProcessNameOffset),

PId,PsGetCurrentThreadId(),

(char*)((char*)PProcess+ProcessNameOffset),

hParentId

);

sprintf(outBuf,“P:

%18s%9d%9d%25s%9d\n”,

(char*)((char*)EProcess+ProcessNameOffset),

PId,PsGetCurrentThreadId(),

(char*)((char*)PProcess+ProcessNameOffset),

hParentId

);

if(gpEventObject!

=NULL)

KeSetEvent((PRKEVENT)gpEventObject,0,FALSE);

}

elseif(CheckList.SHOWTERMINATEPROCESS)

{

DbgPrint(“TERMINATED==PROCESSID:

%d\n”,PId);

sprintf(outBuf,”TERMINATED==PROCESSID:

%d\n”,PId);

if(gpEventObject!

=NULL)

KeSetEvent((PRKEVENT)gpEventObject,0,FALSE);

}

}

NTSTATUSOnUnload(INPDRIVER_OBJECTpDriverObject)

{

NTSTATUSstatus;

DbgPrint(“OnUnloadcalled\n”);

if(gpEventObject)

ObDereferenceObject(gpEventObject);

PsSetCreateProcessNotifyRoutine(ProcessCreateMon,TRUE);

MyRemoveCraeteThreadNotifyRoutine(ThreadCreateMon);

if(pDriverObject->DeviceObject!

=NULL)

{

status=IoDeleteSymbolicLink(&devLinkUnicd);

if(!

NT_SUCCESS(status))

{

DbgPrint((“IoDeleteSymbolicLink()failed\n”));

returnstatus;

}

IoDeleteDevice(pDriverObject->DeviceObject);

}

returnSTATUS_SUCCESS;

}

NTSTATUSDeviceIoControlDispatch(

INPDEVICE_OBJECTDeviceObject,

INPIRPpIrp

{

PIO_STACK_LOCATIONirpStack;

NTSTATUSstatus;

PVOIDinputBuffer;

ULONGinputLength;

PVOIDoutputBuffer;

ULONGoutputLength;

OBJECT_HANDLE_INFORMATIONobjHandleInfo;

status=STATUS_SUCCESS;

//取出IOCTL请求代码

irpStack=IoGetCurrentIrpStackLocation(pIrp);

switch(irpStack->MajorFunction)

{

caseIRP_MJ_CREATE:

DbgPrint(“CallIRP_MJ_CREATE\n”);

break;

caseIRP_MJ_CLOSE:

DbgPrint(“CallIRP_MJ_CLOSE\n”);

break;

caseIRP_MJ_DEVICE_CONTROL:

DbgPrint(“IRP_MJ_DEVICE_CONTROL\n”);

inpu

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 工作总结汇报

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1