unit unhook360; interface uses nt_status, ntoskrnl, native, winioctl, fcall, macros; type THEAD = array[0..4] of byte; THEAD1 = array[0..5] of byte; const NtKernel = 'ntoskrnl.exe'; NtHal = 'hal.dll'; DeviceName = '\Device\unhook250'; ///设备名 DosDeviceName = '\??\unhook250'; ///符号链接名 JmpCode: THEAD = ($E9, $00, $00, $00, $00); OrgCode: THEAD = ($8B, $3F, $8B, $1C, $87); PushRetCode: THEAD1 = ($68, $00, $00, $00, $00, $C3); var f_oldirql: KIRQL; f_spinlock: KSPIN_LOCK; uKiFastCallEntryAddr: ULONG; HookAddr: ULONG; MyJmpRet: ULONG; PushRetMem: ULONG; g_usDeviceName, g_usSymbolicLinkName: UNICODE_STRING; function _DriverEntry(pDriverObject: PDRIVER_OBJECT; pusRegistryPath: PUNICODE_STRING): NTSTATUS; stdcall; function KeRaiseIrqlToDpcLevel(): KIRQL; register; external NtHal name '_KeRaiseIrqlToDpcLevel'; procedure KfLowerIrql(NewIrql: KIRQL); register; external NtHal name '_KfLowerIrql'; procedure KfReleaseSpinLock(SpinLock: PKSPIN_LOCK; NewIrql: KIRQL); register; external NtHal name '_KfReleaseSpinLock'; function KfAcquireSpinLock(SpinLock: PKSPIN_LOCK): KIRQL; register; external NtHal name '_KfAcquireSpinLock'; implementation procedure FakeKiFastCallEntry; stdcall; begin asm mov edi,dword ptr [edi] mov ebx,dword ptr [edi+eax*4] sub esp,ecx shr ecx,2 jmp [MyJmpRet]; end; end; function LoadKiHooker(): ULONG; var oldIrql: KIRQL; status: NTSTATUS; uCr0cpu: ULONG; begin asm pushfd pushad mov ecx,$176 rdmsr mov uKiFastCallEntryAddr,eax //获取KiFastCallEntry地址 xor ecx,ecx @@Label1: cmp ecx,$100 je @@Label3 mov edx,DWORD ptr [eax] cmp edx,$1C8B3F8B //搜索特征码,获取要Hook的位置 je @@Label2 inc eax inc ecx jmp @@Label1 @@Label2: mov HookAddr,eax @@Label3: popad popfd end; if (HookAddr = 0) then result := status; DbgPrint('HookAddr is:%x', HookAddr); PushRetMem := ULONG(ExAllocatePoolWithTag(NonPagedPool, 6, $544D454D)); DbgPrint('PushRetMem is:%x', PushRetMem); if (PVOID(PushRetMem) = nil) then result := status; PULONG(ulong(@JmpCode[1]))^ := PushRetMem - (HookAddr + 5); PULONG(ulong(@PushRetCode[1]))^ := DWORD(@FakeKiFastCallEntry); DbgPrint('FakeKiFastCallEntry is:%x', DWORD(@FakeKiFastCallEntry)); MyJmpRet := HookAddr + 10; KeInitializeSpinLock(@f_spinlock); f_oldirql := KfAcquireSpinLock(@f_spinlock); oldIrql := KeRaiseIrqlToDpcLevel(); asm cli push eax mov eax, cr0 mov [uCr0cpu], eax and eax, not 000010000h mov cr0, eax pop eax end; memcpy(pointer(PushRetMem), pointer(@PushRetCode), 6); DbgPrint('JmpCode is:%x', DWORD(@JmpCode)); memcpy(pointer(HookAddr), pointer(@JmpCode), 5); asm push eax mov eax, [uCr0cpu] mov cr0, eax pop eax sti end; KfLowerIrql(oldIrql); KfReleaseSpinLock(@f_spinlock, f_oldirql); end; function UnloadKiHooker(): ULONG; var oldIrql: KIRQL; status: NTSTATUS; uCr0cpu: ULONG; begin if (HookAddr <> 0) then begin KeInitializeSpinLock(@f_spinlock); f_oldirql := KfAcquireSpinLock(@f_spinlock); oldIrql := KeRaiseIrqlToDpcLevel(); asm cli push eax mov eax, cr0 mov [uCr0cpu], eax and eax, not 000010000h mov cr0, eax pop eax end; RtlCopyMemory(pointer(HookAddr), pointer(@OrgCode), 5); asm push eax mov eax, [uCr0cpu] mov cr0, eax pop eax sti end; KfLowerIrql(oldIrql); KfReleaseSpinLock(@f_spinlock, f_oldirql); ExFreePool(PVOID(PushRetMem)); end; end; function DispatchCreateClose(p_DeviceObject: PDEVICE_OBJECT; p_Irp: PIRP): NTSTATUS; stdcall; ///对打开或关闭请求的响应 ,这里就是简单的返回一个成功 begin p_Irp^.IoStatus.Status := STATUS_SUCCESS; ///设置状态为STATUS_SUCCESS 即成功 p_Irp^.IoStatus.Information := 0; IofCompleteRequest(p_Irp, IO_NO_INCREMENT); ///调用IoCompleteRequest完成IRP Result := STATUS_SUCCESS; end; procedure DriverUnload(DriverObject: PDriverObject); stdcall; begin DbgPrint('DriverUnload(DriverObject:0x%.8X)', DriverObject); DbgPrint('DriverUnload(-)'); UnloadKiHooker(); IoDeleteSymbolicLink(@g_usSymbolicLinkName); IoDeleteDevice(DriverObject^.DeviceObject); end; function _DriverEntry(pDriverObject: PDRIVER_OBJECT; pusRegistryPath: PUNICODE_STRING): NTSTATUS; var oldIrql: KIRQL; status: NTSTATUS; DeviceObject: TDeviceObject; begin status := STATUS_DEVICE_CONFIGURATION_ERROR; RtlInitUnicodeString(g_usDeviceName, DeviceName); RtlInitUnicodeString(g_usSymbolicLinkName, DosDeviceName); if (IoCreateDevice(pDriverObject, 0, @g_usDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, DeviceObject) = STATUS_SUCCESS) then begin DbgPrint('Create Device Success'); ///输出调试字符串 if (IoCreateSymbolicLink(@g_usSymbolicLinkName, @g_usDeviceName) = STATUS_SUCCESS) then begin DbgPrint('Create SymbolicLink Success'); ///输出调试字符串 pDriverObject^.MajorFunction[IRP_MJ_CREATE] := @DispatchCreateClose; ///这里把IRP_MJ_CREATE IRP_MJ_CLOSE设置到一个函数上 pDriverObject^.MajorFunction[IRP_MJ_CLOSE] := @DispatchCreateClose; pDriverObject^.DriverUnload := @DriverUnload; ///当驱动动态卸载时执行DriverUnload status := STATUS_SUCCESS; ///返回STATUS_SUCCESS; end else ///如果创建符号链接不成功 begin DbgPrint('Create SymbolicLink Failed'); ///输出调试字符串 IoDeleteDevice(@DeviceObject); ///删除设备 end; end; LoadKiHooker(); Result := status; end; end.
以下是C版代码
//驱动开发模板 //作者:Tesla.Angela(GDUT.HWL) #include <ntddk.h> #include <windef.h> #include <stdlib.h> #include <ntimage.h> #define dprintf if (DBG) DbgPrint #define MEM_TAG 'TMEM' #define DEVICE_NAME L"\\Device\\hookkifc" #define LINK_NAME L"\\DosDevices\\hookkifc" #define LINK_GLOBAL_NAME L"\\DosDevices\\Global\\hookkifc" #define IOCTL_ULR3IN CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) //In LONG #define IOCTL_NULLIN CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) //In LONG BYTE JmpCode[5]={0xE9,0x00,0x00,0x00,0x00}; BYTE OrgCode[5]={0x8B,0x3F,0x8B,0x1C,0x87}; BYTE PushRetCode[6]={0x68,0x00,0x00,0x00,0x00,0xc3}; KIRQL f_oldirql; KSPIN_LOCK f_spinlock; ULONG uKiFastCallEntryAddr=0; ULONG HookAddr=0; ULONG MyJmpRet=0; ULONG PushRetMem=0; __declspec(naked)void FakeKiFastCallEntry() { _asm { mov edi,dword ptr [edi] mov ebx,dword ptr [edi+eax*4] sub esp,ecx shr ecx,2 jmp [MyJmpRet]; } } NTSTATUS LoadKiHooker() { NTSTATUS status = STATUS_SUCCESS; KIRQL oldIrql; DbgPrint("LoadKiHooker"); //系统调用管理器的地址保存在MSR寄存器里面,标识ID为0x176是SYSENTER_EIP_MSR寄存器,存放着KiFastCallEntry地址!所以在这里用rdmsr读取KiFastCallEntry地址; __asm { pushfd pushad mov ecx,0x176 rdmsr mov uKiFastCallEntryAddr,eax //获取KiFastCallEntry地址 xor ecx,ecx Label1: cmp ecx,0x100 je Label3 mov edx,DWORD ptr [eax] cmp edx,0x1C8B3F8B //搜索特征码,获取要Hook的位置 je Label2 inc eax inc ecx jmp Label1 Label2: mov HookAddr,eax Label3: popad popfd } if (HookAddr==0) { return status; } //申请分配二级跳转内存 PushRetMem=(ULONG)ExAllocatePoolWithTag(NonPagedPool,6,MEM_TAG); if ((PVOID)PushRetMem==NULL) { return status; } DbgPrint("PushRetMem=0x%08X",PushRetMem); //一级跳转地址 *(ULONG*)&JmpCode[1]=(ULONG)(PushRetMem)-(HookAddr+5); //二级跳转地址 *(ULONG*)&PushRetCode[1]=(ULONG)FakeKiFastCallEntry; //HOOK返回地址 MyJmpRet=HookAddr+10; //申请并使用自旋锁 KeInitializeSpinLock(&f_spinlock); KeAcquireSpinLock(&f_spinlock,&f_oldirql); //提升中断请求级 oldIrql = KeRaiseIrqlToDpcLevel(); //关闭中断 _asm { CLI MOV EAX, CR0 AND EAX, NOT 10000H MOV CR0, EAX } //进行HOOK操作 RtlCopyMemory((PVOID)PushRetMem,PushRetCode,6); RtlCopyMemory((PVOID)HookAddr,JmpCode,5); //开启中断 _asm { MOV EAX, CR0 OR EAX, 10000H MOV CR0, EAX STI } //恢复先前中断请求级 KeLowerIrql(oldIrql); //释放自旋锁 KeReleaseSpinLock(&f_spinlock, f_oldirql); DbgPrint("KiFastCallEntry=0x%08X",uKiFastCallEntryAddr); DbgPrint("HookAddr=0x%08X",HookAddr); return status; } VOID UnloadKiHooker() { DbgPrint("UnloadKiHooker"); if (HookAddr!=0) { KIRQL oldIrql; //申请并使用自旋锁 KeInitializeSpinLock(&f_spinlock); KeAcquireSpinLock(&f_spinlock,&f_oldirql); //提升中断请求级 oldIrql = KeRaiseIrqlToDpcLevel(); //关闭中断 _asm { CLI MOV EAX, CR0 AND EAX, NOT 10000H MOV CR0, EAX } //进行还原HOOK操作 RtlCopyMemory((PVOID)HookAddr,OrgCode,5); _asm { MOV EAX, CR0 OR EAX, 10000H MOV CR0, EAX STI } //恢复先前中断请求级 KeLowerIrql(oldIrql); //释放自旋锁 KeReleaseSpinLock(&f_spinlock, f_oldirql); //释放内存 ExFreePool((PVOID)PushRetMem); } } VOID DriverUnload(PDRIVER_OBJECT pDriverObj) { UNICODE_STRING strLink; //unhook// UnloadKiHooker(); //unhook// RtlInitUnicodeString(&strLink, LINK_NAME); IoDeleteSymbolicLink(&strLink); IoDeleteDevice(pDriverObj->DeviceObject); } NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) { pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp) { pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp) { NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST,st2; PIO_STACK_LOCATION pIrpStack; ULONG uIoControlCode; PVOID pIoBuffer; ULONG uInSize; ULONG uOutSize; // pIrpStack = IoGetCurrentIrpStackLocation(pIrp); uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; pIoBuffer = pIrp->AssociatedIrp.SystemBuffer; uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; // switch(uIoControlCode) { /*case IOCTL_ULR3IN: { memcpy(&ppid,pIoBuffer,sizeof(ppid)); DbgPrint("LONG From R3: %ld",ppid); st2=PsLookupProcessByProcessId((HANDLE)ppid,&ppep); if (NT_SUCCESS(st2)) LoadKiHooker(); status = STATUS_SUCCESS; break; } case IOCTL_NULLIN: { UnloadKiHooker(); status = STATUS_SUCCESS; break; }*/ } if(status == STATUS_SUCCESS) pIrp->IoStatus.Information = uOutSize; else pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status; } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING ustrLinkName; UNICODE_STRING ustrDevName; PDEVICE_OBJECT pDevObj; pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl; pDriverObj->DriverUnload = DriverUnload; RtlInitUnicodeString(&ustrDevName, DEVICE_NAME); status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj); if(!NT_SUCCESS(status)) return status; if(IoIsWdmVersionAvailable(1, 0x10)) RtlInitUnicodeString(&ustrLinkName, LINK_GLOBAL_NAME); else RtlInitUnicodeString(&ustrLinkName, LINK_NAME); status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName); if(!NT_SUCCESS(status)) { IoDeleteDevice(pDevObj); return status; } //hook// LoadKiHooker(); //hook// return STATUS_SUCCESS;
转载于:http://www.98exe.net/Article/c/2011-01-07/2494.html