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