We know that in NT / 2K / XP, the operating system utilizes virtual memory management techniques to maintain an address space image, each process allocates a 4GB virtual address space. Running in a user-state application, you cannot directly access the physical memory address; and run the virtual address space to the physical address space to access the physical memory address.
If you want to access memory in your application in a physical address, naturally, you will write a dedicated driver (such as everyone familiar with WinIo), set a certain IOCTL code, the application implements this by calling Deviceioctrol (). Features.
So, there is a way to save this step in writing a dedicated driver, it is convenient to access physical memory? The answer is yes. In fact, Microsoft has long prepared a set of methods, but they secretly declared. The system built a kernel object called PhysicalMemory, which can be manipulated by the API in NTDLL.DLL, thereby implementing direct access to physical memory. Microsoft claims that these APIs are used for driver development, and they do not provide prototype instructions and library files in VC / .NET, but the facts have proved that they are not problematic in the application. The API we are interested in mainly includes:
ZwOpenSection or NtOpenSection - opens kernel objects ZwMapViewOfSection or NtMapViewOfSection - ZwUnmapViewOfSection mapped virtual address space or NtUnmapViewOfSection - canceled address space map RtlInitUnicodeString - UNICODE string initialized to structural UNICODE code described in the following description of the API (s) in NTDLL.DLL how to use, Realize the reading of physical memory. It should be pointed out that only System has read and write permissions, and the Administrator only has read permissions, and the USER is not available. This is not compared to the dedicated driver method.
In VC / .NET, we use getProcAddress () to DLL explicit calls due to no corresponding prototype instructions and library files. The code for the previous segment is used to illustrate the necessary types and structures. The main steps of reading physical memory are: Open Kernel Object → Mapping Virtual Address Space → Read (Copy) Memory → Cancel Address Space Mapping.
TypedEf long NTSTATUS;
Typedef struct _unicate_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_attribute;
#define InitializeObjectttributes (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; /
}
// intending functions in ntdll
TypeDef NTSTATUS (WinAPI * ZWopenseProc)
(
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 dstinationstring,
In Pcwstr SourceString
);
// Global Variables
Static hmodule hmodule = null;
Static handle hphysicalmemory = null;
STATIC ZWOPENSECTIONPROC ZWOPENSECTION;
Static ZwmapViewOfsectionProc ZwmapViewOfSection;
Static ZwunmapViewOfsectionProc ZwunmapViewOfsection;
Static RTLINITUNICODESTRINGPROC RTLINITUNICODESTRING;
// Initialize
BOOL INTPHYSICALMORY ()
{
IF (! (hmodule = loadinglibrary ("ntdll.dll")))))))))
{
Return False;
}
/ / The following items we need from NTDLL will be below.
IF (! (zwopensection = (zwopensectionproc) getProcaddress (HModule, "ZWopents"))))))))
{
Return False;
}
IF (! (zwmapViewofsection = (zwmapViewofsectionproc) getProcaddress (HModule, "ZWMapViewOfSECTION"))))))))
{
Return False;
}
IF (! (zwunmapviewofsection = (zwunmapViewofsectionproc) getProcaddress (HModule, "ZwunmapViewofsection))))))))
{
Return False;
}
IF (! (RTLinitunicodeString = (RTLinitunicodeStringProc) GetProcaddress (HModule, "RTLinitUnicODestring)))))
Return False;
}
// The following open kernel objects
Wchar PhysicalMemoryName [] = l "// device // PhysicalMemory";
Unicode_string physicalmemorystring;
Object_attributes attributes;
RTLinitunicodeString (& PhysicalMemoryString, PhysicalMemoryName);
InitializeObjectAttributes (& Attributes, & PhysicalMemoryString, 0, Null, NULL);
NTSTATUS Status = Zwopensection (& HphysicalMemory, section_map_read, & attributes);
Return (status> = 0);
}
// Terminate - Free Handles
Void exitphysicalmemory ()
{
IF (hphysicalmemory! = null)
{
CloseHandle (HPHYSicalMemory);
}
IF (hmodule! = null)
{
Freelibrary (hmodule);
}
}
Bool ReadphysicalMemory (PVOID BUFFER, DWORD ADDRESS, DWORD LENGTH)
{
DWORD OUTLEN; / / Output length, depending on the size of the memory page may be greater than the required length
Pvoid Vaddress; // Map of virtual address
NTSTATUS STATUS; // NTDLL function returns the status
Large_integer base; // Physical memory address
VADDRESS = 0;
Outlen = Length;
Base.quadpart = (Ulonglong) (Address);
// Mapping the physical memory address to the current process of virtual address space
Status = ZWMapViewOfsection (hphysicalmemory,
(HANDLE) -1,
(Pvoid *) & Vaddress,
0,
Length,
& base,
& Outlen,
Viewshare,
0,
Page_readonly;
IF (Status <0)
{
Return False;
}
// In the virtual address space of the current process, copy data to the output buffer
Memmove (Buffer, Vaddress, Length);
/ / Complete access, cancel address mapping
Status = zwunmapViewofsection (Handle) -1, (pvoid) VAddress;
Return (status> = 0);
}
// A test function starts from the physical address 0xFe000, read 4096 bytes
// For the Award BIOS, you can find information such as serial number from this data.
BOOL TEST ()
{
Uchar BUF [4096];
IF (! initphysicalmemory ())
{
Return False;
}
IF (! ReadphysicalMemory (BUF, 0xFE000, 4096))
{
// ... successfully read the specified data
EXITPHYSICALMORY ();
Return False;
}
EXITPHYSICALMORY ();
Return True;
}
Supplementary description, since the Windows virtual memory page size is 4KB, NTMapViewOfSection () The virtual space base returned by NTMapViewOfSection () is aligned according to 4kb, and the returned length is also a total of 4KB. In the READPHYSICALMORY () above, the physical address that is considered to be entered is also 4KB alignment. If not, it is necessary to consider more comprehensively.
[related resources]
This article Demo Source: Kernel Studio Bhw98 column: http://www.9cbs.net/develop/author/netauthor/bhw98/
First release: 2003-11-11 Last revision: 2003-11-11