|
|
[bgcolor=#ffffff]InlineHook 已导出函数


[/bgcolor][bgcolor=#ffffff]VOID [/bgcolor]
[bgcolor=#ffffff]HookObReferenceObjectByHandle()[/bgcolor]
[bgcolor=#ffffff]{ [/bgcolor]
[bgcolor=#ffffff] KIRQL Irql;[/bgcolor]
[bgcolor=#ffffff] KdPrint(("[ObReferenceObjectByHandle] :0x%x",ObReferenceObjectByHandle)); //地址验证[/bgcolor]
[bgcolor=#ffffff] //保存函数前五个字节内容[/bgcolor]
[bgcolor=#ffffff] RtlCopyMemory(OriginalBytes,(BYTE *)ObReferenceObjectByHandle,5);[/bgcolor]
[bgcolor=#ffffff] //保存新函数五个字节之后偏移地址[/bgcolor]
[bgcolor=#ffffff] *(ULONG *)(JmpAddress+1)=(ULONG)DetourMyObReferenceObjectByHandle-((ULONG)ObReferenceObjectByHandle+5);[/bgcolor]
[bgcolor=#ffffff] _asm [/bgcolor]
[bgcolor=#ffffff] {[/bgcolor]
[bgcolor=#ffffff] push eax [/bgcolor]
[bgcolor=#ffffff] mov eax, cr0 [/bgcolor]
[bgcolor=#ffffff] mov CR0VALUE, eax [/bgcolor]
[bgcolor=#ffffff] and eax, 0fffeffffh [/bgcolor]
[bgcolor=#ffffff] mov cr0, eax[/bgcolor]
[bgcolor=#ffffff] pop eax[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] Irql=KeRaiseIrqlToDpcLevel();[/bgcolor]
[bgcolor=#ffffff] //函数开头五个字节写JMP [/bgcolor]
[bgcolor=#ffffff] RtlCopyMemory((BYTE *)ObReferenceObjectByHandle,JmpAddress,5);[/bgcolor]
[bgcolor=#ffffff] KeLowerIrql(Irql);[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] __asm [/bgcolor]
[bgcolor=#ffffff] { [/bgcolor]
[bgcolor=#ffffff] push eax[/bgcolor]
[bgcolor=#ffffff] mov eax, CR0VALUE [/bgcolor]
[bgcolor=#ffffff] mov cr0, eax[/bgcolor]
[bgcolor=#ffffff] pop eax[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff]}[/bgcolor]
[bgcolor=#ffffff]_declspec (naked) [/bgcolor]
[bgcolor=#ffffff]NTSTATUS [/bgcolor]
[bgcolor=#ffffff]OriginalObReferenceObjectByHandle([/bgcolor]
[bgcolor=#ffffff] IN HANDLE Handle,[/bgcolor]
[bgcolor=#ffffff] IN ACCESS_MASK DesiredAccess, [/bgcolor]
[bgcolor=#ffffff] IN POBJECT_TYPE ObjectType OPTIONAL,[/bgcolor]
[bgcolor=#ffffff] IN KPROCESSOR_MODE AccessMode,[/bgcolor]
[bgcolor=#ffffff] OUT PVOID *Object, [/bgcolor]
[bgcolor=#ffffff] OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL[/bgcolor]
[bgcolor=#ffffff] )[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]{[/bgcolor]
[bgcolor=#ffffff] _asm [/bgcolor]
[bgcolor=#ffffff] { [/bgcolor]
[bgcolor=#ffffff] mov edi,edi // 手动写ObReferenceObjectByHandle函数开头的五个字节, 可用WinDbg查看[/bgcolor]
[bgcolor=#ffffff] push ebp[/bgcolor]
[bgcolor=#ffffff] mov ebp,esp[/bgcolor]
[bgcolor=#ffffff] mov eax,ObReferenceObjectByHandle[/bgcolor]
[bgcolor=#ffffff] add eax,5[/bgcolor]
[bgcolor=#ffffff] jmp eax [/bgcolor]
[bgcolor=#ffffff] } [/bgcolor]
[bgcolor=#ffffff]}[/bgcolor]
[bgcolor=#ffffff]NTSTATUS [/bgcolor]
[bgcolor=#ffffff]DetourMyObReferenceObjectByHandle([/bgcolor]
[bgcolor=#ffffff] IN HANDLE Handle,[/bgcolor]
[bgcolor=#ffffff] IN ACCESS_MASK DesiredAccess,[/bgcolor]
[bgcolor=#ffffff] IN POBJECT_TYPE ObjectType OPTIONAL,[/bgcolor]
[bgcolor=#ffffff] IN KPROCESSOR_MODE AccessMode,[/bgcolor]
[bgcolor=#ffffff] OUT PVOID *Object,[/bgcolor]
[bgcolor=#ffffff] OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL[/bgcolor]
[bgcolor=#ffffff] )[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]{[/bgcolor]
[bgcolor=#ffffff] NTSTATUS status;[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] //调用原函数[/bgcolor]
[bgcolor=#ffffff] status=OriginalObReferenceObjectByHandle(Handle,DesiredAccess,ObjectType,AccessMode,Object,HandleInformation);[/bgcolor]
[bgcolor=#ffffff] if((status==STATUS_SUCCESS)&&(DesiredAccess==1)) // 如果是关闭软件, 从DesiredAccess == 1可知[/bgcolor]
[bgcolor=#ffffff] { [/bgcolor]
[bgcolor=#ffffff] if(ObjectType== *PsProcessType) [/bgcolor]
[bgcolor=#ffffff] { [/bgcolor]
[bgcolor=#ffffff] if( _stricmp((char *)((ULONG)(*Object)+0x174),"notepad.exe")==0) [/bgcolor]
[bgcolor=#ffffff] { [/bgcolor]
[bgcolor=#ffffff] ObDereferenceObject(*Object);[/bgcolor]
[bgcolor=#ffffff] return STATUS_INVALID_HANDLE;[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] return status;[/bgcolor]
[bgcolor=#ffffff]}[/bgcolor]
[bgcolor=#ffffff]void [/bgcolor]
[bgcolor=#ffffff]UnHookObReferenceObjectByHandle()[/bgcolor]
[bgcolor=#ffffff]{[/bgcolor]
[bgcolor=#ffffff] KIRQL Irql;[/bgcolor]
[bgcolor=#ffffff] _asm [/bgcolor]
[bgcolor=#ffffff] {[/bgcolor]
[bgcolor=#ffffff] push eax[/bgcolor]
[bgcolor=#ffffff] mov eax, cr0 [/bgcolor]
[bgcolor=#ffffff] mov CR0VALUE, eax [/bgcolor]
[bgcolor=#ffffff] and eax, 0fffeffffh [/bgcolor]
[bgcolor=#ffffff] mov cr0, eax[/bgcolor]
[bgcolor=#ffffff] pop eax [/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] Irql=KeRaiseIrqlToDpcLevel();[/bgcolor]
[bgcolor=#ffffff] //还原开头的五个字节[/bgcolor]
[bgcolor=#ffffff] RtlCopyMemory((BYTE *)ObReferenceObjectByHandle,OriginalBytes,5);[/bgcolor]
[bgcolor=#ffffff] KeLowerIrql(Irql);[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] __asm [/bgcolor]
[bgcolor=#ffffff] { [/bgcolor]
[bgcolor=#ffffff] push eax[/bgcolor]
[bgcolor=#ffffff] mov eax, CR0VALUE [/bgcolor]
[bgcolor=#ffffff] mov cr0, eax[/bgcolor]
[bgcolor=#ffffff] pop eax [/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff]}[/bgcolor]
[bgcolor=#ffffff]
[/bgcolor][bgcolor=#ffffff]InlineHook 未已导出函数


[/bgcolor][bgcolor=#ffffff]//1、获取KeInsertQueueApc地址[/bgcolor]
[bgcolor=#ffffff]ULONG GetFunctionAddr( IN PCWSTR FunctionName) //PCWSTR常量指针,指向16位UNICODE[/bgcolor]
[bgcolor=#ffffff]{[/bgcolor]
[bgcolor=#ffffff] UNICODE_STRING UniCodeFunctionName;[/bgcolor]
[bgcolor=#ffffff] RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );[/bgcolor]
[bgcolor=#ffffff] return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName ); [/bgcolor]
[bgcolor=#ffffff]}[/bgcolor]
[bgcolor=#ffffff]ULONG GetKiInsertQueueApcAddr()[/bgcolor]
[bgcolor=#ffffff]{[/bgcolor]
[bgcolor=#ffffff] /*[/bgcolor]
[bgcolor=#ffffff] 804fd4d3 894728 mov dword ptr [edi+28h],eax[/bgcolor]
[bgcolor=#ffffff] 804fd4d6 e8dd340000 call nt!KiInsertQueueApc (805009b8)[/bgcolor]
[bgcolor=#ffffff] 804fd4db 8ad8 mov bl,al[/bgcolor]
[bgcolor=#ffffff] */[/bgcolor]
[bgcolor=#ffffff] ULONG sp_code1=0x28,sp_code2=0xe8,sp_code3=0xd88a; //特征码[/bgcolor]
[bgcolor=#ffffff] ULONG address=0;[/bgcolor]
[bgcolor=#ffffff] PUCHAR addr;[/bgcolor]
[bgcolor=#ffffff] PUCHAR p;[/bgcolor]
[bgcolor=#ffffff] addr=(PUCHAR)GetFunctionAddr(L"KeInsertQueueApc");[/bgcolor]
[bgcolor=#ffffff] for(p=addr;p<p+PAGE_SIZE;p++)[/bgcolor]
[bgcolor=#ffffff] {[/bgcolor]
[bgcolor=#ffffff] if((*(p-1)==sp_code1)&&(*p==sp_code2)&&(*(PUSHORT)(p+5)==sp_code3))[/bgcolor]
[bgcolor=#ffffff] {[/bgcolor]
[bgcolor=#ffffff] // 地址换算[/bgcolor]
[bgcolor=#ffffff] // 0x804fd4d6 + 0x000034dd + 0x5 = 0x805009b8[/bgcolor]
[bgcolor=#ffffff] address=*(PULONG)(p+1)+(ULONG)(p+5);[/bgcolor]
[bgcolor=#ffffff] break;[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] KdPrint(("[KeInsertQueueApc] addr %x\n",(ULONG)addr));[/bgcolor]
[bgcolor=#ffffff] KdPrint(("[KiInsertQueueApc] address %x\n",address));[/bgcolor]
[bgcolor=#ffffff] return address;[/bgcolor]
[bgcolor=#ffffff]}[/bgcolor]
[bgcolor=#ffffff]VOID HookKiInsertQueueApc()[/bgcolor]
[bgcolor=#ffffff]{ [/bgcolor]
[bgcolor=#ffffff] KIRQL Irql;[/bgcolor]
[bgcolor=#ffffff] g_KiInsertQueueApc = GetKiInsertQueueApcAddr();[/bgcolor]
[bgcolor=#ffffff] KdPrint(("[KiInsertQueueApc] KiInsertQueueApc %x\n",g_KiInsertQueueApc));[/bgcolor]
[bgcolor=#ffffff] // 保存原函数的前5字节内容[/bgcolor]
[bgcolor=#ffffff] RtlCopyMemory (OriginalBytes, (BYTE*)g_KiInsertQueueApc, 5);[/bgcolor]
[bgcolor=#ffffff] // 新函数对原函数的偏移地址[/bgcolor]
[bgcolor=#ffffff] *( (ULONG*)(JmpAddress + 1) ) = (ULONG)DetourMyKiInsertQueueApc - ((ULONG)g_KiInsertQueueApc + 5);[/bgcolor]
[bgcolor=#ffffff] WPOFF();[/bgcolor]
[bgcolor=#ffffff] Irql = KeRaiseIrqlToDpcLevel();[/bgcolor]
[bgcolor=#ffffff] RtlCopyMemory ( (BYTE*)g_KiInsertQueueApc, JmpAddress, 5 );[/bgcolor]
[bgcolor=#ffffff] KeLowerIrql(Irql);[/bgcolor]
[bgcolor=#ffffff] WPON(); [/bgcolor]
[bgcolor=#ffffff]}[/bgcolor]
[bgcolor=#ffffff]//原函数[/bgcolor]
[bgcolor=#ffffff]_declspec (naked) VOID FASTCALL OriginalKiInsertQueueApc(IN PKAPC Apc,IN KPRIORITY Increment)[/bgcolor]
[bgcolor=#ffffff]{[/bgcolor]
[bgcolor=#ffffff] _asm[/bgcolor]
[bgcolor=#ffffff] {[/bgcolor]
[bgcolor=#ffffff] //原函数前五个字节[/bgcolor]
[bgcolor=#ffffff] mov edi,edi[/bgcolor]
[bgcolor=#ffffff] push ebp[/bgcolor]
[bgcolor=#ffffff] mov ebp,esp[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] mov eax,g_KiInsertQueueApc[/bgcolor]
[bgcolor=#ffffff] add eax,5[/bgcolor]
[bgcolor=#ffffff] jmp eax[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff]}[/bgcolor]
[bgcolor=#ffffff]//处理函数[/bgcolor]
[bgcolor=#ffffff]//apc--kthread--apc_state--eprocess[/bgcolor]
[bgcolor=#ffffff]VOID FASTCALL DetourMyKiInsertQueueApc(IN PKAPC Apc,IN KPRIORITY Increment)[/bgcolor]
[bgcolor=#ffffff]{[/bgcolor]
[bgcolor=#ffffff] ULONG thread;[/bgcolor]
[bgcolor=#ffffff] ULONG process;[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] if(MmIsAddressValid((PULONG)((ULONG)Apc+0x008))) //地址验证 KAPC结构+008--->kthread[/bgcolor]
[bgcolor=#ffffff] thread=*((PULONG)((ULONG)Apc+0x008));[/bgcolor]
[bgcolor=#ffffff] else[/bgcolor]
[bgcolor=#ffffff] return ;[/bgcolor]
[bgcolor=#ffffff] if(MmIsAddressValid((PULONG)((ULONG)thread+0x044))) //kthread+34-->KAPC_STATE+10-->eprocess[/bgcolor]
[bgcolor=#ffffff] process=*((PULONG)((ULONG)thread+0x044));[/bgcolor]
[bgcolor=#ffffff] else[/bgcolor]
[bgcolor=#ffffff] return ;[/bgcolor]
[bgcolor=#ffffff] if(MmIsAddressValid((PULONG)((ULONG)process+0x174))) //eprocess+174---->进程名字[/bgcolor]
[bgcolor=#ffffff] {[/bgcolor]
[bgcolor=#ffffff] if((_stricmp((char *)((ULONG)process+0x174),"notepad.exe")==0)&&(Increment==2))[/bgcolor]
[bgcolor=#ffffff] return ;[/bgcolor]
[bgcolor=#ffffff] else[/bgcolor]
[bgcolor=#ffffff] OriginalKiInsertQueueApc(Apc,Increment); [/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] else[/bgcolor]
[bgcolor=#ffffff] return;[/bgcolor]
[bgcolor=#ffffff]}


[/bgcolor][bgcolor=#ffffff]HotPatch(加了点自己的注释和完善了下Unload)[/bgcolor]
[bgcolor=#ffffff]先用WinDbg看下具体的函数

Hook示意图:



[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]NTSTATUS InlineHookFuncXP(IN PVOID FuncAddress, [/bgcolor]
[bgcolor=#ffffff] IN PVOID NewFuncAddress) [/bgcolor]
[bgcolor=#ffffff]{ [/bgcolor]
[bgcolor=#ffffff] //FuncAddress rignal function address [/bgcolor]
[bgcolor=#ffffff] //NewFuncAddress:new function address to hook [/bgcolor]
[bgcolor=#ffffff] //if function successed,the old function which the hook function will jump to [/bgcolor]
[bgcolor=#ffffff] //is the FuncAddress+2 [/bgcolor]
[bgcolor=#ffffff] KIRQL OldIrql ; [/bgcolor]
[bgcolor=#ffffff] NTSTATUS stat; [/bgcolor]
[bgcolor=#ffffff] KeAcquireSpinLock( &SDTSpinLock, &OldIrql ); [/bgcolor]
[bgcolor=#ffffff] WPOFF(); [/bgcolor]
[bgcolor=#ffffff] //保存原函数的头两个字节[/bgcolor]
[bgcolor=#ffffff] RtlCopyMemory(OriginalBytes,(BYTE *)ObReferenceObjectByHandle,2);[/bgcolor]
[bgcolor=#ffffff] __asm [/bgcolor]
[bgcolor=#ffffff] { [/bgcolor]
[bgcolor=#ffffff] push eax [/bgcolor]
[bgcolor=#ffffff] push ecx [/bgcolor]
[bgcolor=#ffffff] lea eax,[FuncAddress] [/bgcolor]
[bgcolor=#ffffff] mov eax,[eax] [/bgcolor]
[bgcolor=#ffffff] cmp byte ptr[eax],0x8b [/bgcolor]
[bgcolor=#ffffff] jnz failtohook [/bgcolor]
[bgcolor=#ffffff] cmp byte ptr[eax+1],0xff ;判断函数开始头部是不是 "mov edi,edi" [/bgcolor]
[bgcolor=#ffffff] jnz failtohook [/bgcolor]
[bgcolor=#ffffff] mov ecx,0xffffffff ;-1[/bgcolor]
[bgcolor=#ffffff]loopcheck: [/bgcolor]
[bgcolor=#ffffff] cmp byte ptr[eax+ecx],0x90 [/bgcolor]
[bgcolor=#ffffff] jnz failtohook [/bgcolor]
[bgcolor=#ffffff] dec ecx [/bgcolor]
[bgcolor=#ffffff] cmp ecx,0xfffffffa ;循环5次, 判断函数开始上面部分是不是"nop"[/bgcolor]
[bgcolor=#ffffff] jnz loopcheck [/bgcolor]
[bgcolor=#ffffff] mov byte ptr[eax],0xeb ; 短跳jmp[/bgcolor]
[bgcolor=#ffffff] mov byte ptr[eax+1],0xf9 ; 0-偏移量-指令长度 = 0x00-5-2 = f9 [/bgcolor]
[bgcolor=#ffffff] ;write the new function header:jmp short funcaddr-5(0x00-0x07) [/bgcolor]
[bgcolor=#ffffff] mov byte ptr[eax-5],0xe9 ;远跳jmp[/bgcolor]
[bgcolor=#ffffff] ;write 1 byte :jmp xxxxx [/bgcolor]
[bgcolor=#ffffff] mov ecx,[NewFuncAddress] [/bgcolor]
[bgcolor=#ffffff] sub ecx,eax ;得到跳转的相对偏移[/bgcolor]
[bgcolor=#ffffff] mov dword ptr[eax-4],ecx [/bgcolor]
[bgcolor=#ffffff] jmp hookok [/bgcolor]
[bgcolor=#ffffff]failtohook: [/bgcolor]
[bgcolor=#ffffff] mov stat,0xc0000001 [/bgcolor]
[bgcolor=#ffffff] jmp end [/bgcolor]
[bgcolor=#ffffff]hookok: [/bgcolor]
[bgcolor=#ffffff] mov stat,0 [/bgcolor]
[bgcolor=#ffffff]end: [/bgcolor]
[bgcolor=#ffffff] pop ecx [/bgcolor]
[bgcolor=#ffffff] pop eax [/bgcolor]
[bgcolor=#ffffff] } [/bgcolor]
[bgcolor=#ffffff] WPON(); [/bgcolor]
[bgcolor=#ffffff] KeReleaseSpinLock( &SDTSpinLock, OldIrql ); [/bgcolor]
[bgcolor=#ffffff] return stat; [/bgcolor]
[bgcolor=#ffffff]}[/bgcolor]
[bgcolor=#ffffff]VOID UnInlineHookFuncXP(IN PVOID FuncAddress) [/bgcolor]
[bgcolor=#ffffff]{[/bgcolor]
[bgcolor=#ffffff] KIRQL OldIrql ; [/bgcolor]
[bgcolor=#ffffff] NTSTATUS stat; [/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] KeAcquireSpinLock( &SDTSpinLock, &OldIrql ); [/bgcolor]
[bgcolor=#ffffff] WPOFF(); [/bgcolor]
[bgcolor=#ffffff] // 恢复函数的前两个字节[/bgcolor]
[bgcolor=#ffffff] RtlCopyMemory((BYTE *)FuncAddress, OriginalBytes, 2);[/bgcolor]
[bgcolor=#ffffff] // 恢复函数上面的5个nop[/bgcolor]
[bgcolor=#ffffff] __asm [/bgcolor]
[bgcolor=#ffffff] {[/bgcolor]
[bgcolor=#ffffff] push ecx [/bgcolor]
[bgcolor=#ffffff] push eax[/bgcolor]
[bgcolor=#ffffff] lea eax,[FuncAddress] [/bgcolor]
[bgcolor=#ffffff] mov eax,[eax][/bgcolor]
[bgcolor=#ffffff] mov ecx,0xffffffff ;-1[/bgcolor]
[bgcolor=#ffffff]loopcheck: [/bgcolor]
[bgcolor=#ffffff] mov byte ptr[eax+ecx],0x90 [/bgcolor]
[bgcolor=#ffffff] dec ecx [/bgcolor]
[bgcolor=#ffffff] cmp ecx,0xfffffffa [/bgcolor]
[bgcolor=#ffffff] jnz loopcheck [/bgcolor]
[bgcolor=#ffffff] pop eax[/bgcolor]
[bgcolor=#ffffff] pop ecx[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] WPON(); [/bgcolor]
[bgcolor=#ffffff] KeReleaseSpinLock( &SDTSpinLock, OldIrql ); [/bgcolor]
[bgcolor=#ffffff]}[/bgcolor][bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] [/bgcolor] |
|