Windows 驱动实例分析系列:libwdi 驱动分析 - libwdi 篇(五)

子文档五:PKI 签名模块(pki.c)

pki.c 是 libwdi 中最复杂的模块之一,它负责创建自签名证书、安装证书到系统存储、生成 CAT 文件以及对其进行 Authenticode 签名。该模块依赖 Windows CryptoAPI 和 MSSign32,实现了完整的代码签名流程。

自签名证书的创建与安装

CreateSelfSignedCert 函数执行以下步骤:

  1. 获取密钥容器 :调用 CryptAcquireContext 创建一个名为 libwdi key container 的密钥容器(若已存在则打开),并生成一个 4096 位的 RSA 密钥对(CryptGenKey,AT_SIGNATURE)。
  2. 设置主题名称 :通过 CertStrToNameA 将主题字符串(如 CN=USB\VID_1234&PID_5678 (libwdi autogenerated))编码为 ASN.1 格式。
  3. 配置证书扩展 :
    • 增强密钥用法(EKU) :设置为代码签名(1.3.6.1.5.5.7.3.3),且标记为关键(fCritical=TRUE),确保证书只能用于代码签名。
    • 主题备用名称(SAN) :添加一个 RFC822 名称 Created by libwdi (http://libwdi.akeo.ie),用于标识。
    • 证书策略 :包含 CPS(Certification Practice Statement)指针 http://libwdi-cps.akeo.ie,使证书在 Windows 中显示"颁发者声明"按钮。
  4. 创建证书 :调用 CertCreateSelfSignCertificate,指定签名算法(Windows 7 使用 SHA-1,Windows 8+ 使用 SHA-256),有效期至 2029 年。
  5. 安装证书 :AddCertToStore 将证书添加到本地机器的 Root 和 TrustedPublisher 存储区,使得系统信任该证书签署的任何驱动。

CAT 文件生成

CreateCat 函数创建目录文件(.cat),其流程:

  1. 调用 CryptCATOpen 创建 CAT 文件(CRYPTCAT_OPEN_CREATENEW)。
  2. 添加全局属性:HWID(硬件 ID,如 USB\VID_1234&PID_5678)和 OS(操作系统版本列表,如 7_X86,7_X64,...)。
  3. 对于文件列表中的每个文件(由 CAT 模板提供),计算其 SHA-1 哈希(CryptCATAdminCalcHashFromFileHandle)。
  4. 调用 CryptCATPutMemberInfo 将文件哈希作为成员添加到 CAT 中,指定成员类型(PE 文件或 INF/CAB 文件)。
  5. 添加成员属性:File(文件名)和 OSAttr(操作系统属性,如 2:5.1,2:5.2,...)。
  6. 调用 CryptCATPersistStore 将 CAT 数据写入磁盘。

签名与密钥销毁

SelfSignFile 函数对 CAT 文件进行 Authenticode 签名:

  1. 调用 SignerSignEx,传入自签名证书句柄,指定 SHA-256 算法,添加 Authenticode 扩展属性(SPC_SP_OPUS_INFO_OBJID 和 SPC_STATEMENT_TYPE_OBJID)。
  2. 签名成功后,调用 DeletePrivateKey:通过 CryptAcquireCertificatePrivateKey 获取私钥句柄,然后调用 CryptAcquireContext 配合 CRYPT_DELETEKEYSET 删除密钥容器。
  3. 删除私钥至关重要:防止恶意攻击者利用残留的私钥对其他文件进行签名,从而绕过安全措施。

证书安装到受信任发布者

AddCertToTrustedPublisher 函数用于将外部证书(如嵌入的 .cer 文件)安装到 TrustedPublisher 存储区。它首先检查证书是否已存在,若不存在且用户确认(disable_warning 为 FALSE 时弹出警告对话框),则添加证书。该函数在 wdi_install_trusted_certificate API 中被调用。

依赖的 DLL

pki.c 动态加载 Crypt32.dll、MSSign32.dll 和 WinTrust.dll,通过 GetProcAddress 获取所需函数指针,避免静态链接这些系统库,增加兼容性。

错误处理

所有 PKI 操作均检查返回值,失败时调用 winpki_error_str 将错误码转换为可读字符串,并通过 wdi_warn/wdi_err 输出日志。


相关推荐
Funlang2 小时前
在 Windows 95 上跑 Fun
windows
ö Constancy7 小时前
一台电脑的硬件组成与作用:按功能分类详解(Windows 与 Linux 视角)
linux·windows·电脑
雪落漂泊1 天前
Liunux进程(七):程序控制篇(中)
linux·运维·windows
承渊政道2 天前
Fooocus本地AI绘图教程:Windows部署、低门槛生图与远程访问
人工智能·windows·cpolar·fooocus·生图
陈工大模型2 天前
收到乱码压缩包之后,我重新测了 7-Zip、Bandizip 和win解压缩
windows·电脑·软件工程·软件需求·7-zip
谙弆悕博士2 天前
在文件夹右键直接打开 Kali WSL:一条 `wsl --cd` 注册表脚本
windows·脚本·wsl·右击·ksli
陈工大模型2 天前
解压工具的三个技术分水岭:编码、分卷、容器格式
人工智能·windows·安全·解压工具·免费国内办公软件
Zucker n3 天前
文献发现、课题组织与证据可追溯的论文阅读。
论文阅读·windows·ubuntu
flyingonpine4 天前
PowerShell脚本数字签名实战:自签名证书、代码签名与信任链验证
windows·信任链
goehou4 天前
让 AI 替我操作这台电脑,先把手能伸多远定下来
windows·自动化·权限管理·ai agent