成长值: 258 签到天数: 4711 天 [LV.Master]伴坛终老
|
标 题: 【原创】让XP用上4G内存,有图有真相,带破解补丁
作 者: scdeny
时 间: 2011-07-28,00:13:40
链 接: http://bbs.pediy.com/showthread.php?t=137830
先上图,patch之后的,原来只有2.98G,现在是3.86G了
去年7月入手小黑T410,到手就装了4G的内存,WINDOWS 7的破解补丁来的很快,很顺利就用上了3.86G(纠结于剩下的140M哪里去了?至今也没搞明白,只知道主板没有映射),而所谓的XP的种种补丁,不外乎就是Ramdisk,开启PAE之类的,毫无用处,最可怜的是竟然被某网友的“开启了PAE就能用到全部4G内存,系统属性页显示还是2.98G是假的”一说给忽悠了一年,没文化真可怕。。。就这么将信将疑用了一年,中间也纠结过一段时间,没有深入分析,近日越想越感觉不对劲,再来纠结纠结。。。
用WinDbg看看
代码:
lkd> dd MmHighestPhysicalPage8088b124 000bf7ff 000bf399 00000040 00000000lkd> dd MmNumberOfPhysicalPages8088b128 000bf399 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 00000000008009E3 contains 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)8ad75c80 00000007 000bf3ab 00000001 0000009d8ad75c90 00000100 000bf17c 000bf282 000000dd8ad75ca0 000bf40f 00000060 000bf70f 000000088ad75cb0 000bf71f 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[1];} PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR;
从上面可以看出,我的机器有7块可用的内存,总共有bf3ab页(为什么这个数字跟上面看到的MmNumberOfPhysicalPages不符呢?),分别为1 -9d,100- bf17c,…,bf7ff,可见最大物理内存地址为bf7ff,还是与4G内存相去甚远啊。。。
那么是不是我的主板根本就不识别这么大的内存呢??
那么我们再做做实验,用nt4的源代码编译一份NTLDR,把osloader.exe探测到的物理内存输出一份,下面是通过中断获取的内存布局图,BIOS专家们都叫把它做E820图
代码:
Base Size Type0 9E800 19E800 1800 2D2000 2000 2DC000 24000 2100000 BF17C000 1BF27C000 6000 2BF282000 DD000 1BF35F000 12000 2BF371000 1000 4BF3F2000 1D000 2BF40F000 60000 1BF46F000 1F9000 2BF668000 80000 4BF6E8000 27000 2BF717000 8000 1BF71F000 4C000 1BF76B000 C000 4BF777000 3000 3BF77A000 7000 4BF781000 1000 3BF782000 9000 4BF78B000 1000 3BF78C000 13000 4BF79F000 60000 3BF7FF000 1000 1BF800000 800000 2E0000000 10000000 2FEAFF000 1000 2FEC00000 10000 2FED00000 400 2FED1C000 4000 2FED20000 70000 2FEE00000 1000 2FF000000 1000000 2100000000 38000000 1
图中type为1的就是分配给本机物理内存的地址,其他的为其他硬件所用,我们把内存地址挑出来:
代码:
Base Size0 9E800100000 BF17C000BF282000 DD000BF40F000 60000BF717000 8000BF71F000 4C000BF7FF000 1000100000000 38000000
总数为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 MmHighestPhysicalPage8088b124 00137fff 000f7399 00000040 00000000lkd> dd MmNumberOfPhysicalPages8088b128 000f7399 00000040 00000000 7fff0000lkd> !pte d0800000 VA d0800000PDE at C0603420 PTE at C0684000contains 00000001004DF963 contains E15C080000000400pfn 1004df -G-DA--KWEV not valid Proto: E15C0800
数数这个地址1004DF963,9位啊,4G以上了,不要被E15C080000000400这个地址吓到了,64位,有这么大的地址吗?查查PTE的结构体就知道了,前面的几位是标志位
再看物理内存块
代码:
lkd> dd poi(MmPhysicalMemoryBlock)8baa3c70 00000008 000f73ab 00000001 0000009d8baa3c80 00000100 000bf17c 000bf282 000000dd8baa3c90 000bf40f 00000060 000bf70f 000000088baa3ca0 000bf71f 0000004c 000bf7ff 000000018baa3cb0 00100000 00038000 0001000a 6c4d6d4d
看到了吗,我的机器现在有8块可用的内存了,多了一个100000-138000,总共有f73ab页了,0xf73ab*0x1000=3.86G,至于还有140M,主板没映射,用不到了,能不能解决呢?希望各位牛人能够给予指点。。。
后面部分比较仓促,主要是听到重任到来的消息,没时间仔细写了,补丁没写完,估计一时半会完成不了了,仓促发帖,开始潜伏。。。
忙里偷闲,补丁写好了,赶紧传上来共享,本机测试通过,如果使用过程中发现问题请给我留言。。。
——————————————————————————————————————————
最近忙死了,几天没上网了,更没时间去研究这个,让各位失望了。。。 坛子里的牛人们如果有时间去研究研究吧,MengXP执着的钻研精神让我佩服,离成功只有一步之遥了,希望大家能齐心协力,早日解决这些问题,我只能忙过这阵子再来了。。。
---------------------------------------------------------------
实在抱歉,上个版本出的太匆忙了,严重问题都没有发现,下载这个版本XP64G20110805.rar的朋友请骂我,实在是疏忽大意,抱歉抱歉。。。。
----------------------------------------------------------------------------------------------------------------------------------------------
终于有时间继续研究一下了,发现原因主要在DMA,修改之后,USB存储设备基本可以正常使用了,先上补丁,回头再发技术帖
XP64G.exe
(92 KB, 下载次数: 11581)
|
评分
-
查看全部评分
|