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

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

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

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

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

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

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

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

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

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

#pragma pack(1)

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

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

#pragma pack()

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

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

VOID __fastcall NativeApiCall() 

    KIRQL OldIrql; 
     
    DWORD ServiceID; 
    DWORD ProcessId;

__asm mov ServiceID,eax;

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

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

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

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

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

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

}

__declspec(naked) NewInt2eService() 

    __asm{ 
        pushad 
        pushfd 
        push fs 
        mov bx,0x30 
        mov fs,bx 
        push ds 
        push es

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

pop es 
        pop ds 
        pop fs 
        popfd 
        popad

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

VOID InstallNewInt2e() 
{

IDTR         idtr; 
    PIDTENTRY    OIdt; 
    PIDTENTRY    NIdt;

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

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

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

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

}

VOID UninstallNewInt2e() 

    IDTR         idtr; 
    PIDTENTRY    OIdt; 
    PIDTENTRY    NIdt;

__asm { 
        sidt idtr; 
    }

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

NIdt = &(OIdt[SYSTEMCALL]);

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

}

// 驱动入口 
NTSTATUS  DriverEntry( IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath )  

     
    UNICODE_STRING  nameString, linkString; 
    PDEVICE_OBJECT  deviceObject; 
    NTSTATUS        status; 
    HANDLE          hHandle; 
    int                i;

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

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

if (!NT_SUCCESS( status )) 
        return status;

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

status = IoCreateSymbolicLink (&linkString, &nameString);

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

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

DriverObject->MajorFunction[i] = MydrvDispatch; 
    }

DriverObject->DriverUnload = DriverUnload;

ProcessNameOffset = GetProcessNameOffset(); 
    InstallNewInt2e();

return STATUS_SUCCESS;  
}

//处理设备对象操作

static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) 
{  
    Irp->IoStatus.Status = STATUS_SUCCESS; 
    Irp->IoStatus.Information = 0L; 
    IoCompleteRequest( Irp, 0 ); 
    return Irp->IoStatus.Status; 
     
}

VOID DriverUnload (IN PDRIVER_OBJECT    pDriverObject) 

    UNICODE_STRING  nameString;

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

return; 
}

ULONG GetProcessNameOffset() 

        PEPROCESS curproc; 
        int i; 
         
        curproc = PsGetCurrentProcess();

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

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

return i; 
            } 
        }

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

VOID GetProcessName( PCHAR Name ) 
{

PEPROCESS curproc; 
        char *nameptr; 
        ULONG i;

if( ProcessNameOffset ) {

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

} else {

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

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

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

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

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

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

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

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

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

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

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

// 
// Optional header format. 
//

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

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

// 
    // NT additional fields. 
    //

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

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

typedef IMAGE_NT_HEADERS32                  IMAGE_NT_HEADERS; 
typedef PIMAGE_NT_HEADERS32                 PIMAGE_NT_HEADERS;

// 
// Section header format. 
//

#define IMAGE_SIZEOF_SHORT_NAME              8

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

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

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

#define BASEADDRLEN 10

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

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

ZWCREATEFILE    OldZwCreateFile;

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

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

PCHAR MyGetModuleBaseAddress( PCHAR pModuleName )  

    PSYSTEM_MODULE_INFORMATION    pSysModule;

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

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

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

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

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

for ( ui = 0; ui < uCount; ui++ ) 
            { 
                pName = MyStrchr( pSysModule->ImageName, ‘\\’ );

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

else { 
                    pName++; 
                }

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

pSysModule ++; 
            } 
        }

ExFreePool( pBuffer ); 
    }

return NULL; 
}

FARPROC HookFunction( PCHAR pModuleBase, PCHAR HookFunName, FARPROC HookFun ) 

    PIMAGE_DOS_HEADER         pDosHdr; 
    PIMAGE_NT_HEADERS         pNtHdr; 
    PIMAGE_SECTION_HEADER     pSecHdr; 
    PIMAGE_EXPORT_DIRECTORY  pExtDir;

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

pDosHdr = ( PIMAGE_DOS_HEADER )pModuleBase;

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

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

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

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

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

dwAddrName ++; 
                      dwAddrFun ++; 
                    } 
                }

pSecHdr++; 
            } 
        } 
    }

return NULL; 
}

// 驱动入口 
NTSTATUS  DriverEntry( IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath )  

     
    UNICODE_STRING  nameString, linkString; 
    PDEVICE_OBJECT  deviceObject; 
    NTSTATUS        status; 
    HANDLE          hHandle; 
    PCHAR            pModuleAddress; 
    int                i;

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

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

if (!NT_SUCCESS( status )) 
        return status;

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

status = IoCreateSymbolicLink (&linkString, &nameString);

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

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

DbgPrint("HOOK SUCCEED\n");

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

DriverObject->MajorFunction[i] = MydrvDispatch; 
    }

DriverObject->DriverUnload = DriverUnload; 
      
  return STATUS_SUCCESS;  
}

//处理设备对象操作

static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) 
{  
    Irp->IoStatus.Status = STATUS_SUCCESS; 
    Irp->IoStatus.Information = 0L; 
    IoCompleteRequest( Irp, 0 ); 
    return Irp->IoStatus.Status; 
     
}

VOID DriverUnload (IN PDRIVER_OBJECT    pDriverObject) 

    UNICODE_STRING  nameString; 
    PCHAR            pModuleAddress;

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

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

DbgPrint("UNHOOK SUCCEED\n");

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

return; 
}

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

    NTSTATUS    status;

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

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

return status; 
}

VOID DisableWriteProtect( PULONG pOldAttr) 
{

ULONG uAttr;

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

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

}

VOID EnableWriteProtect( ULONG uOldAttr ) 
{

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

}

http://www.cnblogs.com/lzjsky/archive/2010/11/19/1881568.html

内核级HOOK的几种实现与应用的更多相关文章

  1. SSDT Hook实现内核级的进程保护

    目录 SSDT Hook效果图 SSDT简介 SSDT结构 SSDT HOOK原理 Hook前准备 如何获得SSDT中函数的地址呢 SSDT Hook流程 SSDT Hook实现进程保护 Ring3与 ...

  2. Windows平台内核级文件访问

    1.背景     在windows平台下,应用程序通常使用API函数来进行文件访问,创建,打开,读写文件.从kernel32的CreateFile/ReadFile/WriteFile函数,到本地系统 ...

  3. Windows2003 内核级进程隐藏、侦测技术

    论文关键字: 内核 拦截 活动进程链表 系统服务派遣表 线程调度链 驱动程序简介    论文摘要:信息对抗是目前计算机发展的一个重要的方向,为了更好的防御,必须去深入的了解敌人进攻的招式.信息对抗促使 ...

  4. 【原创】内核ShellCode注入的一种方法

    标 题: [原创]内核ShellCode注入的一种方法 作 者: organic 时 间: 2013-05-04,04:34:08 链 接: http://bbs.pediy.com/showthre ...

  5. 多线程 用户级线程和内核级线程 from C++多核高级编程

    转 http://book.51cto.com/art/201006/206946.htm 6.1.1 用户级线程和内核级线程 2010-06-21 20:37 齐宁/董泽惠 译 清华大学出版社 字号 ...

  6. Linux用户级线程和内核级线程区别

    1.内核级线程: (1)线程的创建.撤销和切换等,都需要内核直接实现,即内核了解每一个作为可调度实体的线程.(2)这些线程可以在全系统内进行资源的竞争.(3)内核空间内为每一个内核支持线程设置了一个线 ...

  7. 内核级线程(KLT)和用户级线程(ULT)

    内核级线程(KLT)和用户级线程(ULT) tags: KLT ULT 内核级线程 用户级线程 引言:本文涉及到操作系统的内核模式和用户模式,如果不太懂的话,可以参看我的这篇文章内核模式和用户模式,其 ...

  8. {Python之线程} 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Threading模块 九 锁 十 信号量 十一 事件Event 十二 条件Condition(了解) 十三 定时器

    Python之线程 线程 本节目录 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Thr ...

  9. 从0开始:Windows内核利用的另一种方式

    https://www.anquanke.com/post/id/91063 从0开始:Windows内核利用的另一种方式 阅读量    9168 |   稿费 200   分享到: 发布时间:201 ...

随机推荐

  1. 有结果集的mysqli函数获取行数和列数

    <?php $mysqli=new mysqli("localhost", "root", "123456", "xsphp ...

  2. Python之路第五天,基础(5)-序列化和字符串格式化

    序列化 Python中用于序列化的两个模块 json 用于『字符串』和『python基本数据类型』间进行转换 pickle 用于『python特有的类型』和『python基本数据类型』间进行转换 js ...

  3. sql server 2008 (1)(2)

    ---恢复内容开始--- sql server 2008 (1) 系统数据库 master tempdb module 正文 数据库管理员(DBA)的一项基本的技能是对SQL数据库引擎的系统数据库的深 ...

  4. Python urllib和urllib2模块学习(二)

    一.urllib其它函数 前面介绍了 urllib 模块,以及它常用的 urlopen() 和 urlretrieve()函数的使用介绍.当然 urllib 还有一些其它很有用的辅助方法,比如对 ur ...

  5. 关于LWIP---UDP

    lwip是一个轻量级的TCP/IP协议栈(Lightweight TCP/IP Stack)实现,最初是瑞士计算机科学学院Adam Dunkels编写的一个应用于无操作系统的嵌入式系统中的TCP/IP ...

  6. WPS Office手机版调用接口代码指导帖之一(Android)

    经常会有一些喜欢开发鼓捣的童鞋问我们,WPS Office手机版是否提供调用接口,希望在android中使用一个调用命令,直接调用WPS手机版来打开指定的DOC文件,而不用弹出一个程序可选列表(如果用 ...

  7. 没有产品,没有用户的,绝对不要浪费时间去联系风投——没有过home run的创业人,想办法先做出产品,找到少量用户,没有任何销售成本

    著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:Kuan Huang链接:http://www.zhihu.com/question/19641135/answer/1353 ...

  8. discuz方法赏析

    public static function limit($start, $limit = 0) { $limit = intval($limit > 0 ? $limit : 0); $sta ...

  9. POJ 2429 GCD & LCM Inverse(Pollard_Rho+dfs)

    [题目链接] http://poj.org/problem?id=2429 [题目大意] 给出最大公约数和最小公倍数,满足要求的x和y,且x+y最小 [题解] 我们发现,(x/gcd)*(y/gcd) ...

  10. poj1338

                                                                                 Ugly Numbers Time Limit ...