注册表监控 驱动代码

该代码利用微软提供的注册表回调函数CmRegisterCallback, 无需任何SSDT hook
不仅能够进行注册表监控,还可以拦截。
驱动完整代码如下:
#define NTDDI_WINXPSP2                      0x05010200
#define OSVERSION_MASK      0xFFFF0000
#define SPVERSION_MASK      0x0000FF00
#define SUBVERSION_MASK     0x000000FF

//
// macros to extract various version fields from the NTDDI version
//
#define OSVER(Version)  ((Version) & OSVERSION_MASK)
#define SPVER(Version)  (((Version) & SPVERSION_MASK) >> 8)
#define SUBVER(Version) (((Version) & SUBVERSION_MASK) )
//#define NTDDI_VERSION   NTDDI_WINXPSP2
#include <ntifs.h>
#include <wdm.h>
#include <ntstrsafe.h>
#define FILE_DEVICE_UNKNOWN 0x00000022
#define IOCTL_UNKNOWN_BASE FILE_DEVICE_UNKNOWN
#define IOCTL_CAPTURE_GET_REGEVENTS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_NEITHER,FILE_READ_DATA | FILE_WRITE_DATA)
#define USERSPACE_CONNECTION_TIMEOUT 10
#define REGISTRY_POOL_TAG 'pRE'
typedef unsigned int UINT;
typedef char* PCHAR;
typedef PVOID POBJECT;
/* Registry event */
typedef struct  _REGISTRY_EVENT
{
    REG_NOTIFY_CLASS eventType;
    TIME_FIELDS time;
    HANDLE processId;
    ULONG dataType;
    ULONG dataLengthB;
    ULONG registryPathLengthB;
    /* Contains path and optionally data */
    UCHAR registryData[];
} REGISTRY_EVENT, *PREGISTRY_EVENT;
/* Storage for registry event to be put into a linked list */
typedef struct  _REGISTRY_EVENT_PACKET
{
    LIST_ENTRY     Link;
    PREGISTRY_EVENT pRegistryEvent;
} REGISTRY_EVENT_PACKET, *PREGISTRY_EVENT_PACKET;
/* Context stuff */
typedef struct _CAPTURE_REGISTRY_MANAGER
{
    PDEVICE_OBJECT deviceObject;
    BOOLEAN bReady;
    LARGE_INTEGER  registryCallbackCookie;
    LIST_ENTRY lQueuedRegistryEvents;
    KTIMER connectionCheckerTimer;
    KDPC connectionCheckerFunction;
    KSPIN_LOCK lQueuedRegistryEventsSpinLock;
    ULONG lastContactTime;
} CAPTURE_REGISTRY_MANAGER, *PCAPTURE_REGISTRY_MANAGER;
/* Methods */
NTSTATUS KDispatchIoctl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS KDispatchCreateClose ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID UnloadDriver ( PDRIVER_OBJECT DriverObject );
NTSTATUS RegistryCallback ( IN PVOID CallbackContext, IN PVOID  Argument1, IN PVOID  Argument2 );
//BOOLEAN GetRegistryObjectCompleteName(PREGISTRY_EVENT pRegistryEvent, PUNICODE_STRING pPartialObjectName, PVOID pRegistryObject);
//VOID QueueRegistryEvent(PREGISTRY_EVENT pRegistryEvent);
VOID UpdateLastContactTime();
ULONG GetCurrentTime();
NTSTATUS HandleIoctlGetRegEvents ( IN PDEVICE_OBJECT DeviceObject, PIRP Irp,
                                   PIO_STACK_LOCATION pIoStackIrp, UINT* pdwDataWritten );
VOID ConnectionChecker (
                IN struct _KDPC*  Dpc,
                IN PVOID  DeferredContext,
                IN PVOID  SystemArgument1,
                IN PVOID  SystemArgument2
);
/* Global values */
PDEVICE_OBJECT gpDeviceObject;

/* Main entry point into the driver, is called when the driver is loaded */
NTSTATUS DriverEntry (
                IN PDRIVER_OBJECT DriverObject,
                IN PUNICODE_STRING RegistryPath
)
{
    NTSTATUS status;
    UNICODE_STRING uszDriverString;
    UNICODE_STRING uszDeviceString;
    LARGE_INTEGER registryEventsTimeout;
    PDEVICE_OBJECT pDeviceObject;
    PCAPTURE_REGISTRY_MANAGER pRegistryManager;
    // Point uszDriverString at the driver name
    RtlInitUnicodeString ( &uszDriverString, L"[url=file://\\Device\\RegistryMonitor]\\Device\\RegistryMonitor[/url]" );
    // Create and initialize device object
    status = IoCreateDevice (
                             DriverObject,
                             sizeof ( CAPTURE_REGISTRY_MANAGER ),
                             &uszDriverString,
                             FILE_DEVICE_UNKNOWN,
                             0,
                             FALSE,
                             &pDeviceObject
             );
    if ( !NT_SUCCESS ( status ) )
        {
            DbgPrint ( "RegistryMonitor: ERROR IoCreateDevice ->  [url=file://\\Device\\RegistryMonitor]\\Device\\RegistryMonitor[/url] - %08x\n", status );
            return status;
        }
    /* Set global device object to newly created object */
    gpDeviceObject = pDeviceObject;
    /* Get the registr manager from the extension of the device */
    pRegistryManager = gpDeviceObject->DeviceExtension;
    pRegistryManager->bReady = FALSE;
    /* Point uszDeviceString at the device name */
    RtlInitUnicodeString ( &uszDeviceString, L"[url=file://\\DosDevices\\RegistryMonitor]\\DosDevices\\RegistryMonitor[/url]" );
    /* Create symbolic link to the user-visible name */
    status = IoCreateSymbolicLink ( &uszDeviceString, &uszDriverString );
    if ( !NT_SUCCESS ( status ) )
        {
            DbgPrint ( "RegistryMonitor: ERROR IoCreateSymbolicLink ->  [url=file://\\DosDevices\\RegistryMonitor]\\DosDevices\\RegistryMonitor[/url] - %08x\n",
                       status );
            IoDeleteDevice ( pDeviceObject );
            return status;
        }
    KeInitializeSpinLock ( &pRegistryManager->lQueuedRegistryEventsSpinLock );
    InitializeListHead ( &pRegistryManager->lQueuedRegistryEvents );
    // Load structure to point to IRP handlers
    DriverObject->DriverUnload = UnloadDriver;
    DriverObject->MajorFunction[IRP_MJ_CREATE] = KDispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = KDispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KDispatchIoctl;
    status = CmRegisterCallback ( RegistryCallback, pRegistryManager, &pRegistryManager->registryCallbackCookie );
    if ( !NT_SUCCESS ( status ) )
        {
            DbgPrint ( "RegistryMonitor: ERROR CmRegisterCallback - %08x\n", status );
            return status;
        }
    UpdateLastContactTime();
    /* Create a DPC routine so that it can be called periodically */
    KeInitializeDpc ( &pRegistryManager->connectionCheckerFunction,
                      ( PKDEFERRED_ROUTINE ) ConnectionChecker, pRegistryManager );
    KeInitializeTimer ( &pRegistryManager->connectionCheckerTimer );
    registryEventsTimeout.QuadPart = 0;
    /* Set the ConnectionChecker routine to be called every so often */
    KeSetTimerEx ( &pRegistryManager->connectionCheckerTimer,
                   registryEventsTimeout,
                   ( USERSPACE_CONNECTION_TIMEOUT + ( USERSPACE_CONNECTION_TIMEOUT / 2 ) ) * 1000,
                   &pRegistryManager->connectionCheckerFunction );
    pRegistryManager->bReady = TRUE;
    DbgPrint ( "RegistryMonitor: Successfully Loaded\n" );
    /* Return success */
    return STATUS_SUCCESS;
}
/*  Checks to see if the registry monitor has received an IOCTL from a userspace
    program in a while. If it hasn't then all old queued registry events are
    cleared. This is called periodically when the driver is loaded */
VOID ConnectionChecker (
                IN struct _KDPC*  Dpc,
                IN PVOID  DeferredContext,
                IN PVOID  SystemArgument1,
                IN PVOID  SystemArgument2
)
{
    PCAPTURE_REGISTRY_MANAGER pRegistryManager = ( PCAPTURE_REGISTRY_MANAGER ) DeferredContext;
    if ( ( GetCurrentTime() - pRegistryManager->lastContactTime ) > ( USERSPACE_CONNECTION_TIMEOUT + ( USERSPACE_CONNECTION_TIMEOUT / 2 ) ) )
        {
            DbgPrint ( "RegistryMonitor: WARNING Userspace IOCTL timeout, clearing old queued registry events\n" );
            while ( !IsListEmpty ( &pRegistryManager->lQueuedRegistryEvents ) )
                {
                    PLIST_ENTRY head = ExInterlockedRemoveHeadList ( &pRegistryManager->lQueuedRegistryEvents, &pRegistryManager->lQueuedRegistryEventsSpinLock );
                    PREGISTRY_EVENT_PACKET pRegistryEventPacket = CONTAINING_RECORD ( head, REGISTRY_EVENT_PACKET, Link );
                    ExFreePoolWithTag ( pRegistryEventPacket->pRegistryEvent, REGISTRY_POOL_TAG );
                    ExFreePoolWithTag ( pRegistryEventPacket, REGISTRY_POOL_TAG );
                }
        }
}

NTSTATUS KDispatchCreateClose ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest ( Irp, IO_NO_INCREMENT );
    return STATUS_SUCCESS;
}
NTSTATUS HandleIoctlGetRegEvents ( IN PDEVICE_OBJECT DeviceObject, PIRP Irp,
                                   PIO_STACK_LOCATION pIoStackIrp, UINT* pdwDataWritten )
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    PCHAR pOutputBuffer = Irp->UserBuffer;
    UINT dwOutputBufferSize = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength;
    PCAPTURE_REGISTRY_MANAGER pRegistryManager;
    /* Get the registry manager from the device extension */
    pRegistryManager = gpDeviceObject->DeviceExtension;
    *pdwDataWritten = 0;
    /* Check we are allowed to write into the buffer passed from the user space program */
    if ( pOutputBuffer )
        {
            try
                {
                    ProbeForWrite ( pOutputBuffer,
                                    pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength,
                                    __alignof ( REGISTRY_EVENT ) );
                    if ( pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof ( REGISTRY_EVENT ) )
                        {
                            PLIST_ENTRY pRegistryListHead;
                            PREGISTRY_EVENT_PACKET pRegistryPacket;
                            UINT bufferSpace = dwOutputBufferSize;
                            UINT bufferSpaceUsed = 0;
                            /* Fill the buffer passed from userspace with registry events */
                            while ( !IsListEmpty ( &pRegistryManager->lQueuedRegistryEvents ) &&
                                    ( bufferSpaceUsed < bufferSpace ) &&
                                    ( ( bufferSpace - bufferSpaceUsed ) >= sizeof ( REGISTRY_EVENT ) ) )
                                {
                                    UINT registryEventSize = 0;
                                    pRegistryListHead = ExInterlockedRemoveHeadList ( &pRegistryManager->lQueuedRegistryEvents, &pRegistryManager->lQueuedRegistryEventsSpinLock );
                                    pRegistryPacket = CONTAINING_RECORD ( pRegistryListHead, REGISTRY_EVENT_PACKET, Link );
                                    registryEventSize = sizeof ( REGISTRY_EVENT ) + pRegistryPacket->pRegistryEvent->registryPathLengthB + pRegistryPacket->pRegistryEvent->dataLengthB;
                                    if ( ( bufferSpace - bufferSpaceUsed ) >= registryEventSize )
                                        {
                                            //DbgPrint("Sending-%i: %ls\n",bufferSpaceUsed, pRegistryPacket->pRegistryEvent->registryPath);
                                            RtlCopyMemory ( pOutputBuffer + bufferSpaceUsed, pRegistryPacket->pRegistryEvent, registryEventSize );
                                            bufferSpaceUsed += registryEventSize;
                                            ExFreePoolWithTag ( pRegistryPacket->pRegistryEvent, REGISTRY_POOL_TAG );
                                            ExFreePoolWithTag ( pRegistryPacket, REGISTRY_POOL_TAG );
                                        }
                                    else
                                        {
                                            ExInterlockedInsertHeadList ( &pRegistryManager->lQueuedRegistryEvents, &pRegistryPacket->Link, &pRegistryManager->lQueuedRegistryEventsSpinLock );
                                            break;
                                        }
                                }
                            /* Return the amount of space that is occupied with registry events */
                            *pdwDataWritten = bufferSpaceUsed;
                            status = STATUS_SUCCESS;
                        }
                    else
                        {
                            *pdwDataWritten = sizeof ( REGISTRY_EVENT );
                            status = STATUS_BUFFER_TOO_SMALL;
                        }
                }
            except ( EXCEPTION_EXECUTE_HANDLER )
            {
                status = GetExceptionCode();
                DbgPrint ( "RegistryMonitor: EXCEPTION IOCTL_CAPTURE_GET_REGEVENTS - %i\n", status );
            }
        }
    return status;
}
NTSTATUS KDispatchIoctl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation ( Irp );
    UINT dwDataWritten = 0;
    switch ( irpStack->Parameters.DeviceIoControl.IoControlCode )
        {
        case IOCTL_CAPTURE_GET_REGEVENTS:
            UpdateLastContactTime();
            status = HandleIoctlGetRegEvents ( DeviceObject, Irp, irpStack, &dwDataWritten );
            break;
        default:
            break;
        }
    Irp->IoStatus.Status = status;
    // Set # of bytes to copy back to user-mode...
    if ( NT_SUCCESS ( status ) )
        Irp->IoStatus.Information = dwDataWritten;
    else
        Irp->IoStatus.Information = 0;
    IoCompleteRequest ( Irp, IO_NO_INCREMENT );
    return status;
}
VOID UpdateLastContactTime()
{
    PCAPTURE_REGISTRY_MANAGER pRegistryManager;
    /* Get the process manager from the device extension */
    pRegistryManager = gpDeviceObject->DeviceExtension;
    pRegistryManager->lastContactTime = GetCurrentTime();
}
ULONG GetCurrentTime()
{
    LARGE_INTEGER currentSystemTime;
    LARGE_INTEGER currentLocalTime;
    ULONG time;
    KeQuerySystemTime ( &currentSystemTime );
    ExSystemTimeToLocalTime ( &currentSystemTime, &currentLocalTime );
    RtlTimeToSecondsSince1970 ( &currentLocalTime, &time );
    return time;
}
BOOLEAN GetRegistryObjectCompleteName ( PUNICODE_STRING pRegistryPath, PUNICODE_STRING pPartialRegistryPath, PVOID pRegistryObject )
{
    PCAPTURE_REGISTRY_MANAGER pRegistryManager;
    BOOLEAN foundCompleteName = FALSE;
    BOOLEAN partial = FALSE;
    /* Get the process manager from the device extension */
    pRegistryManager = gpDeviceObject->DeviceExtension;
    /* Check to see if everything is valid */
    /*  We sometimes see a partial registry object name which is actually complete
        however if fails one of these checks for some reason. Not sure whether to report
        this registry event */
    if ( ( !MmIsAddressValid ( pRegistryObject ) ) ||
            ( pRegistryObject == NULL ) )
        {
            return FALSE;
        }
    /* Check to see if the partial name is really the complete name */
    if ( pPartialRegistryPath != NULL )
        {
            if ( ( ( ( pPartialRegistryPath->Buffer[0] == '\\' ) || ( pPartialRegistryPath->Buffer[0] == '%' ) ) ||
                    ( ( pPartialRegistryPath->Buffer[0] == 'T' ) && ( pPartialRegistryPath->Buffer[1] == 'R' ) && ( pPartialRegistryPath->Buffer[2] == 'Y' )
                      && ( pPartialRegistryPath->Buffer[3] == '\\' ) ) ) )
                {
                    RtlUnicodeStringCopy ( pRegistryPath, pPartialRegistryPath );
                    partial = TRUE;
                    foundCompleteName = TRUE;
                }
        }
    if ( !foundCompleteName )
        {
            /* Query the object manager in the kernel for the complete name */
            NTSTATUS status;
            ULONG returnedLength;
            PUNICODE_STRING pObjectName = NULL;
            status = ObQueryNameString ( pRegistryObject, ( POBJECT_NAME_INFORMATION ) pObjectName, 0, &returnedLength );
            if ( status == STATUS_INFO_LENGTH_MISMATCH )
                {
                    pObjectName = ExAllocatePoolWithTag ( NonPagedPool, returnedLength, REGISTRY_POOL_TAG );
                    status = ObQueryNameString ( pRegistryObject, ( POBJECT_NAME_INFORMATION ) pObjectName, returnedLength, &returnedLength );
                    if ( NT_SUCCESS ( status ) )
                        {
                            RtlUnicodeStringCopy ( pRegistryPath, pObjectName );
                            foundCompleteName = TRUE;
                        }
                    ExFreePoolWithTag ( pObjectName, REGISTRY_POOL_TAG );
                }
        }
    //ASSERT(foundCompleteName == TRUE);
    return foundCompleteName;
}
BOOLEAN QueueRegistryEvent ( PREGISTRY_EVENT pRegistryEvent )
{
    PCAPTURE_REGISTRY_MANAGER pRegistryManager;
    /* Get the registry manager from the device extension */
    pRegistryManager = gpDeviceObject->DeviceExtension;
    /* Check the last contact time of the user space program before queuing */
    if ( ( GetCurrentTime() - pRegistryManager->lastContactTime ) <= USERSPACE_CONNECTION_TIMEOUT )
        {
            PREGISTRY_EVENT_PACKET pRegistryEventPacket = ExAllocatePoolWithTag ( NonPagedPool, sizeof ( REGISTRY_EVENT_PACKET ), REGISTRY_POOL_TAG );
            pRegistryEventPacket->pRegistryEvent = pRegistryEvent;
            /* Queue registry event */
            ExInterlockedInsertTailList ( &pRegistryManager->lQueuedRegistryEvents, &pRegistryEventPacket->Link,
                                          &pRegistryManager->lQueuedRegistryEventsSpinLock );
            return TRUE;
        }
    return FALSE;
}
NTSTATUS RegistryCallback ( IN PVOID CallbackContext,
                            IN PVOID  Argument1,
                            IN PVOID  Argument2 )
{
    //REGISTRY_EVENT registryEvent;
    BOOLEAN registryEventIsValid = FALSE;
    BOOLEAN exception = FALSE;
    LARGE_INTEGER CurrentSystemTime;
    LARGE_INTEGER CurrentLocalTime;
    TIME_FIELDS TimeFields;
    int type;
    UNICODE_STRING registryPath;
    UCHAR* registryData = NULL;
    ULONG registryDataLength = 0;
    ULONG registryDataType = 0;
    /* Allocate a large 64kb string ... maximum path name allowed in windows */
    registryPath.Length = 0;
    registryPath.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof ( WCHAR );
    registryPath.Buffer = ExAllocatePoolWithTag ( NonPagedPool, registryPath.MaximumLength, REGISTRY_POOL_TAG );
    if ( registryPath.Buffer == NULL )
        {
            return STATUS_SUCCESS;
        }
    /* Put the time this event occured into the registry event */
    KeQuerySystemTime ( &CurrentSystemTime );
    ExSystemTimeToLocalTime ( &CurrentSystemTime, &CurrentLocalTime );
    //registryEvent.processId = PsGetCurrentProcessId();
    //registryEvent.eventType = (REG_NOTIFY_CLASS)Argument1;
    type = ( REG_NOTIFY_CLASS ) Argument1;
    try
        {
            /* Large switch statement for all registry events ... fairly easy to understand */
            switch ( type )
                {
                case RegNtPostCreateKey:
                {
                    PREG_POST_CREATE_KEY_INFORMATION createKey = ( PREG_POST_CREATE_KEY_INFORMATION ) Argument2;
                    if ( NT_SUCCESS ( createKey->Status ) )
                        {
                            PVOID* registryObject = createKey->Object;
                            registryEventIsValid = GetRegistryObjectCompleteName ( &registryPath, createKey->CompleteName, *registryObject );
                        }
                    break;
                }
                case RegNtPostOpenKey:
                {
                    PREG_POST_OPEN_KEY_INFORMATION openKey = ( PREG_POST_OPEN_KEY_INFORMATION ) Argument2;
                    if ( NT_SUCCESS ( openKey->Status ) )
                        {
                            PVOID* registryObject = openKey->Object;
                            registryEventIsValid = GetRegistryObjectCompleteName ( &registryPath, openKey->CompleteName, *registryObject );
                        }
                    break;
                }
                case RegNtPreDeleteKey:
                {
                    PREG_DELETE_KEY_INFORMATION deleteKey = ( PREG_DELETE_KEY_INFORMATION ) Argument2;
                    registryEventIsValid = GetRegistryObjectCompleteName ( &registryPath, NULL, deleteKey->Object );
                    break;
                }
                case RegNtDeleteValueKey:
                {
                    PREG_DELETE_VALUE_KEY_INFORMATION deleteValueKey = ( PREG_DELETE_VALUE_KEY_INFORMATION ) Argument2;
                    registryEventIsValid = GetRegistryObjectCompleteName ( &registryPath, NULL, deleteValueKey->Object );
                    if ( ( registryEventIsValid ) && ( deleteValueKey->ValueName->Length > 0 ) )
                        {
                            RtlUnicodeStringCatString ( &registryPath, L"\\" );
                            RtlUnicodeStringCat ( &registryPath, deleteValueKey->ValueName );
                        }
                    break;
                }
                case RegNtPreSetValueKey:
                {
                    PREG_SET_VALUE_KEY_INFORMATION setValueKey = ( PREG_SET_VALUE_KEY_INFORMATION ) Argument2;
                    registryEventIsValid = GetRegistryObjectCompleteName ( &registryPath, NULL, setValueKey->Object );
                    if ( ( registryEventIsValid ) && ( setValueKey->ValueName->Length > 0 ) )
                        {
                            registryDataType = setValueKey->Type;
                            registryDataLength = setValueKey->DataSize;
                            registryData = ExAllocatePoolWithTag ( NonPagedPool, registryDataLength, REGISTRY_POOL_TAG );
                            if ( registryData != NULL )
                                {
                                    RtlCopyBytes ( registryData, setValueKey->Data, setValueKey->DataSize );
                                }
                            else
                                {
                                    DbgPrint ( "RegistryMonitor: ERROR can't allocate memory for setvalue data\n" );
                                }
                            RtlUnicodeStringCatString ( &registryPath, L"\\" );
                            RtlUnicodeStringCat ( &registryPath, setValueKey->ValueName );
                        }
                    break;
                }
                case RegNtEnumerateKey:
                {
                    PREG_ENUMERATE_KEY_INFORMATION enumerateKey = ( PREG_ENUMERATE_KEY_INFORMATION ) Argument2;
                    registryDataType = enumerateKey->KeyInformationClass;
                    registryEventIsValid = GetRegistryObjectCompleteName ( &registryPath, NULL, enumerateKey->Object );
                    break;
                }
                case RegNtEnumerateValueKey:
                {
                    PREG_ENUMERATE_VALUE_KEY_INFORMATION enumerateValueKey = ( PREG_ENUMERATE_VALUE_KEY_INFORMATION ) Argument2;
                    registryDataType = enumerateValueKey->KeyValueInformationClass;
                    registryEventIsValid = GetRegistryObjectCompleteName ( &registryPath, NULL, enumerateValueKey->Object );
                    break;
                }
                case RegNtQueryKey:
                {
                    PREG_QUERY_KEY_INFORMATION queryKey = ( PREG_QUERY_KEY_INFORMATION ) Argument2;
                    registryDataType = queryKey->KeyInformationClass;
                    registryEventIsValid = GetRegistryObjectCompleteName ( &registryPath, NULL, queryKey->Object );
                    break;
                }
                case RegNtQueryValueKey:
                {
                    PREG_QUERY_VALUE_KEY_INFORMATION queryValueKey = ( PREG_QUERY_VALUE_KEY_INFORMATION ) Argument2;
                    registryEventIsValid = GetRegistryObjectCompleteName ( &registryPath, NULL, queryValueKey->Object );
                    if ( ( registryEventIsValid ) && ( queryValueKey->ValueName->Length > 0 ) )
                        {
                            registryDataType = queryValueKey->KeyValueInformationClass;
                            RtlUnicodeStringCatString ( &registryPath, L"\\" );
                            RtlUnicodeStringCat ( &registryPath, queryValueKey->ValueName );
                        }
                    break;
                }
                case RegNtKeyHandleClose:
                {
                    PREG_KEY_HANDLE_CLOSE_INFORMATION closeKey = ( PREG_KEY_HANDLE_CLOSE_INFORMATION ) Argument2;
                    registryEventIsValid = GetRegistryObjectCompleteName ( &registryPath, NULL, closeKey->Object );
                    break;
                }
                default:
                    break;
                }
        }
    except ( EXCEPTION_EXECUTE_HANDLER )
    {
        /* Do nothing if an exception occured ... event won't be queued */
        registryEventIsValid = FALSE;
        exception = TRUE;
    }
    if ( registryEventIsValid )
        {
            PREGISTRY_EVENT pRegistryEvent;
            UINT eventSize = sizeof ( REGISTRY_EVENT ) + registryPath.Length + ( sizeof ( WCHAR ) ) + registryDataLength;
            pRegistryEvent = ExAllocatePoolWithTag ( NonPagedPool, eventSize, REGISTRY_POOL_TAG );
            if ( pRegistryEvent != NULL )
                {
                    pRegistryEvent->registryPathLengthB = registryPath.Length + sizeof ( WCHAR );
                    pRegistryEvent->dataType = registryDataType;
                    pRegistryEvent->dataLengthB = registryDataLength;
                    //RtlStringCbCopyUnicodeString(pRegistryEvent->registryPath, pRegistryEvent->registryPathLength, &registryPath);
                    RtlCopyBytes ( pRegistryEvent->registryData, registryPath.Buffer, registryPath.Length );
                    pRegistryEvent->registryData[registryPath.Length] = '\0';
                    pRegistryEvent->registryData[registryPath.Length + 1] = '\0';
                    RtlCopyBytes ( pRegistryEvent->registryData + pRegistryEvent->registryPathLengthB, registryData, registryDataLength );
                    if ( registryData != NULL )
                        {
                            ExFreePoolWithTag ( registryData, REGISTRY_POOL_TAG );
                        }
                    pRegistryEvent->processId = PsGetCurrentProcessId();
                    RtlTimeToTimeFields ( &CurrentLocalTime, &pRegistryEvent->time );
                    pRegistryEvent->eventType = ( REG_NOTIFY_CLASS ) Argument1;
                    if ( !QueueRegistryEvent ( pRegistryEvent ) )
                        {
                            ExFreePoolWithTag ( pRegistryEvent, REGISTRY_POOL_TAG );
                        }
                }
        }
    if ( registryPath.Buffer != NULL )
        {
            ExFreePoolWithTag ( registryPath.Buffer, REGISTRY_POOL_TAG );
        }
    /* Always return a success ... we aren't doing any filtering, just monitoring */
    return STATUS_SUCCESS;
}
void UnloadDriver ( IN PDRIVER_OBJECT DriverObject )
{
    UNICODE_STRING  uszDeviceString;
    NTSTATUS        ntStatus;
    PCAPTURE_REGISTRY_MANAGER pRegistryManager;
    /* Get the registry manager from the device extension */
    pRegistryManager = gpDeviceObject->DeviceExtension;
    if ( pRegistryManager->bReady == TRUE )
        {
            KeCancelTimer ( &pRegistryManager->connectionCheckerTimer );
            CmUnRegisterCallback ( pRegistryManager->registryCallbackCookie );
            pRegistryManager->bReady = FALSE;
        }
    while ( !IsListEmpty ( &pRegistryManager->lQueuedRegistryEvents ) )
        {
            PLIST_ENTRY head = ExInterlockedRemoveHeadList ( &pRegistryManager->lQueuedRegistryEvents, &pRegistryManager->lQueuedRegistryEventsSpinLock );
            PREGISTRY_EVENT_PACKET pRegistryEventPacket = CONTAINING_RECORD ( head, REGISTRY_EVENT_PACKET, Link );
            ExFreePoolWithTag ( pRegistryEventPacket->pRegistryEvent, REGISTRY_POOL_TAG );
            ExFreePoolWithTag ( pRegistryEventPacket, REGISTRY_POOL_TAG );
        }
    RtlInitUnicodeString ( &uszDeviceString, L"[url=file://\\DosDevices\\RegistryMonitor]\\DosDevices\\RegistryMonitor[/url]" );
    IoDeleteSymbolicLink ( &uszDeviceString );
    if ( DriverObject->DeviceObject != NULL )
        {
            IoDeleteDevice ( DriverObject->DeviceObject );
        }
}

 

posted on 2017-10-20 18:35  wongnel  阅读(638)  评论(0)    收藏  举报

导航