首页 电脑 电脑学堂 查看内容

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

2006-2-22 00:08 1018 0

摘要: 作者:suei8423 (suei8423_at_163.com)出处:http://www.xfocus.net/articles/200503/788.html日期:2005-04-04创建时间:...
关键词: nbsp Status DbgPrint CHECKLIST gpEventObject 线程 return NULL 监视 ProcessNameOffse

作者:suei8423 (suei8423_at_163.com)出处:http://www.xfocus.net/articles/200503/788.html日期:2005-04-04创建时间:2005-03-24文章属性:原创文章提交:suei8423 (suei8423_at_163.com)安全稳定的实现进线程监控作者: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////////////////////////////////////////////////////////////////////////////////////////////////////////NTSTATUSPspCreateThread(    ...    ...    ){    ...        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]数组设置值,该值就是监视函数的地址.NTSTATUSPsSetCreateThreadNotifyRoutine(    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定义如下:typedefVOID(*PCREATE_THREAD_NOTIFY_ROUTINE)(    IN HANDLE ProcessId,    IN HANDLE ThreadId,    IN BOOLEAN Create    );相应的,进程的结构也是一样的.通过上面,我们可以看到,只要我们找出该函数数组地址,在我们退出驱动时先将其全部清零,清零的大小为PSP_MAX_CREATE_THREAD_NOTIFY,这样的话下一次的进线程操作就不会调用这个函数指针了.也就让系统回到正常,我们再通过PsSetCreateProcessNotifyRoutine来验证一下:NTSTATUSPsSetCreateProcessNotifyRoutine(    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 20nt!PsRemoveCreateThreadNotifyRoutine:80651d7b 53               push    ebx80651d7c 56               push    esi80651d7d 57               push    edi80651d7e 33db             xor     ebx,ebx80651d80 bf400f5780       mov     edi,0x80570f40    //起始地址80651d85 57               push    edi80651d86 e8a7500100 call nt!ExWaitForRundownProtectionRelease+0x5cf (80666e32)80651d8b 8bf0             mov     esi,eax80651d8d 85f6             test    esi,esi80651d8f 7420         jz nt!PsRemoveCreateThreadNotifyRoutine+0x36 (80651db1)80651d91 56               push    esi80651d92 e8ba1bffff      call nt!IoReportTargetDeviceChange+0x7aa0 (80643951)80651d97 3b442410         cmp     eax,[esp+0x10]80651d9b 750d        jnz nt!PsRemoveCreateThreadNotifyRoutine+0x2f (80651daa)80651d9d 56               push    esi80651d9e 6a00             push    0x080651da0 57               push    edi80651da1 e8c54f0100 call nt!ExWaitForRundownProtectionRelease+0x508 (80666d6b)80651da6 84c0             test    al,al80651da8 751b        jnz nt!PsRemoveCreateThreadNotifyRoutine+0x4a (80651dc5)80651daa 56               push    esi80651dab 57               push    edi80651dac e892510100 call nt!ExWaitForRundownProtectionRelease+0x6e0 (80666f43)80651db1 43               inc     ebx80651db2 83c704           add     edi,0x480651db5 83fb08           cmp     ebx,0x8    //看是否到了最大数(8)80651db8 72cb          jb nt!PsRemoveCreateThreadNotifyRoutine+0xa (80651d85)80651dba b87a0000c0       mov     eax,0xc000007a80651dbf 5f               pop     edi80651dc0 5e               pop     esi80651dc1 5b               pop     ebx80651dc2 c20400           ret     0x4lkd> 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 100const 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进程的IDPWCHAR                    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]  &, nbsp; [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      940T:      explorer.exe     1680     3564             explorer.exe     1680P:       notepad.exe     3568     1684             explorer.exe     1680T:       notepad.exe     3568     3572             explorer.exe     1680T:       svchost.exe     1036     3576              svchost.exe     1036T:           cmd.exe     3580     3084             explorer.exe     1680P:        doskey.exe     3608     3084                  cmd.exe     3580T:       taskmgr.exe      352     3752             explorer.exe     1680T:       svchost.exe     1036     2492              svchost.exe     1036T:        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.html2. 监视远程线程的创建 -一块三毛钱    http://www.luocong.com/bbs/dispbbs.asp?boardID=2&ID=6895&page=23. Windows 2000源代码
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部