科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网安全频道安全稳定的实现进线程监控

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

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

用PsSetCreateProcessNotifyRoutine,PsSetCreateThreadNotifyRoutine来进行进程线程监控我想大家已经都非常熟练了。前一段时间看到网上有人在研究监视远线程的文章,比较有意思。就写代码玩一玩。

作者:zdnet安全频道 来源:论坛整理 2008年9月16日

关键字: 进程

  • 评论
  • 分享微博
  • 分享邮件

用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) {        //首先调用进程监控函数
            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_hCommEv, ent, 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
            ============================================================================


 

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章