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