Windows Vista操作系统加载
bootmgr调用了位于%SystemRoot%System32WINLOAD.EXE下的Vista OS Loader。WINLOAD.EXE替换了NTLDR(Windows NT OS Loader),该小节的最后部分,会引用WINLOAD.EXE在开始入口点(OslMain)的指令。
一个典型的Vista OS载入的BCD入口配置文件如下:
Windows;Boot;Loader IdentifIEr:;{current} Type:;10200003 Device:;partition=C: SYMANTEC;ADVANCED;THREAT;RESEARCH;3 Path:;Windowssystem32WINLOAD.EXE Description:;Microsoft;Windows Locale:;en-US Inherit;options:;{bootloadersettings} Boot;debugger:;No Pre-boot;EMS;Enabled:;No Advanced;options:;No Options;editor:;No Windows;device:;partition=C: Windows;root:;Windows Resume;application:;{3ced334e-a0a5-11da-8c2b-cbb6baaeea6d} No;Execute;policy:;OptIn Detect;HAL:;No No;integrity;checks:;No Disable;boot;display:;No Boot;processor;only:;No Firmware;PCI;settings:;No Log;initialization:;No OS;boot;information:;No Kernel;debugger:;No HAL;breakpoint:;No EMS;enabled;in;OS:;No |
执行从OslMain开始。它重用了与bootmgr阶段相同的代码,因此InitializeLibrary在bootmgr内的工作原理与在WINLOAD.EXE内的工作原理相似。在InitializeLibrary之后,控制权交给OslMain。
如果启动状态日志记录被激活,WINLOAD.EXE将会把结果写入%SystemDrive%Bootbootstat.dat (通过 OslpInitializeBootStatusDataLog和OslpSetBootStatusData)。接下来WINLOAD.EXE调用OslDisplayInitialize,并使用BlResourceFindHTML定位osloader.xsl所在的资源节点。控制权转交给BlXmiInitialize。在系统启动过程中osloader.xsl控制着高级启动选项。在操作完高级启动选项(使用OslDisplayAdvancedOptionsProcess),WINLOAD.EXE现在就准备开始启动。启动阶段首先会使用BlDeviceOpen打开启动设备。根据设备类型,BlDeviceOpen会使用不同的设备函数集来打开设备。
全盘加密(_FvebDeviceFunctionTable) 如下:
dd;0;;;FVE;has;no;EnumerateDeviceClass;callback dd;offset;_FvebOpen@8;;;FvebOpen(x,x) dd;offset;_FvebClose@4;;;FvebClose(x) dd;offset;_FvebRead@16;;;FvebRead(x,x,x,x) dd;offset;_FvebWrite@16;;;FvebWrite(x,x,x,x) dd;offset;_FvebGetInformation@8;;;FvebGetInformation(x,x) dd;offset;_FvebSetInformation@8;;;FvebSetInformation(x,x) dd;offset;_FvebReset@4;;;FvebReset(x) For;block;I/O;(_BlockIoDeviceFunctionTable);these;are: dd;offset;_BlockIoEnumerateDeviceClass@12;;;BlockIoEnumerateDeviceClass(x,x,x) dd;offset;_BlockIoOpen@8;;;BlockIoOpen(x,;x) dd;offset;_BlockIoClose@4;;;BlockIoClose(x) dd;offset;_BlockIoReadUsingCache@16;;;BlockIoReadUsingCache(x,x,x,x) dd;offset;_BlockIoWrite@16;;;BlockIoWrite(x,x,x,x) dd;offset;_BlockIoGetInformation@8;;;BlockIoGetInformation(x,x) dd;offset;_BlockIoSetInformation@8;;;BlockIoSetInformation(x,x) dd;offset;?handleInputChar@OsxmlMeter@@UAEHG@Z;;;OsxmlMeter::handleInputChar(ushort) dd;offset;_BlockIoCreate@12;;;BlockIoCreate(x,x,x) For;console;(_ConsoleDeviceFunctionTable);these;are: dd;offset;_UdpEnumerateDeviceClass@12;;;UdpEnumerateDeviceClass(x,x,x) dd;offset;_ConsoleOpen@8;;;ConsoleOpen(x,x) dd;offset;_ConsoleClose@4;;;ConsoleClose(x) dd;offset;_ConsoleRead@16;;;ConsoleRead(x,x,x,x) dd;offset;_ConsoleWrite@16;;;ConsoleWrite(x,x,x,x) dd;offset;_ConsoleGetInformation@8;;;ConsoleGetInformation(x,x) dd;offset;_ConsoleSetInformation@8;;;ConsoleSetInformation(x,x) dd;offset;_ConsoleReset@4;;;ConsoleReset(x) For;serial;port;(_SerialPortFunctionTable);these;are: dd;offset;_UdpEnumerateDeviceClass@12;;;UdpEnumerateDeviceClass(x,x,x) dd;offset;_SpClose@4;;;SpClose(x) dd;offset;_SpRead@16;;;SpRead(x,x,x,x) dd;offset;_SpWrite@16;;;SpWrite(x,x,x,x) dd;offset;_SpGetInformation@8;;;SpGetInformation(x,x) dd;offset;_SpSetInformation@8;;;SpSetInformation(x,x) dd;offset;_SpReset@4;;;SpReset(x) For;PXE;(_UdpFunctionTable): dd;offset;_UdpEnumerateDeviceClass@12;;;UdpEnumerateDeviceClass(x,x,x) dd;offset;_UdpOpen@8;;;UdpOpen(x,x) dd;offset;_SpClose@4;;;SpClose(x) dd;offset;_UdpRead@16;;;UdpRead(x,x,x,x) dd;offset;_UdpWrite@16;;;UdpWrite(x,x,x,x) dd;offset;_UdpGetInformation@8;;;UdpGetInformation(x,x) dd;offset;_UdpSetInformation@8;;;UdpSetInformation(x,x) dd;offset;_UdpReset@4;;;UdpReset(x) |
你可能注意到有些函数的返回在不同类别之间会存在共享(例如:serial port和PXE)。
接着LOADER_PARAMETER_BLOCK结构通过OslInitializeLoaderBlock进行初始化,LOADER_PARAMETER_BLOCK包含了一些系统状态信息,如:启动设备、ACPI、SMBIOS表等。下面为LOADER_PARAMETER_BLOCK在Vista64位版本的结构:
+0x000;LoadOrderListHead;:;struct;_LIST_ENTRY +0x010;MemoryDescriptorListHead;:;struct;_LIST_ENTRY +0x020;BootDriverListHead;:;struct;_LIST_ENTRY +0x030;KernelStack;:;Uint8B +0x038;Prcb;:;Uint8B +0x040;Process;:;Uint8B +0x048;Thread;:;Uint8B +0x050;RegistryLength;:;Uint4B +0x058;RegistryBase;:;Ptr64;to;Void +0x060;ConfigurationRoot;:;Ptr64;to;struct;_CONFIGURATION_COMPONENT_DATA +0x068;ArcBootDeviceName;:;Ptr64;to;Char +0x070;ArcHalDeviceName;:;Ptr64;to;Char +0x078;NtBootPathName;:;Ptr64;to;Char +0x080;NtHalPathName;:;Ptr64;to;Char +0x088;LoadOptions;:;Ptr64;to;Char +0x090;NlsData;:;Ptr64;to;struct;_NLS_DATA_BLOCK +0x098;ArcDiskInformation;:;Ptr64;to;struct;_ARC_DISK_INFORMATION +0x0a0;OemFontFile;:;Ptr64;to;Void +0x0a8;SetupLoaderBlock;:;Ptr64;to;struct;_SETUP_LOADER_BLOCK +0x0b0;Extension;:;Ptr64;to;struct;_LOADER_PARAMETER_EXTENSION +0x000;Size;:;Uint4B +0x004;Profile;:;struct;_PROFILE_PARAMETER_BLOCK +0x014;MajorVersion;:;Uint4B +0x018;MinorVersion;:;Uint4B +0x020;EmInfFileImage;:;Ptr64;to;Void +0x028;EmInfFileSize;:;Uint4B +0x030;TriageDumpBlock;:;Ptr64;to;Void +0x038;LoaderPagesSpanned;:;Uint4B +0x040;HeadlessLoaderBlock;:;Ptr64;to;struct;_HEADLESS_LOADER_BLOCK +0x048;SMBiosEPSHeader;:;Ptr64;to;struct;_SMBIOS_TABLE_HEADER +0x050;DrvDBImage;:;Ptr64;to;Void +0x058;DrvDBSize;:;Uint4B +0x060;NetworkLoaderBlock;:;Ptr64;to;struct;_NETWORK_LOADER_BLOCK;bytes +0x068;FirmwareDescriptorListHead;:;struct;_LIST_ENTRY +0x078;AcpiTable;:;Ptr64;to;Void +0x080;AcpiTableSize;:;Uint4B +0x084;BootViaWinload;:;Bitfield;Pos;0,;1;Bit +0x084;BootViaEFI;:;Bitfield;Pos;1,;1;Bit +0x084;Reserved;:;Bitfield;Pos;2,;30;Bits +0x088;LoaderPerformanceData;:;Ptr64;to;struct;_LOADER_PERFORMANCE_DATA +0x090;BootApplicationPersistentData;:;struct;_LIST_ENTRY +0x0a0;WmdTestResult;:;Ptr64;to;Void +0x0a8;BootIdentifier;:;struct;_GUID +0x0b8;u;:;union +0x000;I386;:;struct;_I386_LOADER_BLOCK +0x000;CommonDataArea;:;Ptr64;to;Void +0x008;MachineType;:;Uint4B +0x00c;VirtualBias;:;Uint4B |
下面会寻找系统磁盘(通过OslEnumerateDisks)和加载系统注册表项HKEY_LOCAL_MACHINE(通过OslpLoadSystemHive)。当系统注册表项加载后,我们遇到了Vista在启动阶段的第一次代码完整性(通过OslInitializeCodeIntegrity)。在该处首先会调用MincrypL_SelfTest,MincrypL_SelfTest验证SHA1散列值,并使PKCS1的签名验证开始工作(using a pre-defined test case=通过预定义的测试样例?)。如果预先定义的测试样例失败了,会返回错误代码到0xC0000428。然后,检查调试器是否开启(通过BlBdDebuggerEnabled)。如果在这里检测到调试器在开启状态,会调用KnownAnswerTest。如果没有检测到调试器处在开启状态,会直接跳过该处。
接下来通过BlImgRegisterCodeIntegrityCatalogs从%SystemRoot%System32CatRoot{F750E6C3-38EE-11D1-85E5-00C04FC295EE}nt5.cat加载OS的编目录(在内部调用了API函数MinCrypL_AddCatalog)。
标签: