由于我一般使用的虚拟内存, 有时我们需要获取到物理内存中的数据(也就是内存条中的真实数据), 按理说是很简单,打开物理内存,读取就可以了.但似乎没这么简单:
#include "windows.h"
//定义相应的变量类型,见ntddk.h
typedef LONG NTSTATUS;
#define NT_SUCCESS(Status)((NTSTATUS)(Status) >= 0)
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef enum _SECTION_INHERIT
{
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT, *PSECTION_INHERIT;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
// Interesting functions in NTDLL
typedef NTSTATUS (WINAPI *ZwOpenSectionProc)
(
PHANDLE SectionHandle,
DWORD DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes
);
typedef NTSTATUS (WINAPI *ZwMapViewOfSectionProc)
(
HANDLE SectionHandle,
HANDLE ProcessHandle,
PVOID *BaseAddress,
ULONG ZeroBits,
ULONG CommitSize,
PLARGE_INTEGER SectionOffset,
PULONG ViewSize,
SECTION_INHERIT InheritDisposition,
ULONG AllocationType,
ULONG Protect
);
typedef NTSTATUS (WINAPI *ZwUnmapViewOfSectionProc)
(
HANDLE ProcessHandle,
PVOID BaseAddress
);
typedef VOID (WINAPI *RtlInitUnicodeStringProc)
(
IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString
);
class PhysicalMemory
{
public:
PhysicalMemory(DWORD dwDesiredAccess = SECTION_MAP_READ);
~PhysicalMemory();
HANDLE OpenPhysicalMemory(DWORD dwDesiredAccess = SECTION_MAP_READ);
VOID SetPhyscialMemoryAccess(HANDLE hPhysicalMemory,//由ZwOpenSection/NtOpenSection返回的物理内存句柄
DWORD dwDesiredAccess//访问权限
);
BOOL ReadPhysicalMemory(OUT PVOID pvDataBuffer, //用于保存读取数据的缓冲区首地址
IN DWORD dwAddress, //要读取的数据的首地址,要求4KB对齐
IN DWORD dwLength //读取的长度
);
BOOL WritePhysicalMemory(IN PVOID pvDataBuffer, //用于保存要写入的数据的缓冲区首地址
IN DWORD dwAddress, //要目标地址,要求4KB对齐
IN DWORD dwLength //写入的长度
);
private:
static BOOL InitPhysicalMemory() ;
static void ExitPhysicalMemory() ;
private:
HANDLE m_hPhysicalMemory ;
static HMODULE sm_hNtdllModule ;
static ZwOpenSectionProc ZwOpenSection;
static ZwMapViewOfSectionProc ZwMapViewOfSection;
static ZwUnmapViewOfSectionProc ZwUnmapViewOfSection;
static RtlInitUnicodeStringProc RtlInitUnicodeString;
static PhysicalMemory * sm_pFirstObject;
PhysicalMemory * m_pNextObject;
}; ...
#include "windows.h"
#include "Aclapi.h"
#include "PhysicalMemory.h"
//初始化OBJECT_ATTRIBUTES类型的变量
#define InitializeObjectAttributes( p, n, a, r, s ) { (p)->Length = sizeof( OBJECT_ATTRIBUTES );(p)->RootDirectory = r; (p)->Attributes = a; (p)->ObjectName = n; (p)->SecurityDescriptor = s; (p)->SecurityQualityOfService = NULL; }
// #define InitializeObjectAttributes( p, n, a, r, s ) { \
// (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
// (p)->RootDirectory = r; \
// (p)->Attributes = a; \
// (p)->ObjectName = n; \
// (p)->SecurityDescriptor = s; \
// (p)->SecurityQualityOfService = NULL; \
//}
// static variables of class PhysicalMemory
PhysicalMemory* PhysicalMemory::sm_pFirstObject = NULL;
HMODULE PhysicalMemory::sm_hNtdllModule = NULL;
ZwOpenSectionProc PhysicalMemory::ZwOpenSection = NULL;
ZwMapViewOfSectionProc PhysicalMemory::ZwMapViewOfSection = NULL;
ZwUnmapViewOfSectionProc PhysicalMemory::ZwUnmapViewOfSection = NULL;
RtlInitUnicodeStringProc PhysicalMemory::RtlInitUnicodeString = NULL;
PhysicalMemory::PhysicalMemory(DWORD dwDesiredAccess)
{
if(sm_hNtdllModule == NULL)
if(!InitPhysicalMemory())
return;
m_pNextObject = sm_pFirstObject;
sm_pFirstObject = this;
// 以下打开内核对象
m_hPhysicalMemory = OpenPhysicalMemory(dwDesiredAccess);
return ;
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
PhysicalMemory::~PhysicalMemory()
{
if (m_hPhysicalMemory != NULL)
{
CloseHandle(m_hPhysicalMemory);
m_hPhysicalMemory = NULL;
}
PhysicalMemory *pCurrentObject = sm_pFirstObject;
if(pCurrentObject==this)
sm_pFirstObject = sm_pFirstObject->m_pNextObject;
else{
while(pCurrentObject!=NULL){
if(pCurrentObject->m_pNextObject==this){
pCurrentObject->m_pNextObject=this->m_pNextObject;
break;
}
pCurrentObject = pCurrentObject->m_pNextObject;
}
}
if(sm_pFirstObject == NULL)
ExitPhysicalMemory();
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
// initialize
BOOL PhysicalMemory::InitPhysicalMemory()
{
if (!(sm_hNtdllModule = LoadLibrary("ntdll.dll")))
{
return FALSE;
}
// 以下从NTDLL获取我们需要的几个函数指针
if (!(ZwOpenSection = (ZwOpenSectionProc)GetProcAddress(sm_hNtdllModule,"ZwOpenSection")))
{
return FALSE;
}
if (!(ZwMapViewOfSection = (ZwMapViewOfSectionProc)GetProcAddress(sm_hNtdllModule, "ZwMapViewOfSection")))
{
return FALSE;
}
if (!(ZwUnmapViewOfSection = (ZwUnmapViewOfSectionProc)GetProcAddress(sm_hNtdllModule, "ZwUnmapViewOfSection")))
{
return FALSE;
}
if (!(RtlInitUnicodeString = (RtlInitUnicodeStringProc)GetProcAddress(sm_hNtdllModule, "RtlInitUnicodeString")))
{
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
void PhysicalMemory::ExitPhysicalMemory()
{
if (sm_hNtdllModule != NULL)
{
// sm_pFirstObject->~PhysicalMemory();
FreeLibrary(sm_hNtdllModule);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
HANDLE PhysicalMemory::OpenPhysicalMemory(DWORD dwDesiredAccess)
{
ULONG PhyDirectory;
OSVERSIONINFO OSVersion;
OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx (&OSVersion);
if (5 != OSVersion.dwMajorVersion)
return NULL;
switch(OSVersion.dwMinorVersion)
{
case 0:
PhyDirectory = 0x30000;
break; //2k
case 1:
PhyDirectory = 0x39000;
break; //xp
default:
return NULL;
}
WCHAR PhysicalMemoryName[] = L"\\Device\\PhysicalMemory";
UNICODE_STRING PhysicalMemoryString;
OBJECT_ATTRIBUTES attributes;
RtlInitUnicodeString(&PhysicalMemoryString, PhysicalMemoryName);
InitializeObjectAttributes(&attributes, &PhysicalMemoryString, 0, NULL, NULL);
HANDLE hPhysicalMemory ;
NTSTATUS status = ZwOpenSection(&hPhysicalMemory, dwDesiredAccess, &attributes );
if(status == STATUS_ACCESS_DENIED)
{
status = ZwOpenSection(&hPhysicalMemory, READ_CONTROL|WRITE_DAC, &attributes);
SetPhyscialMemoryAccess(hPhysicalMemory,dwDesiredAccess);
CloseHandle(hPhysicalMemory);
status = ZwOpenSection(&hPhysicalMemory, dwDesiredAccess, &attributes);
}
return ( NT_SUCCESS(status) ? hPhysicalMemory : NULL );
// g_pMapPhysicalMemory = MapViewOfFile(g_hMPM, FILE_MAP_READ|FILE_MAP_WRITE, 0, PhyDirectory,
//0x1000);
// if( g_pMapPhysicalMemory == NULL )
// return NULL;
// return g_hMPM;
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
VOID PhysicalMemory::SetPhyscialMemoryAccess(HANDLE hPhysicalMemory,//由ZwOpenSection/NtOpenSection返回的物理内存句柄
DWORD dwDesiredAccess//访问权限
)
//设置物理内存的访问权限,成功返回TRUE,错误返回FALSE
{
PACL pDacl = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pNewDacl = NULL;
DWORD dwRes = GetSecurityInfo(hPhysicalMemory, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL,
NULL, &pDacl, NULL, &pSD);
if(ERROR_SUCCESS != dwRes)
{
if(pSD)
LocalFree(pSD);
if(pNewDacl)
LocalFree(pNewDacl);
}
EXPLICIT_ACCESS ea;
RtlZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = SECTION_MAP_WRITE;
ea.grfAccessMode = GRANT_ACCESS;
ea.grfInheritance= NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
ea.Trustee.ptstrName = "CURRENT_USER";
dwRes = SetEntriesInAcl(1,&ea,pDacl,&pNewDacl);
if(ERROR_SUCCESS != dwRes)
{
if(pSD)
LocalFree(pSD);
if(pNewDacl)
LocalFree(pNewDacl);
}
dwRes = SetSecurityInfo
(hPhysicalMemory,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pNewDacl,NULL);
if(ERROR_SUCCESS != dwRes)
{
if(pSD)
LocalFree(pSD);
if(pNewDacl)
LocalFree(pNewDacl);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
BOOL PhysicalMemory::ReadPhysicalMemory(OUT PVOID pvDataBuffer, //用于保存读取数据的缓冲区首地址
IN DWORD dwAddress, //要读取的数据的首地址,要求4KB对齐
IN DWORD dwLength //读取的长度
)
{
if((dwAddress & 0x0fff ))//若地址不是4KB对齐,则返回
{
return FALSE;
}
if(m_hPhysicalMemory == NULL)
{
return FALSE;
}
DWORD dwOutLenth; // 输出长度,根据内存分页大小可能大于要求的长度
PVOID pvVirtualAddress; // 映射的虚地址
NTSTATUS status; // NTDLL函数返回的状态
LARGE_INTEGER base; // 物理内存地址
pvVirtualAddress = 0;
dwOutLenth = dwLength;
base.QuadPart = (ULONGLONG)(dwAddress);
// 映射物理内存地址到当前进程的虚地址空间
status = ZwMapViewOfSection(m_hPhysicalMemory,
(HANDLE) -1,
(PVOID *)&pvVirtualAddress,
0,
dwLength,
&base,
&dwOutLenth,
ViewShare,
0,
PAGE_READONLY
);
if (status < 0)
{
return FALSE;
}
// 当前进程的虚地址空间中,复制数据到输出缓冲区
memmove(pvDataBuffer,pvVirtualAddress, dwLength);
// 完成访问,取消地址映射
status = ZwUnmapViewOfSection((HANDLE)-1, (PVOID)pvVirtualAddress);
return (status >= 0);
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
BOOL PhysicalMemory::WritePhysicalMemory(IN PVOID pvDataBuffer, //用于保存要写入的数据的缓冲区首地址
IN DWORD dwAddress, //要目标地址,要求4KB对齐
IN DWORD dwLength //写入的长度
)
{
if((dwAddress & 0x0fff ))//若地址不是4KB对齐,则返回
{
return FALSE;
}
if(m_hPhysicalMemory == NULL)
{
return FALSE;
}
DWORD dwOutLenth; // 输出长度,根据内存分页大小可能大于要求的长度
PVOID pvVirtualAddress; // 映射的虚地址
NTSTATUS status; // NTDLL函数返回的状态
LARGE_INTEGER base; // 物理内存地址
pvVirtualAddress = 0;
dwOutLenth = dwLength;
base.QuadPart = (ULONGLONG)(dwAddress);
// 映射物理内存地址到当前进程的虚地址空间
status = ZwMapViewOfSection(m_hPhysicalMemory,
(HANDLE) -1,
(PVOID *)&pvVirtualAddress,
0,
dwLength,
&base,
&dwOutLenth,
ViewShare,
,0
FILE_MAP_WRITE//PAGE_READWRITE
);
if (status < 0)
{
return FALSE;
}
// 当前进程的虚地址空间中,复制数据到输出缓冲区
::memmove(pvVirtualAddress, pvDataBuffer,dwLength);
// 完成访问,取消地址映射
status = ZwUnmapViewOfSection((HANDLE)-1, (PVOID)pvVirtualAddress);
return (status >= 0);
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////

原文:http://www.cnblogs.com/kuangke/p/6259344.html