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

通过MDL读写进程内存

通过MDL读写进程内存

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

MDL

Windows采用了分页机制来管理内存。考虑一个虚拟地址,要经过逐级查表,才可以得到物理地址。

逻辑上连续的虚拟页,很大概率会被映射到不连续的物理页中。

假设现在要求对一块内存进行高效的操作(比如IO),频繁地进行查表转换操作效率太低,所以可以把需要用到的页表的物理地址,以链表的形式进行存储,这样就避免了反复查表的开销。

MDL的具体结构Windows并未公开,这里只能参考其他人逆向得到的布局:

typedefstruct_MDL{struct_MDL*Next;// 指向下一个 MDL,形成 MDL 链CSHORT Size;// 本 MDL 结构的总大小(字节)CSHORT MdlFlags;// 标志位(见下表)struct_EPROCESS*Process;// 所属进程(若为用户模式缓冲区)PVOID MappedSystemVa;// 映射后的系统空间虚拟地址(若已映射)PVOID StartVa;// 缓冲区起始页的虚拟地址(页对齐)ULONG ByteCount;// 缓冲区总字节数ULONG ByteOffset;// 缓冲区在起始页内的字节偏移}MDL,*PMDL;

引用自Microsoft官方文档链接:

MDL 结构是半不透明的。 驱动程序应仅直接访问此结构的 Next 和 MdlFlags 成员。

通过MDL读取进程内存

主要步骤

1. KeStackAttachProcess() // 附加到目标进程 2. IoAllocateMdl() // 创建 MDL 3. MmProbeAndLockPages() // 探测并锁定页面 4. KeUnstackDetachProcess() // 脱离目标进程 5. MmGetSystemAddressForMdlSafe() // 获取系统空间地址 6. RtlCopyMemory() // 读取数据 7. MmUnlockPages() + IoFreeMdl() // 清理资源

附加到目标进程

首先我们需要切换当前线程的地址空间到目标进程中,因为IoAllocateMdl需要知道目标虚拟地址在哪个进程上下文中,并且我们还要在目标进程的地址空间中验证地址有效性,确保后续的MmProbeAndLockPages能正确访问目标进程的页表。

创建MDL

PMDL pMdl=IoAllocateMdl((PVOID)data->pTargetAddr,// 目标虚拟地址data->dwSize,// 要读取的大小false,// SecondaryBuffer(通常为false)false,// ChargeQuota(通常为false)nullptr// Irp(可选));

创建一个 MDL 来描述目标内存区域。

关键:探测并锁定页面

MmProbeAndLockPages(pMdl,UserMode,IoReadAccess);

这是最关键的一步,包含两个操作:

  1. 探测(Probe)

    • 验证地址有效性:确保地址在用户模式地址空间(0x00000000-0x7FFFFFFF)
    • 检查访问权限:验证当前是否有读取权限
    • 对齐检查:确保地址和大小符合对齐要求
    • 异常处理:如果地址无效,会抛出异常(代码中缺少 try/except)
  2. 锁定(Lock)

    • 确保页面驻留:将相关页面锁定在物理内存中,防止被换出到磁盘
    • 建立物理映射:在 MDL 中记录物理页面信息
    • 增加引用计数:防止页面被释放

参数说明:

  • UserMode:表示地址是用户模式地址

  • IoReadAccess:指定只读访问权限

脱离目标进程

MDL 已经捕获了物理页面信息,物理页面被锁定在内存中,不再需要目标进程的地址空间上下文。这样一来,我们就可以减少对目标进程的干扰、允许在脱离状态下长时间访问内存、避免保持附加状态可能导致的死锁问题。

获取系统空间地址

PVOID mappedAddress=MmGetSystemAddressForMdlSafe(pMdl,NormalPagePriority);

目的:将 MDL 描述的物理页面映射到系统空间。

工作原理:

  • 根据 MDL 中的物理页面信息

  • 创建系统空间的虚拟地址映射

  • 返回一个在内核中可以直接访问的指针

该函数返回的地址在内核空间中,我们可以直接使用RtlCopyMemory等进行访问。

示例代码

#include<ntifs.h>#include<windef.h>structData{DWORD dwPID;PVOID pTargetAddr;PBYTE data;DWORD dwSize;};VOIDDriverUnload(PDRIVER_OBJECT pDriverObj){UNREFERENCED_PARAMETER(pDriverObj);DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"Uninstall Driver Successfully!\n");}BOOLMDL_ReadMemory(Data*data){PEPROCESS pEp=nullptr;NTSTATUS status=PsLookupProcessByProcessId((HANDLE)data->dwPID,&pEp);if(!NT_SUCCESS(status)||pEp==nullptr){DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"find process failed!\n");returnFALSE;}// 附加到进程KAPC_STATE stack={0};KeStackAttachProcess(pEp,&stack);// 创建MDLPMDL pMdl=IoAllocateMdl((PVOID)data->pTargetAddr,data->dwSize,false,false,nullptr);if(!pMdl){DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"find process failed!\n");KeUnstackDetachProcess(&stack);ObDereferenceObject(pEp);returnfalse;}// 探测并锁定页面MmProbeAndLockPages(pMdl,UserMode,IoReadAccess);// 取消附加KeUnstackDetachProcess(&stack);// 获取系统空间映射地址PVOID mappedAddress=MmGetSystemAddressForMdlSafe(pMdl,NormalPagePriority);if(!mappedAddress){MmUnlockPages(pMdl);IoFreeMdl(pMdl);ObDereferenceObject(pEp);returnfalse;}// 读取数据RtlCopyMemory(data->data,mappedAddress,data->dwSize);// 清理资源MmUnlockPages(pMdl);IoFreeMdl(pMdl);ObDereferenceObject(pEp);returntrue;}EXTERN_C NTSTATUSDriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegPath){UNREFERENCED_PARAMETER(pRegPath);DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"Installing Driver...\n");pDriverObj->DriverUnload=DriverUnload;Data data;data.dwPID=6776;data.pTargetAddr=(PVOID)0x00000056ac965000;data.dwSize=20;if(MDL_ReadMemory(&data)){for(size_t i=0;i<data.dwSize/sizeof(DWORD);i++){DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"Readed: %x\n",((PDWORD)data.data)[i]);}}else{DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_INFO_LEVEL,"Installing Driver...\n");}returnSTATUS_SUCCESS;}

http://www.jsqmd.com/news/943277/

相关文章:

  • 基于DTMF与Arduino的远程控制机器人:从原理到实现的完整指南
  • AI工具链如何重构UI/UX工作流:从需求输入到高保真原型生成仅需83秒——实测12家AIGC设计平台性能对比报告
  • 百度网盘秒传脚本终极指南:如何实现永久文件分享的完整教程
  • Ozon 跨境卖家必看!源头厂出品 AI 选品神器,选品运营少走大半弯路
  • 从SimCLR到MAE:盘点那些在时序数据上‘水土不服’的CV/NLP自监督方法,我们该如何改造?
  • 广东省官方授权的CPPM注册职业采购经理培训机构选择指南
  • 2026烟台市本地黄金回收铂金白银回收哪家强?TOP5 正规门店榜单 + 联系方式 - 中安检金银铂钻回收
  • ProteinMPNN:革命性蛋白质序列设计工具,让AI为生命科学赋能
  • 刚刚,DeepSeek融资500亿,估值冲4000亿?腾讯急了,宁王也坐不住了
  • 终极色彩科学指南:从经典CIE Lab到现代Jzazbz的完整技术演进
  • Windows 11终极清理指南:用Win11Debloat免费实现系统性能翻倍
  • 百度文库文档免费下载终极指南:三步搞定付费限制,高效保存纯净资料
  • 3分钟极速上手:douyin-downloader 抖音无水印下载实战指南
  • 【监管科技新范式】:为什么83%的金融机构在Q3紧急升级AI合规中台?
  • XMly-Downloader-Qt5:跨平台喜马拉雅音频下载工具深度解析与实战指南 [特殊字符]
  • Matlab多目标人工蜂鸟算法MOAHA仿真包:含ZDT/DTLZ测试函数、Pareto前沿可视化与完整运行脚本
  • 2026年6月阜阳贵金属回收权威门店排行 TOP5 黄金 + 铂金 + 白银回收 附电话地址 - 中业金奢再生回收中心
  • 纸电路入门:用导电铜箔胶带制作会发光的创意卡片
  • 三步搞定Windows和Office智能激活:KMS_VL_ALL_AIO终极指南
  • ChanlunX:通达信缠论分析终极解决方案
  • AI写专著新方法!借助AI工具,20万字专著快速撰写与出版!
  • 2026年6月河北黄金白银铂金回收靠谱门店 TOP5+权威榜单+联系电话汇总 - 信誉隆金银铂奢回收
  • 模拟电路实战:用运算放大器实现音视频混合与故障艺术生成
  • 别再只盯着CNN和RNN了:一份给Python开发者的图神经网络(GNN)避坑与快速上手指南
  • 基于ESP32的医用呼吸机控制系统:从气路设计到闭环控制全解析
  • 揭秘SteamBot:掌握自动化Steam交易的5个核心机制
  • 如何高效部署和使用SI6 Networks IPv6安全评估工具集
  • LangChain4j 开发Java Agent智能体- 整合SpringBoot4
  • 终极指南:如何用Mousecape免费定制macOS光标主题,让桌面焕然一新
  • 3分钟掌握RoundedTB:免费让你的Windows任务栏焕然一新