In this post I’d like to talk about the x86 memory restriction in Windows.
As you may already know, every 32bit build of Windows operating system can’t handle more than 4GB of memory and part of it is already used by the operating system to map hardware peripherals I/O addresses and system-related stuff. This results in even less available memory than the 4GB specified before.
In x86 architecture, each virtual memory address is translated to its relative physical one using specific hardware tables that keep track of virtual/physical map. These tables always used 32bit pointers to address the entire physical memory range and the CPU’s physical memory bus always used 32 lines. These choices restricted the amount of supported memory up to 4GB.
To overcome this architectural limit, Intel decided to implement a new technology called Physical Address Extension, allowing modern CPUs to address up to 64GB of memory. x86 CPUs are now composed by 36 lines – 52 on a full x64 CPU – and, from a low level technical perspective, each page table entry pointer supports a 64 bit pointer.
The question raised here is: why current 32bit operating systems still don’t support more than 4GB of memory, even if PAE is available?
Official explanations from Microsoft can be found online on many websites. Basically they are telling us that some kernel mode drivers are incompatible with higher memory locations and, anyway, high memory is used to map physical peripherals. Readers can check out this article and this article.
While it’s true that some older drivers could be incompatible with high physical memory addresses due to the fact that they could use the highest bits of a plain 64 bit physical address for other goals (which is a behavior that goes against Microsoft’s guidelines anyway), is this the only reason why Microsoft doesn’t support more than 4GB on their 32bit builds of Windows? Or is there something more, e.g. licensing restrictions used to sell more Windows 64bit builds and less 32bit builds?
While analyzing Windows 8’s EFI loader, I got into a call located inside the function MmInitializeNucleus, called by MmInitSystem. This call contains the licensing verification that allow or deny Windows to support more than 4GB of memory.
If the system is not a server, the ntQueryLicenseValue, called with Kernel‐WindowsMaxMemAllowedx86 parameter, returns the value 0x100000. This value is then stored as a system-wide variable and used inside the MmInitSystem function. 0x100000 in hex is 1048576 in dec which, multiplicated by 4KB (size of pages) returns 4GB. If we change that value from 0x100000 to 0x1000000 (16777216 in dec), Windows will be able to see all 64GB of memory.
I have developed a specific bootkit that patches on-the-fly the Windows kernel and changes that specific value. The tool is compatible with Windows Vista/7/8 (release preview) 32 bit builds. Clearly this bootkit is just for testing purposes and it’s not intended to be used on stable systems, as the Windows kernel is being patched and its integrity could be compromised, causing potential system crashes (though this is just a disclaimer, I didn’t get into any kind of trouble while testing it over our 32 bit systems).
Each patched 32 bit operating system has been able to detect and use even more than 4GB of memory, and everything went just fine.
This software and its documentation are free and come “as is” with absolutely no guarantee and no support. The software is just for research purposes and it must be used only on testing environment. This software could potentially break your operating system by overwriting the Master Boot Record, thus preventing it from actually running. Don’t use this software unless you know exactly what you are doing. Use at your own risk.
If you accept this, download the tool from the following link: DOWNLOAD