$theTitle=wp_title(" - ", false); if($theTitle != "") { ?>
About Virtualization, VDI, SBC, Application Compatibility and anything else I feel like
So a few days ago I got new memory for a development box – an upgrade from 4 to 6 GiB (later on even 8 GiB). Much appreciated as you can imagine. After dismissing the BIOS warning about changed amount of memory (oh really? :mrgreen:), I booted into Ubuntu and happily looked at the memory stats. After that I booted into Windows (a Windows 2003 Server Standard, but I’ll just use Windows from here on) and was disappointed to see only 4 GiB available. This is apparently a limitation specific to the Standard edition.
After some pouting, I decided to take action. Of course one of my first thoughts was to ask Remko, because he had done similar things for some other Windows versions. He pointed me to MmInitSystem
, which was not an immediate hit, though. I loaded my kernel .exe into a disassembler to look at the details, but MmInitSystem
was a lengthy and rather boring function. However, the advice was good and got me a good bit closer, especially when Remko also mentioned the use of ExVerifySuite
in the logic that would set the limits. So I brought up the references to ExVerifySuite
and – surprise surprise – only seven other functions used it and out of these only one was not recognized by name from the exports and debug symbols. And since the inspection of that function (at 0x00615FB0
in my kernel) proved that it was being called from MmInitSystem
, this was an immediate hit.
Now the only problem was to figure out the logic of that function. Remko gave me a rough idea here as well. Since I was too lazy to map his findings to my binary, I decided to simply find out which variable held the limitation and fix all instances instead of the one pertaining to my specific edition
The limits in the kernel are expressed in number of pages, instead of bytes or similar. Hence all values in that function in question had to be multiplied by 0x1000, i.e. the default page size. The two 32bit variables at the bottom of the stack (within that function) turned out to be those limits. The code passes some value to ExVerifySuite
several times, obviously expecting either true (1) or false (0) in return. Since my lazy approach didn’t require the deeper understanding, I made a mental notice (after all Geoff Chappell’s site is well known among reversers) about the location where to find the details and proceeded. The apparent maximum for these two variables within the function was 0x10000000 I decided to replace all instances with that value. For the 32bit second value (from stack bottom) this meant replacing a
1 2 | mov edi, 2000000h mov edi, 10000000h |
… at the beginning of the function and several
1 2 3 | mov [ebp-8], ... ; and mov [ebp-4], ... |
… by either populating the assigned register (e.g. eax) correctly on the right side or assigning the proper immediate value.
All in all I patched 16 bytes. It may seem excessive for the job at hand, but I couldn’t help my laziness and thus deemed it cheaper to invest mere seconds in the repetitive task of patching all occurrences rather than understanding the logic entirely within some minutes.
Okay, that work was done, so I thought I would get away with simply placing an additional line in boot.ini
and load the patched kernel. If something went wrong I still had the Linux installation for recovery. So I simply copied the existing line in boot.ini
and appended:
1 | /KERNEL=ntkrnlmy.exe |
One reboot later I knew something was missing. Sure enough Remko was spot on when he asked me whether I had corrected the PE image checksum after the patch. Well, I hadn’t. He also pointed me to one tool that I hadn’t used for this purpose before:
1 | editbin /release [file] |
… fixed the image checksum and the next reboot proved that it worked.
As mentioned at the beginning, meanwhile I have two more GiB of RAM and the screenshots attached to this post prove that the patch works just fine (removed some details from the “General” tab, though).
The dUP2 file can be downloaded below but before you continue please ensure that patching the kernel is allowed according to your country’s laws and your license agreement.
Windows 2003 Standard Kernel Patch (3708 downloads )If you don’t know how to use dUP2, please read Universal Patcher
// Oliver
12 Responses for "Windows 2003 Server Standard memory patch"
Hmmm, ending up with ntoskrnl.exe missing or corrupted… :-/
Is it the problem that would be resolved by editibin.exe? How to use editbin.exe?
Lukas
The function is actually called MiCheckPaeLicense
Its tis an alternative for the patch using PAE??
@miwelon: no, not an alternative since addressing the extra memory already requires PAE.
It’s just a license restriction.
I tried this on a small business server 2003, but the checksum of the original file is wrong so the patch decided to not modify the kernel. After removing the checks and patching the file the os got stuck during boot (of course).
can you help with this?
regards, ldlx
Maybe your sp level or more likely language is different?
Yes, it’s the German localization with SP2.
Can you give me a hint where to look at? Please excuse that I have only basic knowledge on how assembler works, but understanding what has to interesting.
2000000h represents 4GB and 10000000h represents 32GB (enterprise edition) – so 20000000h would be the maximum of the datacenter edition.
I found mov edi, 2000000h at “function chunk for _MiApplyDriverVerifier@8” (only one occurence, disassembled with IDA Free). Could this be ok? There’s no other occurence of this.
As the value now needs an additional byte the address of the value needs to be changed- seems clear till here.
But there are many mov [ebp-8], xxx – which ones needs to be replaced?
I am trying to patch Windows Home Server 2011 to allow more than 8 GB, as i have 16 GB installed and want to use those for VMs as well.
I have put the Kernel into IDA and I can Find ExVerifySuite, but the references are different on this (x64) kernel.
Anybody has a clue how to get the Kernel to allow all the memory ? I have studies Geoff’s article as well but it is a dead lead for x64 as well it seems …
applied on a server 2003 standard sp2 english, results:
a. MD5 check failed;
b. disabled MD5 verify, tried again;
c. “can’t find pattern! trying next one…”
d. File patched, PE Checksum fix: OK
e. backup ok, restore original file time: OK.
So far, seems to be perfect π System properties shows 7,87 GB of RAM instead of 8, it’s ok, it isn’t? π
My sincere thanks!
Great work! Just what I was looking for to use my 8GB with W2k3 Standard π
Just had to change two bytes to make it work with the english SP2 version of ntpakrnl.exe. For those interested, they are in the second patch location at 001F85DE. The original (nl version?) patch looks for “C7 45 FC 00 00 08 00 EB 69 6A 07 E8 1C BE E6 FF”, while in the english file the string is “C7 45 FC 00 00 08 00 EB 69 6A 07 E8 10 D4 E6 FF” (fourth and third last byte are different), both of course not at the location that get’s patched eventually.
Me again π GREAT WORK GUYS ! … i didn’t manage to rebuild MD5 hash for patched file so SBS won’t replace it with original one but i changed boot.ini with custom kernel … and indeed works & rocks.
Anyway … just to metion, seem that ntpakrnl.exe is changing acording to updates/services you install at least MD5 wasn’t the same. On fresh install only with SP2 works like charm, instead when i applied all Exchange & Tools stuff i couldn’t patch the kernel, i ended up with ntoskrnl.exe error.
Did anyone get this working on Server 2003 R2 SP2 UK English version?
thanks,
Leave a reply