分享
 
 
 

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

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

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

作者: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源代码

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有