文章详情
C++驱动层通过进程虚拟地址获取物理地址
Posted on 2018-01-06 23:35:36 by 主打一个C++
ULONG64 TransformationCR3(ULONG64 _cr3, ULONG64 _virtualAddress)
{
//将用于对齐的低四位清零
_cr3 &= ~0xF;
//获取页面偏移
ULONG64 page_offset = _virtualAddress & ~(~0UL << 0x0C);
//读虚拟地址所在的三级页表
SIZE_T bytesTransferred = 0;
ULONG64 a = 0, b = 0, c = 0;
ReadPhysicalAddress((void*)(_cr3 + 0x08 * ((_virtualAddress >> 0x27) & (0x1FFll))), &a, sizeof(a), &bytesTransferred);
//标志判断是否有映射物理内存,0没有,1有
if (~a & 1)return 0;
//读虚拟地址所在的二级页表
ReadPhysicalAddress((void*)((a & ((~0xFULL << 0x08) & 0xFFFFFFFFFULL)) + 0x08 * ((_virtualAddress >> 0x1E) & (0x1FFLL))), &b, sizeof(b), &bytesTransferred);
//标志判断是否有映射物理内存,0没有,1有
if (~b & 1)return 0;
//如果 PS(页面大小)为1,表示该页表项映射的是1GB的物理内存,直接计算出物理地址并返回
if (b & 0x80)return (b & (~0ull << 42 >> 12)) + (_virtualAddress & ~(~0ULL << 0x1E));
//读虚拟地址所在的一级页表
ReadPhysicalAddress((void*)((b & ((~0xFULL << 0x08) & 0xFFFFFFFFFULL)) + 0x08 * ((_virtualAddress >> 0x15) & (0x1FFll))), &c, sizeof(c), &bytesTransferred);
//标志判断是否有映射物理内存,0没有,1有
if (~c & 1)return 0;
//如果 PS 为1,表示该页表项映射的是2MB的物理内存,直接计算出物理地址并返回
if (c & 0x80)return (c & ((~0xfull << 8) & 0xFFFFFFFFFULL)) + (_virtualAddress & ~(~0ull << 21));
//读虚拟地址所在的零级页表,计算出物理地址并返回
ULONG64 address = 0;
ReadPhysicalAddress((void*)((c & ((~0xFULL << 0x08) & 0xFFFFFFFFFull)) + 0x08 * ((_virtualAddress >> 0x0C) & (0x1FFll))), &address, sizeof(address), &bytesTransferred);
address &= ((~0xFULL << 0x08) & 0xFFFFFFFFFULL);
if (!address)return 0;
return address + page_offset;
}
*转载请注明出处:原文链接:https://cpp.vin/page/71.html