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


    实现内核级 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()  ",ProcessName,ProcessId); 
                     break; 

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


                case 0x30: 
                     DbgPrint("NEWINT2E: ProcessName: %s; ProcessID: %d; Native Api: NtCreateToken()  ",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() ",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() "); 
            return 0; 
        } 

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

        DbgPrint("HOOK SUCCEED "); 

        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() "); 
            return ; 
        } 

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

        DbgPrint("UNHOOK SUCCEED "); 

        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() "); 

        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://www.cnblogs.com/lzjsky/archive/2010/11/19/1881568.html

  • 相关阅读:
    【原创】禁止快播自动升级到最新版本,自己发现的方法
    又一灵异事件 Delphi 2007 在 Win7
    [DCC Error] E2161 Error: RLINK32: Error opening file "_____.drf"
    单例模式 改进
    estackoverflow with message 'stack overflow'
    所有可选的快捷键列表[转自万一博客]
    SQL server 除法运算
    正则表达式的一个坑[.\n]无效引起的血案
    getcwd()和__DIR__区别
    并发处理的技巧php
  • 原文地址:https://www.cnblogs.com/findumars/p/5625072.html
Copyright © 2020-2023  润新知