强制CR3驱动读写
作者没钱的诚终书接上文通过KeStackAttachProcess实现赋值CR3切换线程上下文但是这个函数会留下使用痕迹容易被反作弊查到解决思路取KeStackAttachProcess函数最主要的行为手动实现KeStackAttachProcess功能读取目标进程的CR3直接写入 CR3寄存器实现进程上下文切换预备CR3硬件寄存器 装着「当前这个进程页表的物理起始地址」代表CPU核心正在执行的R3层的一块独立的虚拟内存目标进程内核CR3 是完整页表同时映射内核空间和用户空间。用户CR3 只映射极少量内核代码主要映射用户空间。注意这俩个CR3的值可能相等 目的都是为了把虚拟地址翻译成物理地址这里的虚拟地址可以是R3或者R0 但是用户层对于翻译R0有点局限物理页中可能没有此地址注意用户CR3下不能读写内核虚拟内存代码中就0x28偏移 无其他可选原理通过修改CR3的值使CPU执行目标进程的代码同时防止物理页发生错页等问题将中断等级IRQL提升至DPC_lEVEL以应对线程调度中断和APC即当线程调度时 CR3会受到牵连发生变化 而KeStackAttachProcess中有提等级的部分代码注意部分1.由于CR3会切换线程上下文那么如果中途发生中断高等级IRQL会抢占CPU线程另一个APC会在空闲时线程等待处理APC队列 从而使CR3又发生赋值进而导致无法读取正确的R3层指针最后蓝屏CR3有两种类型 如果切换至R3层的CR3 则无法访问内核虚拟内存MmIsAddressValid此函数用于查询虚拟地址对应的物理分页是否存在但是只是瞬时无法在执行拷贝时保证真的存在ProbeForRead此函数只能在PASSIVE_LEVEL等级下执行 高等级直接蓝屏且无法验证所对应的物理页是否存在5.代码部分关键函数分析_disable();暂停中断 解决中断引起的线程调度_enable();还原中断KeRaiseIrqlToDpcLevel()提升IRQL等级至DPC_LEVEL 应对APC和低等级中断KeLowerIrql还原等级__readcr3();获取当前CR3的值__writecr3;修改CR3的值注意_disable()和KeRaiseIrqlToDpcLevel()都可以临时解决线程调度的问题