0x14 内核编程
1. 保护模式
- 分段模式
- 保护模式下段寄存器变成段选择子(高速缓冲区),由 13位索引1位TI 2位RPL 构成
- RPL 表示当前访问段的请求权限
- MAX(CPL,RPL)<= DPL
- jmp fword 0x4B:00000000;
- cpl 是执行这条指令的线程 cs 低两位
- rpl 是 4b 的低两位 11,使用 3 的权限访问 4b对应的段描述符
- dpl: 通过 4b找到的段描述符的 dpl 位
- TI描述了当前使用GDT还是LDT,通常为0
- rgdt是一个48位寄存器,gdtr 是基址 gdtl是范围
- 索引即位于GDT或LDT中的下标
- RPL 表示当前访问段的请求权限
- 保护模式下段寄存器变成段选择子(高速缓冲区),由 13位索引1位TI 2位RPL 构成
- 分页机制
- 没有开启PAE[10-10-12]:CR3(页目录表地址) -> 页目录项 -> 页表项 -> 物理地址
- 开启了PAE[2-9-9-12]:CR3(页目录表指针) -> 页目录表地址->页目录表 -> 页表项 -> 物理页地址
2. 内核编程
相关术语
- DriverEntry:驱动程序的入口函数,参数一是驱动对象,参数二是所在路径
- 注意 DriverEntry 没有名称粉碎,C++编写需要加上 extern “C”
- 驱动对象:DRIVER_OBJECT,类似于三环中应用程序的身份,不能进行直接通信
- 使用其中的 DriverSection 可以遍历系统中的所有驱动对象
- 设备对象:DEVICE_OBJECT,类似于三环中的窗口,是程序的一部分,可用作接收消息
- 需要为设备指定符号链接名供三环访问,格式: \DosDevices\Name \??\Name
- IRP:I/O请求数据包,类似于窗口程序中的消息
- IRQL:中断请求级别,从低到高为 PASSIVE_LEVEL 、APC_LEVEL 、DISPATCH_LEVEL(DPC)
- 如果到来的中断有更高优先级,那么当前中断被挂起,CPU处理高优先级的中断
- SSDT:系统服务描述表,保存了一系列的内核层函数
- 通常使用 SYSENTER 进入内核,调用号保存在 eax寄存器,除此之外msr寄存器中的0x174号负责保存CS段寄存器,0x175号负责保存SS段寄存器,0x176号负责保存eip,通常是 KiFastCall,eax保存的是调用号
- 分页内存和非分页内存
- 分页内存:保存在页交换文件中的数据,使用会产生缺页异常
- 非分页内存:直接保存在物理内存中的数据
- DriverEntry:驱动程序的入口函数,参数一是驱动对象,参数二是所在路径
R0/R3通信的通信方式
- 直接方式(DODIRECT_IO):通过irp->MdlAddress获取_
- 缓冲区方式(DOBUFFERD_IO):通过irp->AssociatedIrp.SystemBuffer获取_
- 其他方式(NULL): _通过irp->UserBuffer获取
_
DeviceIoControl
- 使用 CTL_CODE 定义需要发送的控制码。
- 四种数据的传输方式
- METHOD_BUFFERED:缓冲区
- METHOD_IN_DIRECT \ METHOD_OUT_DIRECT:直接方式
- METHOD_NEITHER:两者都不的方式
内核Hook
- SSDT Hook -> 替换函数
- SYSENTER Hook -> KiFastCallEntry
- Object Hook -> OBJECT_TYPE -> _OBJECT_TYPE_INITIALIZER(保存了用于操作对象的函数)
内核重载
- 开辟一块新内存空间,模拟PE加载器将内核模块重新加载到这段内存,用于修复被Hook的SSDT表
3. 安全基础
- 3环切换到0环
- eax保存调用号
- edx保存用户层栈顶地址
- MSR[0x176]保存进入到0环地址(KiFastCallEntry )
- HOOK KiFastCallEntry
- HOOK SSDT