Windows内核实验:指令TLB(ITLB)和流水线&&Meltdown CPU漏洞
#include <stdio.h> #include <stdlib.h> #include <windows.h> #define PDE(x) (DWORD64 *) (((x >> 21) << 3) + 0xc0600000) #define PTE(x) (DWORD64 *) (((x >> 12) << 3) + 0xc0000000) DWORD g_var; DWORD64 g_pte; #pragma section("new_page",read,write) __declspec(allocate("new_page")) DWORD page1[1024]; __declspec(allocate("new_page")) DWORD page2[1024]; void __declspec(naked) IdtEntry() { g_pte = *PTE(0x0041c000); __asm mov eax, ds: [0x0041c000] __asm { mov eax,cr3 mov cr3,eax } *PTE(0x0041c000) = *PTE(0x0041b000); _asm { mov eax,ds:[0x0041c000] mov g_var,eax } *PTE(0x0041c000) = g_pte; __asm { mov eax, cr3 mov cr3, eax } __asm { iretd } } void interrupt() { page1[0] = 0xc3; page2[0] = 0xc390; ((void(*)(void))page1)(); ((void(*)(void))page2)(); __asm { int 0x20 } } int main() { if (0x401040 != IdtEntry) { printf("Idtentry address wrong"); system("pause"); exit(-1); } for (size_t i = 0; i < 10;i++) { interrupt(); if (0xc3 != g_var) printf("g_var:%x\n", g_var); } system("pause"); }
|
这个程序在我机器上我感觉是由于new_page和IdtEntry之间的距离太大了,导致没有复现成功
简单说一下主要思路把
为了使获得的section page有可执行权限,把page1和page2先当作函数执行了一下,就可以获得可执行权限
kd> !pte 0x0041b000 VA 0041b000 PDE at C0600010 PTE at C00020D8 contains 000000000295C067 contains 0000000002903067 pfn 295c ---DA--UWEV pfn 2903 ---DA--UWEV
kd> !pte 0x0041c000 VA 0041c000 PDE at C0600010 PTE at C00020E0 contains 000000000295C067 contains 000000000A024067 pfn 295c ---DA--UWEV pfn a024 ---DA--UWEV
|
为什么没有用#pragma section(“new_page”,read,write,execute)获取可执行权限
这个是可以编译通过,但似乎xp系统不允许一个页可读可写可执行,崩溃了
page1 2有了可执行权限,由于流水线技术,指令可能会并行,IdtEntry执行时,如果取指令可以一次到达page1 2,会对该指令先执行,就会导致page1 2被提前访问,放入tlb
Meltdown CPU漏洞
突然想起之前在jyy老师那里听到的cpu熔断漏洞,可以在用户态往内核或其他进程里偷出数据
漏洞的原因和乱序执行有关,属于cpu架构的漏洞
xorq %rax, %rax retry: movzbq (%rcx), %rax shlq $0xc, %rax jz retry movq (%rbx, %rax), %rbx
|
- cpu在执行movzbq (%rcx), %rax指令的时候,会造成页错误,但是是先把数据取出来了,然后做数据合法性检查,不合法会处理错误,
- 由于这段代码是符合乱序并行的,下面的指令会在rax有数据的一瞬间和1.步骤里检查合法性一起执行
- 下面的指令大概率是比检查合法性的代码要快的
- movq (%rbx, %rax), %rbx 就会使在未载入缓存的数组中位置是rcx地址处的1byte数据的页进入cache,
- 后续访问rbx各页面,比较访问时间就可以获取这个字节的数据 (cache hit和cache miss访问时间差距可见)
漏洞的原因就是访问不合法后,没有将污染的cache清除