-
-
[求助]NewBluePill获取下级页目录的虚拟地址公式没有看懂求指点
-
发表于: 2018-5-30 23:32 2096
-
问题在 下面这个公式
/----------------------------------------------------------------------------------------------------------------------------
LowerPageTable = (PULONG64)(g_PageTableBases[bLevel - 2] + 8 * (i << (9 * (5 - bLevel))));这个公式是NBP 中的 在复制windows 也分的时候用来获取下级页目录所映射的虚拟地址。。这个公式用于当前我们在3或2级页目录 取 2级 和1 级页目录 的虚拟地址 (也就是获取下级页目录所映射的虚拟地址),只有获取下级页目录的虚拟地址才能继续Walk 判断是否有值 ,,,,
我的疑惑点在于 ,比如 当前我们在二级页目录 通过下标 i 可以得到对应的一级页目录的物理地址 ,如果 i 下标所对应的项不为0 那么就获取下级页目录的虚拟地址 通过这个公式 , 但是 i 的范围只有0-512 一个页内的项数 , 但是二级页目录 有很多个 ,为什么通过上面这个公式就能计算出 该二级页目录内 i 所对应项 的 一级页目录的 虚拟地址?
ULONG64 g_PageTableBases[4] = {
PT_BASE,
PD_BASE,
PDP_BASE,
PML4_BASE
};
NTSTATUS NTAPI MmWalkGuestPageTable(
PULONG64 PageTable, //3级页表的虚拟地址
UCHAR bLevel //当前页表的级数
)
{
ULONG64 i;
PVOID VirtualAddress;
PUCHAR ShortPageVA;
PHYSICAL_ADDRESS PhysicalAddress;
PULONG64 LowerPageTable; //低一级页表
if (!MmIsAddressValid(PageTable))
return STATUS_SUCCESS;
for (i = 0; i < 0x200; i++) //每一个页表有0x200=512项 页表项
if (PageTable[i] & P_PRESENT) {//判断表项是否有值
if (((bLevel == 2) && (PageTable[i] & P_LARGE)) || (bLevel == 1)) // 判断是否是二级页表或者一级页表 //根据自映射关系,计算虚拟地址
{
if (bLevel == 1)
VirtualAddress = (PVOID)(((LONGLONG)(&PageTable[i]) - PT_BASE) << 9); //得到1级页表项对应的的虚拟地址
else
VirtualAddress = (PVOID)(((LONGLONG)(&PageTable[i]) - PD_BASE) << 18); //大页面的情况下就得到二级页表项对应的虚拟地址
//不管是一级页表虚拟地址还是二级页表虚拟地址 ;都是最低层页表了, 所以把这个虚拟地址处理一下
if ((LONGLONG)VirtualAddress & 0x0000800000000000) //判断该虚拟地址是否为内核地址
VirtualAddress = (PVOID)((LONGLONG)VirtualAddress | 0xffff000000000000); //设置高16 位全为FFFFF
PhysicalAddress.QuadPart = PageTable[i] & 0x000ffffffffff000;//2M或4K页表的物理地址
if ((ULONGLONG)VirtualAddress >= PT_BASE && (ULONGLONG)VirtualAddress < PML4_BASE + 0x1000)
// guest pagetable stuff here - so don't map it
continue; //客户机页表自映射,宿主机不映射
DbgPrint("MmWalkGuestPageTable(): %sValid pl%d at 0x%p, index 0x%x, VA 0x%p, PA 0x%p %s\n", bLevel == 3 ? " " : bLevel == 2 ? " " : bLevel == 1 ? " " : "", bLevel, &PageTable[i], i, VirtualAddress, PhysicalAddress.QuadPart, ((bLevel == 2) && (PageTable[i] & P_LARGE)) ? "LARGE" : "");
if (bLevel == 2)
{//Large Page分开映射成标准4k页
for (ShortPageVA = (PUCHAR)VirtualAddress + 0x0 * PAGE_SIZE;
ShortPageVA < (PUCHAR)VirtualAddress + 0x200 * PAGE_SIZE;
ShortPageVA += PAGE_SIZE, PhysicalAddress.QuadPart += PAGE_SIZE)
MmCreateMapping(PhysicalAddress, ShortPageVA, FALSE);
}
else
MmCreateMapping(PhysicalAddress, VirtualAddress, FALSE);
}
if ((bLevel > 1) && !((bLevel == 2) && (PageTable[i] & P_LARGE))) //如果当前页表级数大于 1 并且 页表等级不等2 或者不为 大页面 则
{
LowerPageTable = (PULONG64)(g_PageTableBases[bLevel - 2] + 8 * (i << (9 * (5 - bLevel)))); //得到每一项 下级页表的物理地址对应的虚拟地址
MmWalkGuestPageTable(LowerPageTable, bLevel - 1);//遍历下一级页表
}
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2018-5-31 09:05
被兔oO编辑
,原因:
赞赏
他的文章
看原图
赞赏
雪币:
留言: