I am trying to determine how to read physical memory. I understand that when the OS is in protected mode a process can only access the virtual memory assigned to it without resulting in a segmentation fault. Is it possible to read physical memory using assembly language running in real mode? I'm assuming that using assembly language would be the most effective method rather than using a higher-level language such as C. My goal is to create a program which can scan physical memory to be used for memory forensic applications. I am running a Windows OS using MASM.
I understand that when the OS is in protected mode a process can only access the virtual memory assigned to it without resulting in a segmentation fault.
Correct. By design, all processes are confined to their own address space and cannot access (without the OS help) the address space of other running processes. Kernel is responsible for the VM management of each running process and basically with the help of CR3 register which is the root pointer for Virtual address table for each process. CR3 is updated by kernel on each new scheduled process execution. All addresses in CR3 pointed table are physical addresses with corresponding virtual addresses mappings. (more on this later)
Is it possible to read physical memory using assembly language running in real mode? I'm assuming that using assembly language would be the most effective method rather than using a higher-level language such as C.
Why do you assume that it will be more effective? Doing physical memory inspection in real mode could be pretty challenging task and will require machine reboot which is not advisable for any forensic oriented memory acquisition.
My goal is to create a program which can scan physical memory to be used for memory forensic applications.
This goal could be achieved from the kernel space with the help of a specific kernel driver. Such kernel driver would need to parse a Virtual address table for each running process and kernel itself. There are several ways to do it:
- The main pointers for each process's VAT is stored in CR3 register or in Windows case also available in every
KPROCESS struct @ DirectoryTableBasemore on it here. Once you have this pointer, you can manually parse the table and get the PHY to VIRT mappings. With this information, using Memory Manager Routines you can get the contents of most memory pages. This is the most hard but more proper way to do it.
- Another way is with
MmGetPhysicalMemoryRanges, but it can miss some ranges
I also suggest you to go over Rekall tools where IMO is described one of cleaner forensic memory acquisition ways that you can do relatively easily and comprehensively. Go over some technical papers referenced there if you'd like to get a deeper knowledge on the subject.
In general, forensic memory imaging is pretty broad subject and there are more ways to do it then I've described here.
The language you write in won't make any difference here, the limitation on memory access is coming from the CPU and not the language you're using. In addition, you can't go to
realmode after you've switched to protected mode. This is also a CPU limitation.
But before that, a small correction:
process can only access the virtual memory assigned to it without resulting in a segmentation fault.
It's not that a process cannot access another process's memory, it simply cannot address, describe or reference it, since each process in protected mode has it's own address space. Therefore the address may be valid, so if you'll want to access address
0x401000 in another process and just execute
mov eax, DWORD PTR [0x401000] you might get a value (instead of a segfault), it just won't be the value in that other process.
Now, accessing a memory of another process is impossible to do from a user-mode process's standpoint. Only the kernel can access to memory of different processes (and even that is a complex operation). Because reading memory of other processes is sometimes needed, windows provides two convenient APIs called
WriteProcessMemory. You can also use
VirtualAllocEx to allocate memory in a remote process.
I have some quite old code here which reads physical memory under windows: http://nah6.com/~itsme/cvs-xdadevtools/itsutils/src/sysint-physmem.cpp
In unix like systems you would read
/dev/mem to access physical memory. However, most modern variants - linux, android, macos - disable this by default.