关闭

windows 物理内存获取

标签: windowsattributesnullwinapiobjectinteger
5697人阅读 评论(1) 收藏 举报
分类:

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


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



1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:353552次
    • 积分:4669
    • 等级:
    • 排名:第6206名
    • 原创:126篇
    • 转载:21篇
    • 译文:0篇
    • 评论:38条
    文章分类
    最新评论
    友情链接