windows 物理内存获取

由于我一般使用的虚拟内存, 有时我们需要获取到物理内存中的数据(也就是内存条中的真实数据), 按理说是很简单,打开物理内存,读取就可以了.但似乎没这么简单:


  1. #include "windows.h"  
  2.   
  3. //定义相应的变量类型,见ntddk.h  
  4. typedef LONG    NTSTATUS;  
  5.   
  6. #define NT_SUCCESS(Status)((NTSTATUS)(Status) >= 0)  
  7. #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)  
  8.   
  9. typedef struct _UNICODE_STRING  
  10. {  
  11.     USHORT Length;  
  12.     USHORT MaximumLength;  
  13.     PWSTR Buffer;  
  14. } UNICODE_STRING, *PUNICODE_STRING;  
  15.   
  16. typedef enum _SECTION_INHERIT  
  17. {  
  18.     ViewShare = 1,  
  19.     ViewUnmap = 2  
  20. } SECTION_INHERIT, *PSECTION_INHERIT;  
  21.   
  22. typedef struct _OBJECT_ATTRIBUTES  
  23. {  
  24.     ULONG Length;  
  25.     HANDLE RootDirectory;  
  26.     PUNICODE_STRING ObjectName;  
  27.     ULONG Attributes;  
  28.     PVOID SecurityDescriptor;  
  29.     PVOID SecurityQualityOfService;  
  30. } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;  
  31.   
  32.   
  33. // Interesting functions in NTDLL  
  34. typedef NTSTATUS (WINAPI *ZwOpenSectionProc)  
  35. (  
  36.  PHANDLE SectionHandle,  
  37.  DWORD DesiredAccess,  
  38.  POBJECT_ATTRIBUTES ObjectAttributes  
  39.  );  
  40. typedef NTSTATUS (WINAPI *ZwMapViewOfSectionProc)  
  41. (  
  42.  HANDLE SectionHandle,  
  43.  HANDLE ProcessHandle,  
  44.  PVOID *BaseAddress,  
  45.  ULONG ZeroBits,  
  46.  ULONG CommitSize,  
  47.  PLARGE_INTEGER SectionOffset,  
  48.  PULONG ViewSize,  
  49.  SECTION_INHERIT InheritDisposition,  
  50.  ULONG AllocationType,  
  51.  ULONG Protect  
  52.  );  
  53. typedef NTSTATUS (WINAPI *ZwUnmapViewOfSectionProc)  
  54. (  
  55.  HANDLE ProcessHandle,  
  56.  PVOID BaseAddress  
  57.  );  
  58. typedef VOID (WINAPI *RtlInitUnicodeStringProc)  
  59. (  
  60.  IN OUT PUNICODE_STRING DestinationString,  
  61.  IN PCWSTR SourceString  
  62.  );  
  63.   
  64. class PhysicalMemory  
  65. {  
  66. public:  
  67.     PhysicalMemory(DWORD dwDesiredAccess = SECTION_MAP_READ);  
  68.     ~PhysicalMemory();  
  69.     HANDLE OpenPhysicalMemory(DWORD dwDesiredAccess = SECTION_MAP_READ);  
  70.     VOID SetPhyscialMemoryAccess(HANDLE hPhysicalMemory,//由ZwOpenSection/NtOpenSection返回的物理内存句柄  
  71.         DWORD dwDesiredAccess//访问权限  
  72.         );  
  73.     BOOL ReadPhysicalMemory(OUT PVOID pvDataBuffer, //用于保存读取数据的缓冲区首地址  
  74.         IN DWORD dwAddress, //要读取的数据的首地址,要求4KB对齐  
  75.         IN DWORD dwLength //读取的长度  
  76.         );  
  77.     BOOL WritePhysicalMemory(IN PVOID pvDataBuffer, //用于保存要写入的数据的缓冲区首地址  
  78.         IN DWORD dwAddress, //要目标地址,要求4KB对齐  
  79.         IN DWORD dwLength //写入的长度  
  80.         );  
  81.   
  82.   
  83. private:  
  84.     static BOOL InitPhysicalMemory() ;  
  85.     static void ExitPhysicalMemory() ;  
  86.   
  87. private:  
  88.     HANDLE m_hPhysicalMemory ;  
  89.     static HMODULE sm_hNtdllModule ;  
  90.     static ZwOpenSectionProc ZwOpenSection;  
  91.     static ZwMapViewOfSectionProc ZwMapViewOfSection;  
  92.     static ZwUnmapViewOfSectionProc ZwUnmapViewOfSection;  
  93.     static RtlInitUnicodeStringProc RtlInitUnicodeString;  
  94.     static PhysicalMemory * sm_pFirstObject;  
  95.     PhysicalMemory * m_pNextObject;  
  96. }; ...  
#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;
}; ...

  1. #include "windows.h"  
  2. #include "Aclapi.h"  
  3. #include "PhysicalMemory.h"  
  4. //初始化OBJECT_ATTRIBUTES类型的变量  
  5. #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; }  
  6. // #define InitializeObjectAttributes( p, n, a, r, s ) {    
  7. //  (p)->Length = sizeof( OBJECT_ATTRIBUTES );    
  8. //    (p)->RootDirectory = r;    
  9. //   (p)->Attributes = a;    
  10. //    (p)->ObjectName = n;    
  11. //    (p)->SecurityDescriptor = s;    
  12. //    (p)->SecurityQualityOfService = NULL;    
  13. //}  
  14.   
  15. // static variables of class PhysicalMemory  
  16. PhysicalMemory* PhysicalMemory::sm_pFirstObject = NULL;  
  17. HMODULE PhysicalMemory::sm_hNtdllModule  = NULL;  
  18. ZwOpenSectionProc PhysicalMemory::ZwOpenSection = NULL;  
  19. ZwMapViewOfSectionProc PhysicalMemory::ZwMapViewOfSection = NULL;  
  20. ZwUnmapViewOfSectionProc PhysicalMemory::ZwUnmapViewOfSection = NULL;  
  21. RtlInitUnicodeStringProc PhysicalMemory::RtlInitUnicodeString = NULL;  
  22.   
  23. PhysicalMemory::PhysicalMemory(DWORD dwDesiredAccess)  
  24. {  
  25.     if(sm_hNtdllModule == NULL)  
  26.         if(!InitPhysicalMemory())  
  27.             return;  
  28.     m_pNextObject = sm_pFirstObject;  
  29.     sm_pFirstObject = this;  
  30.     // 以下打开内核对象  
  31.     m_hPhysicalMemory = OpenPhysicalMemory(dwDesiredAccess);  
  32.     return ;  
  33. }  
  34.   
  35. /////////////////////////////////////////////////////////////////////////////////////////////  
  36. /////////////////////////////////////////////////////////////////////////////////////////////  
  37.   
  38. PhysicalMemory::~PhysicalMemory()  
  39. {  
  40.     if (m_hPhysicalMemory != NULL)  
  41.     {  
  42.         CloseHandle(m_hPhysicalMemory);  
  43.         m_hPhysicalMemory = NULL;  
  44.     }  
  45.   
  46.     PhysicalMemory *pCurrentObject = sm_pFirstObject;  
  47.     if(pCurrentObject==this)  
  48.         sm_pFirstObject = sm_pFirstObject->m_pNextObject;  
  49.     else{  
  50.         while(pCurrentObject!=NULL){  
  51.             if(pCurrentObject->m_pNextObject==this){  
  52.                 pCurrentObject->m_pNextObject=this->m_pNextObject;  
  53.                 break;            
  54.             }  
  55.             pCurrentObject = pCurrentObject->m_pNextObject;  
  56.         }  
  57.     }  
  58.     if(sm_pFirstObject == NULL)  
  59.         ExitPhysicalMemory();  
  60. }  
  61. /////////////////////////////////////////////////////////////////////////////////////////////  
  62. /////////////////////////////////////////////////////////////////////////////////////////////  
  63.   
  64. // initialize  
  65. BOOL PhysicalMemory::InitPhysicalMemory()  
  66. {  
  67.     if (!(sm_hNtdllModule = LoadLibrary("ntdll.dll")))  
  68.     {  
  69.         return FALSE;  
  70.     }  
  71.     // 以下从NTDLL获取我们需要的几个函数指针  
  72.     if (!(ZwOpenSection = (ZwOpenSectionProc)GetProcAddress(sm_hNtdllModule,"ZwOpenSection")))  
  73.     {  
  74.         return FALSE;  
  75.     }  
  76.   
  77.     if (!(ZwMapViewOfSection = (ZwMapViewOfSectionProc)GetProcAddress(sm_hNtdllModule, "ZwMapViewOfSection")))  
  78.     {  
  79.         return FALSE;  
  80.     }  
  81.   
  82.     if (!(ZwUnmapViewOfSection = (ZwUnmapViewOfSectionProc)GetProcAddress(sm_hNtdllModule, "ZwUnmapViewOfSection")))  
  83.     {  
  84.         return FALSE;  
  85.     }  
  86.   
  87.     if (!(RtlInitUnicodeString = (RtlInitUnicodeStringProc)GetProcAddress(sm_hNtdllModule, "RtlInitUnicodeString")))  
  88.     {  
  89.         return FALSE;  
  90.     }  
  91.     return TRUE;  
  92. }  
  93. /////////////////////////////////////////////////////////////////////////////////////////////  
  94. /////////////////////////////////////////////////////////////////////////////////////////////  
  95. void PhysicalMemory::ExitPhysicalMemory()  
  96. {  
  97.     if (sm_hNtdllModule != NULL)  
  98.     {  
  99.         //      sm_pFirstObject->~PhysicalMemory();  
  100.         FreeLibrary(sm_hNtdllModule);  
  101.     }  
  102. }  
  103. /////////////////////////////////////////////////////////////////////////////////////////////  
  104. /////////////////////////////////////////////////////////////////////////////////////////////  
  105. HANDLE PhysicalMemory::OpenPhysicalMemory(DWORD dwDesiredAccess)  
  106. {  
  107.     ULONG PhyDirectory;  
  108.   
  109.     OSVERSIONINFO OSVersion;  
  110.     OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);  
  111.     GetVersionEx (&OSVersion);  
  112.   
  113.     if (5 != OSVersion.dwMajorVersion)  
  114.         return NULL;  
  115.   
  116.     switch(OSVersion.dwMinorVersion)  
  117.     {  
  118.     case 0:  
  119.         PhyDirectory = 0x30000;  
  120.         break//2k  
  121.     case 1:  
  122.         PhyDirectory = 0x39000;  
  123.         break//xp  
  124.     default:  
  125.         return NULL;  
  126.     }  
  127.   
  128.     WCHAR PhysicalMemoryName[] = L"\Device\PhysicalMemory";  
  129.     UNICODE_STRING PhysicalMemoryString;  
  130.     OBJECT_ATTRIBUTES attributes;  
  131.     RtlInitUnicodeString(&PhysicalMemoryString, PhysicalMemoryName);  
  132.     InitializeObjectAttributes(&attributes, &PhysicalMemoryString, 0, NULL, NULL);  
  133.     HANDLE hPhysicalMemory ;  
  134.     NTSTATUS status = ZwOpenSection(&hPhysicalMemory, dwDesiredAccess, &attributes );  
  135.     if(status == STATUS_ACCESS_DENIED)  
  136.     {   
  137.         status = ZwOpenSection(&hPhysicalMemory, READ_CONTROL|WRITE_DAC, &attributes);   
  138.         SetPhyscialMemoryAccess(hPhysicalMemory,dwDesiredAccess);   
  139.         CloseHandle(hPhysicalMemory);  
  140.         status = ZwOpenSection(&hPhysicalMemory, dwDesiredAccess, &attributes);   
  141.     }  
  142.     return ( NT_SUCCESS(status) ? hPhysicalMemory : NULL );  
  143.     //    g_pMapPhysicalMemory = MapViewOfFile(g_hMPM, FILE_MAP_READ|FILE_MAP_WRITE, 0, PhyDirectory,   
  144.     //0x1000);  
  145.     //    if( g_pMapPhysicalMemory == NULL )  
  146.     //        return NULL;  
  147.     //    return g_hMPM;  
  148. }  
  149. /////////////////////////////////////////////////////////////////////////////////////////////  
  150. /////////////////////////////////////////////////////////////////////////////////////////////  
  151. VOID PhysicalMemory::SetPhyscialMemoryAccess(HANDLE hPhysicalMemory,//由ZwOpenSection/NtOpenSection返回的物理内存句柄  
  152.                                              DWORD dwDesiredAccess//访问权限  
  153.                                              )  
  154.                                              //设置物理内存的访问权限,成功返回TRUE,错误返回FALSE  
  155. {   
  156.     PACL pDacl                    = NULL;   
  157.     PSECURITY_DESCRIPTOR pSD    = NULL;   
  158.     PACL pNewDacl = NULL;   
  159.   
  160.     DWORD dwRes = GetSecurityInfo(hPhysicalMemory, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL,   
  161.   
  162.         NULL, &pDacl, NULL, &pSD);  
  163.   
  164.     if(ERROR_SUCCESS != dwRes)  
  165.     {  
  166.   
  167.         if(pSD)   
  168.             LocalFree(pSD);   
  169.         if(pNewDacl)   
  170.             LocalFree(pNewDacl);   
  171.     }  
  172.   
  173.     EXPLICIT_ACCESS ea;   
  174.     RtlZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));   
  175.     ea.grfAccessPermissions = SECTION_MAP_WRITE;   
  176.     ea.grfAccessMode = GRANT_ACCESS;   
  177.     ea.grfInheritance= NO_INHERITANCE;   
  178.     ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;   
  179.     ea.Trustee.TrusteeType = TRUSTEE_IS_USER;   
  180.     ea.Trustee.ptstrName = "CURRENT_USER";   
  181.   
  182.     dwRes = SetEntriesInAcl(1,&ea,pDacl,&pNewDacl);  
  183.   
  184.     if(ERROR_SUCCESS != dwRes)  
  185.     {  
  186.   
  187.         if(pSD)   
  188.             LocalFree(pSD);   
  189.         if(pNewDacl)   
  190.             LocalFree(pNewDacl);   
  191.     }  
  192.     dwRes = SetSecurityInfo  
  193.   
  194.         (hPhysicalMemory,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pNewDacl,NULL);  
  195.   
  196.     if(ERROR_SUCCESS != dwRes)  
  197.     {  
  198.   
  199.         if(pSD)   
  200.             LocalFree(pSD);   
  201.         if(pNewDacl)   
  202.             LocalFree(pNewDacl);   
  203.     }  
  204.   
  205. }   
  206. /////////////////////////////////////////////////////////////////////////////////////////////  
  207. /////////////////////////////////////////////////////////////////////////////////////////////  
  208. BOOL PhysicalMemory::ReadPhysicalMemory(OUT PVOID pvDataBuffer, //用于保存读取数据的缓冲区首地址  
  209.                                         IN DWORD dwAddress, //要读取的数据的首地址,要求4KB对齐  
  210.                                         IN DWORD dwLength //读取的长度  
  211.                                         )  
  212. {  
  213.     if((dwAddress & 0x0fff ))//若地址不是4KB对齐,则返回  
  214.     {  
  215.         return FALSE;  
  216.     }  
  217.     if(m_hPhysicalMemory == NULL)  
  218.     {  
  219.         return FALSE;  
  220.   
  221.     }  
  222.   
  223.     DWORD dwOutLenth;            // 输出长度,根据内存分页大小可能大于要求的长度  
  224.     PVOID pvVirtualAddress;          // 映射的虚地址  
  225.     NTSTATUS status;         // NTDLL函数返回的状态  
  226.     LARGE_INTEGER base;      // 物理内存地址  
  227.   
  228.     pvVirtualAddress = 0;  
  229.     dwOutLenth = dwLength;  
  230.     base.QuadPart = (ULONGLONG)(dwAddress);  
  231.   
  232.     // 映射物理内存地址到当前进程的虚地址空间  
  233.     status = ZwMapViewOfSection(m_hPhysicalMemory,  
  234.         (HANDLE) -1,  
  235.         (PVOID *)&pvVirtualAddress,  
  236.         0,  
  237.         dwLength,  
  238.         &base,  
  239.         &dwOutLenth,  
  240.         ViewShare,  
  241.         0,  
  242.         PAGE_READONLY  
  243.         );  
  244.   
  245.     if (status < 0)  
  246.     {  
  247.         return FALSE;  
  248.     }  
  249.   
  250.     // 当前进程的虚地址空间中,复制数据到输出缓冲区  
  251.     memmove(pvDataBuffer,pvVirtualAddress, dwLength);  
  252.     // 完成访问,取消地址映射  
  253.     status = ZwUnmapViewOfSection((HANDLE)-1, (PVOID)pvVirtualAddress);  
  254.   
  255.     return (status >= 0);  
  256. }  
  257. /////////////////////////////////////////////////////////////////////////////////////////////  
  258. /////////////////////////////////////////////////////////////////////////////////////////////  
  259. BOOL PhysicalMemory::WritePhysicalMemory(IN PVOID pvDataBuffer, //用于保存要写入的数据的缓冲区首地址  
  260.                                          IN DWORD dwAddress, //要目标地址,要求4KB对齐  
  261.                                          IN DWORD dwLength //写入的长度  
  262.                                          )  
  263. {  
  264.     if((dwAddress & 0x0fff ))//若地址不是4KB对齐,则返回  
  265.     {  
  266.         return FALSE;  
  267.     }  
  268.     if(m_hPhysicalMemory == NULL)  
  269.     {  
  270.         return FALSE;  
  271.   
  272.     }  
  273.     DWORD dwOutLenth;            // 输出长度,根据内存分页大小可能大于要求的长度  
  274.     PVOID pvVirtualAddress;          // 映射的虚地址  
  275.     NTSTATUS status;         // NTDLL函数返回的状态  
  276.     LARGE_INTEGER base;      // 物理内存地址  
  277.   
  278.     pvVirtualAddress = 0;  
  279.     dwOutLenth = dwLength;  
  280.     base.QuadPart = (ULONGLONG)(dwAddress);  
  281.   
  282.     // 映射物理内存地址到当前进程的虚地址空间  
  283.     status = ZwMapViewOfSection(m_hPhysicalMemory,  
  284.         (HANDLE) -1,  
  285.         (PVOID *)&pvVirtualAddress,  
  286.         0,  
  287.         dwLength,  
  288.         &base,  
  289.         &dwOutLenth,  
  290.         ViewShare,  
  291.         ,0  
  292.         FILE_MAP_WRITE//PAGE_READWRITE  
  293.         );  
  294.   
  295.     if (status < 0)  
  296.     {  
  297.         return FALSE;  
  298.     }  
  299.   
  300.     // 当前进程的虚地址空间中,复制数据到输出缓冲区  
  301.     ::memmove(pvVirtualAddress, pvDataBuffer,dwLength);  
  302.     // 完成访问,取消地址映射  
  303.     status = ZwUnmapViewOfSection((HANDLE)-1, (PVOID)pvVirtualAddress);  
  304.   
  305.     return (status >= 0);  
  306. }  
  307. /////////////////////////////////////////////////////////////////////////////////////////////  
  308. /////////////////////////////////////////////////////////////////////////////////////////////  
#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);
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////

jpg改rar


原文地址:https://www.cnblogs.com/kuangke/p/6259344.html