We know that in NT/2 k/XP, the operating system uses virtual memory management technology to maintain the address space image, and each process allocates a 4 GB virtual address space. Applications Running in user modeProgramYou cannot directly access the physical memory address. Drivers running in the core State can map the virtual address space to the physical address space to access the physical memory address.
If you want to access the memory using a physical address in the application, the natural way is to write a dedicated driver (such as winio) and set a certain IOCTL code, applications call deviceioctrol () to implement this function.
Is there a way to easily access the physical memory without writing a dedicated driver? The answer is yes. In fact, Microsoft has already prepared a set of solutions for us, but they just kept them confidential. Create a kernel object named physicalmemory in the system. You can use the APIs in the system core file NTDLL. DLL to perform operations to achieve direct access to the physical memory. Microsoft claims that these APIs are used for driver development and do not provide prototype instructions and library files in VC/. net. However, it turns out that there is no problem to call them in applications. APIS we are interested in mainly include:
Zwopensection or ntopensection-open the Kernel Object
Zwmapviewofsection or ntmapviewofsection- ing virtual address space
Zwunmapviewofsection or ntunmapviewofsection-cancel address space ing
Rtlinitunicodestring-uses a unicode string to initialize the structure of the Unicode description.The followingCodeDescribes how to use the preceding APIs in Ntdll. DLL to read physical memory. It should be noted that only the system has the read and write permissions, and the Administrator has only the read permission, but the user does not even have the read permission. This cannot be compared with the dedicated driver method direction.
In VC/. net, because there is no prototype description and library file, we use getprocaddress () for DLL explicit calling. The code in the preceding section describes the required types and structures. The main steps for reading physical memory are: Open the kernel object → map virtual address space → read (copy) memory → cancel address space ing.
Typedef Long ntstatus; 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; # 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 ;\} // Interesting functions in Ntdll Typedef Ntstatus (winapi * zwopensectionproc) (phandle sectionhandle, DWORD desiredaccess, pobject_attributes objectattributes ); Typedef Ntstatus (winapi * callback) (handle sectionhandle, handle processhandle, pvoid * baseaddress, ulong zerobits, ulong commitsize, interval sectionoffset, Pulong viewsize, interval, ulong allocationtype, ulong protect ); Typedef Ntstatus (winapi * zwunmapviewofsectionproc) (handle processhandle, pvoid baseaddress ); Typedef Void (winapi * rtlinitunicodestringproc) (IN out punicode_string destinationstring, in pcwstr sourcestring ); // Global variables Static Hmodule = NULL; Static Handle hphysicalmemory = NULL; Static Zwopensectionproc zwopensection; Static Zwmapviewofsectionproc zwmapviewofsection; Static Zwunmapviewofsectionproc zwunmapviewofsection; Static Rtlinitunicodestringproc rtlinitunicodestring; // Initialize Bool initphysicalmemory (){ If (! (Hmodule = loadlibrary ( "NTDLL. dll" ))){ Return False ;} // Obtain the required function pointers from NTDLL. If (! (Zwopensection = (zwopensectionproc) getprocaddress (hmodule, "Zwopensection" ))){ 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 ;} // Open the kernel object below 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, which may be larger than the required length based on the memory paging size Pvoid vaddress; // Mapped virtual address Ntstatus status; // Status returned by the NTDLL Function Large_integer base; // Physical memory address Vaddress = 0 ; Outlen = length; base. quadpart = (ulonglong) (Address ); // Map the physical memory address to the virtual address space of the current process Status = zwmapviewofsection (hphysicalmemory, (handle) -1 , (Pvoid *) & vaddress, 0 , Length, & base, & outlen, viewshare, 0 , Page_readonly ); If (Status < 0 ){ Return False ;} // Copy data to the output buffer in the virtual address space of the current process Memmove (buffer, vaddress, length ); // Complete access and cancel address ing Status = zwunmapviewofsection (handle) -1 , (Pvoid) vaddress ); Return (Status> = 0 );} // A test function that reads 4096 bytes from the physical address 0xfe000 // For Award bios, you can find the serial number and other information from this data segment. Bool test () {uchar Buf [ 4096 ]; If (! Initphysicalmemory ()){ Return False ;} If (! Readphysicalmemory (BUF, 0xfe000 , 4096 )){ //... The specified data is read successfully. Exitphysicalmemory (); Return False;} exitphysicalmemory (); Return True ;}
Note that, because the windows Virtual Memory Page size is 4 kb by default, the virtual space base address returned by ntmapviewofsection () is 4 kb aligned, and the returned length is an integer multiple of 4 kb. In the preceding readphysicalmemory (), the physical address is also 4 kb aligned. If not, you need to consider it more comprehensively.
[Related resources]
demo source code: Kernel studio