內核級HOOK的幾種實現與應用 |
|
conundrum
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:893 回覆:1272 積分:643 註冊:2004-01-06 發送簡訊給我 |
內核級HOOK的幾種實現與應用 文章來源:http://www.whitecell.org 文章提交:sinister (jiasys_at_21cn.com) 內核級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; }; }發表人 - conundrum 於 2004/05/30 16:19:06 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |