技术心得记录:周壑x64位内核学习(四)、x64分页机制

简介: 技术心得记录:周壑x64位内核学习(四)、x64分页机制

64位寻址,前16位是符号扩展,后48位才是要寻找的地址


一、四级页表


二、根据地址找物理页


以fffff8003846efc0为例</p> <p>1、舍弃前16位 11111000 00000000 00111000 01000110 11101111 11000000</p> <p>2、拆分</p> <p>1 1111 0000 0x1f0</p> <p>0 0000 0000 0x0</p> <p>1 1100 0010 0x1c2</p> <p>0 0110 1110 0x6e</p> <p>1 1111 1000 000 0xfc0</p> <p>3、找物理地址</p> <p>三、x64位下PTE的位置</p> <p>ge根据不同机型有所不同</p> <p>0地址对应的pte地址是这一个,从此时起,每多1000//代码效果参考:http://www.lyjsj.net.cn/wz/art_23761.html<p></p> 字节的地址,pte的地址就会增加8</p> <p>假如我们要求的地址为0xffffxxxxxxxxxxxx,那么其pte地址为


(0xffffxxxxxxxxxxxx & 0x0000ffffffffffff ] 12) [3 + FFFF878000000000


同理,x64下的PDT,PPE,PXE也可以这样得到


注意这三句话,pte也需要指向它自己的地址,指向他的地址就是pdt,以此类推


我们把pte当作普通地址经过上面那个公式演算就可以得到pte


用代码的话,就像这样


也就是说,只要我们知道pte的基地址,就可以求出所有页表的值


四、pte的基地址每次打开都是随机的


我们需要获取pte的基址


这里,周哥提供了一种方法,找调用pte基址的系统api


再根据内核文件的位置,找到这个偏移,每次读取这个偏移的数据即可!


五、实验


微软虚拟地址映射也是通过PTE的方式进行的


根据cr3的值,根据cr3找到pte的值,强搜调用这个值的API,再找到相对内核文件的偏移即可


lm


(IDA修改基址)


找到!!


算相对内核偏移


FFFFF80333403D6a - fffff80333400000 = 3D6A


下面求nt模块的基址,可以通过遍历内核模块的方法,或驱动driver结构体直接获取


这里我们写死地址


成功!!!


代码如下:


#include


ULONG64 g_NT_BASE = 0xfffff8064de00000;


ULONG64 g_PTE_BASE;


ULONG64 g_PDE_BASE;


ULONG64 g_PPE_BASE;


ULONG64 g_PXE_BASE;


void DriverUnload(PDRIVER_OBJECT driver)


{


DbgPrint("Unload Driver Success!!\r\n");


}


PULONG64 GetPteAddress(PVOID addr)


{


return (PULONG64)(((((ULONG64)addr & 0xffffffffffff) ] 12) [ 3) + g_PTE_BASE);


}


PULONG64 GetPdeAddress(PVOID addr)


{


return (PULONG64)(((((ULONG64)addr & 0xffffffffffff) ] 21) [ 3) + g_PDE_BASE);


}


PULONG64 GetPpeAddress(PVOID addr)


{


return (PULONG64)(((((ULONG64)addr & 0xffffffffffff) ] 30) [ 3) + g_PPE_BASE);


}


PULONG64 GetPxeAddress(PVOID addr)


{


return (PULONG64)(((((ULONG64)addr & 0xffffffffffff) ] 39) [ 3) + g_PXE_BASE);


}


NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)


{


g_PTE_BASE = *(PULONG64)(g_NT_BASE + 0x3D6A);


g_PDE_BASE = (ULONG64)GetPteAddress((PVOID)g_PTE_BASE);


g_PPE_BASE //代码效果参考:http://www.lyjsj.net.cn/wz/art_23759.html

= (ULONG64)GetPteAddress((PVOID)g_PDE_BASE);

g_PXE_BASE = (ULONG64)GetPteAddress((PVOID)g_PPE_BASE);


DbgPrint("PXE: %p\n", GetPxeAddress((PVOID)0xfffff8065246efd0));


DbgPrint("PPE: %p\n", GetPpeAddress((PVOID)0xfffff8065246efd0));


DbgPrint("PDE: %p\n", GetPdeAddress((PVOID)0xfffff8065246efd0));


DbgPrint("PTE: %p\n", GetPteAddress((PVOID)0xfffff8065246efd0));


driver->DriverUnload = DriverUnload;


return STATUS_SUCCESS;


}


EOF


本文链接:


关于博主:评论和私信会在第一时间回复。或者直接私信我。


版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!


声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!

相关文章
|
6月前
|
存储 监控 算法
【C++ 软件设计思路】高效管理历史任务记录:内存与磁盘结合的策略解析
【C++ 软件设计思路】高效管理历史任务记录:内存与磁盘结合的策略解析
121 0
|
6月前
|
算法 Ubuntu Linux
【操作系统】探究进程奥秘:显示进程列表的解密与实战
【操作系统】探究进程奥秘:显示进程列表的解密与实战
60 0
|
NoSQL Linux 编译器
操作系统课程设计:新增Linux驱动程序(重制版)(一)
操作系统课程设计:新增Linux驱动程序(重制版)
207 1
操作系统课程设计:新增Linux驱动程序(重制版)(一)
|
Linux Shell
操作系统课程设计:新增Linux驱动程序(重制版)(二)
操作系统课程设计:新增Linux驱动程序(重制版)
147 0
操作系统课程设计:新增Linux驱动程序(重制版)(二)
|
Linux C语言 Windows
操作系统课程设计:新增Linux驱动程序(重制版)(三)
操作系统课程设计:新增Linux驱动程序(重制版)
219 0
操作系统课程设计:新增Linux驱动程序(重制版)(三)
|
Java Linux
【收集】【Linux】常出没的指令(持续更新...)
【收集】【Linux】常出没的指令(持续更新...)
111 0
【收集】【Linux】常出没的指令(持续更新...)
|
监控 Java 关系型数据库
【收集】【Linux】记录常用的操作指令 不定时更新
【参考资料】: 【1】www.cnblogs.com/fjzhang/p/1… 【2】www.51codefly.com/article/516 【3】www.cnblogs.com/liuchuanfen… 【4】www.cnblogs.com/ftl1012/p/h…
155 0
【收集】【Linux】记录常用的操作指令 不定时更新
|
弹性计算 运维 监控
如何解决 Linux 内核调测两大难题:内存被改与内存泄露
一直以来,内核内存调测领域一直持续存在着两大行业难题: "内存被改" 和 "内存泄漏"。内存问题行踪诡异、飘忽不定,在 Linux 内核的调测问题中,是最让开发者头疼的 bug 之一,因为内存问题往往发生故障的现场已经是第 N 现场了,尤其是在生产环境上出现,截止目前并没有一个很有效的方案能够进行精准的线上 debug,导致难以排查、耗时耗力。
543 0
如何解决 Linux 内核调测两大难题:内存被改与内存泄露
|
Linux 调度
内核开发基础-如何使用内核延时
从事Linux内核开发特别是驱动开发的小伙伴,肯定需要经常使用到定时器,比如,按键的去抖、LED屏幕显存buffer的刷新等。同时,在控制硬件时,可能会用到十分精确地短延时,这时,定时器的精度就不能满足这种需求了,这时就会使用到高精度定时器和忙等延时。今天就来简要说一下如何正确的使用内核提供的delay和sleep函数。
371 0
|
弹性计算 运维 前端开发