当前位置: 首页 > news >正文

通过cr3读写进程内存

通过cr3读写进程内存

本文总结于lyshark的《Windows内核安全编程技术实践》。

技术原理

cr3保存着当前进程的最高级页目录地址(物理地址),修改cr3为目标进程的最高级页目录地址,即可读写目标进程的内存空间。

目标进程的最高级页目录地址存放于KPEOCESS结构体偏移0x28处,同时也是EPROCESS结构体0x28处。

我们通过PsLookupProcessByProcessId和PsGetProcessImageFileName函数获取获取目标进程的EPROCESS地址。之后加上0x28便得到最高级页目录地址。

获取目标进程EPROCESS

我们希望通过目标进程的可执行文件名称获取EPROCESS结构体:

staticPEPROCESS sg_pEprocess=nullptr;EXTERN_C NTKERNELAPI NTSTATUSPsLookupProcessByProcessId(HANDLE ProcessId,PEPROCESS*Process);EXTERN_C NTKERNELAPI CHAR*PsGetProcessImageFileName(PEPROCESS Process);// 通过进程名获取EPROCESS结构NTSTATUSGetProcessObjectByName(char*name){NTSTATUS status=STATUS_UNSUCCESSFUL;SIZE_T i;__try{for(i=0;i<20000;i++){PEPROCESS ep;NTSTATUS st=PsLookupProcessByProcessId((HANDLE)i,&ep);if(NT_SUCCESS(st)){char*pn=PsGetProcessImageFileName(ep);// 带下划线版本的是微软的标准扩展实现,应该优先使用if(_stricmp(pn,name)==0){DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"Found %s\n",name);sg_pEprocess=ep;__leave;}}}DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"Not Found %s\n",name);}__except(EXCEPTION_EXECUTE_HANDLER){returnstatus;}returnSTATUS_SUCCESS;}

读写目标进程的内存

现在有了EPROCESS,我们开着手修改cr3寄存器的内容,也就是开始切换页表:

// 切换页表_disable();UINT64 cr3=__readcr3();__writecr3(pDTB);_enable();

这里使用_disable()来关闭中断,CR3寄存器控制当前进程的页表基址,切换CR3会立即改变地址空间映射。如果在切换过程中被中断打断,中断处理程序可能在不正确的地址空间中执行,导致数据访问错误或系统崩溃。

示例代码

#include<ntddk.h>#include<windef.h>#include<intrin.h>// 页表偏移#defineDIRECTORY_TABLE_BASE0x028// _disable直接生成cli指令,需要在内核模式中使用#pragmaintrinsic(_disable)// 将_disable声明为内联函数#pragmaintrinsic(_enable)EXTERN_C NTKERNELAPI NTSTATUSPsLookupProcessByProcessId(HANDLE ProcessId,PEPROCESS*Process);EXTERN_C NTKERNELAPI CHAR*PsGetProcessImageFileName(PEPROCESS Process);staticPEPROCESS sg_pEprocess=nullptr;// 通过进程名获取EPROCESS结构NTSTATUSGetProcessObjectByName(char*name){NTSTATUS status=STATUS_UNSUCCESSFUL;SIZE_T i;__try{for(i=0;i<20000;i++){PEPROCESS ep;NTSTATUS st=PsLookupProcessByProcessId((HANDLE)i,&ep);if(NT_SUCCESS(st)){char*pn=PsGetProcessImageFileName(ep);// 带下划线版本的是微软的标准扩展实现,应该优先使用if(_stricmp(pn,name)==0){DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"Found %s\n",name);sg_pEprocess=ep;__leave;}}}DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"Not Found %s\n",name);}__except(EXCEPTION_EXECUTE_HANDLER){returnstatus;}returnSTATUS_SUCCESS;}VOIDDriverUnload(PDRIVER_OBJECT pDriverObj){UNREFERENCED_PARAMETER(pDriverObj);DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"Uninstall Driver Successfully\n");}ULONG64CheckAddressVal(PVOID p){if(MmIsAddressValid(p)==FALSE){return0;}// 返回p指向的地址所存的内存return*(PULONG64)p;}BOOLEANCR3_ReadProcessMemory(PEPROCESS ep,PVOID addr,UINT32 length,PVOID buf){ULONG64 pDTB=CheckAddressVal((UCHAR*)ep+DIRECTORY_TABLE_BASE);if(pDTB==0){returnfalse;}// 切换页表_disable();UINT64 cr3=__readcr3();__writecr3(pDTB);_enable();if(MmIsAddressValid(addr)){RtlCopyMemory(buf,addr,length);DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"read data: %ld\n",*(PDWORD)buf);returntrue;}_disable();__writecr3(cr3);_enable();returnFALSE;}EXTERN_C NTSTATUSDriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegPath){UNREFERENCED_PARAMETER(pRegPath);DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"AccessMem Hello\n");pDriverObj->DriverUnload=DriverUnload;NTSTATUS status=GetProcessObjectByName("x64dbg.exe");if(NT_SUCCESS(status)){DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"[+] eprocess = %p\n",sg_pEprocess);}DWORD buf=0;PVOID addr=(PVOID)0x0000000009edc800;BOOLEAN bl=CR3_ReadProcessMemory(sg_pEprocess,addr,4,&buf);UNREFERENCED_PARAMETER(bl);DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"read process x64 address %p: %x, %d\n",addr,buf,buf);returnSTATUS_SUCCESS;}
http://www.jsqmd.com/news/932322/

相关文章:

  • Spring Boot 2.5.4项目里,如何给Swagger 3.0和Knife4j一键加上全局Header参数(附完整代码)
  • IDEA 2023.3 创建 Spring Boot 项目,如何让 Java 8 和 Spring Boot 3.x 共存?保姆级配置指南
  • 天价域名AI.com背后:数字入口的战略价值与AGI生态未来
  • 告别裸奔:用STM32CubeMX给STM32F407ZGT6快速移植FreeRTOS内核(含串口打印任务状态)
  • KAIST 把文本、SQL、知识图谱、属性图全打通:一句话提问,跨四种知识源一起检索
  • STM32掉电检测PVD的5个常见坑与优化技巧:从电压迟滞到中断优先级设置
  • Lab 3-1
  • Arduino蓝牙控制LED:从硬件连接到APP开发的物联网入门实践
  • LaTeX子图排版避坑指南:为什么你的图总对不齐?从原理到实战
  • 三维立体重构智慧矿产透明化安防监测预警及AI预案
  • 如何快速修复Garry‘s Mod游戏问题:面向玩家的完整解决方案
  • 保姆级教程:在ROS Gazebo中为Livox Mid-360激光雷达更换真实3D模型(附Blender缩放技巧)
  • DIY免焊接Ryobi 18V转12V电源:闲置工具电池的再生利用方案
  • 别让大模型把公司机密带出去!企业 RAG 离线隔离与权限硬控制实战
  • ap_ctrl_none接口 + hls::stream非阻塞设计
  • C++进阶:1. 引用折叠规则
  • 基于姿态传感器与Nintendo LABO的互动木偶发声系统实现
  • 从STM32无缝迁移到普冉PY32F003:以UART中断收发为例,对比HAL库异同
  • AI驱动智能合约开发:ChatGPT+Truffle+Infura+MetaMask全流程实战
  • 民谣网站|基于Springboot的民谣网站管理系统(源码+数据库+文档)
  • KMS智能激活终极指南:告别Windows和Office激活烦恼的完整解决方案
  • AI如何守护加密货币高额交易安全:从异常检测到实时防御
  • Sora 2水印去除技术白皮书(仅限首批内测开发者流通版):基于频域掩码+时序一致性修复的工业级方案
  • AI意识之谜:从整合信息理论到硅基困境与未来路径
  • WebToEpub:三步将网页小说转换为EPUB电子书的终极解决方案
  • 从伯德图斜率到阶跃响应:手把手教你用Matlab分析控制系统,并选择PD、PI还是PID校正
  • 跨可用区高可用云原生集群节点规划中关于 K8s Pod健康检查探针设计部署的架构思考
  • 告别卡顿!用Faster-Whisper在CPU上5分钟搞定中文语音转文字(附Tiny模型下载与转换)
  • 用2针排针自制纽扣电池座:零焊接快速原型供电方案
  • 别再瞎猜了!用 Javassist 给 G1/ZGC 装个“黑匣子”,GC 停顿秒级定位