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

内核级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;

  };

 

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值