View Full Version : Reading Virtual Memory

March 30th, 2011, 16:56
During a project i did lately i had to deal with the detection of hidden device drivers... while researching i stumbled upon a problem i came across several years but never had the patience to deal with it, yet now i had to. Well what happened ?! See for yourself:

I used such pseudocode to scan for the DRIVER_OBJECTs:
unsigned char * pKernel = 0x80000000;
for (i = 0; i < KernelSpaceSize; i++)
if (pKernel[I] == x)

at one point the machine simply freezed (no bugcheck) and i couldn't make any clue out of it, this effect was a 100% reproducible.

I tried pretty much everything to get rid of the problem like using seh, probing the page, physically accessing it etc you name it.

(Try it for yourself, in windbg do a "s 0 L -1 0xff", at some point it will most likely freeze your machine)

After further research on this i saw that others faced this problem also, like Joanna Rutkowska, which can't solve the problem either.
Her solution was to reduce the range of memory that she scans for [a] (which is absolutely bullshit if you ask me).

To shorten the whole story, the problem arised because some memory areas are mapped to physical devices (memory mapped io) like your graphic card once you touch those areas your machine will go into an undefined state.
The reason for all this is the north bridge of your motherboard which is the router for those requests, it will decide if the request will be forwarded to your mem chips or if it is an attempt to access a device. [B]

So how does Windows handle it ?! That's pretty much the first question that came to my mind, because seriously i have never ever seen a "bugcheck" freezing while creating a memory dump.

The answer is again simple if you know how it works, basically the bios is the key to all of it, the devices "register" their areas and the ntldr queries the bios for the accessible memory areas during boot.

This is all done via INT 15h, the keyword if you are interested in it is "System Address Map" [c], luckily windows needs to keep track of those areas. It does so in a structure called PHYSICAL_MEMORY_RUN, which is nothing else than an array of elements that tell you the areas that can be touched and which you can't.

And there you go... as long as you are aware of the limits described in the run's it's all good...



[a] http://invisiblethings.org/tools/modGREPER/changelog.txt

[B] http://duartes.org/gustavo/blog/post/motherboard-chipsets-memory-map

[c] http://www.uruk.org/orig-grub/mem64mb.html

April 3rd, 2011, 22:01
Hi Daemon, nice to see you blogging. So I've been doing a lot of reading trying to figure out your interesting post, thought I'd pass along a few things I found.

I found a utility which outputs the system address map information through the Int15/E820 interface. For Vista and above only, but it's quite interesting in that it uses new and undocumented Hal functions for accessing the 16-bit firmware, known as the x86 BIOS Emulator. Something for further study at some point.

Viewing the Firmware Memory Map

Here are the results on Windows 7:



Map of firmware memory ranges (from int 15h function E820h)

Address Size Type
=================== =================== =================
0x00000000`00000000 0x00000000`0009F800 1 (memory)
0x00000000`0009F800 0x00000000`00000800 2 (reserved)
0x00000000`000DC000 0x00000000`00008000 2 (reserved)
0x00000000`000E8000 0x00000000`00018000 2 (reserved)
0x00000000`00100000 0x00000000`3FDE0000 1 (memory)
0x00000000`3FEE0000 0x00000000`0001F000 3 (ACPI Reclaim)
0x00000000`3FEFF000 0x00000000`00001000 4 (ACPI NVS)
0x00000000`3FF00000 0x00000000`00100000 1 (memory)
0x00000000`E0000000 0x00000000`10000000 2 (reserved)
0x00000000`FEC00000 0x00000000`00010000 2 (reserved)
0x00000000`FEE00000 0x00000000`00001000 2 (reserved)
0x00000000`FFFE0000 0x00000000`00020000 2 (reserved)

Summary (in MB, ignoring partial MB):

Total memory: 1023
Memory above 4GB: 0

Sure enough, the physical addresses marked Reserved/ACPI are unreadable:


kd> !dc fffe0000
Physical memory read at fffe0000 failed

Getting off the topic of the reserved ranges, those of Type 1, regular, accessible memory can be found in a few other ways.

MmPhysicalMemoryBlock is a structure that provides information regarding the physical memory ranges used by the system. It's exported by the version dependant KDDEBUGGER_DATA64, and where that's not available, the following article shows how to retrieve it programatically


By chance I discovered that MmPhysicalMemoryBlock can also be found by searching (!pooltag MmMl) for the pooltag 'MmMl' (physical memory range information). It points to the same address as the MmPhysicalMemoryBlock pointer, valid in XP and Win7.

Here is what the raw MmPhysicalMemoryBlock looks like, and as typedef to PHYSICAL_MEMORY_DESCRIPTOR and showing the first of 3 PHYSICAL_MEMORY_RUN array elements.


kd> dd 8b720fe0
8b720fe0 00000003 0003ff7e 00000001 0000009e
8b720ff0 00000100 0003fde0 0003ff00 00000100

kd> dt -b 8b720fe0 nt!_PHYSICAL_MEMORY_DESCRIPTOR
+0x000 NumberOfRuns : 3
+0x004 NumberOfPages : 0x3ff7e
+0x008 Run :
+0x000 BasePage : 1
+0x004 PageCount : 0x9e

Another way of getting this information is through the registry under
HKEY_LOCAL_MACHINE\HARDWARE\RESOURCEMAP\System Resources\Physical Memory\.Translated


Finally, RamMap by Sysinternals will also show these same physical ranges.

All 3 of these methods match the Type 1 memory as listed through the more complete output of the Int15 interface.

Back to the original topic, so what's the best solution then if one wants to create a searching algorithm and avoid trying to read reserved memory?


April 22nd, 2011, 05:33
probably same problem happens to me

April 24th, 2011, 06:36
Once I dealt with memory dumping, and had similar problem. My solution was to use bootable usb/cd to store smap entries in memory, and later driver could read it without a problem. I agree it's not exactly what you want or need, but was my way of doing things

The other solution is on Vista and Windows 7 to use SuperfetchInformationClass which Alex Ionescu used in this tool : http://www.winsiderss.com/tools/meminfo/meminfo.htm . It shows memory ranges same to the ones from int 0x15/0xE820 interface.

May 1st, 2011, 20:33
It's always a please to see you leet kernel pros shoot the breeze. Keep it up, and stick around.