32位/64位WINDOWS驱动之物理地址读写内存方法4

本文详细介绍了在32位和64位Windows环境下,如何通过驱动开发实现物理地址的读写内存操作。通过GetPhysicalAddress函数计算目标进程物理地址,使用ZwMapViewOfSection进行映射,结合ReadPVirtualMemory和WritePVirtualMemory函数实现读写。在驱动和MFC应用层分别进行了相关代码实现,并在虚拟机上成功调试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、32位/64位WINDOWS驱动之物理地址读写内存方法4

GetPhysicalAddress ;自写函数 通过PID切换到目标进程环境 计算出物理地址
ZwMapViewOfSection ;把物理地址映射到当前进程 不使用时需要用ZwUnmapViewOfSection取消映射

BOOLEAN ReadPVirtualMemory(UINT64 ProcessID, IN PVOID VBaseAddress, IN UINT32 nSize, OUT PVOID pBuf);//转换成 物理地址的方式 读取进程虚拟地址
BOOLEAN WritePVirtualMemory(UINT64 ProcessID, IN PVOID VBaseAddress, IN UINT32 nSize, IN PVOID pBuf);

二、驱动层,过保护读写筛选器中添加 通过物理地址读写目标进程内存.c

在这里插入图片描述
代码如下:

#include "ntifs.h"
//#include "rwPhysicalMemory.h"
//#include "VMProtectDDK.h"

//InfoType   Array index Bit range Information
//0x80000008  0       0 - 7              Physical address bits
//0x80000008  0       8 - 15             Virtual address bits
//0x80000008  0       16 - 31            Reserved
//0x80000008  1 - 3   0 - 31             Reserved

UINT64 g_maxPhysAddress = 0;
//利用cpuid取出 物理地址Bits
UINT64 getg_maxPhysAddress(void)
{
   
	if (g_maxPhysAddress == 0)
	{
   
		int physicalbits;
		UINT32 r[4]; //四个整数的数组,包含在 EAX、EBX、ECX 和 EDX 中返回的有关 CPU 支持的功能的信息
		__cpuid(r, 0x80000008); //只有r[0]的前 8位和 8至15们有用 后边3个 全保留

		//get max physical address
		physicalbits = r[0] & 0xff;

		g_maxPhysAddress = 0xFFFFFFFFFFFFFFFFULL;
		g_maxPhysAddress = g_maxPhysAddress >> physicalbits; //if physicalbits==36 then g_maxPhysAddress=0x000000000fffffff
		g_maxPhysAddress = ~(g_maxPhysAddress << physicalbits); //<< 36 = 0xfffffff000000000 .  after inverse : 0x0000000fffffffff		
	}

	return g_maxPhysAddress;
}

//对于分页内存来说,调用MmProbeAndLockPages以及MmGetSystemAddressForMdlSafe来锁定内存页,以防止被page out出去;
//对于非分页内存而言,调用MmBuildMdlForNonPagedPool映射到物理内存上。
//__noop(("yjx:Too small map"));
//physicalBase本身就是物理地址
BOOLEAN ReadPhysicalMemory(char *physicalBase, UINT_PTR bytestoread, void *output)
{
   
	HANDLE			physmem;
	UNICODE_STRING	physmemString;
	OBJECT_ATTRIBUTES attributes;
	const	WCHAR			*physmemName = L"\\device\\physicalmemory"; //VMProtectDecryptStringW(L"\\device\\physicalmemory");
	UCHAR*			vaddress; // 用于映射后的虚地址 供访问
	NTSTATUS		ntStatus = STATUS_UNSUCCESSFUL;
	PMDL			outputMDL;//存放读取的到的数据

	KdPrint(("yjx:ReadPhysicalMemory(%p, %d, %p)", physicalBase, bytestoread, output));

	if (((UINT64)physicalBase > getg_maxPhysAddress()) || ((UINT64)physicalBase + bytestoread > getg_maxPhysAddress()))
	{
   
		KdPrint(("yjx:SYS Invalid physical address\n"));
		return ntStatus == FALSE;
	}

	outputMDL = IoAllocateMdl(output, (ULONG)bytestoread, FALSE, FALSE, NULL);
	__try
	{
   
		MmProbeAndLockPages(outputMDL, KernelMode, IoWriteAccess); //MmBuildMdlForNonPagedPool 
		//MmBuildMdlForNonPagedPool(outputMDL);
		//MmGetSystemAddressForMdlSafe(outputMDL,)
	}
	__except (1)
	{
   
		IoFreeMdl(outputMDL);
		return FALSE; //STATUS_UNSUCCESSFUL;
	}

	//__try
	//{
   
	//	PVOID	pMapedAddr = MmMapLockedPagesSpecifyCache(outputMDL, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
	//	if (!pMapedAddr)
	//	{
   
	//		KdPrint(("yjx:SYS:Error MmMapLockedPagesSpecifyCache pMapedAdd == NULL\n"));
	//		return FALSE;
	//	}
	//}
	//__except (1)
	//{
   
	//	KdPrint(("yjx:SYS:Error MmMapLockedPagesSpecifyCache  fail \n"));
	//	return FALSE;
	//}

	__try
	{
   
		RtlInitUnicodeString(&physmemString, physmemName);

		InitializeObjectAttributes(&attributes, &physmemString, OBJ_CASE_INSENSITIVE, NULL, NULL);
		ntStatus = ZwOpenSection(&physmem, SECTION_ALL_ACCESS, &attributes);
		if (ntStatus == STATUS_SUCCESS)
		{
   
			//hey look, it didn't kill it
			SIZE_T length;
			PHYSICAL_ADDRESS	viewBase;//物理内存地址
			UINT_PTR offset;
			UINT_PTR toread;

			viewBase.QuadPart = (ULONGLONG)(physicalBase);

			length = 0x2000;//pinp->bytestoread; //in case of a overlapping region
			toread = bytestoread;

			vaddress = NULL;

			KdPrint(("yjx:ReadPhysicalMemory:viewBase.QuadPart=%x", viewBase.QuadPart));

			//映射物理内存地址到当前进程的虚地址空间
			ntStatus = ZwMapViewOfSection(
				physmem,  //sectionhandle
				NtCurrentProcess(), //processhandle (should be -1)
				&vaddress, //BaseAddr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

a756598009

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值