让XP用上4G内存,有图有**,带破解补丁
标 题: 【原创】让XP用上4G内存,有图有真相,带破解补丁作 者: scdeny
时 间: 2011-07-28,00:13:40
链 接: http://bbs.pediy.com/showthread.php?t=137830
先上图,patch之后的,原来只有2.98G,现在是3.86G了
http://bbs.pediy.com/attachment.php?attachmentid=59381&thumb=1&d=1311811704http://bbs.pediy.com/attachment.php?attachmentid=59383&thumb=1&d=1311811908
去年7月入手小黑T410,到手就装了4G的内存,WINDOWS 7的破解补丁来的很快,很顺利就用上了3.86G(纠结于剩下的140M哪里去了?至今也没搞明白,只知道主板没有映射),而所谓的XP的种种补丁,不外乎就是Ramdisk,开启PAE之类的,毫无用处,最可怜的是竟然被某网友的“开启了PAE就能用到全部4G内存,系统属性页显示还是2.98G是假的”一说给忽悠了一年,没文化真可怕。。。就这么将信将疑用了一年,中间也纠结过一段时间,没有深入分析,近日越想越感觉不对劲,再来纠结纠结。。。
用WinDbg看看
代码:
lkd> dd MmHighestPhysicalPage8088b124000bf7ff 000bf399 00000040 00000000lkd> dd MmNumberOfPhysicalPages8088b128000bf399 00000040 00000000 7fff0000
可见最高物理内存页号MmHighestPhysicalPage值为bf7ff,物理内存总页数MmNumberOfPhysicalPages值为bf399,换算成物理内存数0xbf399*0x1000=2.98G正好是系统属性页显示的2.98G,改变这个值,系统属性页的值也会跟着变,是不是把这个值改了你就能用到更多的内存了呢,当然不是,任务管理器里记录的内存使用量确是真是的。
那是不是我的PAE没有真正启用呢?
那我们再用WinDbg看看
代码:
lkd> !pte 80800000 VA 80800000PDE at C0602020 PTE at C0404000contains 00000000008009E3contains 0000000000000000pfn 800 -GLDA--KWEV LARGE PAGE pfn 800
看吧,PDE和PTE里面的物理地址00000000008009E3和0000000000000000都是64位的,而在没有启用PAE的系统里,页表项里的物理地址是32位的。(为什么PTE里是一串0呢?因为我们看的80800000这个虚拟地址是ntkrnlpa.exe的基地址,它当然是加载在物理内存的0地址的)
那么是不是系统偷偷地在用我的4G内存了,而给我显示出2.96G的假象呢?
再祭出我们的法宝WinDbg
代码:
lkd> dd poi(MmPhysicalMemoryBlock)8ad75c8000000007 000bf3ab 00000001 0000009d8ad75c9000000100 000bf17c 000bf282 000000dd8ad75ca0000bf40f 00000060 000bf70f 000000088ad75cb0000bf71f 0000004c 000bf7ff 00000001
这里有两个结构体:
代码:
typedef struct _PHYSICAL_MEMORY_RUN { PFN_NUMBER BasePage; PFN_NUMBER PageCount;} PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN;typedef struct _PHYSICAL_MEMORY_DESCRIPTOR { ULONG NumberOfRuns; PFN_NUMBER NumberOfPages; PHYSICAL_MEMORY_RUN Run;} PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR;
从上面可以看出,我的机器有7块可用的内存,总共有bf3ab页(为什么这个数字跟上面看到的MmNumberOfPhysicalPages不符呢?),分别为1 -9d,100- bf17c,…,bf7ff,可见最大物理内存地址为bf7ff,还是与4G内存相去甚远啊。。。
那么是不是我的主板根本就不识别这么大的内存呢??
那么我们再做做实验,用nt4的源代码编译一份NTLDR,把osloader.exe探测到的物理内存输出一份,下面是通过中断获取的内存布局图,BIOS专家们都叫把它做E820图
代码:
BaseSizeType0 9E80019E80018002D200020002DC000240002100000BF17C0001BF27C00060002BF282000DD0001BF35F000120002BF37100010004BF3F20001D0002BF40F000600001BF46F0001F90002BF668000800004BF6E8000270002BF71700080001BF71F0004C0001BF76B000C0004BF77700030003BF77A00070004BF78100010003BF78200090004BF78B00010003BF78C000130004BF79F000600003BF7FF00010001BF8000008000002E0000000100000002FEAFF00010002FEC00000100002FED000004002FED1C00040002FED20000700002FEE0000010002FF00000010000002100000000380000001
图中type为1的就是分配给本机物理内存的地址,其他的为其他硬件所用,我们把内存地址挑出来:
代码:
Base Size0 9E800100000 BF17C000BF282000DD000BF40F00060000BF7170008000BF71F0004C000BF7FF000100010000000038000000
总数为F73AC800=3.86G,尽管4G以下的地址空间被硬件占用了不少,主板并没有放弃那块内存嘛,只是把他们映射到了4G以上的空间,即100000000-138000000,看来是XP那家伙太不地道,活生生把咱们使用这块内存给掐掉了,故而产生了MmHighestPhysicalPage= BF7FF,无耻的家伙!什么?XP的内存机制不支持?不要为XP辩解,PAE技术早在Intel P6家族的CPU身上就已经开始使用了,Intel手册第一卷3.3.6节关于PAE有如下表述:
Beginning with P6 family processors, the IA-32 architecture supports addressing of
up to 64 GBytes (2^36 bytes) of physical memory.
也就是说,从Intel P6家族的CPU开始,(PAE技术让)IA-32架构的CPU就支持对64G的物理内存进行寻址, P6家族可是很老CPU了,奔二,奔三就属于P6家族的,所以XP这个后来才发布的操作系统不可能连PAE都没考虑进去吧。
既然那块4G以上的内存地址被主板识别,NTLDR也探测到了,操作系统也支持,那我们为什么还是用不到呢?到底是NTLDR没有告诉ntkrnlpa.exe,还是ntkrnlpa.exe自己给我们截断了?
这怎么调试呢?Bochs?不行,我总共才4G内存,哪有那么多内存分配给Bochs用呢,要有XP的ntos的源码就好了,ntos的入口函数为
VOID KiSystemStartup(PLOADER_PARAMETER_BLOCK KissLoaderBlock)
在NTLDR向ntos交权的时候,会将内存描述链表通过结构体参数LOADER_PARAMETER_BLOCK传过去,这个结构体原型为
代码:
typedef struct _LOADER_PARAMETER_BLOCK { LIST_ENTRY LoadOrderListHead; LIST_ENTRY MemoryDescriptorListHead; LIST_ENTRY BootDriverListHead;ULONG KernelStack;……后面太长,省略掉} LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK;
既然没有XP的源码,那就用wrk将就一下吧,将wrk编译的内核文件wrkx86.exe来替换ntkrnlpa.exe,系统肯定是起不来的,不过我们只需要在wrkx86.exe的入口点打印出NTLDR传过来的内存描述链表就好了,MEMORY_ALLOCATION_DESCRIPTOR的原型为
代码:
typedef struct _MEMORY_ALLOCATION_DESCRIPTOR { LIST_ENTRY ListEntry; TYPE_OF_MEMORY MemoryType; ULONG BasePage; ULONG PageCount;} MEMORY_ALLOCATION_DESCRIPTOR, *PMEMORY_ALLOCATION_DESCRIPTOR;
于是我们很快得到了结果:(无法上图,遗憾)
咦!NTLDR貌似真的没有把4G以上的地址传过来啊,怎么到FF000这块内存就完了呢?
难道NTLDR私自把4G以上的地址给裁了?难道一切罪恶的源泉在NTLDR?在此我犯了个严重的错误,以为胜利在望,加班加点研究NTLDR,最好成功跳过NTLDR截去4G以上内存的代码了,启动发现XP依然显示2.98G的可用内存,怎么回事呢?回过头来再分析NTLDR,才发现了如下的代码
代码:
if ( (_BYTE)BlUsePae_0 ) { v10 = BlpAllocatePAETables(); if ( v10 ) return v10; } else { BlpTruncateDescriptors(0xFFFFFu);}
BlpTruncateDescriptors(0xFFFFFu)函数的功能就是设置内存描述链表的最大页面号为0xFFFFF,即截去4G以上的内存,原来我们编译的wrkx86.exe不支持PAE,被NTLDR发现了,故而才调用BlpTruncateDescriptors截断的,而我们的XP用的内核ntkrnlpa.exe是支持PAE的,那么就不会截断了,哎,马虎啊。。。
那还是锁定ntkrnlpa.exe分析吧,充分发扬废寝忘食的精神,终于找到了一个可疑的函数ExVerifySuite,这不会就是验证我们版本的函数吧,网上一查,发现有位“老生常谈”早就发现了,他的文章在这里
http://thxlp.wordpress.com/2008/08/03/%E8%80%81%E7%94%9F%E5%B8%B8%E8%B0%88-windows%E5%92%8C4g%E4%BB%A5%E4%B8%8A%E7%89%A9%E7%90%86%E5%86%85%E5%AD%98/
汗。。。。差距啊,不过这位老大发现这么久竟然不出补丁,拯救我们广大百姓于水货,哎。。。害我熬夜伤神这么久。。。。
不过这位“老生”的代码不知道从哪里搞的,nt4源码里没有MiCheckPaeLicense这个函数,而windows2000的源代码里虽然有这个函数,但差别很大,wrk的源代码里也不是那样的,反汇编XP的ntkrnlpa.exe,代码如下
代码:
int __usercall MiCheckPaeLicense<eax>(PLOADER_PARAMETER_BLOCK LoaderBlock<eax>){EndPage = 0;LoaderBlock1 = LoaderBlock;MaxPageCount = 0x100000u;MaxPage = 0;if ( ExVerifySuite(DataCenter) == 1 ){ if (LoaderBlock->u.I386.VirtualBias ) { MaxPageCount = 0x400000u; // booting /3gb: 16G MaxPage = 0x400000u; } else { MaxPageCount = 0x1000000u; } // DataCenter: 64G}else{ if ( MmProductType == 0x690057 || ExVerifySuite(Enterprise) != 1 ) { if ( ExVerifySuite(ServerAppliance) == 1 ) MaxPageCount = 0x80000u; // 2G else MaxPage = 0x100000u; // 4G } else { MaxPageCount = 0x800000u;// Advanced Server is permitted a maximum of 32gb }}
实在是不知道这位高人的代码来自哪里,恳请各位高人给予指点。。。
从这段代码里可以看出,MiCheckPaeLicense函数会检查操作系统的版本,如果是DataCenter,就允许使用64G内存,Advanced Server为32G,如果为精简版则为2G,其他版本为4G,看来真是ntkrnlpa.exe在作怪,先别急着patch,验证内存限制的还有一个地方,在MmAddPhysicalMemoryEx函数里也会调用ExVerifySuite这个函数,代码如下:
代码:
if ( ExVerifySuite(DataCenter) == 1 ){ LimitPage = 0x1000000u; // DataCenter : 64G}else{ if ( MmProductType == 0x690057 || (v9 = ExVerifySuite(Enterprise) == 1, LimitPage = 0x800000u, !v9) )// Advanced Server : 32G LimitPage = 0x100000u; // Other : 4G}
代码都差不多,要patch的话两个地方要一起改,至于怎么改?代码都在这么里,想怎么改就怎么改吧,只要两个地方都改了就行,只要其中一个地方不改,ntos都会阴魂不散的把你多出来的内存吃掉…
看成果吧
代码:
lkd> dd MmHighestPhysicalPage8088b12400137fff 000f7399 00000040 00000000lkd> dd MmNumberOfPhysicalPages8088b128000f7399 00000040 00000000 7fff0000lkd> !pte d0800000 VA d0800000PDE at C0603420 PTE at C0684000contains 00000001004DF963contains E15C080000000400pfn 1004df -G-DA--KWEV not valid Proto: E15C0800
数数这个地址1004DF963,9位啊,4G以上了,不要被E15C080000000400这个地址吓到了,64位,有这么大的地址吗?查查PTE的结构体就知道了,前面的几位是标志位
再看物理内存块
代码:
lkd> dd poi(MmPhysicalMemoryBlock)8baa3c7000000008 000f73ab 00000001 0000009d8baa3c8000000100 000bf17c 000bf282 000000dd8baa3c90000bf40f 00000060 000bf70f 000000088baa3ca0000bf71f 0000004c 000bf7ff 000000018baa3cb000100000 00038000 0001000a 6c4d6d4d
看到了吗,我的机器现在有8块可用的内存了,多了一个100000-138000,总共有f73ab页了,0xf73ab*0x1000=3.86G,至于还有140M,主板没映射,用不到了,能不能解决呢?希望各位牛人能够给予指点。。。
后面部分比较仓促,主要是听到重任到来的消息,没时间仔细写了,补丁没写完,估计一时半会完成不了了,仓促发帖,开始潜伏。。。
忙里偷闲,补丁写好了,赶紧传上来共享,本机测试通过,如果使用过程中发现问题请给我留言。。。
——————————————————————————————————————————
最近忙死了,几天没上网了,更没时间去研究这个,让各位失望了。。。 坛子里的牛人们如果有时间去研究研究吧,MengXP执着的钻研精神让我佩服,离成功只有一步之遥了,希望大家能齐心协力,早日解决这些问题,我只能忙过这阵子再来了。。。
---------------------------------------------------------------
实在抱歉,上个版本出的太匆忙了,严重问题都没有发现,下载这个版本XP64G20110805.rar的朋友请骂我,实在是疏忽大意,抱歉抱歉。。。。
----------------------------------------------------------------------------------------------------------------------------------------------
假的 我的系统属性页显示的3.24G,为什么呢 难道装的64位的XP? 让大家winxp用上4G内存,真感谢这位大侠的共享,在这里我致以衷心的感谢! 这个我一直在用,很不错。 膜拜大神
我的Xp有必要去试试,谢谢楼主。 4G+就去换X64系统了,谢谢分享补丁,给还在继续坚持XP的朋友! 32位系统能用吗?????