一、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