程序员王马头像
关注
Windows 驱动实例分析系列:libwdi 驱动分析 - libwdi 篇(五)封面图

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 输出日志。


转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/m0_72813396/article/details/164094819

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--