转自安焦
????实现内核级 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)))
#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
??????????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
????????????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
????????????{
????????????????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 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 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
??????????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;
??};
}