内核级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、付费专栏及课程。

余额充值