驱动强制签名(一)

😄

1 PE 文件签名概述

1.1 代码签名

代码签名(Code Signing Certificates):代码签名证书主要用于软件开发者对各种软件和代码进行数字签名,不仅能证明代码的开发者真实身份,而且能确保用户通过互联网下载时能确信此代码没有被非法篡改和来源可信,从而保护了代码的完整性、保护了用户不会被病毒、恶意代码和间谍软件所侵害,当然也就保护了软件开发商的利益,使得软件开发商能安全地快速地通过网络发布软件。

代码签名证书主要分为两类:

  1. 标准代码签名证书:标准代码签名(OV)只需要验证申请企业的基本信息、税务信息,验证成功后通过邮件等形式通常针对 32/64 位应用程序进行签名,以防止各类杀毒软件的误报。仅需较短的处理时间及较低的成本,但无法用于 LSA 和 UEFI 文件签名、无法用于内核模式驱动程序。
  2. EV 扩展型代码签名证书:EV 扩展型代码签名证书除了验证企业的基本信息、税务信息外,还会对企业的经营地址、申请人身份进行审查,区别于标准代码签名的重要特点是支持 Windows 10 内核驱动文件签名和消除 SmartScreen 筛选器安全提醒,此外 EV 代码签名针对内核模式的驱动文件需要进行微软的交叉签名。 这里需要注意,驱动文件要用EV证书进行签名才可以用。

没有代码签名和有代码签名的区别在哪里? 以微软代码签名为例,当用户在Windows系统上下载、安装、运行没有代码签名的软件或程序时,会被系统阻止,并提示用户“未知发布者”的安全警告。 如使用了 EV 代码签名证书,下载、安装、运行时会显示开发者名称,让用户知道该软件的合法而且能立即获得微软SmartScreen的信誉,消除SmartScreen弹出提示。如图所示。

3.jpeg

1.2 驱动强制签名

驱动强制签名策略是从 Windows Vista 开始的,加载的驱动如果没有微软/合法的第三方数字签名,系统无法加载驱动。从 Windows 1607 开始,驱动在合法第三方数字签名的基础上,还必须获得微软 WHQL(WindowsHardware Quality Labs,Windows 硬件设备质量实验室)的认证才能够被系统加载。

如下图引自《Kernel Mode Threats And Practical Defense》。

1.png

关于 WHQL:

WHQL 认证,也称为 Windows 徽标计划,是由微软设立的针对第三方驱动程序进行的测试认证,通过使用微软的测试平台对设备和驱动进行严格的测试,旨在确保硬件设备和驱动程序的可靠性和兼容性。通过 WHQL 认证的硬件产品可以获得使用“Designedfor Windows”徽标的资格,并列入 Windows 硬件兼容性列表(HCL)和 Windows 目录。WHQL 签名可以在线签也可以下载 Windows HLK (硬件实验室工具包) 进行签名。

  1. 驱动必须先通过第三方 EV 签名,才能去申请 WHQL 签名。
  2. WHQL 实际上就是一个驱动安全性及其他一些安全动态检查运行认证平台,驱动认证通过后,就会给驱动打上微软认证的签名。

2015 年 10 月 31 日起 Windows 10(10240.16590)中普通代码签名证书无法用于内核模式驱动签名,必须用 EV 代码签名证书签名。

2016 年 8 月 1 日起 Windows 10(14393.10)还没有签名的驱动,除了必须有 EV 代码证书签名,还必须获取微软 WHQL 签名。

从微软 Driver Signing Policy 了解到,以下三种场景,驱动程序即使只有合法第三方数字签名(没有WHQL认证签名)也可以在 Windows 1607 及以后的系统加载:

  1. 系统是从早前的版本升级到 Windows 1607 的。
  2. 在 BIOS 中 关闭安全启动。
  3. 驱动程序使用 2015 年 7 月 29 日之前颁发的最终实体证书进行签名的,可以在后续 Windows 10 上加载(为了兼容老旧驱动)。

2.png

1.3 安全启动

Rootkit

Rootkit 是一种复杂且危险的恶意软件。 它们在内核模式下运行,使用与 OS 相同的权限。 由于 rootkit 与 OS 具有相同的权限并在其之前/后启动,因此它们可以完全隐藏自身和其他应用程序。 通常,rootkit 是整套恶意软件的一部分,可以绕过本地登录、记录密码和按键、传输私有文件以及捕获加密数据。

不同类型的 rootkit 在启动过程的不同阶段中进行加载:

  • 固件 rootkit(Firmware rootkits)。 这些工具包覆盖电脑的基本输入/输出系统或其他硬件的固件,因此 rootkit 可以在 Windows 之前启动。
  • Bootkit。 这些工具包取代了操作系统的启动加载程序, 以便电脑在 OS 之前加载引导工具包的小型软件。
  • 内核 rootkit(Kernel rootkits)。 这些工具包替换了 OS 内核的一部分,因此在 OS 加载时,rootkit 可以自动启动。
  • 驱动程序 rootkit(Driver rootkits)。 这些套件假装成 Windows 与电脑硬件进行通信所使用的其中一款受信任的驱动程序。

为了应对 Rootkit 攻击,微软在系统启动过程中使用以下四项保护:

  1. 安全启动(Secure Boot):可以将具有 UEFI 固件和受信任的平台模块 (TPM) 的电脑配置为仅加载受信任的 OS 启动加载程序(OS Loader)。
  2. 受信任的启动(Trusted Boot):Windows 先检查启动过程的每个组件的完整性,然后再加载组件(主要是系统相关的内核模块)。
  3. 开机初期启动的反恶意软件 (Early Launch Anti-Malware, ELAM):ELAM 先测试所有驱动程序然后再进行加载,并且会阻止加载未经批准的驱动程序。
  4. 测量的启动(Measured Boot):电脑的固件记录启动过程,Windows 可以将它发送到可客观评估电脑运行状况的受信任服务器(联网)。

4.png

启动阶段 描述 备注
安全启动 配备有 UEFI 的电脑启动时,电脑首先验证固件是否经过了数字签名,从而减少了固件 rootkit 风险。 如果启用了安全启动,固件将检查 OS 引导加载程序的数字签名,以验证它是否已修改。 如果启动加载程序未被改动,则只有满足以下条件之一时,固件才会启动此启动加载程序:
1、使用受信任证书对启动加载程序进行了签名。 对于经过 Windows 认证的电脑,Microsoft证书是受信任的。
2、用户已手动批准启动加载程序的数字签名。 此操作允许用户加载非Microsoft操作系统。
所有基于 x86 的 Windows 电脑认证都必须满足与安全启动相关的几个要求:
1、默认情况下,电脑必须启用安全启动。
2、电脑必须信任 Microsoft 的证书 (因此任何启动加载程序都已通过 Microsoft 签名。
3、必须允许用户将电脑安全启动配置为信任其他启动加载程序。
4、必须允许用户彻底禁用安全启动。
=======================
可以使用以下三个选项来运行非 Microsoft 操作系统:
1、将 OS 与经过认证的引导加载程序配合使用。 由于所有经 Windows 认证的电脑都必须信任Microsoft的证书,Microsoft会提供一项服务来分析和签署任何非Microsoft引导加载程序,以便所有 Windows 认证电脑都信任它。
2、将 UEFI 配置为信任自定义的启动加载程序。 所有经 Windows 认证的电脑都允许你通过向 UEFI 数据库添加签名来信任未经认证的引导加载程序,从而允许运行任何 OS,包括自制操作系统。
3、关闭安全启动。 所有经 Windows 认证的电脑都允许关闭安全启动,以便可以运行任何软件。 但是,此操作无助于保护你免受启动工具包的防护。
受信任的启动 受信任的启动接管安全启动结束的位置。启动加载程序将先验证 Windows 10 内核的数字签名,然后再加载它。 而 Windows 10 内核将验证 Windows 启动过程的每一个其他组件,包括启动驱动程序、启动文件和 ELAM。 如果文件已被修改,则启动加载程序会检测到问题并拒绝加载损坏的组件。 通常,Windows 可以自动修复损坏的组件、还原 Windows 的完整性并允许电脑正常启动。
开机初期启动的反恶意软件 因为安全启动已经保护了启动加载程序,受信任启动已经保护了 Windows 内核,所以恶意软件启动的下一个机会就是感染非 Microsoft 启动驱动程序。 传统的反恶意软件应用直到加载启动驱动程序后才会启动,这让伪装成驱动程序的 rootkit 有机会工作。 开机初期启动的反恶意软件 (ELAM) 可以在所有非 Microsoft 启动驱动程序和应用程序之前加载 Microsoft 或非 Microsoft 反恶意软件驱动程序,因此可以继续形成安全启动和受信任启动所建立的任信链。 由于操作系统尚未启动,并且 Windows 需要尽快启动,ELAM 有一个简单的任务:检查每个启动驱动程序,并确定它是否在受信任的驱动程序列表中。 如果它不受信任,Windows 不会加载它。
测量的启动 测量启动适用于 Windows 中的 TPM 和非Microsoft软件。 它允许网络上的受信任服务器验证 Windows 启动过程的完整性。 该启动最后验证失败,似乎不会影响系统的运行。因为系统有时是在断网的情况下启动的。

2 代码完整性

驱动强制签名(DSE)的实现只是内核代码完整性(Kernel Code Integrity)的一部分。

代码完整性的初始化、完整性校验逻辑存放在 ci.dll 中,包括镜像的完整性校验、数字签名校验等。

  • 在镜像被加载前静态 Patch 内核文件,镜像被加载时代码完整性校验不会通过,数字证书也会被破坏。
  • 镜像加载后,ntoskrnl.exe 中的关键数据会被 PatchGuard保护。其他重要的驱动会被内核数据保护(KDP)。
    • 部分只读内存是不允许修改属性的,因为有 VBS、HVCI 保护。

常用的两种禁用 DSE 的方式:

  1. HOOK CiValidateImageHeader 函数前几个字节,让其然后 STATUS_SUCCESS。文章说该函数代码不受 KDP 保护,且从之前的分析来看,应该也不受 PatchGuard 保护。

  2. 通过脆弱的驱动程序禁用DSE。这种方式是最常用的,就是在一个存在任意地址写的合法签名驱动程序中:

    • 如果漏洞任意地址读写任意多个字节数的内存,那么就直接内存加载驱动就行。
    • 如果任意地址读写一个字节或以上内存漏洞的驱动,可先将 g_CiOptions = 0,立刻加载恶意无签名的驱动,然后立即将 g_CiOptions 恢复,因为 g_CiOptions 受 PatchGuard 保护。

    5.png

DSE 初始化相关:

通过脆弱的驱动程序禁用DSE:

  1. 分析 DSE 相关
  2. ETW—软件调试2
  3. 对象管理,IO管理