`
no791no
  • 浏览: 18996 次
社区版块
存档分类
最新评论

windows x64 vista以上系统代码完整性校验分析

阅读更多

windows x64 vista以上系统代码完整性校验分析
2011年04月18日
  .text:00000001400E63EE MiResolveTransitionFault           mov     eax, 0C0000428h
  .text:00000001400E640D MiResolveTransitionFault           mov     eax, 0C0000428h
  .text:00000001400E671C MiResolveProtoPteFault             mov     eax, 0C0000428h
  PAGE:000000014039C6A8  SeValidateImageData                mov     eax, 0C0000428h
  PAGE:00000001403BA850  SeValidateImageHeader              mov     eax, 0C0000428h
  PAGE:00000001404EC7C7  PipCallDriverAddDeviceQueryRoutine cmp     eax, 0C0000428h
  PAGE:00000001404EC81D  PipCallDriverAddDeviceQueryRoutine cmp     ebx, 0C0000428h
  PAGE:00000001404EC9FF  PipCallDriverAddDeviceQueryRoutine cmp     ebx, 0C0000428h
  kd> kb
  RetAddr           : Args to Child                                                           : Call Site
  fffff800`03f39534 : 00000000`00000024 00000000`01000000 fffffa80`090c29c0 00000000`00000000 : nt!SeValidateImageHeader+0x11
  fffff800`0402c3c2 : fffffa80`08db3170 fffffa80`090c29c0 00000000`00000001 00000000`00000001 : nt!MiValidateImageHeader+0xa4
  fffff800`03fbc893 : fffff880`0456d400 00000000`00000000 fffff880`0456d6b8 fffff880`0456d3f8 : nt! ?? ::NNGAKEGL::`string'+0x50c03
  fffff800`03cce153 : fffffa80`06d67b60 fffff880`0456d658 fffff880`0456d448 00000000`00000000 : nt!NtCreateSection+0x162
  fffff800`03cca6f0 : fffff800`040a7416 fffffa80`06d67b60 00000000`00000000 00000000`00f80076 : nt!KiSystemServiceCopyEnd+0x13
  fffff800`040a7416 : fffffa80`06d67b60 00000000`00000000 00000000`00f80076 fffff8a0`019c3370 : nt!KiServiceLinkage
  fffff800`040a77dc : ffffffff`80000844 00000000`00100000 fffff880`0456d8a0 00000000`00000000 : nt!MmCheckSystemImage+0x96
  fffff800`040a79f7 : ffffffff`80000844 fffff800`00000001 fffff8a0`01553960 00000000`00000000 : nt!MiCreateSectionForDriver+0xcc
  fffff800`040b329a : 00000000`00000000 fffff880`0456d9f8 fffffa80`06d67b60 00000000`00000000 : nt!MiObtainSectionForDriver+0xd7
  fffff800`040b5ebd : fffff880`0456d9f8 00000000`00000000 00000000`00000000 00000000`00000000 : nt!MmLoadSystemImage+0x23a
  fffff800`040b6875 : 00000000`00000001 00000000`00000000 00000000`00000000 fffff800`03ed2ee0 : nt!IopLoadDriver+0x44d
  fffff800`03cdc161 : fffff800`00000000 ffffffff`80000838 fffff800`040b6820 00000000`00000000 : nt!IopLoadUnloadDriver+0x55
  fffff800`03f72166 : f0d69f7c`0bc556a2 fffffa80`06d67b60 00000000`00000080 fffffa80`06d43400 : nt!ExpWorkerThread+0x111
  fffff800`03cad486 : fffff800`03e47e80 fffffa80`06d67b60 fffffa80`06d67040 1aed37e5`683df1a6 : nt!PspSystemThreadStartup+0x5a
  00000000`00000000 : fffff880`0456e000 fffff880`04568000 fffff880`0456d1e0 00000000`00000000 : nt!KxStartSystemThread+0x16
  kd> kb
  RetAddr           : Args to Child                                                           : Call Site
  fffff800`03f39534 : 00000000`00000024 00000000`01000000 fffffa80`090c29c0 00000000`00000000 : nt!SeValidateImageHeader+0x11
  fffff800`0402c3c2 : fffffa80`08db3170 fffffa80`090c29c0 00000000`00000001 00000000`00000001 : nt!MiValidateImageHeader+0xa4
  fffff800`03fbc893 : fffff880`0456d530 00000000`00000000 fffff880`0456d7c0 fffff880`0456d528 : nt! ?? ::NNGAKEGL::`string'+0x50c03
  fffff800`03cce153 : fffffa80`06d67b60 fffff880`0456d788 fffff880`0456d578 00000000`00000000 : nt!NtCreateSection+0x162
  fffff800`03cca6f0 : fffff800`040a7874 ffffffff`80000844 00000000`08000000 00000000`00220000 : nt!KiSystemServiceCopyEnd+0x13
  fffff800`040a7874 : ffffffff`80000844 00000000`08000000 00000000`00220000 ffffffff`80000840 : nt!KiServiceLinkage
  fffff800`040a79f7 : ffffffff`80000844 fffff800`00000001 fffff8a0`01553960 00000000`00000000 : nt!MiCreateSectionForDriver+0x164
  fffff800`040b329a : 00000000`00000000 fffff880`0456d9f8 fffffa80`06d67b60 00000000`00000000 : nt!MiObtainSectionForDriver+0xd7
  fffff800`040b5ebd : fffff880`0456d9f8 00000000`00000000 00000000`00000000 00000000`00000000 : nt!MmLoadSystemImage+0x23a
  fffff800`040b6875 : 00000000`00000001 00000000`00000000 00000000`00000000 fffff800`03ed2ee0 : nt!IopLoadDriver+0x44d
  fffff800`03cdc161 : fffff800`00000000 ffffffff`80000838 fffff800`040b6820 00000000`00000000 : nt!IopLoadUnloadDriver+0x55
  fffff800`03f72166 : f0d69f7c`0bc556a2 fffffa80`06d67b60 00000000`00000080 fffffa80`06d43400 : nt!ExpWorkerThread+0x111
  fffff800`03cad486 : fffff800`03e47e80 fffffa80`06d67b60 fffffa80`06d67040 1aed37e5`683df1a6 : nt!PspSystemThreadStartup+0x5a
  00000000`00000000 : fffff880`0456e000 fffff880`04568000 fffff880`0456c220 00000000`00000000 : nt!KxStartSystemThread+0x16
  fffff800`0404caee 483bc3          cmp     rax,rbx
  kd> kb
  RetAddr           : Args to Child                                                           : Call Site
  fffff800`041f3a76 : ffffffff`80000008 fffff800`00814210 fffff800`0081cd90 00000000`00000001 : nt!SepInitializeCodeIntegrity+0x8e
  fffff800`041f3c61 : 00000000`00000001 fffff800`041fce41 00000000`00000001 fffff800`0081cd90 : nt!SepInitializationPhase1+0x236
  fffff800`042044e6 : 00000000`00000001 fffff800`00814210 fffff800`00814210 00000000`00000003 : nt!SeInitSystem+0x31
  fffff800`04155419 : 00000000`00000000 fffffa80`06cfc040 00000000`00000080 fffffa80`06cfb400 : nt!Phase1InitializationDiscard+0xc56
  fffff800`03f77166 : 00000000`00000000 00000000`00000080 00000000`00000000 fffff800`03cb2479 : nt!Phase1Initialization+0x9
  fffff800`03cb2486 : fffff800`03e4ce80 fffffa80`06cfc040 fffff800`03e5ac40 00000000`00000000 : nt!PspSystemThreadStartup+0x5a
  00000000`00000000 : fffff880`009aa000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KxStartSystemThread+0x16
  kd> dq nt!KeLoaderBlock
  fffff800`03f0a120  fffff800`00814210 00000000`00007530
  fffff800`03f0a130  00000200`00000000 fffff880`00961000
  fffff800`03f0a140  00000000`00000000 00000000`00000000
  fffff800`03f0a150  fffff800`03cf8f00 00000000`00000000
  fffff800`03f0a160  00000000`00002710 00000100`0000004b
  fffff800`03f0a170  fffff8bf`ffffffff fffffa80`06d22c90
  fffff800`03f0a180  00000002`01010009 00000000`00000000
  fffff800`03f0a190  fffffa80`1be00000 00000000`029ff000
  kd> dq fffff800`00814210+98
  fffff800`008142a8  fffff800`0081cd90 fffff800`008c2c40
  fffff800`008142b8  fffff800`00889f70 fffff800`00bfd1d0
  fffff800`008142c8  fffff800`00888930 00000000`00000000
  fffff800`008142d8  00000000`00000000 00000000`00000000
  fffff800`008142e8  00000000`00000000 00000000`00000000
  fffff800`008142f8  00000000`00000000 fffff800`00814380
  fffff800`00814308  fffff800`00814200 00000003`00000004
  fffff800`00814318  00000007`00000000 00000000`005438c8
  kd> dc fffff800`0081cd90
  fffff800`0081cd90  53455420 47495354 474e494e 4f4e2020   TESTSIGNING  NO
  fffff800`0081cda0  43455845 3d455455 4954504f 4420204e  EXECUTE=OPTIN  D
  fffff800`0081cdb0  47554245 45442020 50475542 3d54524f  EBUG  DEBUGPORT=
  fffff800`0081cdc0  314d4f43 41422020 41524455 313d4554  COM1  BAUDRATE=1
  fffff800`0081cdd0  30323531 00000030 00000000 00000000  15200...........
  fffff800`0081cde0  0081ce20 fffff800 0081cd80 fffff800   ...............
  fffff800`0081cdf0  008110d0 fffff800 00889660 fffff800  ........`.......
  fffff800`0081ce00  000001aa 00000000 00000000 00000000  ................
  C0000428
  cmp     cs:g_CiEnabled, al
  kd> dc nt!SeLoadDriverPrivilege 
  fffff800`0419e170  0000000a
  nt!SepInitializeCodeIntegrity proc near
  mov     cs:g_CiOptions, ecx
  CipInitialize
  http://www.woodmann.com/forum/archive/index.php/t- 13722.html
  http://www.bilgiguvenligi.gov.tr/teknik-yazilar-ka tegorisi/64-bit-vista-kernel-hacking.html
  http://book.51cto.com/art/200812/102471.htm
  http://www.soidc.net/articles/1215485053493/200906 11/1215945596179_1.html
  http://j00ru.vexillium.org/?p=377
  \Registry\MACHINE\System\CurrentControlSet\Control \CI\
  CipCheckConfigOptions()中涉及到DebugFlags的解析过程。
  00000001
  Results in a debug break into the debugger and unsigned driver is allowed to load with g.
  00000010
  CI will ignore the presence of the debugger and unsigned drivers are blocked from loading. 
  bcdedit.exe /set loadoptions DISABLE_INTEGRITY_CHECKS
  bcdedit.exe /set loadoptions ENABLE_INTEGRITY_CHECKS
  g_CiOption 
  默认是4|2 = 6
  Disable_Intergrity_Check     0x0
  DebugFlags            0x1    //enable load when debugger    
  Testsigning            0x8
  DebugFlags            0x10    //
  nt!SeValidateImageData
  if(!g_ciEnable)
  {
  return 0;    
  }
  else
  {
  if(g_CiCallbacks[1])            //CiValidateImageData()
  return g_CiCallbacks[1]();
  else
  return 0C0000428h;
  }    
  nt!SeValidateImageHeader
  if(!g_ciEnable)
  {
  return 0;    
  }
  else
  {
  if(g_CiCallbacks[0])            //CiValidateImageHeader()
  return g_CiCallbacks[0]();
  else
  return 0C0000428h;
  }    
  MiCreateSectionForDriver()
  Vista Bootmgr/Winload使用的大部分选项ID
  vista bootmgr的选项存储在systemdevice\boot\bcd,这个HIVE文件类似以前的boot,ini
  boot.ini的选项在该HIVE中是以guid->option id的形式来体现的
  除了保留了原来boot.ini可以使用的大部分选项外,还新增了许多选项,例如test signing, disable integrity checks,hypervisor debug options,cmdcons等等等
  以下是我分析WINLOAD.EXE和bootmgr找出的一些选项ID(50个,包括大部分选项),通过这些选项ID可以查看、修改VISTA的许多启动设置(结合参考:http://www.debugman.com/read.php?tid=1999)
  10100002 os type
  12000002 boot loader path
  12000004 os name
  12000005 locate language
  12000016 target name
  15000007 max memory
  1500000d relocate physical memory range
  15000011 1394 or usb debug
  15000013 debug port(COM 1 ,2 ,3 4)
  15000014 brudrate
  15000022 redirect(COM 1, 2, 3,4)
  15000023 redirect baudrate
  15000047 config access policy (default or disallow low memory config)
  15000052 graphics resolution (800×600 or 1024×768)
  16000009: recovery
  16000010 Boot debugging
  16000048 disable integrity checks or no integrity checks!
  16000049 test signing
  22000001 "cmdcons" :cmdcons(Windows Recovery Console)
  "undo" roll back
  22000002 system root
  22000011 kernel =
  22000012 hal =
  23000006 default resume os
  24000001 os list
  24000010 memory test
  25000004 boot menu timeout
  25000020 DEP option(optin/optout/alwayson/alwaysoff)
  25000021 pae or nopae
  25000032 3GB user memory(user rva)
  25000071 MSI policy (default or force disable)
  25000072 pci express policy (default or force disable)
  25000080 safeboot :boot network or dsrepair
  250000f6 :hypervisor dbg ch
  26000004 stamp disks (stamp raw disk when winpe)
  26000010 detect hal
  26000026 disable integrity checks
  26000027 test signing
  26000040 base video
  26000041 (noguiboot, bootlogo)load bitmap logo : \osload800x600.bmp or \osload1024x768.bmp
  26000042 novesa
  26000051 use physical APIC
  26000060 one cpu
  26000062 max processor
  26000070 pci lock
  26000081 safeboot :boot minimal or minimal(alter nate shell)
  26000090 boot log
  26000091 SOS
  260000a0 debug or nodebug
  260000a1 kernel debug break on ntoskrnl
  评估Vista内核模式的安全性
  Windows Vista与之前的MS Windows版本(包括Windows XP SP2)相比增加了很多的安全性。Vista新安全性的特征可以包括以下几个方面:
  [1]驱动签名
  [2]PatchGuard
  [3]内核模式代码完整性检查
  [4]可选择支持使用TPM芯片的安全启动
  [5]限制用户模式访问\Device\PhysicalMemory
  上述的这些功能使得Vista64位版本与Linux或MacOS相比更具备安全性。该文档的主要贡献在:(1)通过拟向工程较全面的分析内核模式的安全组件;(2)评估可能存在的内核模式攻击。
  A、What's Covered
  该文档检查新的安全特性,通过这些安全特性来阻止恶意代码危及内核。由于这些特性都仅存在于64位的Windows Vista系统内,因此该文档的关注点在Vista64位版本。
  B、What's Not Covered
  该文档没有分析PatchGuard的执行,针对PatchGuard的分析在前期已经有Skape和Skywing[6]进行了较全面的分析,值得注意的是PatchGuard发展到目前已经有所改变(在skape与skywing分析完后)。仅当下面章节对PatchGuard进行攻击评估时才会讨论这些问题。针对Vista用户模式的安全性评估在前面已经有所讨论。
  C、必要条件
  由于无法访问Windows Vista的源代码,我们通过debugger(调试器)、disassembler(反编译)、hex editor(16进制编辑器,例如UE)学习了Windows Vista Community Technical Preview (CTP) Build 5365版本。如果读者不熟悉X86体系架构和汇编语言的知识,推荐大家一本不错的关于X86汇编语言的在线图书[8]。另外,在看该文档前你需要熟悉一些Windows系统架构的知识,推荐大家阅读[9],该书讲解了Windows系统架构的知识,同时这本书的一些知识同样可以应用到Vista系统上。在该文档公布时Vista系统还在测试阶段,但Vista在后来版本的安全性方面又做了一些改动。我们希望Vista在最终的发布版本上有更多的改变,同时我们也计划继续对未来的Vista版本的内核改动进行研究。
  Windows Vista Boot 管理
  Windows Vista支持从PC/AT BIOS和Intel新的EFI(可扩展固件接口)启动。我们的分析过程忽略了EFI部分。在本章节的最后部分,引用了bootmgr入口点的开始指令(DllMail为EFI的入口点指令,offset 0为PC/AT的入口点指令)这个过程从Vista启动管理器开始,定位%SystemDrive%\bootmgr 文件 (for PC/AT legacy BIOS)或%SystemDrive%\Boot\EFI\bootmgr.efi (for EFI BIOS)。Vista Boot Manager是启动Vista的必须环节,但也适用于启动Windows Vista之前的Windows版本。
  Vista Boot Manager首先调用InitializeLibrary,然后依次调用BlpArchInitialize (GDT, IDT, etc.), BlMmInitialize (memory management), BlpFwInitialize (firmware=固件?), BlpTpmInitialize (TPM), BlpIoInitialize (file systems), BlpPltInitialize (PCI configuration), BlBdInitialize (debugging), BlDisplayInitialize, BlpResourceInitialize (finds its own .rsrc section), and BlNetInitialize。
  在Vista系统内,Windows传统的boot.ini配置文件已经被启动配置数据文件(BCD)所代替,Vista下该文件位于%SystemDrive%\Boot\BCD,该文件也是注册表的值(在Vista下被挂载在HKEY_LOCAL_MACHINE\BCD00000000下)。可以使用bcdedit.exe来查看该文件的内容。
  一个典型的Boot Manager的BCD配置文件如下:
  Windows Boot Manager
  Identifier: {bootmgr}
  Type: 10100002
  Device: partition=C:
  Description: Windows Boot Manager
  Locale: en-US
  Inherit options: {globalsettings}
  Boot debugger: No
  Pre-boot EMS Enabled: No
  Default: {current}
  Resume application: {3ced334e-a0a5-11da-8c2b-cbb6baaeea6d}
  Display order: {current}
  Timeout: 30
  如果只有一个启动入口在BCD文件内,启动管理器会直接从该入口启动。如果多于一个启动入口,Boot Manager会给用户一个可选择的列表,并提示用户选择启动那个OS。如果启动阶段激活了日志记录,启动管理器会把状态信息写入%SystemDrive%\Boot\bootstat.dat文件内(通过BmpInitializeBootStatusDataLog)。紧接着启动管理器会使用BlResourceFindHtml把bootmgr.xsl定位在资源节点,而后把它传给BlXmiInitialize。bootmgr.xsl文件控制启动菜单和位于启动菜单的选项。
  如果启动列表的某个条目被选择,跟随BmpTransferExecution之后,将使用BmpLaunchBootEntry对该条目进行加载。BmpTransferExecution将重新找回启动选项(通过BlGetBootOptionString)并把他们交给BlImgLoadBootApplication。如果FVE(Full Volume Encryption)被激活,BlFveSecureBootUnlockBootDevice和 BlFveSecureBootCheckpointBootApp将被调用。由于Windows分区被加密,必须在把控制权交给Vista OS Loader前对分区进行解密。
  最后,Boot Manager调用BlImgStartBootApplication把控制权交给Vista OS Loader。
  Windows Vista系统载入
  bootmgr调用了位于%SystemRoot%\System32\WINLOAD.EXE下的Vista OS Loader。WINLOAD.EXE替换了NTLDR(Windows NT OS Loader),该小节的最后部分,会引用WINLOAD.EXE在开始入口点(OslMain)的指令。
  A typical BCD entry for the Windows Vista OS Loader looks like this:
  一个典型的Vista OS Loader的BCD入口配置文件如下:
  Windows Boot Loader
  Identifier: {current}
  Type: 10200003
  Device: partition=C:
  SYMANTEC ADVANCED THREAT RESEARCH 3
  Path: \Windows\system32\WINLOAD.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%\Boot\bootstat.dat (通过 OslpInitializeBootStatusDataLog和OslpSetBootStatusData)。接下来WINLOAD.EXE调用OslDisplayInitialize,并使用BlResourceFindHtml定位osloader.xsl所在的资源节点。控制权转交给BlXmiInitialize。在系统启动过程中osloader.xsl控制着高级启动选项。在操作完高级启动选项(使用OslDisplayAdvancedOptionsProcess),WINLOAD.EXE现在就准备开始启动。启动阶段首先会使用BlDeviceOpen打开启动设备。根据设备类型,BlDeviceOpen会使用不同的设备函数集来打开设备。
  For Full Volume Encryption (_FvebDeviceFunctionTable) these are:
  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%\System32\CatRoot\{F750E6C3-38EE-11D1- 85E5-00C04FC295EE}\nt5.cat加载OS的编目录(在内部调用了API函数MinCrypL_AddCatalog)。
  当OS 编目录 nt5.cat被加载后,WINLOAD.EXE通过SelfIntegrityCheck对其自身进行完整性检查,这里的检查做了两个事情:
  1. 计算PE映像(image)的SHA1哈希值,然后与PE证书表内的SHA1哈希值进行对比,这里的对比必须是匹配的,如果不匹配就会返回一个错误信息。
  2. 调用ImgpValidateImageHash来验证映象(image)哈希值是否与nt5.cat内的相匹配。ImgpValidateImageHash会调用API函数MinCrypL_CheckSignedFile来验证证书,调用MinCrypL_CheckImageHash来寻找nt5.cat上的映象(image)匹配哈希值。在下面的章节III会讨论通过MinCrypL_CheckSignedFile和 MinCrypL_CheckImageHash进行驱动签名验证。
  如果上述的签名过程不匹配,但是调试器在开启状态(BlBdDebuggerEnabled returns TRUE),那么在这里会打印处如下的调试信息:
  ---------------------------------------------
  *** Windows is unable to verify the signature of the file %s.
  It will be allowed to load because the boot debugger is enabled.
  Use g to continue!!
  ---------------------------------------------
  如果调试器是存在的,那么可以通过调用DbgBreakPoint来进行激活;另外,在这里通过调用ReportCodeIntegrityFailure替换了系统提示致命错误的错误形式。
  当所有的完整性检查结束后(unless all integrity checks have been disabled),OslInitializeCodeIntegrity会返回成功状态,然后会继续从OslMain开始执行。接着,OslpLoadAllModules被调用并开始加载系统模块。首先,会调用OslLoadImage来加载NTOSKRNL.EXE和HAL.DLL,在这里仅仅是加载,此时没有解决Imports;第二,如果内核调试被开启,调试驱动会依靠启动调试选项的情况被加载(kdcom.dll for serial port, kd1394.dll for IEEE1394, or kdusb.dll for USB)。第三,NTOSKRNL.EXE的Imports被加载和初始化(使用LoadImports和BindImportRefences函数)。
  OslLoadImage调用GetImageValidationFlags来检查在LoadBootImagesTable中预先定义好的boot drivers文件名。如果启用了完整性检查,除非在这里调试器被开启,否则boot drivers必须进行可信任的root权威签名,并且所有的映象哈希值(image hashes)要与编目录签名相匹配。在上面提到调试器开启状态会使该处的完整性检查有些许不同,如果在这里调试器是开启的,WINLOAD.EXE不会强烈要求上面的要求。WINLOAD.EXE会打印一个错误信息给调试器,但是却忽略了代码完整性检查的失败。无论如何,接下来的boot drivers(参考附录A)必须通过代码完整性检查,即使调试器在开启状态也必须检查。(如果没有进行检查,vista不会被启动起来):
  \Windows\system32\bootvid.dll
  \Windows\system32\ci.dll
  \Windows\system32\clfs.sys
  \Windows\system32\hal.dll
  \Windows\system32\kdcom.dll (or kd1394.sys or kdusb.dll, depending on boot options)
  \Windows\system32\ntoskrnl.exe
  \Windows\system32\pshed.dll
  \Windows\system32\WINLOAD.EXE
  \Windows\system32\drivers\ksecdd.sys
  \Windows\system32\drivers\spldr.sys
  \Windows\system32\drivers\tpm.sys
  加载映象和验证代码完整性都在BlImgLoadPEImageEx内,都使用了SelfIntegrityCheck(在前面章节有描述)函数。所有的映象(image)都通过代码完整性校验后,NTOSKRNL.EXE和它所有的Imports此时会被加载。列表(版本:Build 5363)如下:
  \Windows\system32\NTOSKRNL.exe
  \Windows\system32\HAL.dll
  \Windows\system32\PSHED.dll
  \Windows\system32\BOOTVID.dll
  \Windows\system32\CLFS.SYS
  \Windows\system32\CI.dll
  接下来使用OslHiveFindDrivers查找所有的boot drivers,并且根据组(which is ordered according to HKEY_LOCAL_MACHINE\CurrentControlSet\Control\Group OrderList)和标记(an integer which determines each driver's order within its respective group)对他们进行分类。这个分类好的boot drivers列表通过OslLoadDrivers进行加载。OslLoadDrivers为列表中的每个驱动调用LoadImageEx。LoadImageEx将会加载每个驱动及相关信息。
  此时,剩余的boot drivers也被加载和初始化。列表如下(按照年月日排列,64位Vista):
  1. \Windows\system32\drivers\Wdf01000.sys
  2. \Windows\system32\drivers\WDFLDR.SYS
  3. \Windows\system32\drivers\acpi.sys
  4. \Windows\system32\drivers\WMILIB.SYS
  5. \Windows\system32\drivers\msisadrv.sys
  6. \Windows\system32\drivers\pci.sys
  7. \Windows\system32\drivers\volmgr.sys
  8. \Windows\system32\drivers\isapnp.sys
  9. \Windows\system32\drivers\mpio.sys
  10. \Windows\system32\drivers\compbatt.sys
  11. \Windows\system32\drivers\BATTC.SYS
  12. \Windows\System32\drivers\mountmgr.sys
  13. \Windows\system32\drivers\intelide.sys
  14. \Windows\system32\drivers\PCIIDEX.SYS
  15. \Windows\system32\drivers\pcmcia.sys
  16. \Windows\system32\drivers\aliide.sys
  17. \Windows\system32\drivers\amdide.sys
  18. \Windows\system32\drivers\cmdide.sys
  19. \Windows\system32\drivers\msdsm.sys
  20. \Windows\system32\drivers\pciide.sys
  21. \Windows\system32\drivers\viaide.sys
  22. \Windows\System32\drivers\volmgrx.sys
  23. \Windows\system32\drivers\atapi.sys
  24. \Windows\system32\drivers\ataport.SYS
  25. \Windows\system32\drivers\hpcisss.sys
  26. \Windows\system32\drivers\storport.sys
  27. \Windows\system32\drivers\adp94xx.sys
  28. \Windows\system32\drivers\adpu160m.sys
  29. \Windows\system32\drivers\SCSIPORT.SYS
  30. \Windows\system32\drivers\adpu320.sys
  31. \Windows\system32\drivers\djsvs.sys
  32. \Windows\system32\drivers\arc.sys
  33. \Windows\system32\drivers\arcsas.sys
  34. \Windows\system32\drivers\elxstor.sys
  35. \Windows\system32\drivers\i2omp.sys
  36. \Windows\system32\drivers\iirsp.sys
  37. \Windows\system32\drivers\iteraid.sys
  38. \Windows\system32\drivers\lsi_fc.sys
  39. \Windows\system32\drivers\lsi_sas.sys
  40. \Windows\system32\drivers\lsi_scsi.sys
  41. \Windows\system32\drivers\megasas.sys
  42. \Windows\system32\drivers\mraid35x.sys
  43. \Windows\system32\drivers\msahci.sys
  44. \Windows\system32\drivers\nfrd960.sys
  45. \Windows\system32\drivers\ql2300.sys
  46. \Windows\system32\drivers\ql40xx.sys
  47. \Windows\system32\drivers\sisraid2.sys
  48. \Windows\system32\drivers\sisraid4.sys
  49. \Windows\system32\drivers\symc8xx.sys
  50. \Windows\system32\drivers\sym_hi.sys
  51. \Windows\system32\drivers\sym_u3.sys
  52. \Windows\system32\drivers\vsmraid.sys
  53. \Windows\system32\drivers\fltmgr.sys
  54. \Windows\system32\drivers\fileinfo.sys
  55. \Windows\system32\drivers\ndis.sys
  56. \Windows\system32\drivers\msrpc.sys
  57. \Windows\system32\drivers\NETIO.SYS
  58. \Windows\System32\Drivers\Ntfs.sys
  此时,所有的boot drivers被加载(参考附录B,完整的boot drivers列表)。接下来,调用OslpLoadNlsData从注册表项HKEY_LOCAL_MACHINE\CurrentControlSet\Control\NLS加载操作系统的语言版本。最后调用OslpLoadAllModules做了下面的几个事情:
  1. 显示Vista启动过程中的进度条。
  2. 加载%SystemRoot%\AppPatch\drvmain.sdb(the application compatability database)
  3. 加载%SystemRoot%\System32\acpitabl.dat
  4. 加载HKEY_LOCAL_MACHINE\CurrentControlSet\Control\Errat a\InfName注册表项的INF文件。
  在OslpLoadAllModules结束后,OslMain保存启动日志(OslpLogSaveInformation),如果FVE(Full Volume Encryption)选项开启,结束FVE的加载(BlFveSecureBootRestrictToOne and BlTpmShutdown)。最后,调用OslArchTransferToKernel把控制权转交给NTOSKRNL.EXE。
  Vista Windows OS Kernel
  Vista使用了与先前版本一样的名门惯例。64位Vista会在%SystemRoot%\System32\ntoskrnl.exe查找NTOSKRNL.EXE,在本章节的剩余部分,会引用ntoskrnl.exe在开始入口点的操作指令(KiSystemStartup)。
  执行首先从KiSystemStartup开始。Vista下的NTOSKRNL.EXE内的一些重要部分与Windows 2003 SP1版相比,并没有太多的改变,因此我们的重点为分析Vista下改变的特殊部分。在Vista下,NTOSKRNL.EXE添加了一个新函数SepInitializeCodeIntegrity,但该函数仅仅是把CL.DLL内的CiInitialize(关于CiInitialize会在后面的章节VI进行讨论)进行了另外的包装而已。如果代码完整性检查开启,SepInitializeCodeIntegrity会调用CiInitialize,除此之外,它没有做任何其它的事情。
  WINLOAD.EXE还负责检查boot drivers签名的完整性。与WINLOAD.EXE相比,NTOSKRNL.EXE负责查证system drivers(在boot driver加载后)和运行时加载的drivers(即:当一个设备被插进系统)。当完整性检查开启,会使用SeValidateImageHeader(在CI.DLL内CiValidateImageHeader函数的包装)和SeValidateImageData(在CI.DLL内CiValidateImageData函数的包装)对加载的映象(image)进行代码完整性检查。只要一个执行映射进kernel memeory都会调用SeValidateImageHeader(通过MmCreateSection)。当一个内核模块加载时,都会调用SeValidateImageData对kernel drivers的代码段进行校验。运行时检查(例如:不断的检查kernel drivers的代码段是否被修改)由PatchGuard和CI.DLL进行处理(会在后面部分讨论)。
  Vista/WIN7驱动完整性校验解析PE蓝屏BUG
  在VISTA 和WINDOWS 7 (ALL SP,全补丁)的内核代码完整性校验组件中,存在一处解析PE的BUG,可引发系统蓝屏。不过从现在看来,此问题似乎需要LoadDriver权限才能触发,因此不能算安全性问题,属于稳定性问题。
  在VISTA以后的操作系统,系统使用MmLoadSystemImage加载驱动之前,会调用MmCheckSystemImage函数来检查镜像正确性,在VISTA及以后的操作系统中,MmCheckSystemImage发生了一个有意思的变化.
  原本MmCheckSystemImage(vista以前的系统上),会使用SEC_IMAGE作为AllocationAttributes来调用ZwCreateSection为驱动文件创建Section,但是VISTA以后的系统上,该参数被换成了一个未公开的值: 0x100000(注意,SEC_IMAGE是0x1000000,6个0)。
  在ZwCreateSection 中,系统会检查如果调用线程的上个模式不是KernelMode,则不允许使用这个未公开的AllocationAttributes:
  NtCreateSection:
  ............无关部分........
  //取当前线程上个模式
  if (KeGetPreviousMode() != KernelMode)
  {
  //如果是用户模式,如果Attributes有0x2000000或0x10000的话,则返回无效参数
  v13 = 0;
  if ( !(Attributes & 0x2100000) )
  {
  .....无关处理....
  }
  return STATUS_INVALID_PARAMETER_6;
  }
  然后在NtCreateSection->MmCreateSection(这个函数在VISTA开始发生了巨大的变化)中,进行一些判断后(包括这个特殊的Attributes),系统会调用MiValidateImageHeader进行镜像检查,此时系统会将这个镜像通过MiMapImageInSystemCache函数map到系统缓存中,然后将按镜像的页数 * PAGE_SIZE大小的,分配分页内存,并将PE数据COPY到内存中
  接着系统会调用SeValidateImageHeader函数,这个函数只是简单地为_g_CiCallbacks中存放的函数准备函数,便调用_g_CiCallbacks存放的函数。_g_CiCallbacks这个全局变量中存放着系统初始化时(SeInitSystem->SepInitializationPhase1->SepInitialize CodeIntegrity)存入的 ci.dll的CiValidateImageHeader函数。
  CiValidateImageHeader首先会对镜像进行一些检查工作,然后开始调用CipValidateFileHash函数,CipValidateFileHash函数对文件做一些解析工作后,开始调用CipImageGetImageHash,此函数会分析PE的每一个节,并对其节内数据调用SHA签名算法函数A_SHAUpdate。
  注意前面加粗的文字,由于是按整页数来分配和COPY数据的,因此如果某一个节的数据长度(SizeOfRawData)超出了页对齐的范围(MiMapImageInSystemCache似乎并不将这个数据算成一个新的节),那么A_SHAUpdate中的数据COPY函数将触及到未分配内存,从而引发BSOD。
  这里提供一个简单的例子, bsodxx.rar
  这个PE文件的最后一个节的SizeOfRawData为0x1004
  使用任意一个加载工具加载此文件,系统将立即BSOD,BSOD时的Stack类似:
  kd> kc
  nt!MmAccessFault
  nt!KiTrap0E
  nt!memcpy
  CI!A_SHAUpdate
  CI!CipImageGetImageHash
  CI!CipValidateFileHash
  CI!CiValidateImageHeader
  nt!SeValidateImageHeader
  nt!MiValidateImageHeader
  nt!MmCreateSection
  nt!NtCreateSection
  nt!KiFastCallEntry
  nt!ZwCreateSection
  nt!MmCheckSystemImage
  nt!MiCreateSectionForDriver
  nt!MiObtainSectionForDriver
  nt!MmLoadSystemImage
  nt!IopLoadDriver
  nt!IopLoadUnloadDriver 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics