zoukankan      html  css  js  c++  java
  • 内核级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;
    }


    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;
      };

    }

  • 相关阅读:
    如何通过命令行窗口查看sqlite数据库文件
    eclipse自动补全的设置
    文本装饰
    注释和特殊符号
    文本装饰
    网页背景
    通过ArcGIS Server admin 查看和删除已注册的 Web Adaptor
    通过 ArcGIS Server Manager 查看已安装的 Web Adaptor
    通过 ArcGIS Server Manager 验证 DataStore
    Windows上安装ArcGIS Enterprise——以 Windows Server 2012 R2上安装 ArcGIS 10.8为例
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1881568.html
Copyright © 2011-2022 走看看