二进制文件签名是执行前强制验证来源与完整性的机制,需精确哈希.text/.rodata/.dynamic等关键节,嵌入.signatures节并由内核IMA+evm在execve时校验,配合Secure Boot、只读挂载与私钥硬件保护实现纵深防御。

对系统二进制文件签名,本质是让操作系统在加载执行前验证其来源和完整性。只要签名验证失败,程序就无法运行——这不是“事后检测”,而是执行前的强制拦截。
签名必须覆盖关键可执行段
不是给整个文件打个包签名就行。ELF格式中,真正决定行为的是 .text 节(代码段) 和部分 .dynamic/.init_array 等控制节。签名工具(如 elf-sign)需精确提取这些区域计算哈希,排除签名自身所在节(如 .signature),否则会形成自循环验证漏洞。
- 推荐做法:只哈希 .text + .rodata(只读数据)+ .dynamic,忽略 .data/.bss 等可变区域
- 错误做法:对整个文件做 SHA256 —— 一旦签名写入文件尾部,哈希值就失效
- 内核验证时也按同样范围重新计算哈希,再与签名中解密出的摘要比对
签名要嵌入文件且不破坏可执行性
签名不能改写原有代码或破坏 ELF 加载结构。主流方案是在文件末尾追加自定义节区(如 .signature),或复用未使用的节头表空位。
- 新增节区需设置正确标志:SHF_ALLOC=0(不加载进内存)、SHF_WRITE=0(不可写)
- 节头表要更新:增加新节描述项,并调整 e_shnum、e_shoff 等头部字段
- 签名内容包含算法标识(如 ECDSA-SHA256)、公钥指纹、签名本身及长度字段,便于验证端解析
验证必须由可信环境完成
签名本身不防篡改,防篡改靠的是验证环节的不可绕过性。Linux 内核从 5.15 起支持 IMA(Integrity Measurement Architecture)+ evm(Extended Verification Module),配合内核编译时嵌入的公钥,可在 execve 系统调用入口处自动校验。
- 启用 CONFIG_IMA_APPRAISE 和 CONFIG_EVM 后,内核会拒绝加载未签名或签名无效的二进制
- 公钥必须固化在内核镜像中(而非用户空间配置),防止被 root 用户替换
- 若使用模块化签名(如基于 LSM 的 verifier),需确保该模块无法被 rmmod 卸载
配套机制堵住绕过路径
仅签名还不够。攻击者可能跳过验证逻辑、替换验证模块、或直接 patch 内核。需组合防御:
- 启用 Secure Boot:确保启动链可信,防止恶意内核或 initramfs 加载
- 锁定 sysctl 参数:如 kernel.modules_disabled=1、vm.unprivileged_userfaultfd=0,减少攻击面
- 使用只读挂载 /usr/bin 和 /lib:配合签名,使篡改后文件甚至无法写入磁盘
- 对签名私钥严格管控:离线保存、硬件加密模块(HSM)保护,避免泄露导致批量伪造
















