说来也真不好意思,我是把董岩翻译的undocumented windowsNT和Raymond老大的《调试软件》一起阅读的。
前者05年就通读过一次,今年打算温故而知新。
我在阅读第三章内存管理的那个copy on write的时候,我看了那个showdir的例子,通过调用门,让内核调用0x0041xxxx的代码--这个能理解吧
例子中,内核调用下面这个代码
DWORD PageDirectory[ 1024 ];
void _stdcall CFuncGetPageDirectory() { DWORD *PageDir = (DWORD *)0xC0300000; int i = 0;
for (i = 0; i < 1024; i++) { PageDirectory[ i ] = PageDir[ i] ; } }
然后执行两次,作者在重点讲述--“会发现两进程页表目录的高半部除两个表项外几乎完全相同”--里面那两个表项,我对这个兴趣不大,我的兴趣在于看0x00400000的两个例子的页表内容是否一样,就是是否都是一个物理页。
我用windbg来看两个calc.exe是没有问题的,见《调试软件》第二章的方法,但我总想自己写程序来验证下。
(注意calc.exe还比较搞笑,我等会说)
于是我修改了下上面那个片断
DWORD PageDirectory[ 1024 ]; DWORD *ppte40 = 0; DWORD imagebase = 0; /* C functions calld from the assembly stub */ void _stdcall CFuncGetPageDirectory() { DWORD *PageDir=(DWORD *)0xC0300000; int i=0;
for (i=0; i<1024; i++) { PageDirectory[ i ]=PageDir[ i ]; if (i == 1) { //这个1好理解吧,我硬编码的,就是打算阅读00400000的地址 DWORD pte40 = PageDirectory[ i ]; pte40 = pte40&0xFFFFF000; ppte40 = (DWORD *)pte40;
imagebase = *ppte40;//这里就bsod了
} } }
结果执行到ppte40 = (DWORD *)pte40这里bsod了,我很奇怪,为什么能执行PageDirectory[ i ]=PageDir[ i ];,而我的却不行。
阅读dump文件,就是mov edx, [ ecx ]
而ecx就是页表,用windbg来看也是一样的内容,就是程序一访问就bsod。
calc.exe比较搞笑的是,我最初发现两个calc.exe的逻辑地址0x00400000的物理地址内容稍有差别,本来我用write on copy来解释,但也觉得不对,不是exe文件头啊,而用ollyice装载又没有问题啊,后来突然明白了,它的imagebase不是0x00400000,而ollyice似乎把它强行安装到了0x0040000。
说了太多啰嗦话,还是请各位帮我看看那个代码有什么问题么?
|