百度一下 藏锋者 就能快速找到本站! 每日资讯归档 下载藏锋者到桌面一键访问

当前位置:主页 > 网络安全 > Inline Hook Ke(i)InsertQueueApc进程保护

Inline Hook Ke(i)InsertQueueApc进程保护

所在栏目:网络安全 时间:04-13 10:22 分享:

关于网络安全中的进程保护和进程防杀,个人认为是不同的概念,保护的范围要大于进程的防杀!举个简单的例子就是,Hook了NtTerminateProcess函数,是可以起到进程防杀的功能,但如果是调用NtSuspendProcess将进程挂起,是不是你的保护程序如同虚设,什么也干不了啊(当然,前提是你的函数句柄可以获得到)!?说真的,进程保护得再好,都可以被关闭!MJ0011曾经说过:都驱动了,什么干不了啊!所以,今天我们就学学江民,Hook掉这两个函数,来个简单的进程保护!如同我所说,此时的进程保护,说白了也是不堪一击的!做一个全面的进程保护不是一朝一夕的事情!
KeInsertQueueApc进程防杀这个自不必说,网络安全杀毒工具江民就是最好的榜样,但如果单单Hook了这个函数和Hook了NtTerminateProcess没什么两样!缺点是该进程还是可以被挂起的!如何防止进程被挂起,就从WRK中找答案吧!“ZwSuspendProcess->NtSuspendProcess->NtSuspendThread->KeSuspendThread->KiInsertQueueApc;”,这次应该知道为什么不能防止挂起了吧!?看看Windows XP是不是真的也是这么做的。

lkd> u KeSuspendThread
nt!KeSuspendThread:
804fe4c0 8bff mov edi,edi
……
804fe544 e83d240000 call nt!KiInsertQueueApc (80500986)
//看来还是一样的啊

得到KeInsertQueueApc函数地址的值很容易,因为导出了,所以这样就可以了。

ULONG GetFunAddress()
{
/*NTKERNELAPI
PVOID
MmGetSystemRoutineAddress(
IN PUNICODE_STRING  SystemRoutineName
);*/
UNICODE_STRING m_fun_name;
ULONG m_fun_address=0;
RtlInitUnicodeString(&m_fun_name,L"KeInsertQueueApc");
m_fun_address=(ULONG)MmGetSystemRoutineAddress(&m_fun_name);
return m_fun_address;
}

但是KiInsertQueueApc函数地址必须要根据KeInsertQueueApc或者其他函数进程搜索定位!(感觉这种方法很暴力,很有效!)再看看搜索的特征码,具体如下:

lkd> s -b KeInsertQueueApc l50 e8
804fd465  e8 00 00 00 8d 55 f4 ff-15 2c 91 4d 80 64 a1 20  .....U...,.M.d.
804fd47e  e8 dd 43 04 00 32 db 38-9e 66 01 00 00 74 18 8b  ..C..2.8.f...t..
804fd49e  e8 e3 34 00 00 8a d8 64-a1 20 00 00 00 8d 88 18  ..4....d. ......

搜索这个call指令e8,可以定位到3个!观察一下在call KiInsertQueueApc之前的那个字节,是0x28!

804fd49b 894728 mov dword ptr [edi+28h],eax
804fd49e e8e3340000 call nt!KiInsertQueueApc (80500986)
lkd> db 804fd49b
804fd49b  89 47 28 e8 e3 34 00 00-8a d8 64 a1 20 00 00 00  .G(..4....d. ...

再次搜索:
lkd> s -b KeInsertQueueApc l50 28 e8
804fd49d  28 e8 e3 34 00 00 8a d8-64 a1 20 00 00 00 8d 88  (..4....d. .....

此时定位到的就是我们想要的函数KiInsertQueueApc!测试发现,这种方法在Windows 2000/XP/2003 Server,甚至在Windows Vista下都可以得到!

ULONG GetKiFromKeInsertFun()
{
ULONG m_index=0;
ULONG m_ki_fun=0;
ULONG m_ke_address=GetFunAddress();//得到了KeInsertQueueApc的地址~
for (m_index=m_ke_address;m_index<(m_ke_address+1024);m_index++)
{
//在此范围内搜索28 e8这两个连续的字节
if (((*(PUCHAR)(UCHAR*)(m_index-1))==0x28)&&((*(PUCHAR)(UCHAR*)(m_index))==0xe8))
{
//函数地址找到!
//8082944d e807fcffff  call nt!KiInsertQueueApc (80829059)
//80829059-(8082944d+5)=fffffc07
ULONG m_offset=*(PULONG)(m_index+1);
m_ki_fun=m_index+5+m_offset;
//DbgPrint("KiInsertQueueApc的函数地址为:0x%x",m_ki_fun);
break;
}
}
return m_ki_fun;
}

到这儿就定位到了这两个函数的地址!Inline Hook很强大,也很麻烦,麻烦的地方是如何维护堆栈的平衡!sudami给出了3个比较不错的宏用来维护平衡,这在代码中已有体现,还是说说Hook时的注意点吧!
KeInsertQueueApc没什么说的,调用方式也是经常见到的!所以,取得我们想要的参数就是从ebp+8、ebp+c……中取就可以啦!但KiInsertQueueApc是fast call调用,取得参数就要小心了!ecx是第一个参,edx是第二个参数,[ebx]就是第三个参数了,这个需要注意!最后编写的进程保护如下:

BOOLEAN CheckKiInsertQueueApc(PRKAPC m_apc)
{
PEPROCESS m_eprocess;
PETHREAD  m_apc_thread;
PEPROCESS m_apc_process;
PETHREAD  m_current_thread;
m_eprocess=PsGetCurrentProcess();
m_current_thread=PsGetCurrentThread();
m_apc_thread=m_apc->Thread;
m_apc_process=IoThreadToProcess(m_apc_thread);//根据线程得到对应的进程~
if((_stricmp((char *)((char *)m_apc_process+0x174),"huazi.exe--+"))==0&&(m_apc_process!=m_eprocess))
{
DbgPrint("KiInsertQueueApc----警报-----%s进程试图插入APC到我们的保护进程:%s!遭到我们的反击~^_^!\n",(char *)((char *)m_eprocess+0x174),(char *)((char *)m_apc_process+0x174));
}
return TRUE;
}

整个网络安全进程反杀简单的描述一下就是:先启动一个名为huazi.exe的进程(这儿是因为我直接将进程固化了,如果先加载了驱动,我们的保护程序也不能正常启动了啊),之后加载我们的驱动程序。
经过最后测试,冰刃、Rootkit Unhooker、任务管理器都被反杀,试图将我们的程序挂起的都被我们反挂起!由于针对这个函数的一些标志位做了更改,所以测试一次后,该程序就不怎么能够插入APC了,这点需要注意!至于如何去实现Inline Hook,大家可以自己打开源代码仔细看看,本文就不赘述了。

Inline Hook Ke(i)InsertQueueApc进程保护 免费邮件订阅: 邮件订阅

图片推荐

热点排行榜

CopyRight? 2013 www.cangfengzhe.com All rights reserved