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