objcopy移除签名段后ELF二进制与原文件不一致问题求助
ELF二进制嵌入GPG签名后验证失败的问题解决
移除签名段后二进制不一致的原因
objcopy在添加/移除ELF section时,会对原文件做这些隐性修改,导致无法完全恢复原始二进制:
- ELF头部字段变更:包括section表的偏移量(
e_shoff)、section数量(e_shnum)等字段会被更新,即使移除新增的sigdata段,objcopy不会恢复原始的头部对齐参数,可能额外添加填充字节。 - section表结构调整:section表的剩余条目可能被重新对齐、排序,表本身的大小或偏移会被修改,直接导致文件整体尺寸变化(比如你的案例中
binary_after比原文件多89字节,就是这类调整导致的)。 - 尾部填充修改:objcopy会按照目标架构的对齐规则处理文件,添加section时可能调整了文件尾部的填充字节,移除section后不会恢复原始填充状态。
不修改原二进制的签名嵌入方案
方案1:将签名追加到文件末尾(推荐)
这种方式完全不改动原ELF结构,仅把签名拼在文件尾部,验证时通过文件大小分离原内容和签名:
- 签名操作:
gpg --yes --output sig_before --detach-sign --sign binary_before cat binary_before sig_before > binary_signed - 验证操作:
优化建议:可以在签名前将原文件大小写入一个固定长度的前缀(比如4字节的无符号整数),这样验证时无需手动记录大小,自动计算分割点。# 提前记录原文件大小(示例中为4608135字节),分离原内容和签名 head -c 4608135 binary_signed > binary_after tail -c 119 binary_signed > sig_after gpg --verify sig_after binary_after
方案2:保留ELF section但直接用原文件验证
如果必须使用ELF section嵌入,不要依赖移除section后的文件验证,直接用原始文件验证提取出的签名:
- 签名操作:
这里gpg --yes --output sig_before --detach-sign --sign binary_before objcopy --add-section sigdata=sig_before --set-section-flags sigdata=noload,readonly --preserve-dates binary_before binary_signed--set-section-flags标记签名段为不可加载,避免影响程序运行;--preserve-dates保持文件元数据不变。 - 验证操作:
objcopy --dump-section sigdata=sig_after binary_signed gpg --verify sig_after binary_before
差异定位工具
可以用以下命令确认binary_before和binary_after的具体差异:
# 对比ELF头部的section表相关字段 readelf -h binary_before | grep -E 'Start of section headers|Size of section headers|Number of section headers' readelf -h binary_after | grep -E 'Start of section headers|Size of section headers|Number of section headers' # 对比文件头部的十六进制内容 xxd binary_before | head -50 > before.hex xxd binary_after | head -50 > after.hex diff before.hex after.hex
内容的提问来源于stack exchange,提问作者bdrun33
相关产品推荐
相关产品推荐

