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

Posted 朝闻道

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内核级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() \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; 


以上是关于内核级HOOK的几种实现与应用的主要内容,如果未能解决你的问题,请参考以下文章

关于数据同步的几种实现第五种基于软件应用程序进行同步(前四种基于数据库级,第四种做集群一主多从。)

iOS 逆向hook的几种方法

golang协程同步的几种方法

JAVA 远程 调用的几种实现方式简析 详细�0�3

(笔记)Linux内核学习之内核介绍

漏洞检测的几种方法