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

来源:http://www.xfocus.net

作者:ZwelL

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

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

        }
    ...
    ...
     (PspCreateThreadNotyRoutineCount != 0) {
        ULONG i;

        for (i=0; i<PSP_MAX_CREATE_THREAD_NOTIFY; i) {    //再线程监控
             (PspCreateThreadNotyRoutine[i] != NULL) {
                (*PspCreateThreadNotyRoutine[i])( Thread->Cid.UniqueProcess,
                                                    Thread->Cid.UniqueThread,
                                                    TRUE
                                                   );
            }
        }
    }
    ...
    ...
}

从上面可以看到,在每创建个线程后会PspCreateProcessNotyRoutine[i]地址指向.而PsSetCreateThreadNotyRoutine作用就是将PspCreateThreadNotyRoutine[i]设置值,该值就是监视地址.

NTSTATUS
PsSetCreateThreadNotyRoutine(
    IN PCREATE_THREAD_NOTIFY_ROUTINE NotyRoutine
    )
{
    ULONG i;
    NTSTATUS Status;

    Status = STATUS_INSUFFICIENT_RESOURCES;
    for (i = 0; i < PSP_MAX_CREATE_THREAD_NOTIFY; i 1) {
         (PspCreateThreadNotyRoutine[i] NULL) {
            PspCreateThreadNotyRoutine[i] = NotyRoutine;
            PspCreateThreadNotyRoutineCount 1;
            Status = STATUS_SUCCESS;
            ;
        }
    }

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

ULONG PspCreateThreadNotyRoutineCount;    //用来记数
PCREATE_THREAD_NOTIFY_ROUTINE PspCreateThreadNotyRoutine[ 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,
这样话下进线程操作就不会这个指针了.也就让系统回到正常,我们再通过PsSetCreateProcessNotyRoutine来验证下:

NTSTATUS
PsSetCreateProcessNotyRoutine(
    IN PCREATE_PROCESS_NOTIFY_ROUTINE NotyRoutine,
    IN BOOLEAN Remove
    )
{
    ULONG i;

    for (i=0; i < PSP_MAX_CREATE_PROCESS_NOTIFY; i) {
         (Remove) {    
             (PspCreateProcessNotyRoutine[i] NotyRoutine) {    //清除时就是简单赋植操作
                PspCreateProcessNotyRoutine[i] = NULL;
                PspCreateProcessNotyRoutineCount -= 1;        //将计数器减
                 STATUS_SUCCESS;
            }
        } {
             (PspCreateProcessNotyRoutine[i] NULL) {        //设置时也是简单赋值操作
                PspCreateProcessNotyRoutine[i] = NotyRoutine;
                PspCreateProcessNotyRoutineCount 1;        //将计数器加
                 STATUS_SUCCESS;
            }
        }
    }

     Remove ? STATUS_PROCEDURE_NOT_FOUND : STATUS_INVALID_PARAMETER;
}

好了,思路方法已经知道了,只要找出地址,我们就能够"全身而退"了.看下windows2003下面PsRemoveCreateThreadNotyRoutine实现:
lkd> u PsRemoveCreateThreadNotyRoutine l 20
nt!PsRemoveCreateThreadNotyRoutine:
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!PsRemoveCreateThreadNotyRoutine+0x36 (80651db1)
80651d91 56               push    esi
80651d92 e8ba1bffff      call nt!IoReportTargetDeviceChange+0x7aa0 (80643951)
80651d97 3b442410         cmp     eax,[esp+0x10]
80651d9b 750d        jnz nt!PsRemoveCreateThreadNotyRoutine+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!PsRemoveCreateThreadNotyRoutine+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!PsRemoveCreateThreadNotyRoutine+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

# "ntddk.h"
# "windef.h"
# ".h"

# SYSNAME ""
# VERSIONLEN 100

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

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

ULONG GetProcessNameOff
{
    PEPROCESS curproc;
     i;

    curproc = PsGetCurrentProcess;

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

     0;
}

NTSTATUS GetRegValue(PCWSTR RegPath,PCWSTR ValueName,PWCHAR Value)
{
     ReturnValue = 0;
    NTSTATUS Status;
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE KeyHandle;
    PKEY_VALUE_PARTIAL_INFORMATION valueInfoP;
    ULONG valueInfoLength,Length;
    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);
     (Status != STATUS_SUCCESS)
    {
        DbgPr("ZwOpenKey Wrong\n");
         0;
    }

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

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

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

VOID MyRemoveCraeteThreadNotyRoutine(
                                       IN PCREATE_THREAD_NOTIFY_ROUTINE  NotyRoutine
                                       )
{
    //PsRemoveCreateThreadNotyRoutine(ThreadCreateMon);
    PVOID ptr=NULL;
    (BuildNumber2195)                                    //Windows 2000 Sp4,2195
                                                            //低于sp4我没有调试
    {
        ptr=0x80484520;
    }
     (BuildNumber2600)        
    {
        (wcscmp(Version,L"Service Pack 1")0)            //Windows Xp Sp1,2600
            ptr=0x8054efc0;
         (wcscmp(Version,L"Service Pack 2")0)        //Windows Xp Sp2,2600
            ptr=0x80561d20;
    }
     (BuildNumber3790)                                //Windows 2003 server,3790
    {
        ptr=0x80570f40;
    }
    (ptr!=NULL)
        mem(ptr, 0, (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);
     (!NT_SUCCESS( status ))
    {
        DbgPr("PsLookupProcessByProcessId\n");
         ;
    }    

     ( bCreate )
    {
        dwParentPID=PsGetCurrentProcessId;
        status = PsLookupProcessByProcessId(
            (ULONG)dwParentPID,
            &PEProcess);
         (!NT_SUCCESS( status ))
        {
            DbgPr("PsLookupProcessByProcessId\n");
             ;
        }
        (PId4)    //进程创建东东我们不管
                //在2000下是0,在XP后是4
            ;
        ((g_bMainThreadTRUE)
            &&(g_dwParentId != dwParentPID)
            &&(dwParentPID != PId)
            )
        {
            g_bMainThread=FALSE;
            sprf(outBuf, ""
                "Remote Thread :"
                ""
                "\nT:%18s%9d%9d%25s%9d\n"
                ""
                "\n",
                (char *)((char *)EProcess+ProcessNameOff),
                PId, TId,
                (char *)((char *)PEProcess+ProcessNameOff),dwParentPID);
            (gpEventObject!=NULL)
                KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
        }
        (CheckList.ONLYSHOWREMOTETHREAD)    //只显示远线程
            ;
        DbgPr( "T:%18s%9d%9d%25s%9d\n",
            (char *)((char *)EProcess+ProcessNameOff),
            PId, TId,
            (char *)((char *)PEProcess+ProcessNameOff),dwParentPID);
        sprf(outBuf, "T:%18s%9d%9d%25s%9d\n",
            (char *)((char *)EProcess+ProcessNameOff),
            PId, TId,
            (char *)((char *)PEProcess+ProcessNameOff),dwParentPID);
        (gpEventObject!=NULL)
            KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
    }
     (CheckList.SHOWTERMINATETHREAD)
    {
        DbgPr( "TERMINATED THREAD ID: %d\n", TId);
        sprf(outBuf,"TERMINATED THREAD ID: %d\n", TId);
        (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);
     (!NT_SUCCESS( status ))
    {
        DbgPr("PsLookupProcessByProcessId\n");
         ;
    }
    status = PsLookupProcessByProcessId((ULONG)hParentId, &PProcess);
     (!NT_SUCCESS( status ))
    {
        DbgPr("PsLookupProcessByProcessId\n");
         ;
    }

     ( bCreate )
    {
        g_bMainThread = TRUE;
        DbgPr( "P:%18s%9d%9d%25s%9d\n",
            (char *)((char *)EProcess+ProcessNameOff),
            PId,PsGetCurrentThreadId,
            (char *)((char *)PProcess+ProcessNameOff),
            hParentId
            );
        sprf(outBuf, "P:%18s%9d%9d%25s%9d\n",
            (char *)((char *)EProcess+ProcessNameOff),
            PId,PsGetCurrentThreadId,
            (char *)((char *)PProcess+ProcessNameOff),
            hParentId
            );
        (gpEventObject!=NULL)
            KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
    }
     (CheckList.SHOWTERMINATEPROCESS)
    {
        DbgPr( "TERMINATED PROCESS ID: %d\n", PId);
        sprf(outBuf,"TERMINATED PROCESS ID: %d\n", PId);
        (gpEventObject!=NULL)
            KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
    }

}

NTSTATUS _disibledevent=>     {
        status=IoDeleteSymbolicLink( &devLinkUnicd );
         ( !NT_SUCCESS( status ) )
        {
            DbgPr((  "IoDeleteSymbolicLink failed\n" ));
             status;
        }
        IoDeleteDevice( pDriverObject->DeviceObject );
    }
     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)
    {
     IRP_MJ_CREATE :
        DbgPr("Call IRP_MJ_CREATE\n");
        ;
     IRP_MJ_CLOSE:
        DbgPr("Call IRP_MJ_CLOSE\n");
        ;
     IRP_MJ_DEVICE_CONTROL:
        DbgPr("IRP_MJ_DEVICE_CONTROL\n");
        inputLength=irpStack->Parameters.DeviceIoControl.InputBufferLength;
        outputLength=irpStack->Parameters.DeviceIoControl.OutputBufferLength;
        switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
        {
         IOCTL_PASSEVENT:    //用事件做通信
            inputBuffer = pIrp->AssociatedIrp.Buffer;

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

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

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

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

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

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

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

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

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

    ProcessNameOff = GetProcessNameOff;

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

    Status = PsSetCreateProcessNotyRoutine(ProcessCreateMon, FALSE);
     (!NT_SUCCESS( Status ))
    {
        DbgPr("PsSetCreateProcessNotyRoutine\n");
         Status;
    }

    Status = PsSetCreateThreadNotyRoutine(ThreadCreateMon);
     (!NT_SUCCESS( Status ))
    {
        DbgPr("PsSetCreateThreadNotyRoutine\n");
         Status;
    }

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


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

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


{
    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);
    (hDevice INVALID_HANDLE_VALUE)
    {
        prf("createfile wrong\n");
        getchar;
         0;
    }

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

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

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

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

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

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

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

.h
/////////////////////////////////////////////////////////////////////////////////////////////////////////
# "stdio.h"

# FILE_DEVICE_EVENT  0x8000

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

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

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

typedef struct        //这个结构主要用于调试用
{
    BOOL SHOWTHREAD;
    BOOL _disibledevent=> T:            hh.exe     3116     3832               remote.exe     3824




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


  • 篇文章: 服务器端常用

  • 篇文章: 网络扫描器设计和实现
  • Tags:  什么是线程安全 java线程安全 线程安全 java线程监控

    延伸阅读

    最新评论

    发表评论