Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

基于虚拟化的安全(part1):引导过程 虚拟化 虚拟化安全 引导过程安全 网络安全

$
0
0

基于虚拟化的安全(part1):引导过程。本文是覆盖基于虚拟化的安全和设备保护功能的文章的一部分。这些文章的目的是从技术的角度分享这些功能以便更好的理解。这第一篇文章将涵盖系统引导过程,从windows bootloader到VTL0启动。

0x01 基于虚拟化的安全

基于虚拟化的安全(VBS)是微软Windows10和Windows Server2016的一个主要的安全特性。例如,DeviceGuard和CredentialGuard都依赖它。DeviceGuard允许系统阻止任何不受信任的程序。同时CredentialGuard允许系统隔离lsass.exe进程,以便阻止类似Mimikatz等工具内存读取密码。

这个新功能的主要思想是使用硬件虚拟化技术(例如Intel VT-x),以便在两个虚拟机(VM)之间实现强隔离,并且将来功能可能更丰富。这些技术允许虚拟机管理器(VMM)使用扩展页表(EPT)来对物理页设置不同的权限。换句话说,一个VM能够在它的页表入口(PTE)设置一个物理页可写(+W),并且VMM能够通过在它的EPT上设置适当的权限来授权或阻止这种行为。

基于虚拟化的安全依赖Hyper-V技术,其将产生不同虚拟信任等级(VTL)的虚拟机。Hyper-V包括一个hypervisor,并且任何操作系统,甚至主操作系统,都包含在VM中。这个主操作系统(Windows)被认为是根VM。Hyper-V信任它且接受像控制其他VM的管理命令。其他的VM可能是“开明的”,如果这样,则向Hyper-V发送受限消息以便他们自己管理。

VTL是有序号的,更高的是最受信任的。现在有两个VTL:

1. VTL0,是一个普通的环境,且基本包含标准的Windows操作系统。

2. VTL1,是一个安全的环境,且包含一个微内核和安全的应用程序,称为trustlet。


基于虚拟化的安全(part1):引导过程 虚拟化 虚拟化安全 引导过程安全 网络安全

图1 – 基于虚拟化的安全的概览

CredentialGuard安全机制使用这个技术在VTL1 trustlet(lsaiso.exe,上图中“Isolated LSA”)中隔离关键的lsass.exe进程,甚至使得VTL0内核不能访问它的内存。只有消息可以从VTL0转发到隔离的进程,有效的阻止了像Mimikatz这类的密码和哈希收集工具。

DeviceGuard安全机制使得VTL0内核地址空间的W^X内存缓解(物理页不能同时具有可执行和可写权限),并且接受包含授权代码签名者的策略。如果VTL0内核想要使一个物理页可执行,它必须请求VTL1来改变(图中的“HVCI”),它会根据策略校验签名。对于用户模式的代码,这不起作用,只有VTL0内核才请求签名验证。策略在引导启动时加载,且之后不能修改,只有强制用户重启才能加载新的策略。

策略也是被签名的:在这种情况下,授权签名者在UEFI变量中设置,且新的策略将校验这个签名者。UEFI变量设置他们的Setup和Boot标志,意味着在启动后他们将无法被访问和修改。为了清除这些变量,本地用户必须使用一个自定义的微软EFI bootloader重启,在用户交互操作(通过输入密码)后移除他们。

因此,VBS强依赖SecureBoot。引导加载器的完整性必须被校验,因为它负责加载策略、Hyper-V和VTL1等等。

如果你对设备保护的细节感兴趣,你能阅读这个MDSN的文章:https://blogs.technet.microsoft.com/ash/2016/03/02/windows-10-device-guard-and-credential-guard-demystified/。

我们也鼓励你阅读Alex lonescu和Rafal Wojtczuk的BlackHat 2015/2016的演讲,将有很大帮助:

http://www.alex-ionescu.com/blackhat2015.pdf

https://www.youtube.com/watch?v=LqaWIn4y26E

https://www.blackhat.com/docs/us-16/materials/us-16-Wojtczuk-Analysis-Of-The-Attack-Surface-Of-Windows-10-Virtualization-Based-Security.pdf

https://www.blackhat.com/docs/us-16/materials/us-16-Wojtczuk-Analysis-Of-The-Attack-Surface-Of-Windows-10-Virtualization-Based-Security-wp.pdf

https://www.youtube.com/watch?v=_646Gmr_uo0

本文中,我们将涵盖系统引导过程,从Windows bootloader到VTL0启动。为了分析VBS怎么在引导过程期间初始化自身,下面的Windows 10 1607的一些文件已经被逆向过了:

Bootmgr.efi:EFI引导加载器(一小部分)

Winload.efi:EFI Windows加载器

Hvix.exe:Hyper-V(相当小的一部分)

Ntoskrnl.exe:NTOS内核

Securekernel.exe:安全内核

Ci.dll:VTL0代码完整性

Skci.dll:VTL1代码完整性

因此让我们来深入到VBS引导过程中,从winload.efi的执行开始,到ntoskrnl.exe的入口点执行。

0x02 引导过程

引导过程可以总结为5个必须的步骤:

Bootmgr.efi是第一个加载的组件。由SecureBoot验证并执行

Bootmgr.efi加载并校验winload.efi

Winload加载并校验VBS配置

Winload加载并校验Hyper-V和VTL0/VTL1内核组件

Winload退出EFI模式,启动Hyper-V

Bootmgr.efi

当系统开始引导,bootmgr.efi是第一个被加载执行的。它的完整性和签名已经由Secure Boot UEFI代码校验过。为了能够识别过期的签名,DBX数据库包含了过期的签名(截至2016年底,这个数据库包含了71个黑名单和未知的SHA256的哈希值)。在bootmgr.efi的最后,执行将转到winload.efi的入口点:OslpMain/OslMain。

OslpMain首先调用OslpPrepareTarget,其是winload.efi的核心函数。它将初始化hypervisor,内核等。但是先会使用OslSetVsmPolicy初始化VBS配置。

VBS策略加载

OslSetVsmPolicy首先校验VbsPolicyDisabled EFI变量的值(参见下面的微软命名空间)。如果设置了,这个变量是0,意味着没有凭据保护配置将要加载。这个EFI变量因此将在引导时禁用凭据保护(并且能够在VTL0 ring3调用设置权限)。如果没有设置,配置将从SYSTEM注册表的hive中加载,并且由BlVsmSetSystemPolicy调用执行,其将读取和更新VbsPolicy EFI 变量。相应的值被存储到全局变量BlVsmpSystemPolicy中。如果UEFI锁开启,这个EFI变量被设置,并且不能通过winload.efi禁用(它不能移除它,只能使用自定义的EFI代码才能)。

函数OslpPrepareTarget也会调用OslpProcessSIPolicy(被调用两次,第一次直接从函数OslInitializeCodeIntegrity中调用)。OslpProcessSIPolicy使用3个EFI变量“pools”来校验SI策略签名。每个pool包含3个EFI变量,第一个包含策略,第二个包含版本,第三个包含授权的策略更新签名者。例如,对于C:\Windows\System32\CodeIntegrity\SIPolicy.p7b,变量是Si,SiPolicyVersion和SiPolicyUpdateSigners。如果“version”和“update signers”变量被设置,系统将增强SI策略签名:它必须是存在且正确的签名,否则引导将失败。通过BlSiPolicyIsSignedPolicyRequired函数来验证它自己。

3种策略和相关的变量总结如下:


基于虚拟化的安全(part1):引导过程 虚拟化 虚拟化安全 引导过程安全 网络安全

我们不确定“revokeSiPolicy”和“skuPolicy”的目的,但是他们似乎和普通的“SiPolicy”使用类似。

Hyper-V和内核组件的加载

执行将转移到OslArchHypervisorSetup函数,其需要使用与执行的步骤相应的参数来调用,从0开始。在第一次,它将初始化Hyper-V(加载hvloader.efi且通过HvlpLaunchHvLoader执行它)。SecureBoot设置通过OslInitializeCodeIntegrity来校验。

OslpPrepareTarget然后加载NTOS内核(ntoskrnl.exe),并且使用OslpLoadAllModules函数来加载hal.dll和mcupdate.dll模块。然后“Local Key”和“Identification Key”由OslVsmProvisionLKey和OslVsmProvisionIdk函数加载。

此时,NTOS内核初始化了但还没哟启动。以步骤“0”为参数的OslVsmSetup被调用(与OslArchHypervisorSetup一样:以“步骤”为参数),首先校验Hyper-V已经启动,然后初始化OslVsmLoaderBlock(参数在初始化期间由安全内核提供)。然后,OslVsmSetup加载安全内核(securekernel.exe),并且通过OslpVsmLoadModules函数加载它依赖的skci.dll(OslLoadImage再次被用来校验他们的签名)。EFI变量OslLoaderIndications第一位被设置为1。

最后,OslVsmSetup函数再次被调用,但是参数是步骤“1”。这个触发了OslVsmLoaderBlock的初始化。

当函数OslpPrepareTarget返回后,VBS参数已经被验证完了,并且NTOS和安全内核都被加载了。他们的入口点地址被存储在全局变量OslpVsmSystemStartup和OslEntryPoint中(securekernel.exe和ntoskrnl.exe)以便将来使用。

Viewing all articles
Browse latest Browse all 12749

Trending Articles