linux内存写保护,[原创]不用CR0或MDL修改内核非分页写保护内存的一种思路(x64)

开门见山,本文的核心思路就是通过填充页表项,将一块连续的虚拟地址映射到新的地址,同时将需要修改的只读内存对应页表项的Dirty位置位。在Windows操作系统下,写保护是通过保护特定虚拟地址实现的,若不建立新映射,则即使将Dirty位置位,尝试写只读内存照样会触发BugCheck,若建立了新映射但不置位Dirty则触发PAGE_FAULT的BugCheck,两个步骤缺一不可。

填充页表项首先需要动态定位PTEBase,国际惯例是采用大表哥的页表自映射法,代码如下:ULONG_PTR PTEBase = 0;

BOOLEAN hzqstGetPTEBase()

{

BOOLEAN Result = FALSE;

ULONG_PTR PXEPA = __readcr3() & 0xFFFFFFFFF000;

PHYSICAL_ADDRESS PXEPAParam;

PXEPAParam.QuadPart = (LONGLONG)PXEPA;

ULONG_PTR PXEVA = (ULONG_PTR)MmGetVirtualForPhysical(PXEPAParam);

if (PXEVA)

{

ULONG_PTR PXEOffset = 0;

do

{

if ((*(PULONGLONG)(PXEVA + PXEOffset) & 0xFFFFFFFFF000) == PXEPA)

{

PTEBase = (PXEOffset + 0xFFFF000) <

Result = TRUE;

break;

}

PXEOffset += 8;

} while (PXEOffset 

}

return Result;

}

这里我顺便也给出另一种获取方案,基本思路是通过NT导出函数NTKERNELAPI ULONG NTAPI KeCapturePersistentThreadState(PCONTEXT Context, PKTHREAD Thread, ULONG BugCheckCode, ULONG_PTR BugCheckParameter1, ULONG_PTR BugCheckParameter2, ULONG_PTR BugCheckParameter3, ULONG_PTR BugCheckParameter4, PVOID VirtualAddress);

Dump下0x40000大小的数据,里面就存放有MmPfnDataBase,MmPfnDataBase是一个以物理地址页帧号为索引的内存信息数组,其中就有物理页对应的PTE项的地址PteAddress,我们传一个有效的物理地址进去(如当前CR3: __readcr3() & 0xFFFFFFFFF000)取出其中的PteAddress,由于PTEBase必定是0x8000000000的倍数,因此可由PteAddress直接算出PTEBase。另外,从Win10 RS1周年预览版开始,KeCapturePersistentThreadState开始受全局变量ForceDumpDisabled的控制,若注册表“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CrashControl”中有关子项满足条件,此变量会在开机启动时置为1,导致KeCapturePersistentThreadState调用失败。综上所述我们得到第二种获取PTEBase的代码如下://若在Win10上测试,需要在这里加上"#define _WIN10 1"

#ifdef _WIN10

#define OFFSET_PTEADDRESS 0x8

#elif

#define OFFSET_PTEADDRESS 0x10

#endif

ULONG_PTR PTEBase = 0;

PBOOLEAN LocateForceDumpDisabledInRange(ULONG_PTR StartAddress, ULONG MaximumBytesToSearch)

{

PBOOLEAN Result = 0;

ULONG_PTR p = StartAddress;

ULONG_PTR pEnd = p + MaximumBytesToSearch;

do

{

//cmp cs:ForceDumpDisabled, al

//jnz ...

if ((*(PULONGLONG)p & 0xFFFF00000000FFFF) == 0x850F000000000538)

{

Result = p + 6 + *(PLONG)(p + 2);

break;

}

p++;

} while (p 

return Result;

}

BOOLEAN GetPTEBase()

{

BOOLEAN Result = FALSE;

CONTEXT Context = { 0 };

Context.Rcx = (ULONG64)&Context;

<
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值