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

内核级HOOK的几种实现与应用
[  文章来源:网络     发表日期:2003/09/22    提交: TomyDan网络工作室   ]
   
内核级HOOK的几种实现与应用

Author  : sinister
Email   : sinister@whitecell.org
HomePage: http://www.whitecell.org  


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

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值