简单粗暴!验证Windows内核的TLB

365 阅读3分钟

1.TLB种类 TLB在X86体系的CPU中的实际应用最早是从Intel的486CPU开始的,在X86体系的CPU中,一般都设有如下4组TLB: 第一组:缓存一般页表(4K字节页面)的指令页表缓存(Instruction-TLB); 第二组:缓存一般页表(4K字节页面)的数据页表缓存(Data-TLB); 第三组:缓存大尺寸页表(2M/4M字节页面)的指令页表缓存(Instruction-TLB); 第四组:缓存大尺寸页表(2M/4M字节页面)的数据页表缓存(Data-TLB) 具体TLB的详情可以去网上看。本节主要讲解用代码验证TLB功能。

2.验证TLB的存在 实现方式,通过门提权到零环进入到指定的函数来进行实现tlb的功能。 这里我构建的调用门 kd> r gdtr gdtr=80b99000 kd> dq 80b99000 80b99000 0000000000000000 00cf9b000000ffff 80b99010 00cf93000000ffff 00cffb000000ffff 80b99020 00cff3000000ffff 80008b1e400020ab 80b99030 834093f6cc003748 0040f30000000fff 80b99040 0000f2000400ffff 0040ec0000081005 //门 80b99050 830089f6a0000068 830089f6a0680068 80b99060 0000000000000000 0000000000000000 80b99070 800092b9900003ff 0000000000000000

之后跳转到门,通过call跳转。

int main(int argc, char* argv[]) { char buf[6] = {0,0,0,0,0X48,0}; printf("%x\n",test); __asm{ pushad; pushfd; push fs; call fword ptr buf; pop fs; popfd; popad; } printf("%x\n",temp); return 0;

}

看一下我们的TLB实现函数(这里就是门跳转过来的函数),首先给0地址挂一个物理页(0x01234867),我这里是随机挂的...只能保佑别蓝屏。在将12345678写入到0地址内。之后又重新给0地址挂一个物理页(0x02345867),然后将读到的值保存到temp里面。

void __declspec(naked) test(){

__asm{

mov dword ptr ds:[0XC0000000],0x01234867;
mov dword ptr ds:[0],0x12345678;

/* mov ecx,cr3; mov cr3,ecx; //刷新TLB */ mov dword ptr ds:[0XC0000000],0x02345867; mov eax,dword ptr ds:[0]; mov temp,eax; retf;

} } 按正常来说,可能不了解TLB的人会感觉输出的是0x02345867的值,但是我们运行程序看一下,发现值还是0x01234867物理页的值。

那么如何刷新TLB,其实在进程切换的时候,TLB就会进行刷新。所以将cr3刷新即可。

void __declspec(naked) test(){

__asm{

mov dword ptr ds:[0XC0000000],0x01234867;
mov dword ptr ds:[0],0x12345678;

mov ecx,cr3;
mov cr3,ecx; //刷新TLB

mov dword ptr ds:[0XC0000000],0x02345867;
mov eax,dword ptr ds:[0];
mov temp,eax;
retf;

} } 在看一下运行结果,发现TLB成功被刷新 最后:希望大家可以点赞加关注,想要获取网络安全资料的请加V;gogquick