|
不想多说什么直接贴代码,本文以挂钩KiInsertQueueApc为例
首先是挂钩代码:
- void StartHook()
- {
- PMDL pMdl;
- PVOID Msct;
- PVOID AddressOf_KeInsertQueueApc;
- UNICODE_STRING uniFuncName;
- ULONG i;
- BYTE g_HookCode[4]={0xEB,0xF8,0x55,0x8B};
- BYTE g_PushRetCode[6]={0x68,0,0,0,0,0xC3};
- BYTE g_JmpOrigCode[9]={0x8B,0xFF,0xEA,0,0,0,0,0x08,0};
- RtlInitUnicodeString(&uniFuncName,L"KeInsertQueueApc");
- AddressOf_KeInsertQueueApc=MmGetSystemRoutineAddress(&uniFuncName);
- for(i=(ULONG)AddressOf_KeInsertQueueApc;i<=(ULONG)AddressOf_KeInsertQueueApc+0x40;i++)
- {
- if(*(PUSHORT)i==0xE828)
- {
- KiInsertQueueApc=(PVOID)(*(PULONG)(i+2)+i+6);
- Old_KiInsertQueueApc=ExAllocatePool(NonPagedPool,9);
- *(PULONG)((ULONG)g_JmpOrigCode+3)=(ULONG)KiInsertQueueApc+2;
- RtlCopyMemory(Old_KiInsertQueueApc,g_JmpOrigCode,9);
- *(PULONG)((ULONG)g_PushRetCode+1)=(ULONG)fake_KiInsertQueueApc;
- pMdl=MmCreateMdl(NULL,(PVOID)((ULONG)KiInsertQueueApc-6),10);
- if(pMdl)
- {
- MmBuildMdlForNonPagedPool(pMdl);
- __try
- {
- MmProbeAndLockPages(pMdl,KernelMode,IoWriteAccess);
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- IoFreeMdl(pMdl);
- }
- Msct=MmMapLockedPagesSpecifyCache(pMdl,KernelMode,MmWriteCombined,NULL,FALSE,HighPagePriority);
- RtlCopyMemory(Msct,g_PushRetCode,6);
- InterlockedExchange((PULONG)((ULONG)Msct+6),*(PULONG)g_HookCode);
- MmUnmapLockedPages(Msct,pMdl);
- MmUnlockPages(pMdl);
- IoFreeMdl(pMdl);
- }
- break;
- }
- }
- }
复制代码
然后是卸载钩子代码:
- void StopHook()
- {
- PMDL pMdl;
- PVOID Msct;
- ULONG Code1=0xCCCCCCCC;
- ULONG Code2=0xFF8BCCCC;
- pMdl=MmCreateMdl(NULL,(PVOID)((ULONG)KiInsertQueueApc-6),8);
- if(pMdl)
- {
- MmBuildMdlForNonPagedPool(pMdl);
- __try
- {
- MmProbeAndLockPages(pMdl,KernelMode,IoWriteAccess);
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- IoFreeMdl(pMdl);
- }
- Msct=MmMapLockedPagesSpecifyCache(pMdl,KernelMode,MmWriteCombined,NULL,FALSE,HighPagePriority);
- InterlockedExchange((PULONG)Msct,Code1);
- InterlockedExchange((PULONG)((ULONG)Msct+4),Code2);
- MmUnmapLockedPages(Msct,pMdl);
- MmUnlockPages(pMdl);
- IoFreeMdl(pMdl);
- }
- }
复制代码
再然后是处理KiInsertQueueApc的代码,注意这里是__fastcall的调用约定
- void __fastcall fake_KiInsertQueueApc(IN PKAPC Apc,IN KPRIORITY Increment)
- {
- PEPROCESS txps;
- if(PsGetCurrentProcess()==ProtectedProcess)
- {
- Old_KiInsertQueueApc(Apc,Increment);
- }
- else
- {
- txps=IoThreadToProcess((PETHREAD)Apc->Thread);
- if(txps!=ProtectedProcess)
- {
- Old_KiInsertQueueApc(Apc,Increment);
- }
- }
- }
复制代码
编译后,网上流行的Ke(i)InsertQueueApc插APC杀进程的代码将会失效,除非绕过,恢复或者自己实现插APC才能用APC法结束本文中的例子。当然咯对付本文的进程保护完全可以使用内存清零法。相比用在KiInsertQueueApc头部写上E9 XX XX XX XX的方式挂钩,这种方法更加稳定,即便老方法用上了投递DPC锁定其他核心的代码。
看看PCHunter的钩子检测结果,如图所示
钩子检测
很搞笑的是我明明只挂了一个钩子却显示了两行。第一行标记出了KiInsertQueueApc,可是却检测不到跳的位置,说明PCHunter无法识别短跳,第二行才把我的跳转之黑手标注出来。
本文的示例在Windows XP SP3测试通过 |
评分
-
查看全部评分
|