上次经过一段时间的研究后,发现了通过修改ntkrnlpa.exe可以突破Windows XP 4G内存限制,完全使用4G以上物理内存(http://bbs.pediy.com/showthread.php?t=137830),但是在测试过程中发现使用USB存储设备时会出现蓝屏等问题,后来因为太忙,也没能继续研究。最近难得短暂清闲,功夫不负有心人,花了一个多星期终于找到问题所在了,下面谈谈在探索过程中的一些心得。
1.首先替换usb相关驱动
既然一插U盘就蓝屏,而使用USB鼠标、摄像头等都没有问题,那么首先怀疑是usbstor.sys的问题。Windows 2003可以支持4G以上物理内存,那么我们将Windows 2003的USB驱动替换到XP上来,首先替换usbstor.sys,现象依旧。那么全部替换usb相关驱动,包括usbstor.sys、usbport.sys、usbhub.sys、usbehci.sys等,XP可以正常启动,USB设备也能使用,但经反复测试,发现使用U盘时有时还是会蓝屏。
2.是谁造成了内存访问越界?
种种蓝屏迹象表明,很可能是因为内存读写越界造成的。破解4G限制后,虽然物理地址扩展到32位以上,但是虚拟地址依然是32位的啊,使用虚拟地址的程序不可能造成内存访问越界啊。那么有哪些代码用到了物理地址呢?
首先想到的是内存分页管理,负责映射物理地址到虚拟地址空间,维护了一个物理内存的页帧数据库MmPfnDatabase,会不会是因为物理地址空间扩大后,这个页帧数据库并没有扩大,而导致映射4G以上物理内存时发生错误呢?
一番折腾,在MiInitMachineDependent函数中找到了如下代码
MmFreePagesByColor[0] = (PMMCOLOR_TABLES)&MmPfnDatabase[MmHighestPossiblePhysicalPage + 1];
lkd> dd MmPfnDatabase
8088b0c8 818c6000 0000ff00 00000006 0000003f
lkd> dd MmHighestPossiblePhysicalPage
8088b120 00137fff 00137fff 000f7379 00000040
lkd> dt _MMPFN
nt!_MMPFN
+0x000 u1 : __unnamed
+0x004 PteAddress : Ptr32 _MMPTE
+0x008 u2 : __unnamed
+0x00c u3 : __unnamed
+0x010 OriginalPte : _MMPTE
+0x018 u4 : __unnamed
lkd> ?818c6000+(137fff+1)*1c
Evaluate expression: -2085724160 = 83ae6000
lkd> dd MmFreePagesByColor
80886388 83ae6000 83ae6300 c0883000 f77fffff
b82540e0 f805a042 81fc29dc 81840c80 817e88f4 usbehci!EHCI_SubmitTransfer+0x53
b8254128 f805a74a 81fc2028 81840b08 804e3ec4 USBPORT!USBPORT_DmaEndpointActive+0x1f0
b8254154 f805cb7c 81fc2028 00000000 804e3ec4 USBPORT!USBPORT_DmaEndpointWorker+0x140
b825417c f805e4c3 81fc2028 00000003 00000001 USBPORT!USBPORT_CoreEndpointWorker+0x6d2
b82541f0 806f2a98 81fc2028 00000000 413e504d USBPORT!USBPORT_MapTransfer+0x76f
b825421c 8052e551 821c7788 81fc205c 00000001 hal!HalAllocateAdapterChannel+0x126
b8254234 f805e6df 821c7788 81fc2028 00000001 nt!IoAllocateAdapterChannel+0x2a
b8254278 f805f4d9 81fc2028 817adad0 804e3ec4 USBPORT!USBPORT_FlushMapTransferList+0x1b1
signed int __stdcall USBPORT_MapTransfer(PDEVICE_OBJECT DeviceObject, PIRP CurrentIrp, PVOID MapRegisterBase, PTRANSFER pTransfer)
typedef struct _TRANSLATION_ENTRY {
PVOID VirtualAddress;
ULONG PhysicalAddress;
ULONG Index;
} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
__int64 __stdcall IoMapTransfer(PADAPTER_OBJECT AdapterObject, PMDL Mdl, PVOID MapRegisterBase, PVOID CurrentVa, PULONG Length, BOOLEAN WriteToDevice)
if ( MapRegisterBase )
{
result = HalpMapTransfer(AdapterObject, Mdl, MapRegisterBase, CurrentVa, Length, WriteToDevice);
}
else
{
计算缓冲区Mdl中的连续物理内存块,返回64位物理基址
}
return result;
}
PHYSICAL_ADDRESS
HalpMapTransfer(
IN PADAPTER_OBJECT AdapterObject,
IN PMDL Mdl,
IN PVOID MapRegisterBase,
IN PVOID CurrentVa,
IN OUT PULONG Length,
IN BOOLEAN WriteToDevice
)
{
if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
&& transferLength < *Length) {
logicalAddress = translationEntry->PhysicalAddress + pageOffset;
translationEntry->Index = COPY_BUFFER;
index = 0;
transferLength = *Length;
useBuffer = TRUE;
}
if (useBuffer && WriteToDevice) {
HalpCopyBufferMap(
Mdl,
translationEntry + index,
CurrentVa,
*Length,
WriteToDevice
);
}
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!