|  | 
 
| 不想多说什么直接贴代码,本文以挂钩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测试通过
 | 
评分
查看全部评分
 |