习惯于在应用程序用ZwOpenSection打开"Device"PhysicalMemory访问物理内存的朋友可能要郁闷了,微软出于安全考 虑的原因,在x64/vista/2003 sp1系统中所有用户模式的程序将不能访问"Device"PhysicalMemory对象。
经过测试,原来应用程序在2k/xp中使用ZwOpenSection,ZwMapViewOfSection可以正常访问物理内存,而同样的代码在 x64上却在ZwOpenSection时返回"拒绝访问"(C0000022 STATUS_ACCESS_DENIED)。
幸运的是在驱动中,仍然能通过这个方法访问物理内存。所以在x64/vista/2003 sp1下使用ZwOpenSection直接读写物理内存,必须在驱动中进行。
相关代码如下:
NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress,
ULONG PhysMemSizeInBytes,
PVOID *ppPhysMemLin,
HANDLE *pPhysicalMemoryHandle)
{
UNICODE_STRING PhysicalMemoryUnicodeString;
PVOID PhysicalMemorySection = NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
PHYSICAL_ADDRESS ViewBase;
NTSTATUS ntStatus;
PHYSICAL_ADDRESS pStartPhysAddress;
PHYSICAL_ADDRESS pEndPhysAddress;
PHYSICAL_ADDRESS MappingLength;
BOOLEAN Result1, Result2;
ULONG IsIOSpace;
unsigned char *pbPhysMemLin = NULL;
OutputDebugString ("Entering MapPhysicalMemoryToLinearSpace");
RtlInitUnicodeString (&PhysicalMemoryUnicodeString,
L"""Device""PhysicalMemory");
InitializeObjectAttributes (&ObjectAttributes,
&PhysicalMemoryUnicodeString,
OBJ_CASE_INSENSITIVE,
(HANDLE) NULL,
(PSECURITY_DESCRIPTOR) NULL);
*pPhysicalMemoryHandle = NULL;
ntStatus = ZwOpenSection (pPhysicalMemoryHandle,
SECTION_ALL_ACCESS,
&ObjectAttributes);
if (NT_SUCCESS(ntStatus))
{
ntStatus = ObReferenceObjectByHandle (*pPhysicalMemoryHandle,
SECTION_ALL_ACCESS,
(POBJECT_TYPE) NULL,
KernelMode,
&PhysicalMemorySection,
(POBJECT_HANDLE_INFORMATION) NULL);
if (NT_SUCCESS(ntStatus))
{
pStartPhysAddress.QuadPart = (ULONGLONG)pPhysAddress;
pEndPhysAddress = RtlLargeIntegerAdd (pStartPhysAddress,
RtlConvertUlongToLargeInteger(PhysMemSizeInBytes));
IsIOSpace = 0;
Result1 = HalTranslateBusAddress (1, 0, pStartPhysAddress, &IsIOSpace, &pStartPhysAddress);
IsIOSpace = 0;
Result2 = HalTranslateBusAddress (1, 0, pEndPhysAddress, &IsIOSpace, &pEndPhysAddress);
if (Result1 && Result2)
{
MappingLength = RtlLargeIntegerSubtract (pEndPhysAddress, pStartPhysAddress);
if (MappingLength.LowPart)
{
// Let ZwMapViewOfSection pick a linear address
PhysMemSizeInBytes = MappingLength.LowPart;
ViewBase = pStartPhysAddress;
ntStatus = ZwMapViewOfSection (*pPhysicalMemoryHandle,
(HANDLE) -1,
&pbPhysMemLin,
0L,
PhysMemSizeInBytes,
&ViewBase,