暴露内核内存并通过滥用COW机制实现一个注射器
本文由
创作,已纳入「FreeBuf原创奖励计划」,未授权禁止转载
滥用Windows地址
在Windows内核中(例如ntoskrnl.exe)可以通过修改页表的用户权限标志来暴露内核内存给用户模式进程。
用IDA查看ntoskrnl.exe可以看到:
在MiReadWriteVirtualMemory
和MmQueryVirtualMemory
函数中,检查了内存地址是否超出用户模式的内存范围,即0x7FFFFFFEFFFF
。这俩个检查确保用户模式不能访问内核模式地址。
这里的关键点是,虽然系统有硬编码的常量(如0x7FFFFFFEFFFF
)来检查地址,但真正决定一个内存页是否可以被用户模式访问的并不是这些地址,而是页表项中的user
标志。user
标志决定了一个页面是否可以被 CPL3(用户模式)访问。如果在页表的所有级别(PML4、PDPT、PDE、PTE)中user
标志均为真,则用户模式可以访问该页面。
虚拟内存的工作原理:虚拟地址的前 12 位 (&0xFFF) 表示与已解析页面的偏移量,接下来的四个 9 位组合 (&0x1FF000、&0x3FE00000、&0x7FC0000000、&0xFF8000000000) 分别表示页表、页目录、页目录指针和页映射级别 4 中的条目索引。这些条目除了链接到较低级别外,还包含某些标志,如写入禁用、执行禁用等;它的定义如下:
#pragma pack(push, 1)
typedef union CR3_
{
uint64_t value;
struct
{
uint64_t ignored_1 : 3;
uint64_t write_through : 1;
uint64_t cache_disable : 1;
uint64_t ignored_2 : 7;
uint64_t pml4_p : 40;
uint64_t reserved : 12;
};
} PTE_CR3;
typedef union VIRT_ADDR_
{
uint64_t value;
void *pointer;
struct
{
uint64_t offset : 12;
uint64_t pt_index : 9;
uint64_t pd_index : 9;
uint64_t pdpt_index : 9;
uint64_t pml4_index : 9;
uint64_t reserved : 16;
};
} VIRT_ADDR;
typedef uint64_t PHYS_ADDR;
typedef union PML4E_
{
uint64_t value;
struct
{
uint64_t present : 1;
uint64_t rw : 1;
uint64_t user : 1;
uint64_t write_through : 1;
uint64_t cache_disable : 1;
uint64_t accessed : 1;
uint64_t ignored_1 : 1;
uint64_t reserved_1 : 1;
uint64_t ignored_2 : 4;
uint64_t pdpt_p : 40;
uint64_t ignored_3 : 11;
uint64_t xd : 1;
};
} PML4E;
typedef union PDPTE_
{
uint64_t value;
struct
{
uint64_t present : 1;
uint64_t rw : 1;
uint64_t user : 1;
uint64_t write_through : 1;
uint64_t cache_disable : 1;
uint64_t accessed : 1;
uint64_t dirty : 1;
uint64_t page_size : 1;
uint64_t ignored_2 : 4;
uint64_t pd_p : 40;
uint64_t ignored_3 : 11;
uint64_t xd : 1;
};
} PDPTE;
typedef union PDE_
{
uint64_t value;
struct
{
uint64_t present : 1;
uint64_t rw : 1;
uint64_t user : 1;
uint64_t write_through : 1;
uint64_t cache_disable : 1;
uint64_t accessed : 1;
uint64_t dirty : 1;
uint64_t page_size : 1;
uint64_t ignored_2 : 4;
uint64_t pt_p : 40;
uint64_t ignored_3 : 11;
uint64_t xd : 1;
};
} PDE;
typedef union PTE_
{
uint64_t value;
VIRT_ADDR vaddr;
struct
{
uint64_t present : 1;
uint64_t rw : 1;
uint64_t user : 1;
uint64_t write_through : 1;
uint64_t cache_disable : 1;
uint64_t accessed : 1;
uint64_t dirty : 1;
uint64_t pat : 1;
uint64_t global : 1;
uint64_t ignored_1 : 3;
uint64_t page_frame : 40;
uint64_t ignored_3 : 11;
uint64_t xd : 1;
};
} PTE;
#pragma pack(pop)
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
文章目录