Python signify包解析Linux内核PE文件时出现不一致解析异常
同环境下signify解析PE格式Linux内核行为不一致问题排查
问题背景
使用signify包跨机器解析PE格式Linux内核文件时出现异常:同一份文件在部分机器可正常完成解析,部分机器抛出固定解析错误,且两台机器公示的系统、signify版本、待解析文件哈希值完全一致。
已验证的环境共性
两台机器不存在表层配置差异,核对项如下:
- 操作系统版本完全一致:均为
Ubuntu 18.04.5 LTS - signify依赖版本完全一致:均为
0.3.0 - Python运行时版本完全一致:均为
Python 3.6.9 (GCC 8.4.0) - 待解析内核文件完全一致:SHA256校验值均为
956df917ddbcc82cc0b8205bb86452eaee99b5cb4af218e23968f8e0f07bae0d
分场景复现步骤
解析成功场景
# 核对系统版本 $ grep PRETTY /etc/os-release PRETTY_NAME="Ubuntu 18.04.5 LTS" # 核对目标文件哈希 $ shasum -a 256 kernel 956df917ddbcc82cc0b8205bb86452eaee99b5cb4af218e23968f8e0f07bae0d kernel # 核对signify版本 $ pip list | grep signify signify 0.3.0 # 执行解析逻辑 $ python Python 3.6.9 (default, Oct 8 2020, 12:12:24) [GCC 8.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from signify.signed_pe import SignedPEFile >>> kf = open('kernel', 'rb') >>> spef = SignedPEFile(kf) >>> list(spef.signed_datas) [<signify.authenticode.AuthenticodeSignedData object at 0x7f3d5f37c0b8>]
解析失败场景
# 核对系统版本 $ grep PRETTY /etc/os-release PRETTY_NAME="Ubuntu 18.04.5 LTS" # 核对目标文件哈希 $ shasum -a 256 kernel 956df917ddbcc82cc0b8205bb86452eaee99b5cb4af218e23968f8e0f07bae0d kernel # 核对signify版本 $ pip list | grep signify signify 0.3.0 # 执行解析逻辑 $ python Python 3.6.9 (default, Oct 8 2020, 12:12:24) [GCC 8.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from signify.signed_pe import SignedPEFile >>> kf = open('kernel', 'rb') >>> spef = SignedPEFile(kf) >>> list(spef.signed_datas) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.6/dist-packages/signify/signed_pe.py", line 221, in signed_datas yield AuthenticodeSignedData.from_envelope(certificate['certificate'], pefile=self) File "/usr/local/lib/python3.6/dist-packages/signify/signeddata.py", line 41, in from_envelope signed_data = cls(data, *args, **kwargs) File "/usr/local/lib/python3.6/dist-packages/signify/authenticode.py", line 139, in __init__ super().__init__(data) File "/usr/local/lib/python3.6/dist-packages/signify/signeddata.py", line 26, in __init__ self._parse() File "/usr/local/lib/python3.6/dist-packages/signify/authenticode.py", line 158, in _parse raise AuthenticodeParseError("SignedData.crls is present, but that is unexpected.") signify.exceptions.AuthenticodeParseError: SignedData.crls is present, but that is unexpected.
问题根因
- 解析行为差异的核心来源是未做版本锁定的底层依赖
asn1crypto的版本不一致,该差异不会通过signify版本查询暴露:- 解析成功的机器安装的是
asn1crypto <1.4.0的旧版本:该版本对PKCS#7 SignedData结构的解析未映射可选的CRL(证书吊销列表)字段,解析生成的对象中不存在crls属性,完全匹配signify 0.3.0版本的旧解析逻辑,不会触发异常校验 - 解析失败的机器安装的是
asn1crypto >=1.4.0的新版本:该版本更新了PKCS系列结构的解析规则,会正确识别SignedData结构中可选的CRL字段,哪怕字段值为空也会在解析对象中生成crls属性;但signify 0.3.0的代码写死了严格校验规则,认为存在crls属性的SignedData结构不符合Authenticode规范,因此主动抛出解析错误
- 解析成功的机器安装的是
解决方案
- 方案一:统一所有机器的
asn1crypto依赖版本为兼容signify 0.3.0的1.3.0版本,执行安装命令:
安装完成后重新执行解析逻辑即可恢复正常。pip install asn1crypto==1.3.0 - 方案二:将signify升级到最新稳定版本,新版本已适配高版本
asn1crypto的解析规则,放宽了对SignedData结构可选字段的校验逻辑,可兼容带CRL字段的PE签名结构,升级命令:pip install --upgrade signify - 方案三:针对不方便修改全局依赖的场景,可在代码加载阶段对signify的
_parse方法做补丁,跳过对crls字段的强制校验逻辑,即可正常完成解析。
内容的提问来源于stack exchange,提问作者user3473000
相关产品推荐
相关产品推荐

