MDL内存读写是最常用的一种读写模式,通常需要附加到指定进程空间内然后调用内存拷贝得到对端内存中的数据,在调用结束后再将其空间释放掉,通过这种方式实现内存读写操作,此种模式的读写操作也是最推荐使用的相比于CR3切换来说,此方式更稳定并不会受寄存器的影响。

MDL读取内存步骤

  • 1.调用PsLookupProcessByProcessId得到进程Process结构
  • 2.调用KeStackAttachProcess附加到对端进程内
  • 3.调用ProbeForRead检查内存是否可读写
  • 4.拷贝内存空间中的数据到自己的缓冲区内
  • 5.调用KeUnstackDetachProcess接触绑定
  • 6.调用ObDereferenceObject使对象引用数减1

代码总结起来应该是如下样子,用户传入一个结构体,输出对应长度的字节数据:

#include <ntifs.h>
#include <windef.h> typedef struct
{
DWORD pid; // 要读写的进程ID
DWORD64 address; // 要读写的地址
DWORD size; // 读写长度
BYTE* data; // 要读写的数据
}ReadMemoryStruct; // MDL读内存
BOOL MDLReadMemory(ReadMemoryStruct* data)
{
BOOL bRet = TRUE;
PEPROCESS process = NULL; PsLookupProcessByProcessId(data->pid, &process); if (process == NULL)
{
return FALSE;
} BYTE* GetData;
__try
{
GetData = ExAllocatePool(PagedPool, data->size);
}
__except (1)
{
return FALSE;
} KAPC_STATE stack = { 0 };
KeStackAttachProcess(process, &stack); __try
{
ProbeForRead(data->address, data->size, 1);
RtlCopyMemory(GetData, data->address, data->size);
}
__except (1)
{
bRet = FALSE;
} ObDereferenceObject(process);
KeUnstackDetachProcess(&stack);
RtlCopyMemory(data->data, GetData, data->size);
ExFreePool(GetData);
return bRet;
} VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint(("Uninstall Driver Is OK \n"));
} NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint(("hello lyshark \n")); ReadMemoryStruct ptr; ptr.pid = 6672;
ptr.address = 0x402c00;
ptr.size = 100; // 分配空间接收数据
ptr.data = ExAllocatePool(PagedPool, ptr.size); // 读内存
MDLReadMemory(&ptr); // 输出数据
for (size_t i = 0; i < 100; i++)
{
DbgPrint("%x \n", ptr.data[i]);
} Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}

读取内存地址0x402c00效果如下所示:

MDL写入内存步骤

  • 1.调用PsLookupProcessByProcessId得到进程Process结构
  • 2.调用KeStackAttachProcess附加到对端进程内
  • 3.调用ProbeForRead检查内存是否可读写
  • 4.拷贝内存空间中的数据到自己的缓冲区内
  • 5.调用MmMapLockedPages锁定当前内存页面(写入)
  • 6.调用RtlCopyMemory内存拷贝完成写入(写入)
  • 7.调用IoFreeMdl释放MDL锁(写入)
  • 8.调用KeUnstackDetachProcess接触绑定
  • 9.调用ObDereferenceObject使对象引用数减1

写入时与读取类似,只是多了锁定页面和解锁操作。

#include <ntifs.h>
#include <windef.h> typedef struct
{
DWORD pid; // 要读写的进程ID
DWORD64 address; // 要读写的地址
DWORD size; // 读写长度
BYTE* data; // 要读写的数据
}ReadMemoryStruct; // MDL写内存
BOOL MDLWriteMemory(ReadMemoryStruct* data)
{
BOOL bRet = TRUE;
PEPROCESS process = NULL; PsLookupProcessByProcessId(data->pid, &process);
if (process == NULL)
{
return FALSE;
} BYTE* GetData;
__try
{
GetData = ExAllocatePool(PagedPool, data->size);
}
__except (1)
{
return FALSE;
} for (int i = 0; i < data->size; i++)
{
GetData[i] = data->data[i];
} KAPC_STATE stack = { 0 };
KeStackAttachProcess(process, &stack); PMDL mdl = IoAllocateMdl(data->address, data->size, 0, 0, NULL);
if (mdl == NULL)
{
return FALSE;
} MmBuildMdlForNonPagedPool(mdl); BYTE* ChangeData = NULL; __try
{
ChangeData = MmMapLockedPages(mdl, KernelMode);
RtlCopyMemory(ChangeData, GetData, data->size);
}
__except (1)
{
bRet = FALSE;
goto END;
} END:
IoFreeMdl(mdl);
ExFreePool(GetData);
KeUnstackDetachProcess(&stack);
ObDereferenceObject(process); return bRet;
} VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint(("Uninstall Driver Is OK \n"));
} NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint(("hello lyshark \n")); ReadMemoryStruct ptr; ptr.pid = 6672;
ptr.address = 0x402c00;
ptr.size = 5; // 需要写入的数据
ptr.data = ExAllocatePool(PagedPool, ptr.size); // 循环设置
for (size_t i = 0; i < 5; i++)
{
ptr.data[i] = 0x90;
} // 写内存
MDLWriteMemory(&ptr); Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}

写出效果如下:

驱动开发:内核MDL读写进程内存的更多相关文章

  1. 驱动读写进程内存R3,R0通信

    stdafx.h 头文件代码 #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. #defin ...

  2. Windows驱动开发-内核常用内存函数

    搞内存常用函数 C语言 内核 malloc ExAllocatePool memset RtlFillMemory memcpy RtlMoveMemory free ExFreePool

  3. Linux驱动开发常用头文件

    头文件目录中总共有32个.h头文件.其中主目录下有13个,asm子目录中有4个,linux子目录中有10个,sys子目录中有5个.这些头文件各自的功能如下: 1.主目录 <a.out.h> ...

  4. 驱动开发:内核CR3切换读写内存

    首先CR3是什么,CR3是一个寄存器,该寄存器内保存有页目录表物理地址(PDBR地址),其实CR3内部存放的就是页目录表的内存基地址,运用CR3切换可实现对特定进程内存地址的强制读写操作,此类读写属于 ...

  5. 驱动开发:内核R3与R0内存映射拷贝

    在上一篇博文<驱动开发:内核通过PEB得到进程参数>中我们通过使用KeStackAttachProcess附加进程的方式得到了该进程的PEB结构信息,本篇文章同样需要使用进程附加功能,但这 ...

  6. 驱动开发:内核中实现Dump进程转储

    多数ARK反内核工具中都存在驱动级别的内存转存功能,该功能可以将应用层中运行进程的内存镜像转存到特定目录下,内存转存功能在应对加壳程序的分析尤为重要,当进程在内存中解码后,我们可以很容易的将内存镜像导 ...

  7. 驱动开发:内核遍历进程VAD结构体

    在上一篇文章<驱动开发:内核中实现Dump进程转储>中我们实现了ARK工具的转存功能,本篇文章继续以内存为出发点介绍VAD结构,该结构的全程是Virtual Address Descrip ...

  8. 用Visual studio2012在Windows8上开发内核驱动监视进程创建

    在Windows NT中,80386保护模式的“保护”比Windows 95中更坚固,这个“镀金的笼子”更加结实,更加难以打破.在Windows 95中,至少应用程序I/O操作是不受限制的,而在Win ...

  9. 《Windows内核安全与驱动开发》 3.2 内存与链表

    <Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 3.2 内存与链表 1. 尝试生成一个链表头并将其初始化. 2. 尝试向内存 ...

  10. 驱动开发:通过Async反向与内核通信

    在前几篇文章中给大家具体解释了驱动与应用层之间正向通信的一些经典案例,本章将继续学习驱动通信,不过这次我们学习的是通过运用Async异步模式实现的反向通信,反向通信机制在开发中时常被用到,例如一个杀毒 ...

随机推荐

  1. Mongodb--用户/权限

    mongodb分为管理员用户和普通用户,并且还有个验证库,建立用户时use到的库(验证库),信息就存储在admin数据库下. 在使用用户时,要加上验证库才能登录,对于管理员用户,必须在admin下创建 ...

  2. COGI控制删除按钮增强

    1.业务需求 COGI在SAP中主要用于解决生产订单异常的问题.通常发生在生产订单执行过程中,当出现了特定的异常情况时,需要进行处理.这些异常情况可能包括物料缺失.数量不匹配.质量问题等等. 当这些异 ...

  3. 在Windows下配置Clang编译器

    Preferences Linux & macOS 平台LLVM 相关工具链下载 2019年,在Windows下配置Clang编译器 Visual Studio 2022 中使用 Clang ...

  4. LeetCode 第 193 场周赛 解题报告

    5436. 一维数组的动态和 时间复杂度:O(n) 知识点:前缀和 根据题目给出的公式 runningSum[i] = sum(nums[0]-nums[i]),可得: 当 i > 0 时,ru ...

  5. SCA 技术进阶系列(二):代码同源检测技术在供应链安全治理中的应用

    直击痛点:为什么需要同源检测 随着 "数字中国" 建设的不断提速,企业在数字化转型的创新实践中不断加大对开源技术的应用,引入开源组件完成应用需求开发已经成为了大多数研发工程师开发软 ...

  6. 打破 Serverless 落地边界,阿里云 SAE 发布 5 大新特性

    微服务场景,开源自建真的最快最省最稳的?复杂性真的会成为 Kubernetes 的"致命伤"吗?企业应用容器化,一定得过 K8s 这座"独木桥"吗?Server ...

  7. warning: LF will be replaced by CRLF in public/tinymce/langs/zh_CN.js

    windows使用git时出现:warning:LF will be replaced by CRLF windows中的换行符为 CRLF, 而在linux下的换行符为LF,所以在执行add . 时 ...

  8. 3 分钟将免费无限制的 Claude 2.0 接入任意 GPT 套壳应用,太香了!

    Claude 是 ChatGPT 的最强竞争对手,由 OpenAI 早期团队成员创建,目标就是打造出能 赶超 ChatGPT 的 AI.最新版的 Claude 2.0,能力已经开始领先 ChatGPT ...

  9. OpenShift image registry 访问镜像

    1. OpenShift 内部 image registry Openshift 自带内部 image registry,可通过 podman 实现 image 的 pull 和 push 操作. 对 ...

  10. python中BeautifulSoup库使用小结

    转载请注明出处: BeautifulSoup是一个用于解析HTML和XML文档的Python库,它提供了一些简单但强大的API,让你可以从文档中提取数据.以下是一些BeautifulSoup的主要特性 ...