www.pudn.com > PhysicalMemory.rar > PhysicalMemory.cpp


#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); 
} 
///////////////////////////////////////////////////////////////////////////////////////////// 
/////////////////////////////////////////////////////////////////////////////////////////////