习惯于在应用程序用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, (PSIZE_T)&PhysMemSizeInBytes, ViewShare, 0, PAGE_READWRITE | PAGE_NOCACHE);
if (!NT_SUCCESS(ntStatus)) OutputDebugString ("ERROR: ZwMapViewOfSection failed"); else { pbPhysMemLin += (ULONG)pStartPhysAddress.LowPart - (ULONG)ViewBase.LowPart; *ppPhysMemLin = pbPhysMemLin; } } else OutputDebugString ("ERROR: RtlLargeIntegerSubtract failed"); } else OutputDebugString ("ERROR: MappingLength = 0"); } else OutputDebugString ("ERROR: ObReferenceObjectByHandle failed"); } else OutputDebugString ("ERROR: ZwOpenSection failed"); if (!NT_SUCCESS(ntStatus)) ZwClose(*pPhysicalMemoryHandle); OutputDebugString ("Leaving MapPhysicalMemoryToLinearSpace");
return ntStatus; }