如何检测文件曾存在但现已被移除的数字签名?
检测EXE文件曾绑定数字签名的可行方案
针对你描述的「带签名的EXE经记事本编辑后签名失效移除」的场景,可通过以下静态特征检测文件是否曾绑定数字签名,这类检测对非PE感知编辑器(比如记事本、普通文本编辑器)修改后的文件命中率接近100%:
- PE头安全目录项残留检测
Windows平台EXE采用PE格式规范,数字签名对应的配置存放在PE可选头DataDirectory数组的第5项(安全目录表),从未被签过名的原生编译EXE,该表项的RVA(相对虚拟地址)、大小字段值均为0。
用记事本修改EXE内容时,程序不会识别PE结构,更不会主动修正PE头里的签名配置字段,哪怕文件内容被改坏、签名校验失效,该字段的旧值大概率会留存。你可以用PE解析工具直接查看该字段值,只要非全0,就证明文件曾配置过数字签名。 - 文件尾部签名块特征检测
Windows Authenticode数字签名的内容整体追加在PE文件末尾,签名块有固定的格式特征:开头为WIN_CERTIFICATE结构,版本标识固定为0x00000200,类型标识固定为0x0002(对应PKCS#7签名数据格式),后续紧跟完整的证书链、签名哈希等PKCS结构内容。
用记事本编辑文件时,如果修改位置不在文件最末尾,尾部的签名块不会被完全覆盖,用十六进制编辑器搜索文件尾部的固定特征值,只要能匹配到签名结构片段,即可证明文件曾存在数字签名。
无需第三方工具的快速检测脚本(PowerShell):
$filePath = "待检测文件的完整路径\B.EXE" $fileStream = [System.IO.File]::OpenRead($filePath) $binaryReader = New-Object System.IO.BinaryReader($fileStream) # 定位PE头偏移 $fileStream.Position = 0x3C $peHeaderOffset = $binaryReader.ReadInt32() # 定位安全目录表项位置 $fileStream.Position = $peHeaderOffset + 4 + 20 + 96 + 128 $signDirRva = $binaryReader.ReadInt32() $signDirSize = $binaryReader.ReadInt32() $binaryReader.Close() $fileStream.Close() if ($signDirRva -ne 0 -or $signDirSize -ne 0) { Write-Output "检测结果:文件曾绑定过数字签名" } else { Write-Output "检测结果:未检测到历史签名残留" }
- 检测局限性说明
上述静态检测方法仅对未做PE结构清理的修改场景生效,如果文件被专门的PE编辑工具、签名擦除工具处理过(主动清零PE头安全目录项、完整擦除尾部签名块、覆写所有签名相关残留字节),静态特征会被清除,无法通过上述方法溯源。你当前测试场景用记事本编辑保存的文件,不会触发这类清理操作,完全可以被检测到。
内容的提问来源于stack exchange,提问作者insulina1994
相关产品推荐
相关产品推荐

