首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>系统安全>文章内容
安全稳定的实现进线程监控
来源:xfocus.net 作者:ZwelL 发布时间:2005-03-25  

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

作者:ZwelL

用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;
}

好了,方法已经知道了,只要找出地址,我们就能够"全身而退"了.看一下windows2003下面的PsRemoveCreateThreadNotifyRoutine实现:
lkd> u PsRemoveCreateThreadNotifyRoutine l 20
nt!PsRemoveCreateThreadNotifyRoutine:
80651d7b 53 push ebx
80651d7c 56 push esi
80651d7d 57 push edi
80651d7e 33db xor ebx,ebx
80651d80 bf400f5780 mov edi,0x80570f40 //起始地址
80651d85 57 push edi
80651d86 e8a7500100 call nt!ExWaitForRundownProtectionRelease+0x5cf (80666e32)
80651d8b 8bf0 mov esi,eax
80651d8d 85f6 test esi,esi
80651d8f 7420 jz nt!PsRemoveCreateThreadNotifyRoutine+0x36 (80651db1)
80651d91 56 push esi
80651d92 e8ba1bffff call nt!IoReportTargetDeviceChange+0x7aa0 (80643951)
80651d97 3b442410 cmp eax,[esp+0x10]
80651d9b 750d jnz nt!PsRemoveCreateThreadNotifyRoutine+0x2f (80651daa)
80651d9d 56 push esi
80651d9e 6a00 push 0x0
80651da0 57 push edi
80651da1 e8c54f0100 call nt!ExWaitForRundownProtectionRelease+0x508 (80666d6b)
80651da6 84c0 test al,al
80651da8 751b jnz nt!PsRemoveCreateThreadNotifyRoutine+0x4a (80651dc5)
80651daa 56 push esi
80651dab 57 push edi
80651dac e892510100 call nt!ExWaitForRundownProtectionRelease+0x6e0 (80666f43)
80651db1 43 inc ebx
80651db2 83c704 add edi,0x4
80651db5 83fb08 cmp ebx,0x8 //看是否到了最大数(8)
80651db8 72cb jb nt!PsRemoveCreateThreadNotifyRoutine+0xa (80651d85)
80651dba b87a0000c0 mov eax,0xc000007a
80651dbf 5f pop edi
80651dc0 5e pop esi
80651dc1 5b pop ebx
80651dc2 c20400 ret 0x4

lkd> dd 0x80570f40 //设置了监视函数后
80570f40 e316e557 00000000 00000000 00000000
.............................

lkd> dd 0x80570f40 //清除了监视函数后
80570f40 00000000 00000000 00000000 00000000

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

Drivers.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Made By ZwelL

#include "ntddk.h"
#include "windef.h"
#include "define.h"

#define SYSNAME "System"
#define VERSIONLEN 100

const WCHAR devLink[] = L"\\??\\MyEvent";
const WCHAR devName[] = L"\\Device\\MyEvent";
UNICODE_STRING devNameUnicd;
UNICODE_STRING devLinkUnicd;
PVOID gpEventObject = NULL; // 与应用程序通信的 Event 对象
ULONG ProcessNameOffset =0;
PVOID outBuf[255];
BOOL g_bMainThread;
ULONG g_dwParentId;
CHECKLIST CheckList;
ULONG BuildNumber; //系统版本号
ULONG SYSTEMID; //System进程的ID
PWCHAR Version[VERSIONLEN];

NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId, OUT PEPROCESS * pEProcess);

ULONG GetProcessNameOffset()
{
PEPROCESS curproc;
int i;

curproc = PsGetCurrentProcess();

for( i = 0; i < 3*PAGE_SIZE; i++ )
{
if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) ))
{
return i;
}
}

return 0;
}

NTSTATUS GetRegValue(PCWSTR RegPath,PCWSTR ValueName,PWCHAR Value)
{
int ReturnValue = 0;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE KeyHandle;
PKEY_VALUE_PARTIAL_INFORMATION valueInfoP;
ULONG valueInfoLength,returnLength;
UNICODE_STRING UnicodeRegPath;
UNICODE_STRING UnicodeValueName;

RtlInitUnicodeString(&UnicodeRegPath, RegPath);
RtlInitUnicodeString(&UnicodeValueName, ValueName);

InitializeObjectAttributes(&ObjectAttributes,
&UnicodeRegPath,
OBJ_CASE_INSENSITIVE, // Flags
NULL, // Root directory
NULL); // Security descriptor

Status = ZwOpenKey(&KeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (Status != STATUS_SUCCESS)
{
DbgPrint("ZwOpenKey Wrong\n");
return 0;
}

valueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)+VERSIONLEN;
valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool
(NonPagedPool, valueInfoLength);
Status = ZwQueryValueKey(KeyHandle,
&UnicodeValueName,
KeyValuePartialInformation,
valueInfoP,
valueInfoLength,
&returnLength);

if (!NT_SUCCESS(Status))
{
DbgPrint("ZwQueryValueKey Wrong:%08x\n",Status);
return Status;
}
else
{
RtlCopyMemory((PCHAR)Value, (PCHAR)valueInfoP->Data, valueInfoP->DataLength);
ReturnValue = 1;
}

if(!valueInfoP);
ExFreePool(valueInfoP);
ZwClose(KeyHandle);
return ReturnValue;
}

VOID MyRemoveCraeteThreadNotifyRoutine(
IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
{
//PsRemoveCreateThreadNotifyRoutine(ThreadCreateMon);
PVOID ptr=NULL;
if(BuildNumber==2195) //Windows 2000 Sp4,2195
//低于sp4的我没有调试
{
ptr=0x80484520;
}
else if(BuildNumber==2600)
{
if(wcscmp(Version,L"Service Pack 1")==0) //Windows Xp Sp1,2600
ptr=0x8054efc0;
else if(wcscmp(Version,L"Service Pack 2")==0) //Windows Xp Sp2,2600
ptr=0x80561d20;
}
else if(BuildNumber==3790) //Windows 2003 server,3790
{
ptr=0x80570f40;
}
if(ptr!=NULL)
memset(ptr, 0, sizeof(ULONG)*8);
}

VOID ThreadCreateMon (IN HANDLE PId, IN HANDLE TId, IN BOOLEAN bCreate)
{

PEPROCESS EProcess,PEProcess;
NTSTATUS status;
HANDLE dwParentPID;

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, "=============================="
"Remote Thread :"
"=============================="
"\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);
}
else if(CheckList.SHOWTERMINATETHREAD)
{
DbgPrint( "TERMINATED == THREAD ID: %d\n", TId);
sprintf(outBuf,"TERMINATED == THREAD ID: %d\n", TId);
if(gpEventObject!=NULL)
KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
}
}


VOID ProcessCreateMon ( HANDLE hParentId, HANDLE PId, BOOLEAN bCreate )
{

PEPROCESS EProcess,PProcess;
NTSTATUS status;
HANDLE TId;

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);
}
else if(CheckList.SHOWTERMINATEPROCESS)
{
DbgPrint( "TERMINATED == PROCESS ID: %d\n", PId);
sprintf(outBuf,"TERMINATED == PROCESS ID: %d\n", PId);
if(gpEventObject!=NULL)
KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
}

}

NTSTATUS OnUnload( IN PDRIVER_OBJECT pDriverObject )
{
NTSTATUS status;
DbgPrint("OnUnload called\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" ));
return status;
}
IoDeleteDevice( pDriverObject->DeviceObject );
}
return STATUS_SUCCESS;
}

NTSTATUS DeviceIoControlDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status;
PVOID inputBuffer;
ULONG inputLength;
PVOID outputBuffer;
ULONG outputLength;
OBJECT_HANDLE_INFORMATION objHandleInfo;

status = STATUS_SUCCESS;
// 取出IOCTL请求代码
irpStack = IoGetCurrentIrpStackLocation(pIrp);

switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE :
DbgPrint("Call IRP_MJ_CREATE\n");
break;
case IRP_MJ_CLOSE:
DbgPrint("Call IRP_MJ_CLOSE\n");
break;
case IRP_MJ_DEVICE_CONTROL:
DbgPrint("IRP_MJ_DEVICE_CONTROL\n");
inputLength=irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputLength=irpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_PASSEVENT: //用事件做通信
inputBuffer = pIrp->AssociatedIrp.SystemBuffer;

DbgPrint("inputBuffer:%08x\n", (HANDLE)inputBuffer);
status = ObReferenceObjectByHandle(*(HANDLE *)inputBuffer,
GENERIC_ALL,
NULL,
KernelMode,
&gpEventObject,
&objHandleInfo);

if(status!=STATUS_SUCCESS)
{
DbgPrint("wrong\n");
break;
}
break;
case IOCTL_UNPASSEVENT:
if(gpEventObject)
ObDereferenceObject(gpEventObject);
DbgPrint("UNPASSEVENT called\n");
break;
case IOCTL_PASSBUF:
RtlCopyMemory(pIrp->UserBuffer, outBuf, outputLength);
break;
case IOCTL_PASSEVSTRUCT:
inputBuffer = pIrp->AssociatedIrp.SystemBuffer;
memset(&CheckList, 0, sizeof(CheckList));
RtlCopyMemory(&CheckList, inputBuffer, sizeof(CheckList));
DbgPrint("%d:%d\n", CheckList.ONLYSHOWREMOTETHREAD, CheckList.SHOWTHREAD);
break;
default:
break;
}
break;
default:
DbgPrint("Call IRP_MJ_UNKNOWN\n");
break;
}

pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
return status;
}

NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING theRegistryPath )
{
NTSTATUS Status;
PDEVICE_OBJECT pDevice;

DbgPrint("DriverEntry called!\n");
g_bMainThread = FALSE;

if(1!=GetRegValue(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"CSDVersion", Version))
{
DbgPrint("GetRegValueDword Wrong\n");
}
PsGetVersion(NULL, NULL, &BuildNumber, NULL);
DbgPrint("[[[%d]]]:[[[%ws]]]", BuildNumber, Version);

RtlInitUnicodeString (&devNameUnicd, devName );
RtlInitUnicodeString (&devLinkUnicd, devLink );

Status = IoCreateDevice ( pDriverObject,
0,
&devNameUnicd,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
&pDevice );
if( !NT_SUCCESS(Status))
{
DbgPrint(("Can not create device.\n"));
return Status;
}

Status = IoCreateSymbolicLink (&devLinkUnicd, &devNameUnicd);
if( !NT_SUCCESS(Status))
{
DbgPrint(("Cannot create link.\n"));
return Status;
}

ProcessNameOffset = GetProcessNameOffset();

pDriverObject->DriverUnload = OnUnload;
pDriverObject->MajorFunction[IRP_MJ_CREATE] =
pDriverObject->MajorFunction[IRP_MJ_CLOSE] =
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceIoControlDispatch;

Status = PsSetCreateProcessNotifyRoutine(ProcessCreateMon, FALSE);
if (!NT_SUCCESS( Status ))
{
DbgPrint("PsSetCreateProcessNotifyRoutine()\n");
return Status;
}

Status = PsSetCreateThreadNotifyRoutine(ThreadCreateMon);
if (!NT_SUCCESS( Status ))
{
DbgPrint("PsSetCreateThreadNotifyRoutine()\n");
return Status;
}

return STATUS_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////


main.c, 这里我用事件做为通信驱动
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Made By ZwelL

#include <windows.h>
#include <stdio.h>
#include "define.h"

int main()
{
HANDLE hDevice;
bool status;
HANDLE m_hCommEvent;
ULONG dwReturn;
char outbuf[255];
CHECKLIST CheckList;

hDevice = NULL;
m_hCommEvent = NULL;
hDevice = CreateFile( "\\\\.\\MyEvent",
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hDevice == INVALID_HANDLE_VALUE)
{
printf("createfile wrong\n");
getchar();
return 0;
}

m_hCommEvent = CreateEvent(NULL,
false,
false,
NULL);
printf("hEvent:%08x\n", m_hCommEvent);

status =DeviceIoControl(hDevice,
IOCTL_PASSEVENT,
&m_hCommEvent,
sizeof(m_hCommEvent),
NULL,
0,
&dwReturn,
NULL);
if( !status)
{
printf("IO wrong+%d\n", GetLastError());
getchar();
return 0;
}

CheckList.ONLYSHOWREMOTETHREAD=TRUE;
CheckList.SHOWTHREAD=TRUE;
CheckList.SHOWTERMINATETHREAD=FALSE;
CheckList.SHOWTERMINATEPROCESS=FALSE;
status =DeviceIoControl(hDevice,
IOCTL_PASSEVSTRUCT,
&CheckList,
sizeof(CheckList),
NULL,
0,
&dwReturn,
NULL);
if( !status)
{
printf("IO wrong+%d\n", GetLastError());
getchar();
return 0;
}

printf(" [Process Name] [PID] [TID] [Parent Process Name] [PID] [TID]\n");
while(1)
{
ResetEvent(m_hCommEvent);
WaitForSingleObject(m_hCommEvent, INFINITE);
status =DeviceIoControl(hDevice,
IOCTL_PASSBUF,
NULL,
0,
&outbuf,
sizeof(outbuf),
&dwReturn,
NULL);
if( !status)
{
printf("IO wrong+%d\n", GetLastError());
getchar();
return 0;
}
printf("%s", outbuf);
}

status =DeviceIoControl(hDevice,
IOCTL_UNPASSEVENT,
NULL,
0,
NULL,
0,
&dwReturn,
NULL);
if( !status)
{
printf("UNPASSEVENT wrong+%d\n", GetLastError());
getchar();
return 0;
}

status = CloseHandle( hDevice );
status = CloseHandle(m_hCommEvent);
getchar();
return 0;
}

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

define.h
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "stdio.h"

#define FILE_DEVICE_EVENT 0x8000

// Define Interface reference/dereference routines for
// Interfaces exported by IRP_MN_QUERY_INTERFACE

#define EVENT_IOCTL(index) \
CTL_CODE(FILE_DEVICE_EVENT, index, METHOD_BUFFERED, FILE_READ_DATA)

#define IOCTL_PASSEVENT \
CTL_CODE(FILE_DEVICE_EVENT, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_PASSBUF \
CTL_CODE(FILE_DEVICE_EVENT, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_UNPASSEVENT \
CTL_CODE(FILE_DEVICE_EVENT, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_PASSEVSTRUCT \
CTL_CODE(FILE_DEVICE_EVENT, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)

typedef struct //这个结构主要用于调试用
{
BOOL SHOWTHREAD;
BOOL ONLYSHOWREMOTETHREAD;
BOOL SHOWTERMINATEPROCESS;
BOOL SHOWTERMINATETHREAD;
}CHECKLIST, *PCHECKLIST;


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

先用驱动加载工具加载驱动,再运行程序,可以监视到进程线的操作信息,并且可以实现监视远线程的创建.个人认为很完美.
如果您有更好的方法,请告知我一声,谢谢了. ^_^
下面的运行结果:

hEvent:00000010
[Process Name] [PID] [TID] [Parent Process Name] [PID] [TID]
T: svchost.exe 940 3540 svchost.exe 940
T: explorer.exe 1680 3564 explorer.exe 1680
P: notepad.exe 3568 1684 explorer.exe 1680
T: notepad.exe 3568 3572 explorer.exe 1680
T: svchost.exe 1036 3576 svchost.exe 1036
T: cmd.exe 3580 3084 explorer.exe 1680
P: doskey.exe 3608 3084 cmd.exe 3580
T: taskmgr.exe 352 3752 explorer.exe 1680
T: svchost.exe 1036 2492 svchost.exe 1036
T: remote.exe 3824 3828 cmd.exe 3580
==============================Remote Thread :==============================
T: hh.exe 3116 3832 remote.exe 3824
============================================================================

参考资料:
1. 编写进程/线程监视器 -sinister
http://www.xfocus.net/articles/200303/495.html
2. 监视远程线程的创建 -一块三毛钱
http://www.luocong.com/bbs/dispbbs.asp?boardID=2&ID=6895&page=2
3. Windows 2000源代码



 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·Windows 系统调用功能列表
·windows入侵提权-创建隐藏帐号(
· CC_STACKPROTECTOR防止内核stac
·Linux内核安全研究之Stack Overf
· Exploit The Linux Kernel NULL
·Kernel Locking 中文版
·IA32上Linux内核中断机制分析
·Award BIOS Rootkit,universal
·PHP代码审计
·N种内核注入DLL的思路及实现
·glibc 2.3.5 的一些新安全特性
·Struts2/XWork < 2.2.0 Remote C
  相关文章
·IIS6另类优化及安全配置
·虚拟主机最安全设置
·建立主动性网络安全体系
·反黑防黑:一个显为人知的 木马
·windows2003服务器A级BT安全配置
·Windows下权限设置详解
·Win 2000内置安全命令的威力
·SQL Server 中各个系统表的作用
·检测并禁用隐藏服务
·常见木马和未授权控制软件的关闭
·深入刨析EFS
·ways to find 2.6 kernel rootki
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved