Windows X64内核简述

手册的话AMD看起来条例清晰一点,尤其是amd的目录找东西非常快,二者不一致的话还是intel为准(怪我答辩一样的英语水平)

cpu64位运行模式 Intel叫IA-32e AMD叫Long Mode 32位兼容模式都叫Legacy Mode

由下面的寄存器来标识模式

image-20240313095113751

实验操作系统版本:Windows 10 (business edition), version 1903 (updated June 2019) (x64) - DVD (Chinese-Simplified)

ed2k://|file|cn_windows_10_business_edition_version_1903_updated_june_2019_x64_dvd_830837d9.iso|5032351744|DFF5FF3B87D209D16ECE7543255FA573|/

win10测试模式

bcdedit /set testsigning on

win10开启调试

bcdedit /copy {current} /d "Windows Debug Entry"
bcdedit /dbgsettings serial baudrate:115200 debugport:1
bcdedit /debug {ID} ON
bcdedit /set {ID} TESTSIGNING on

S=1 Code or Data 段描述符

段描述符的样子

image-20240313100509451

代码段描述符

image-20240313103030244

amd手册描述段基址,粒度和限制都被忽略,段保护基址被废除,毕竟页保护和段保护功能太冲突了,windows32位中cs基址都为0,限制都为4G大小的平坦段,64位现在也为最大,这种机制叫做强制平坦,和32位一样逻辑地址等于线性地址

L=1处理器是在64位模式,此时D位的唯一有效设置是0

L=0处理器是在兼容模式,D位保持原来32位的功能

L=1 D=1保留供将来使用

数据段描述符

image-20240313104320012

除了GS和FS寄存器的数据段描述符,其他数据段描述符都被忽略

S=0 系统段描述符

image-20240313110054050

拓展到128位

任务门被删除,TSS段里面只存各种栈

image-20240313155434318

其中ISTn可以给一些中断的单独栈,由中断或陷阱门指出

image-20240313155830794

MSR寄存器

比较重要的是下面三个

  1. IA32_FS_BASE(下标0xC0000100)
  2. IA32_GS_BASE(下标0xC0000101)
  3. IA32_KERNEL_GS_BASE(下标0xC0000102)

0环时,FS不再指向KPCR,而是由GS指向KPCR,在3环时GS指向TEB。

可以用SWAPGS指令将当前的GS基址寄存器值与MSR地址C0000102H(IA32_KERNEL_GS_BASE)中包含的值进行交换。

IA32_FS_BASE为了兼容原来32位程序而留下

系统调用

64位程序通过syscall进入内核 sysret返回

32位程序通过 jmp far 33:77196009的长跳转把cs从0x23变为0x33,即从32位切换到64位模式,并从77196009执行

kd> dq gdtr
fffff803`80690fb0 00000000`00000000 00000000`00000000
fffff803`80690fc0 00209b00`00000000 00409300`00000000
fffff803`80690fd0 00cffb00`0000ffff 00cff300`0000ffff
fffff803`80690fe0 0020fb00`00000000 00000000`00000000
fffff803`80690ff0 80008b68`f0000067 00000000`fffff803

0x23描述符 00cffb00`0000ffff L位为0 D为1 32位模式

0x33描述符 0020fb00`00000000 L位为1 D为0 64位模式

可以试图利用这种切换机制做下面的代码混淆

#include <Windows.h>
#include <stdio.h>
int main() {
int nNum = 0;
__asm {
//int 3
mov eax, 0
push 0x33
call $ + 5
add[esp], 5
retf//切换cs位33 到64位模式
mode64 :
//48:C7C0 34120000 | mov rax,1234
__emit 0x48
__emit 0xc7
__emit 0xc0
__emit 0x34
__emit 0x12
__emit 0x00
__emit 0x00
//切换回32位模式
/*
00007FF83D473A62 | E8 00000000 | call 7FF83D473A67
00007FF83D473A67 | C64424 04 23 | mov byte ptr ss:[rsp+4],23//改cs为23
00007FF83D473A6C | 800424 0A | add byte ptr ss:[rsp],A
00007FF83D473A70 | CB | ret far 这里retf 返回地址和cs依旧各个占4个字节
*/
__emit 0xe8
__emit 0x00
__emit 0x00
__emit 0x00
__emit 0x00

__emit 0xc6
__emit 0x44
__emit 0x24
__emit 0x04
__emit 0x23

__emit 0x80
__emit 0x04
__emit 0x24
__emit 0x0a

__emit 0xcb
}
__asm {
mov nNum, eax
}
printf("%x\n", nNum);
puts("sucess");
system("pause");
}

image-20240313234746807

内存管理

52bit物理地址 48bit线性地址(高位做符号拓展)

4k页采用9 9 9 9 12分页

增加了nx标志位

保护机制

smep smap cr4 20 21位

smap除了控制cr4关闭21位,还可以用STAC指令—Set AC Flag in EFLAGS Register指令来绕过

image-20240314141218112

PG:PatchGuard(KPP:Kenrel Patch Protection)

DSE:Driver Signature Enforcement(vuln 不联网验证,总不能说不联网你就不让用户正常用电脑吧)

KVAS: Kernel Virtual Address Shadow(KPTI)

image-20240315130538085

lfence指令:LFENCE指令不会执行,直到所有先前的指令在本地完成,并且在 LFENCE 完成之前不会开始执行任何后续指令。

CFG:Control Flow Guard

PG(PATCH GUARD)

reference

https://space.bilibili.com/37877654/channel/seriesdetail?sid=1467288