Hook Dispatch 实时监控[zz]

来源:互联网 发布:软件开发项目进度报告 编辑:程序博客网 时间:2024/04/28 21:35

作者:pker

/*++

Module Name:

    FSHook.c


Abstract:

    I  wanted  to  build a filter driver when I first  thought about doing such
    kind of things.  But then I found that it's not realistic 'cause it have to
    hook every filesystem driver to prevent from missing any IRPs. But we don't
    know  when  there's a new driver  coming.  When we install a virtual CD-ROM
    program, for instance,  it installs a driver to control the virtual CD-ROM.
    There  can be  viruses in the  image of the  disk,  so we have to hook that
    driver as well.

    Then a new idea,  which then I found that it's being used by most of the AV
    softs, comes out of my head. The driver's final goal is to inercept all the
    I/O behavior to disk A~Z, so we can use  ObReferenceObjectByXXX  to get the
    _FILE_OBJECT of  /??/X:/,  then   we   can   get   the   device  chain   by
    IoGetRelatedDeviceObject.  We are interested in the MajorFunction  field of
    the _DEVICE_OBJECT. We can hook the IRP_MJ_XXX we interest by replacing the
    entries of the dispatch routines with our own.


Environment:

    Kernel mode.


Copyright:

    Copyright (c) 2005, pker / CVC.GB

--*/

#include "fshook.h"


///////////////////////////////////////////////////////////////////////////////
//
//                             Global Variables
//
///////////////////////////////////////////////////////////////////////////////

// save hooked device objects and driver objects

PDEVICE_OBJECT g_pDevObjTab[MAX_DISK]={NULL};
PDRIVER_OBJECT g_pDrvObjTab[MAX_DISK]={NULL};

// entries of original dispatch routines of each hooked driver

PAV_DRIVER_DISPATCH_ROUTINE g_pOriginalDispatch[MAX_DISK];

// process ID of the AV scanner

ULONG g_ulPid;

// shared memory address (kernel mode)

PVOID g_pKrnlSBuffer=NULL;


///////////////////////////////////////////////////////////////////////////////
//
//                                 Functions
//
///////////////////////////////////////////////////////////////////////////////

ULONG
PAV_GetObjectTabIndex (
    IN ULONG *pObject,
    IN ULONG **pObjTab
)

/*++

Routine Discription:

    The routine searches the suitable object  (device object and driver object)
    and returns the index of the object in the global object table.

--*/

{
    ULONG i;

    for (i=0; i<MAX_DISK; i++)
    {
        if (pObjTab[i] == pObject)
        {
            return i;
        }
    }

    // object not found

    return (ULONG)-1;
}


NTSTATUS
PAV_DispatchRoutineHook (
    IN PDEVICE_OBJECT pDeviceObject,
    IN PIRP pIrp
)

/*++

Routine Discription:

    This is the hook of the IRPs.  When in DEBUG mode.  It  DbgPrint the driver
    name,  which is dealing with the I/O request, and the target filename, with
    which the I/O request is going to handle.

    The  main  function  of this procedure is to intercept all the I/O request,
    and wakeup the Ring3 virus scanning routine.

--*/

{
    ULONG i;
    HANDLE pid;
    PIO_STACK_LOCATION piosl;
#ifdef __PAV_MON_DEBUG__
    ANSI_STRING as;
#endif

    pid=PsGetCurrentProcessId ();

#ifdef __PAV_MON_DEBUG__
    // debug print the pid

    DbgPrint ("PavAP!PAV_DispatchRoutineHook: PsGetCurrentProcessId = %x/n",pid);

    // get the driver name which is dealing with the IRP

    RtlUnicodeStringToAnsiString (&as,&(pDeviceObject->DriverObject->DriverName),TRUE);
    DbgPrint ("PavAP!PAV_DispatchRoutineHook: Intercepted a I/O Request from Driver: %s/n",as.Buffer);
    RtlFreeAnsiString (&as);
#endif

    // determine where the I/O request came from

    i=PAV_GetObjectTabIndex ((ULONG *)pDeviceObject,(ULONG **)g_pDevObjTab);
    if (i == (ULONG)-1)
    {
        i--;
    }
#ifdef __PAV_MON_DEBUG__
    DbgPrint ("Target Filename: %c:",(CHAR)i+'A');
#endif

    // get the filename that the I/O request would effect

    piosl=IoGetCurrentIrpStackLocation (pIrp);
#ifdef __PAV_MON_DEBUG__
    if (piosl->FileObject != NULL)
    {
        RtlUnicodeStringToAnsiString (&as,&(piosl->FileObject->FileName),TRUE);
        DbgPrint ("%s/n",as.Buffer);
        RtlFreeAnsiString (&as);
    }
#endif

    // call original dispatch routine and returns

    i=PAV_GetObjectTabIndex ((ULONG *)pDeviceObject->DriverObject,(ULONG **)g_pDrvObjTab);
    if (i != (ULONG)-1)
    {
        switch (piosl->MajorFunction)
        {
            case IRP_MJ_CREATE:
#ifdef __PAV_MON_DEBUG__
                DbgPrint ("MajorFunction Code: IRP_MJ_CREATE/n/n");
#endif
                return g_pOriginalDispatch[i].pfnCreate (pDeviceObject,pIrp);

            case IRP_MJ_WRITE:
#ifdef __PAV_MON_DEBUG__
                DbgPrint ("MajorFunction Code: IRP_MJ_WRITE/n/n");
#endif
                return g_pOriginalDispatch[i].pfnWrite (pDeviceObject,pIrp);

            case IRP_MJ_CLOSE:
#ifdef __PAV_MON_DEBUG__
                DbgPrint ("MajorFunction Code: IRP_MJ_CLOSE/n/n");
#endif
                return g_pOriginalDispatch[i].pfnClose (pDeviceObject,pIrp);

            case IRP_MJ_CLEANUP:
#ifdef __PAV_MON_DEBUG__
                DbgPrint ("MajorFunction Code: IRP_MJ_CLEANUP/n/n");
#endif
                return g_pOriginalDispatch[i].pfnCleanup (pDeviceObject,pIrp);
        }
    }

    // no suitable driver object found, so complete this IRP

    return PAV_CompleteRequest (pIrp,STATUS_SUCCESS,0);
}


PDEVICE_OBJECT
PAV_GetDeviceObject (
    IN PUNICODE_STRING pusDeviceName
)

/*++

Routine Discription:

    Get the related device object according to the device name.

--*/

{
    NTSTATUS ns;
    HANDLE hFile;
    OBJECT_ATTRIBUTES oa;
    IO_STATUS_BLOCK iosb;
    PFILE_OBJECT pFileObject;
    PDEVICE_OBJECT pDeviceObject;

    // open the device

    InitializeObjectAttributes (&oa,pusDeviceName,OBJ_CASE_INSENSITIVE,NULL,NULL);
    ns=ZwCreateFile (&hFile,SYNCHRONIZE | FILE_ANY_ACCESS,&oa,&iosb,0,0,
                     FILE_SHARE_READ | FILE_SHARE_WRITE,FILE_OPEN,
                     FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,NULL,0);
    if (!NT_SUCCESS(ns))
    {
        return NULL;
    }

    // reference the file object by the handle...

    ns=ObReferenceObjectByHandle (hFile,FILE_READ_DATA,NULL,KernelMode,&pFileObject,NULL);
    if (!NT_SUCCESS(ns))
    {
        ZwClose (hFile);
        return NULL;
    }

    // get related device object chain

    pDeviceObject=IoGetRelatedDeviceObject (pFileObject);

    // dereference file object and close the file (device)

    ObDereferenceObject (pFileObject);
    ZwClose (hFile);

    return pDeviceObject;
}


VOID
PAV_IrpHookInstall (
    VOID
)

/*++

Routine Discription:

    This function hooks IRPs of each disk device, from A~Z.

--*/

{
    ULONG i;
    NTSTATUS ns;
    PDEVICE_OBJECT fdo;
    UNICODE_STRING usDeviceName;
    WCHAR DeviceName[]=L"
//??//X://";

    // hook disk A~Z

    for (i=0; i<MAX_DISK; i++)
    {
        // get device object

        DeviceName[4]='A'+(WCHAR)i;
        RtlInitUnicodeString (&usDeviceName,DeviceName);
        fdo=PAV_GetDeviceObject (&usDeviceName);

        if (fdo == NULL)
        {
            continue;
        }

        // hook IRPs...

        g_pDevObjTab[i]=fdo;
        g_pDrvObjTab[i]=fdo->DriverObject;

        if (PAV_DispatchRoutineHook != g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CREATE])
        {
            g_pOriginalDispatch[i].pfnCreate=g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CREATE];
            g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CREATE]=PAV_DispatchRoutineHook;
        }

        if (PAV_DispatchRoutineHook != g_pDrvObjTab[i]->MajorFunction[IRP_MJ_WRITE])
        {
            g_pOriginalDispatch[i].pfnWrite=g_pDrvObjTab[i]->MajorFunction[IRP_MJ_WRITE];
            g_pDrvObjTab[i]->MajorFunction[IRP_MJ_WRITE]=PAV_DispatchRoutineHook;
        }

        if (PAV_DispatchRoutineHook != g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CLOSE])
        {
            g_pOriginalDispatch[i].pfnClose=g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CLOSE];
            g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CLOSE]=PAV_DispatchRoutineHook;
        }

        if (PAV_DispatchRoutineHook != g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CLEANUP])
        {
            g_pOriginalDispatch[i].pfnCleanup=g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CLEANUP];
            g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CLEANUP]=PAV_DispatchRoutineHook;
        }
    }
}


VOID
PAV_IrpHookRemove (
    VOID
)

/*++

Routine Discription:

    Removes  the  IRP  hooks and restore the original dispatch routines of each
    hooked device.

--*/

{
    ULONG i;

    // restore every hooked driver's dispatch routine entries

    for (i=0; i<MAX_DISK; i++)
    {
        if (g_pDrvObjTab[i] != NULL)
        {
            if (g_pOriginalDispatch[i].pfnCreate != NULL)
            {
                g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CREATE]=g_pOriginalDispatch[i].pfnCreate;
            }

            if (g_pOriginalDispatch[i].pfnWrite != NULL)
            {
                g_pDrvObjTab[i]->MajorFunction[IRP_MJ_WRITE]=g_pOriginalDispatch[i].pfnWrite;
            }

            if (g_pOriginalDispatch[i].pfnClose != NULL)
            {
                g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CLOSE]=g_pOriginalDispatch[i].pfnClose;
            }

            if (g_pOriginalDispatch[i].pfnCleanup != NULL)
            {
                g_pDrvObjTab[i]->MajorFunction[IRP_MJ_CLEANUP]=g_pOriginalDispatch[i].pfnCleanup;
            }
        }
    }
}

原创粉丝点击