• 内核级HOOK的几种实现与应用


    创建时间:2003-03-26
    文章来源:http://www.whitecell.org
    文章提交:sinister (jiasys_at_21cn.com)

    内核级HOOK的几种实现与应用

    Author  : sinister
    Email   : sinister@whitecell.org
    HomePage: http://www.whitecell.org  


        实现内核级 HOOK 对于拦截、分析、跟踪系统内核起着致关重要的作用。实现的方法不同意味着应用侧重点的不同。如想要拦截 NATIVE API 那么可能常用的就是 HOOK SERVICE TABLE 的方法。如果要分析一些系统调用,那么可能想到用 HOOK INT 2E 中断来实现。如果想要拦截或跟踪其他内核 DRIVER 的调用,那么就要用到HOOK PE 的方法来实现。这里我们更注重的是实现,原理方面已有不少高手在网上发表过文章。大家可以结合起来读。下面以我写的几个实例程序来讲解一下各种方法的实现。错误之处还望各位指正。


    1、HOOK SERVICE TABLE 方法:
       这种方法对于拦截 NATIVE API 来说用的比较多。原理就是通过替换系统导
    出的一个 SERVICE TABLE 中相应的 NATIVE API 的地址来达到拦截的目的。
    因为此方法较为简单,网上也有不少资料来介绍。所以这里就不给出实例程序了。SERVICE TABLE 的结构如下:

    typedef struct ServiceDescriptorEntry {
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; 
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
    } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
       

    2、HOOK INT 2E 方法:
       这种方法对于跟踪、分析系统调用来说用的比较多。原理是通过替换 IDT
    表中的 INT 2E 中断,使之指向我们自己的中断服务处理例程来实现的。掌握
    此方法需要你对保护模式有一定的基础。下面的程序演示了这一过程。


    /*****************************************************************
    文件名        : WssHookInt2e.c
    描述          : 系统调用跟踪
    作者          : sinister
    最后修改日期  : 2002-11-02
    *****************************************************************/

    #include "ntddk.h"
    #include "string.h"

    #define DWORD unsigned __int32
    #define WORD unsigned __int16
    #define BYTE unsigned __int8
    #define BOOL __int32

    #define LOWORD(l)           ((WORD)(l))
    #define HIWORD(l)           ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
    #define LOBYTE(w)           ((BYTE)(w))
    #define HIBYTE(w)           ((BYTE)(((WORD)(w) >> 8) & 0xFF))

    #define MAKELONG(a, b) ((LONG) (((WORD) (a)) | ((DWORD) ((WORD) (b))) << 16)) 

    #define SYSTEMCALL 0x2e
    #define SYSNAME "System"
    #define PROCESSNAMELEN 16

    #pragma pack(1)

    //定义 IDTR 
    typedef struct tagIDTR {
            WORD IDTLimit;
            WORD LowIDTbase;
            WORD HiIDTbase;
    }IDTR, *PIDTR;

    //定义 IDT 
    typedef struct tagIDTENTRY{
        WORD OffsetLow;
        WORD selector;
        BYTE unused_lo;
        unsigned char unused_hi:5;
        unsigned char DPL:2;
        unsigned char P:1;
        WORD OffsetHigh;
    } IDTENTRY, *PIDTENTRY;


    #pragma pack()

    DWORD    OldInt2eService;
    ULONG    ProcessNameOffset;
    TCHAR   ProcessName[PROCESSNAMELEN];

    static NTSTATUS  MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
    VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);
    ULONG GetProcessNameOffset();
    VOID GetProcessName( PCHAR Name );
    VOID InstallNewInt2e();
    VOID UninstallNewInt2e();

    VOID __fastcall NativeApiCall()
    {
        KIRQL OldIrql;
        
        DWORD ServiceID;
        DWORD ProcessId;

        __asm mov ServiceID,eax;


        ProcessId = (DWORD)PsGetCurrentProcessId();
        GetProcessName(ProcessName);

        KeRaiseIrql(HIGH_LEVEL, &OldIrql); // 提升当前的 IRQL 级别防止被中断


        switch ( ServiceID )
        {
                case 0x20:
                     DbgPrint("NEWINT2E: ProcessName: %s; ProcessID: %d; Native Api: NtCreateFile() /n",ProcessName,ProcessId);
                     break;

                case 0x2b:
                     DbgPrint("NEWINT2E: ProcessName: %s; ProcessID: %d; Native Api: NtCreateSection() /n",ProcessName,ProcessId);                 
                     break;


                case 0x30:
                     DbgPrint("NEWINT2E: ProcessName: %s; ProcessID: %d; Native Api: NtCreateToken() /n",ProcessName,ProcessId);                 
                     break;
                     
        }

        KeLowerIrql(OldIrql); //恢复原始 IRQL

    }

    __declspec(naked) NewInt2eService()
    {
        __asm{
            pushad
            pushfd
            push fs
            mov bx,0x30
            mov fs,bx
            push ds
            push es

            sti
            call NativeApiCall; // 调用记录函数
            cli

            pop es
            pop ds
            pop fs
            popfd
            popad

            jmp    OldInt2eService;  //跳到原始 INT 2E 继续工作
        }
    }

    VOID InstallNewInt2e()
    {

        IDTR         idtr;
        PIDTENTRY    OIdt;
        PIDTENTRY    NIdt;

        //得到 IDTR 中得段界限与基地址
        __asm { 
            sidt idtr;
        }

        //得到IDT基地址
        OIdt = (PIDTENTRY)MAKELONG(idtr.LowIDTbase,idtr.HiIDTbase); 

        //保存原来的 INT 2E 服务例程
        OldInt2eService = MAKELONG(OIdt[SYSTEMCALL].OffsetLow,OIdt[SYSTEMCALL].OffsetHigh);
        
        NIdt = &(OIdt[SYSTEMCALL]);

        __asm {
            cli
            lea eax,NewInt2eService;  //得到新的 INT 2E 服务例程偏移
            mov ebx, NIdt;
            mov [ebx],ax;   //INT 2E 服务例程低 16 位
            shr eax,16      //INT 2E 服务例程高 16 位
            mov [ebx+6],ax;
            lidt idtr  //装入新的 IDT
            sti
        }

    }

    VOID UninstallNewInt2e()
    {
        IDTR         idtr;
        PIDTENTRY    OIdt;
        PIDTENTRY    NIdt;

        __asm {
            sidt idtr;
        }

        OIdt = (PIDTENTRY)MAKELONG(idtr.LowIDTbase,idtr.HiIDTbase); 

        NIdt = &(OIdt[SYSTEMCALL]);

        _asm {
            cli
            lea eax,OldInt2eService;
            mov ebx, NIdt;
            mov [ebx],ax;
            shr eax,16
            mov [ebx+6],ax;
            lidt idtr
            sti
        }

    }




    // 驱动入口
    NTSTATUS  DriverEntry( IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath ) 
    {
        
        UNICODE_STRING  nameString, linkString;
        PDEVICE_OBJECT  deviceObject;
        NTSTATUS        status;
        HANDLE          hHandle;
        int                i;
        

        //卸载驱动
        DriverObject->DriverUnload = DriverUnload;

        //建立设备
        RtlInitUnicodeString( &nameString, L"//Device//WssHookInt2e" );
        
        status = IoCreateDevice( DriverObject,
                                 0,
                                 &nameString,
                                 FILE_DEVICE_UNKNOWN,
                                 0,
                                 TRUE,
                                 &deviceObject
                               );
                               

        if (!NT_SUCCESS( status ))
            return status;
        

        RtlInitUnicodeString( &linkString, L"//DosDevices//WssHookInt2e" );

        status = IoCreateSymbolicLink (&linkString, &nameString);

        if (!NT_SUCCESS( status ))
        {
            IoDeleteDevice (DriverObject->DeviceObject);
            return status;
        }    
        

        for ( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)    {

              DriverObject->MajorFunction[i] = MydrvDispatch;
        }

          DriverObject->DriverUnload = DriverUnload;

        ProcessNameOffset = GetProcessNameOffset();
        InstallNewInt2e();

      return STATUS_SUCCESS; 




    //处理设备对象操作

    static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0L;
        IoCompleteRequest( Irp, 0 );
        return Irp->IoStatus.Status;
        
    }



    VOID DriverUnload (IN PDRIVER_OBJECT    pDriverObject)
    {
        UNICODE_STRING  nameString;

        UninstallNewInt2e();
        RtlInitUnicodeString( &nameString, L"//DosDevices//WssHookInt2e" );    
        IoDeleteSymbolicLink(&nameString);
        IoDeleteDevice(pDriverObject->DeviceObject);

        return;
    }



    ULONG GetProcessNameOffset()
    {
            PEPROCESS curproc;
            int i;
            
            curproc = PsGetCurrentProcess();

            //
            // Scan for 12KB, hopping the KPEB never grows that big!
            //
            for( i = 0; i < 3*PAGE_SIZE; i++ ) {

                if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) {

                    return i;
                }
            }

            //
            // Name not found - oh, well
            //
            return 0;
    }

    VOID GetProcessName( PCHAR Name )
    {

            PEPROCESS curproc;
            char *nameptr;
            ULONG i;

            if( ProcessNameOffset ) {

                curproc = PsGetCurrentProcess();
                nameptr = (PCHAR) curproc + ProcessNameOffset;
                strncpy( Name, nameptr, 16 );

            } else {

                strcpy( Name, "???");
            }



    3、 HOOK PE 方法
        这种方法对于拦截、分析其他内核驱动的函数调用来说用的比较多。原理
    是根据替换 PE 格式导出表中的相应函数来实现的。此方法中需要用到一些小
    技巧。如内核模式并没有直接提供类似应用层的 GetModuleHandl()、GetProcAddress() 等函数来获得模块的地址。那么我们就需要自己来编写,这
    里用到了一个未公开的函数与结构。ZwQuerySystemInformation 与 SYSTEM_MODULE_INFORMATION 来实现得到模块的基地址。这样我们就可以根据
    PE 格式来枚举导出表中的函数来替换了。但这又引出了一个问题,那就是从
    WINDOWS 2000 后内核数据的页属性都是只读的,不能更改。内核模式也没有
    提供类似应用层的 VirtualProtectEx() 等函数来修改页面属性。那么也需要
    我们自己来编写。因为我们是在内核模式所以我们可以通过修改 cr0 寄存器的
    的写保护位来达到我们的目的。这样我们所期望的拦截内核模式函数的功能便
    得以实现。此方法需要你对 PE 格式有一定的基础。下面的程序演示了这一过程。



    /*****************************************************************
    文件名        : WssHookPE.c
    描述          : 拦截内核函数
    作者          : sinister
    最后修改日期  : 2002-11-02
    *****************************************************************/

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


    typedef enum _SYSTEM_INFORMATION_CLASS {
        SystemBasicInformation,
        SystemProcessorInformation,
        SystemPerformanceInformation,
        SystemTimeOfDayInformation,
        SystemNotImplemented1,
        SystemProcessesAndThreadsInformation,
        SystemCallCounts,
        SystemConfigurationInformation,
        SystemProcessorTimes,
        SystemGlobalFlag,
        SystemNotImplemented2,
        SystemModuleInformation,
        SystemLockInformation,
        SystemNotImplemented3,
        SystemNotImplemented4,
        SystemNotImplemented5,
        SystemHandleInformation,
        SystemObjectInformation,
        SystemPagefileInformation,
        SystemInstructionEmulationCounts,
        SystemInvalidInfoClass1,
        SystemCacheInformation,
        SystemPoolTagInformation,
        SystemProcessorStatistics,
        SystemDpcInformation,
        SystemNotImplemented6,
        SystemLoadImage,
        SystemUnloadImage,
        SystemTimeAdjustment,
        SystemNotImplemented7,
        SystemNotImplemented8,
        SystemNotImplemented9,
        SystemCrashDumpInformation,
        SystemExceptionInformation,
        SystemCrashDumpStateInformation,
        SystemKernelDebuggerInformation,
        SystemContextSwitchInformation,
        SystemRegistryQuotaInformation,
        SystemLoadAndCallImage,
        SystemPrioritySeparation,
        SystemNotImplemented10,
        SystemNotImplemented11,
        SystemInvalidInfoClass2,
        SystemInvalidInfoClass3,
        SystemTimeZoneInformation,
        SystemLookasideInformation,
        SystemSetTimeSlipEvent,
        SystemCreateSession,
        SystemDeleteSession,
        SystemInvalidInfoClass4,
        SystemRangeStartInformation,
        SystemVerifierInformation,
        SystemAddVerifier,
        SystemSessionProcessesInformation
    } SYSTEM_INFORMATION_CLASS;


    typedef struct tagSYSTEM_MODULE_INFORMATION {
        ULONG Reserved[2];
        PVOID Base;
        ULONG Size;
        ULONG Flags;
        USHORT Index;
        USHORT Unknown;
        USHORT LoadCount;
        USHORT ModuleNameOffset;
        CHAR ImageName[256];
    } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

    #define IMAGE_DOS_SIGNATURE        0x5A4D      // MZ
    #define IMAGE_NT_SIGNATURE      0x50450000  // PE00
    #define IMAGE_NT_SIGNATURE1        0x00004550    // 00EP

    typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
        WORD   e_magic;                     // Magic number
        WORD   e_cblp;                      // Bytes on last page of file
        WORD   e_cp;                        // Pages in file
        WORD   e_crlc;                      // Relocations
        WORD   e_cparhdr;                   // Size of header in paragraphs
        WORD   e_minalloc;                  // Minimum extra paragraphs needed
        WORD   e_maxalloc;                  // Maximum extra paragraphs needed
        WORD   e_ss;                        // Initial (relative) SS value
        WORD   e_sp;                        // Initial SP value
        WORD   e_csum;                      // Checksum
        WORD   e_ip;                        // Initial IP value
        WORD   e_cs;                        // Initial (relative) CS value
        WORD   e_lfarlc;                    // File address of relocation table
        WORD   e_ovno;                      // Overlay number
        WORD   e_res[4];                    // Reserved words
        WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
        WORD   e_oeminfo;                   // OEM information; e_oemid specific
        WORD   e_res2[10];                  // Reserved words
        LONG   e_lfanew;                    // File address of new exe header
      } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;


    typedef struct _IMAGE_FILE_HEADER {
        WORD    Machine;
        WORD    NumberOfSections;
        DWORD   TimeDateStamp;
        DWORD   PointerToSymbolTable;
        DWORD   NumberOfSymbols;
        WORD    SizeOfOptionalHeader;
        WORD    Characteristics;
    } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

    typedef struct _IMAGE_DATA_DIRECTORY {
        DWORD   VirtualAddress;
        DWORD   Size;
    } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

    #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

    //
    // Optional header format.
    //

    typedef struct _IMAGE_OPTIONAL_HEADER {
        //
        // Standard fields.
        //

        WORD    Magic;
        BYTE    MajorLinkerVersion;
        BYTE    MinorLinkerVersion;
        DWORD   SizeOfCode;
        DWORD   SizeOfInitializedData;
        DWORD   SizeOfUninitializedData;
        DWORD   AddressOfEntryPoint;
        DWORD   BaseOfCode;
        DWORD   BaseOfData;

        //
        // NT additional fields.
        //

        DWORD   ImageBase;
        DWORD   SectionAlignment;
        DWORD   FileAlignment;
        WORD    MajorOperatingSystemVersion;
        WORD    MinorOperatingSystemVersion;
        WORD    MajorImageVersion;
        WORD    MinorImageVersion;
        WORD    MajorSubsystemVersion;
        WORD    MinorSubsystemVersion;
        DWORD   Win32VersionValue;
        DWORD   SizeOfImage;
        DWORD   SizeOfHeaders;
        DWORD   CheckSum;
        WORD    Subsystem;
        WORD    DllCharacteristics;
        DWORD   SizeOfStackReserve;
        DWORD   SizeOfStackCommit;
        DWORD   SizeOfHeapReserve;
        DWORD   SizeOfHeapCommit;
        DWORD   LoaderFlags;
        DWORD   NumberOfRvaAndSizes;
        IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
    } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

    typedef struct _IMAGE_NT_HEADERS {
        DWORD Signature;
        IMAGE_FILE_HEADER FileHeader;
        IMAGE_OPTIONAL_HEADER32 OptionalHeader;
    } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

    typedef IMAGE_NT_HEADERS32                  IMAGE_NT_HEADERS;
    typedef PIMAGE_NT_HEADERS32                 PIMAGE_NT_HEADERS;

    //
    // Section header format.
    //

    #define IMAGE_SIZEOF_SHORT_NAME              8

    typedef struct _IMAGE_SECTION_HEADER {
        BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
        union {
                DWORD   PhysicalAddress;
                DWORD   VirtualSize;
        } Misc;
        DWORD   VirtualAddress;
        DWORD   SizeOfRawData;
        DWORD   PointerToRawData;
        DWORD   PointerToRelocations;
        DWORD   PointerToLinenumbers;
        WORD    NumberOfRelocations;
        WORD    NumberOfLinenumbers;
        DWORD   Characteristics;
    } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

    #define IMAGE_SIZEOF_SECTION_HEADER          40
    //
    // Export Format
    //

    typedef struct _IMAGE_EXPORT_DIRECTORY {
        DWORD   Characteristics;
        DWORD   TimeDateStamp;
        WORD    MajorVersion;
        WORD    MinorVersion;
        DWORD   Name;
        DWORD   Base;
        DWORD   NumberOfFunctions;
        DWORD   NumberOfNames;
        DWORD   AddressOfFunctions;     // RVA from base of image
        DWORD   AddressOfNames;         // RVA from base of image
        DWORD   AddressOfNameOrdinals;  // RVA from base of image
    } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

    #define BASEADDRLEN 10

    NTSYSAPI
    NTSTATUS
    NTAPI
    ZwQuerySystemInformation(
        IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
        IN OUT PVOID SystemInformation,
        IN ULONG SystemInformationLength,
        OUT PULONG ReturnLength OPTIONAL
        );


    typedef NTSTATUS (* ZWCREATEFILE)(
      OUT PHANDLE FileHandle,
      IN ACCESS_MASK DesiredAccess,
      IN POBJECT_ATTRIBUTES ObjectAttributes,
      OUT PIO_STATUS_BLOCK IoStatusBlock,
      IN PLARGE_INTEGER AllocationSize  OPTIONAL,
      IN ULONG FileAttributes,
      IN ULONG ShareAccess,
      IN ULONG CreateDisposition,
      IN ULONG CreateOptions,
      IN PVOID EaBuffer  OPTIONAL,
      IN ULONG EaLength
      );

    ZWCREATEFILE    OldZwCreateFile;

    static NTSTATUS  MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
    VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);
    VOID DisableWriteProtect( PULONG pOldAttr);
    VOID EnableWriteProtect( ULONG ulOldAttr );
    FARPROC HookFunction(    PCHAR pModuleBase, PCHAR pHookName, FARPROC pHookFunc );

    NTSTATUS  
    HookNtCreateFile(
      OUT PHANDLE FileHandle,
      IN ACCESS_MASK DesiredAccess,
      IN POBJECT_ATTRIBUTES ObjectAttributes,
      OUT PIO_STATUS_BLOCK IoStatusBlock,
      IN PLARGE_INTEGER AllocationSize  OPTIONAL,
      IN ULONG FileAttributes,
      IN ULONG ShareAccess,
      IN ULONG CreateDisposition,
      IN ULONG CreateOptions,
      IN PVOID EaBuffer  OPTIONAL,
      IN ULONG EaLength
      );



    PCHAR MyGetModuleBaseAddress( PCHAR pModuleName ) 
    {
        PSYSTEM_MODULE_INFORMATION    pSysModule;    

        ULONG            uReturn;
        ULONG            uCount;
        PCHAR            pBuffer = NULL;
        PCHAR            pName    = NULL;
        NTSTATUS        status;
        UINT            ui;

        CHAR            szBuffer[BASEADDRLEN];
        PCHAR            pBaseAddress;
        
        status = ZwQuerySystemInformation( SystemModuleInformation, szBuffer, BASEADDRLEN, &uReturn );

        pBuffer = ( PCHAR )ExAllocatePool( NonPagedPool, uReturn );

        if ( pBuffer )
        {
            status = ZwQuerySystemInformation( SystemModuleInformation, pBuffer, uReturn, &uReturn );

            if( status == STATUS_SUCCESS )
            {
                uCount = ( ULONG )*( ( ULONG * )pBuffer );
                pSysModule = ( PSYSTEM_MODULE_INFORMATION )( pBuffer + sizeof( ULONG ) );

                for ( ui = 0; ui < uCount; ui++ )
                {
                    pName = MyStrchr( pSysModule->ImageName, '//' );

                    if ( !pName ) 
                    {
                        pName = pSysModule->ImageName;
                    }

                    else {
                        pName++;
                    }

                    if( !_stricmp( pName, pModuleName ) )
                    {
                        pBaseAddress = ( PCHAR )pSysModule->Base;
                        ExFreePool( pBuffer );
                        return pBaseAddress;
                    }

                    pSysModule ++;
                }
            }

            ExFreePool( pBuffer );
        }

        return NULL;
    }


    FARPROC HookFunction( PCHAR pModuleBase, PCHAR HookFunName, FARPROC HookFun )
    {
        PIMAGE_DOS_HEADER         pDosHdr;
        PIMAGE_NT_HEADERS         pNtHdr;
        PIMAGE_SECTION_HEADER     pSecHdr;
        PIMAGE_EXPORT_DIRECTORY  pExtDir;

        UINT                    ui,uj;
        PCHAR                    FunName;
        DWORD                    *dwAddrName;
        DWORD                    *dwAddrFun;
        FARPROC                    pOldFun;
        ULONG                    uAttrib;


        pDosHdr = ( PIMAGE_DOS_HEADER )pModuleBase;

        if ( IMAGE_DOS_SIGNATURE == pDosHdr->e_magic )
        {
            pNtHdr = ( PIMAGE_NT_HEADERS )( pModuleBase + pDosHdr->e_lfanew );

            if( IMAGE_NT_SIGNATURE  == pNtHdr->Signature ||    IMAGE_NT_SIGNATURE1 == pNtHdr->Signature )
            {
                pSecHdr = ( PIMAGE_SECTION_HEADER )( pModuleBase + pDosHdr->e_lfanew + sizeof( IMAGE_NT_HEADERS ) );

                for ( ui = 0; ui < (UINT)pNtHdr->FileHeader.NumberOfSections; ui++ )
                {
                    if ( !strcmp( pSecHdr->Name, ".edata" ) )
                    {                
                        pExtDir = ( PIMAGE_EXPORT_DIRECTORY )( pModuleBase + pSecHdr->VirtualAddress );
                        dwAddrName = ( PDWORD )(pModuleBase + pExtDir->AddressOfNames );
                        dwAddrFun = ( PDWORD )(pModuleBase + pExtDir->AddressOfFunctions );

                        for ( uj = 0; uj < (UINT)pExtDir->NumberOfFunctions; uj++ )
                        {
                            FunName = pModuleBase + *dwAddrName;

                            if( !strcmp( FunName, HookFunName ) )
                            {
                                DbgPrint(" HOOK  %s()/n",FunName);
                                DisableWriteProtect( &uAttrib );
                                pOldFun = ( FARPROC )( pModuleBase + *dwAddrFun );
                                *dwAddrFun = ( PCHAR )HookFun - pModuleBase;
                                EnableWriteProtect( uAttrib );
                                return pOldFun;
                            }

                          dwAddrName ++;
                          dwAddrFun ++;
                        }
                    }

                    pSecHdr++;
                }
            }
        }

        return NULL;
    }


    // 驱动入口
    NTSTATUS  DriverEntry( IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath ) 
    {
        
        UNICODE_STRING  nameString, linkString;
        PDEVICE_OBJECT  deviceObject;
        NTSTATUS        status;
        HANDLE          hHandle;
        PCHAR            pModuleAddress;
        int                i;
        

        //卸载驱动
        DriverObject->DriverUnload = DriverUnload;

        //建立设备
        RtlInitUnicodeString( &nameString, L"//Device//WssHookPE" );
        
        status = IoCreateDevice( DriverObject,
                                 0,
                                 &nameString,
                                 FILE_DEVICE_UNKNOWN,
                                 0,
                                 TRUE,
                                 &deviceObject
                               );
                               

        if (!NT_SUCCESS( status ))
            return status;
        

        RtlInitUnicodeString( &linkString, L"//DosDevices//WssHookPE" );

        status = IoCreateSymbolicLink (&linkString, &nameString);

        if (!NT_SUCCESS( status ))
        {
            IoDeleteDevice (DriverObject->DeviceObject);
            return status;
        }    
        
        pModuleAddress = MyGetModuleBaseAddress("ntoskrnl.exe");
        if ( pModuleAddress == NULL)
        {
            DbgPrint(" MyGetModuleBaseAddress()/n");
            return 0;
        }

        OldZwCreateFile = (ZWCREATEFILE)HookFunction( pModuleAddress, "ZwCreateFile",(ZWCREATEFILE)HookNtCreateFile);
        if ( OldZwCreateFile == NULL)
        {
            DbgPrint(" HOOK FAILED/n");
            return 0;
        }

        DbgPrint("HOOK SUCCEED/n");

        for ( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)    {

              DriverObject->MajorFunction[i] = MydrvDispatch;
        }

          DriverObject->DriverUnload = DriverUnload;
         
      return STATUS_SUCCESS; 




    //处理设备对象操作

    static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0L;
        IoCompleteRequest( Irp, 0 );
        return Irp->IoStatus.Status;
        
    }



    VOID DriverUnload (IN PDRIVER_OBJECT    pDriverObject)
    {
        UNICODE_STRING  nameString;
        PCHAR            pModuleAddress;

        pModuleAddress = MyGetModuleBaseAddress("ntoskrnl.exe");
        if ( pModuleAddress == NULL)
        {
            DbgPrint("MyGetModuleBaseAddress()/n");
            return ;
        }

        OldZwCreateFile = (ZWCREATEFILE)HookFunction( pModuleAddress, "ZwCreateFile",(ZWCREATEFILE)OldZwCreateFile);
        if ( OldZwCreateFile == NULL)
        {
            DbgPrint(" UNHOOK FAILED!/n");
            return ;
        }

        DbgPrint("UNHOOK SUCCEED/n");

        RtlInitUnicodeString( &nameString, L"//DosDevices//WssHookPE" );    
        IoDeleteSymbolicLink(&nameString);
        IoDeleteDevice(pDriverObject->DeviceObject);

        return;
    }

    NTSTATUS  
    HookNtCreateFile(
      OUT PHANDLE FileHandle,
      IN ACCESS_MASK DesiredAccess,
      IN POBJECT_ATTRIBUTES ObjectAttributes,
      OUT PIO_STATUS_BLOCK IoStatusBlock,
      IN PLARGE_INTEGER AllocationSize  OPTIONAL,
      IN ULONG FileAttributes,
      IN ULONG ShareAccess,
      IN ULONG CreateDisposition,
      IN ULONG CreateOptions,
      IN PVOID EaBuffer  OPTIONAL,
      IN ULONG EaLength
      )
    {
        NTSTATUS    status;

        DbgPrint("Hook ZwCreateFile()/n");

        status = ((ZWCREATEFILE)(OldZwCreateFile))(
                   FileHandle,
                   DesiredAccess,
                   ObjectAttributes,
                   IoStatusBlock,
                   AllocationSize,
                   FileAttributes,
                   ShareAccess,
                   CreateDisposition,
                   CreateOptions,
                   EaBuffer,
                   EaLength
                  );

        return status;
    }


    VOID DisableWriteProtect( PULONG pOldAttr)
    {

         ULONG uAttr;

         _asm
        {
              push eax;
              mov  eax, cr0;
              mov  uAttr, eax;
              and  eax, 0FFFEFFFFh; // CR0 16 BIT = 0
              mov  cr0, eax;
              pop  eax;
        };

         *pOldAttr = uAttr; //保存原有的 CRO 属性

    }

    VOID EnableWriteProtect( ULONG uOldAttr )
    {

      _asm
      {
           push eax;
           mov  eax, uOldAttr; //恢复原有 CR0 属性
           mov  cr0, eax;
           pop  eax;
      };

    }

     http://blog.csdn.net/kl222/article/details/1658910

  • 相关阅读:
    天气渐凉,意渐浓
    WebBrowser 多线程 DocumentCompleted 和定时器
    浅谈 Glide
    浅谈 maxMemory , totalMemory , freeMemory 和 OOM 与 native Heap
    XGoServer 一个基础性、模块完整且安全可靠的服务端框架
    GreenDao 兼容升级,保留旧数据的---全方面解决方案
    基于 xorm 的服务端框架 XGoServer
    全面总结: Golang 调用 C/C++,例子式教程
    通俗易懂,各常用线程池的执行 流程图
    为什么我的子线程更新了 UI 没报错?借此,纠正一些Android 程序员的一个知识误区
  • 原文地址:https://www.cnblogs.com/findumars/p/5087475.html
Copyright © 2020-2023  润新知