老雷看Win7(1)——序
Windows 7(Win7)是Windows操作系统的下一个客户端版本,计划在明年中正式发布。在前不久的WinHec上,每个参会者都得到了一份Win7的预览版本,是比Beta版本还早的所谓Milestone 3(M3)版本。
老雷曾经说过他是使用调试器来了解和学习操作系统的。但到底可以怎么用调试器来帮我们了解新的操作系统或者它的新版本呢?这个系列文章就想以这种方法来学习一下Win7。今天是第一个部分,到底写多少次还没有计划,如果大家喜欢,老雷写的高兴,那么就一直写下去,不然可能就这一篇。
首先该介绍一下道具(工具),第一,当然少不了WinDBG,老雷机器上有从WinDBG2.x开始的n个版本,但大多数时候用的还是6.X。第二,要有目标机来运行Win7,为了可以随时唤出来把玩,我还是把它运行在虚拟机里,用的是VPC2007。第三,要有一些附属的小工具,比如观察符号的SymView小工具,触发异常的I'm Buggy和AcsVio,DEPENDS等等。
第二步,当然是启用内核调试,使用BCDEDIT在有管理员权限的控制台窗口执行下面这群命令:
bcdedit /copy {current} /d "DBG"
bcdedit /set {GUID} /debugtype serial
bcdedit /set {GUID} /debugport 1
bcdedit /set {GUID} /baudrate 115200
bcdedit /set {GUID} /bootdebug on
把后四条命令中的GUID换成BootMgr再执行一遍,目的是启用对引导管理器(BootMgr)的调试。
接下来设置好虚拟机的串口,开启WinDBG。
准备好后,便可以启动Win7了,启动的过程中,随时可以按下Ctrl+Break,让其停下来接受观摩。按下Ctrl+Break后,WinDBG中便出现了Win7的身影:
Connected to Windows 7 6801 x86 compatible target, ptr64 FALSE
Kernel Debugger connection established.
WARNING: Inaccessible path: 'D:\new\SYMBOLS.PRI\retail'
Symbol search path is: SRV*d:\symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
Windows 7 Kernel Version 6801 MP (1 procs) Free x86 compatible
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 6801.0.x86fre.winmain_win7m3.080913-2030
Kernel base = 0x82041000 PsLoadedModuleList = 0x8219d4d0
Debug session time: Tue Dec 23 08:33:20.234 2008 (GMT+8)
System Uptime: 0 days 0:11:39.875
注意上面的粗体信息,Windows 7曾经是这个版本的开发代号,后来确定为正式的产品名称。6801是Win7使用的构建号,Vista使用的是6000,XP使用的2600。
构建字符串6801.0.x86fre.winmain_win7m3.080913-2030中的m3代表了这个构建版本的名称,080913是构建日期,即2008年9月13日。
下一步是看一下内核文件,可以使用lmv命令来帮忙:
kd> lmv a nt
start end module name
82041000 8244d000 nt (pdb symbols)d:\symbols\ntkrnlmp.pdb\7D...812\ntkrnlmp.pdb
Loaded symbol image file: ntkrnlmp.exe
Image path: ntkrnlmp.exe
Image name: ntkrnlmp.exe
Timestamp: Sun Sep 14 10:55:57 2008 (48CCB57D)
CheckSum: 003C2CE1
ImageSize: 0040C000
File version: 6.1.6801.0
Product version: 6.1.6801.0
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 1.0 App
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft® Windows® Operating System
InternalName: ntkrnlmp.exe
OriginalFilename: ntkrnlmp.exe
ProductVersion: 6.1.6801.0
FileVersion: 6.1.6801.0 (winmain_win7m3.080913-2030)
FileDescription: NT Kernel & System
LegalCopyright: © Microsoft Corporation. All rights reserved.
想说明的要点有两个,一是内部版本号(文件版本号),Win7之所以叫Win7的一个原因是它可以算是Windows操作系统的第7代产品,从运行在DOS上的Windows 1.0算起,Windows 2000算是第5代,内部版本号为5.0,XP为5.1,Vista为6.0。按这个规律,Win7的文件版本号似乎应该为7.0,但是目前来看还没有这么做,没有把文件版本号提升到7.0,只是很谦逊的增大了一下小版本号,成为6.1,这与当年XP的做法是一样的。
另外值得注意一下的是内核的文件大小0040C000,也就是4MB多,XP的是不到2MB
lkd> lmv a nt
start end module name
804d7000 806cdc80 nt (pdb symbols) d:\symbols\ntkrnlpa.pdb\CF7B79A8CE864FCF8ABF248F0B69F4C91\ntkrnlpa.pdb
Loaded symbol image file: ntkrnlpa.exe
Image path: ntkrnlpa.exe
Image name: ntkrnlpa.exe
Timestamp: Wed Feb 28 12:15:53 2007 (45E54849)
CheckSum: 001FFC7C
ImageSize: 001F6C80
File version: 5.1.2600.3093
Product version: 5.1.2600.3093
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 1.0 App
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft® Windows® Operating System
InternalName: ntkrnlpa.exe
OriginalFilename: ntkrnlpa.exe
ProductVersion: 5.1.2600.3093
FileVersion: 5.1.2600.3093 (xpsp_sp2_qfe.070227-2300)
FileDescription: NT Kernel & System
LegalCopyright: © Microsoft Corporation. All rights reserved.
Vista的是3.5MB左右:
0: kd> lmv a nt
start end module name
82c00000 82fa1000 nt (pdb symbols) d:\symbols\ntkrpamp.pdb\FD50D285751D4684938604B2CC1B41682\ntkrpamp.pdb
Loaded symbol image file: ntkrpamp.exe
Image path: ntkrpamp.exe
Image name: ntkrpamp.exe
Timestamp: Thu Nov 02 11:36:16 2006 (4549AE00)
CheckSum: 00360858
ImageSize: 003A1000
File version: 6.0.6000.16386
Product version: 6.0.6000.16386
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 1.0 App
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft® Windows® Operating System
InternalName: ntkrpamp.exe
OriginalFilename: ntkrpamp.exe
ProductVersion: 6.0.6000.16386
FileVersion: 6.0.6000.16386 (vista_rtm.061101-2205)
FileDescription: NT Kernel & System
LegalCopyright: © Microsoft Corporation. All rights reserved
这样看来,Win7的内核文件大小改变幅度不算大。这应该与所谓的MinWin努力有关吧。或者说Win7对NT内核的改动不算是很大,至少没有Vista的改动大,这应该也是没有把内部版本号提升到7的理性原因吧。
接下来想从函数一级看看Win7的变化。这可以通过符号来看,但是还没有到时候。不妨先看看导出函数,因这代表着NT内核对外的接口变化。怎么比较呢?可以先把符号路径设置成空,然后.reload,这样WinDBG便会使用NTOSKRNL.exe的导出信息作为符号,于是x nt!*便可以列出所有导出函数。其数量也得以千记,手工对比不是不可行,只是效率太低了。可以将其复制到EXCEL中,略作格式化后,写些代码(做软件的不会写代码怎么行?),让其自动对比,把新的函数显示为红色,一目了然。
Win7总共导出的函数有2000多个(2091),比Vista(1942)增加了149个。按字母排序以便让属于同一职能的同一类函数在一起,浏览一下,除了以Ke开头的内核部分有成片的增加外,其它部分只是零星增加,增加一两个或者三五个。调试相关的也有增加,比如针对本地内核调试增加了:
nt!DbgkLkmdRegisterCallback |
nt!DbgkLkmdUnregisterCallback |
ETW机制也有补充:
nt!EtwRegisterClassicProvider |
nt!EtwSendTraceBuffer |
WHEA方面增加了四个,Vista只输出了一个 WheaReportHwError。
nt!WheaAddErrorSource |
nt!WheaConfigureErrorSource |
nt!WheaGetErrorSource |
nt!WheaInitializeRecordHeader |
系统服务、电源管理、IO方面也都有增加,但是Mm开头的内存管理器在导出函数方面没看到变化。在以后的文章中,我们每次选择一个方面来深入挖掘一下新增函数的作用。
接下来再观察一下进程,使用!process 0 0列出所有进程,初步来看,没有明显变化,唯一值得一提的是服务进程增加了,打开服务管理程序或者任务管理器的服务页,可以看到很多新的面孔,它们代表着很多Win7的主要变化。
短文不算短了,如果您是中午休息时读这篇文章,那么下午上班时间快到了吧?所以就先写到这,下次见。