PE数字签名的移植

admin 2024年10月7日19:03:28评论14 views字数 3870阅读12分54秒阅读模式

    “数字签名”是个老话题,相关文章多如牛毛。那年写的那个《Windows安全检测工具》里面有个“对进程或驱动文件的签名验证”的功能,好像用到了Windowsapi,曾是个特色。

    为什么写这个?一是好久没来怪想念的;二是源于看到一段代码,顺便学习下这个知识点。事后,自感学习能力下降得厉害;花了不少的时间才理出个头绪,确实烧脑,各位可能会头晕。

    言归正传,那段py代码的功能是将一个PE的官方签名的移植到另一个无签名的PE程序,以作...之用。看了下,挺有意思的,如下:

    flItms = {}

    binary = open(binary, 'rb')

    binary.seek(int('3C', 16))

    flItms['buffer'] = 0

    flItms['JMPtoCodeAddress'] = 0

    flItms['dis_frm_pehdrs_sectble'] = 248

    ......

    flItms['Characteristics'] = struct.unpack('<H', binary.read(2))[0]

    flItms['OptionalHeader_start'] = flItms['COFF_Start'] + 20

......

    binary.seek(flItms['OptionalHeader_start'])

    flItms['Magic'] = struct.unpack('<H', binary.read(2))[0]

    ......

    flItms['ImportTableRVA'] = struct.unpack('<I', binary.read(4))[0]

    flItms['ImportTableSize'] = struct.unpack('<I', binary.read(4))[0]

    flItms['ResourceTable'] = struct.unpack('<Q', binary.read(8))[0]

    flItms['ExceptionTable'] = struct.unpack('<Q', binary.read(8))[0]

    flItms['CertTableLOC'] = binary.tell()

    flItms['CertLOC'] = struct.unpack("<I", binary.read(4))[0]

    flItms['CertSize'] = struct.unpack("<I", binary.read(4))[0]

    binary.close()

    return flItms

    顺着好奇一路走来,感觉实现难度不大,但现实是我花了不少时间且在若干资料的帮助下才完成了这篇习作,感觉当年大伽们设计数字签名的公私钥验证真非常有智慧,环环相扣,缜密绵绵。现按照我的理解整理出来,方便大家学习......

工具准备:

A、工具:makecert、signtool、asn1dump、010editor、dd、openssl等;

B、原始(x86) exe一个(x64的exe等也行),名为test.exe

一、自制数字签名

1、makecert --help

-r: 自签名 

-n: 证书名称,格式为-n “CN=名称, E=Email,O=组织名称,C=国家, S=省份(州), P=县城” 

-a: 指定散列算法,其值必须是md5(默认值)或SHA1 ; 

-$: 指定证书的签名权限,其值必须是commercial(商业软件)或individual(个人软件) ;

-b: 证书有效期的开始时间,格式为mm/dd/yyyy 

-e: 证书有效期的结束时间,格式为mm/dd/yyyy

命令:makecert -r -$ "individual" /sv "test.PVK" -n "CN=YXZ,O=WHU,C=China,S=AnHui" -a md5 -b 03/16/2020 -e 01/01/2030 test.cer

PE数字签名的移植

生成了“test.cer(数字证书文件)、test.PVK(数字签名的私钥文件)”;

2、安装证书:

双击test.cer,输入密码,下一步...,成功安装;(略)

3、signtool进行签名

复制一个test.exetest02.exe,对test02.exe进行数字签名;test.exe方便和test02.exe进行比对;

PE数字签名的移植

这里为test03.exe,因为02已经签名成功了,以03为例吧。

PE数字签名的移植

PE数字签名的移植

PE数字签名的移植

PE数字签名的移植

注意,这里的散列算法选择“SHA1”。这里的散列算法是PE文件的签名信息, 而之前makecert.exe设置的md5是证书的散列算法。

PE数字签名的移植

打开test02.exe文件属性,可以看到它增加了一个“数字签名”的区域,并且能够看到此数字签名是正常的及详细信息。

二、PE数字签名的头格式

1、签名在PE头的位置,位于:

PE头的struct IMAGE_NT_HEADERS NtHeader-->struct IMAGE_OPTIONAL_HEADER32 OptionalHeader-->struct IMAGE_DATA_DIRECTORY_ARRAY DataDirArray-->struct IMAGE_DATA_DIRECTORY Security这里,两项内容“偏移VirtualAddress和大小Size”,

PE数字签名的移植

从而得知,在文件偏移“BD8000h”处,大小为1176(498h)

我们比较下 无签名 的此处位置值:

PE数字签名的移植

都为0;

2、偏移处BD8000hCertificate Table

PE数字签名的移植

可以看到Certificate Table存储相关签名信息: 

文件开始位置BD8000h

表项长度:4字节,头部和签名数据的总长度498h

证书版本:2字节,常见0x0200表示WIN_CERT_REVISION_2

证书类型:2字节,常见0x0002表示包含PKCS#7SignData结构 

SignedData包含PE文件Hash值的签名数据、软件发布者公钥,选用的签名及散列算法等。(在文件中为ASN.1编码)

PE数字签名的移植

PE数字签名的移植

3、提取签名数据

可以用010editor来提取,也可以用dd工具来提取;

Certificate Table从第9个字节开始后为签名信息,存为文件“test02Pkcs7Data.bin”;

这里我们用dd工具:

dd if=./test02.exe of=./test02Pkcs7Data.bin skip=12419080 bs=1 count=1168

BD8000h转换为十进制为12419072+8498h1176-8,(减去8个字节的版本号和证书类型);

PE数字签名的移植

如果导出正确了,可以用asn1dump正常打开,

PE数字签名的移植

三、PE签名数据分析

PE数字签名的移植

上图中左半部分为PE结构。右半部分,微软对PKCS#7格式的数字签名数据部分做了一个大概的结构介绍,实际的结构对应SignedData

1、PKCS#7 微软官方文档

一个PKCS#7 SignedData结构包括PE文件的哈希值,一个被软件出版厂商的私钥创建的签名、将软件出版厂商的签名密钥和法人代表进行绑定的(系列)X.509 v3证书。PKCS#7 1.5版本规范定义了如下关于SignedData 的 ASN.1(抽象语法符号)结构:

SignedData的定义:

PE数字签名的移植

注意,导出的“test02Pkcs7Data.bin”签名数据为ASN.1抽象结构,需要用ASN1View或ASN1Dump进行解析,

PE数字签名的移植

如果不方便,可以将hex导出,放入这个网站https://holtstrom.com/michael/tools/asn1decoder.phphex转换成asn1:

PE数字签名的移植

在这里对应的flag,如:指定SignedData结构值为“1.2.840.113549.1.7.2”,表示采用PKCS#7结构;生成签名的哈希算法MD5SHA1SHA256签名属性SPC证书颁发者信息(包括md5withRSA签名、证书颁发者YXZ、组织WHU、国家及省份)等。核心数据包括:散列算法摘要数据公钥数据签名后数据; 

PE数字签名的移植

所有的对应最后显示成这张图;

2、分析Contentinfo部分数据。

该部分主要存储PE文件的hash值、以及标记变量、散列算法等。

PE数字签名的移植

PE数字签名的移植

比如上面的sha1算法。

3、分析Certificates部分数据。

该部分主要存储证书相关信息,包括证书发布者、证书时间戳等信息。注意,该部分内容可以直接导出,再和“test02.exe”的数字证书 进行对比。

PE数字签名的移植

PE数字签名的移植

比如省份“AnHui”。

4、采用010Editor导出证书部分数据,并进行对比实验。

PE数字签名的移植

我们从“30 82”开始复制。这里采用010Editor工具复制。

PE数字签名的移植

保存为h.cer,和test02.exe中的证书对比下,

PE数字签名的移植

对比从010Editor导出的“h.cer”证书和“test02.exe”数字签名信息,发现是一致的(包括公钥),该实验也证明了签名数据的 第二部分为证书信息。

四、数字签名的移植

将数字签名移植到无数字签名的程序上,移花接木。

步骤如下:

1、有签名程序开展,找到PE头的struct IMAGE_DATA_DIRECTORY Security,取出其签名的偏移和大小长度,移到偏移处,取大小长度的内容;

2、将以上长度的内容复制到无签名程序的尾部,修改struct IMAGE_DATA_DIRECTORY Security处的偏移和长度值,指向Certificates

3、完工。

要不要写个程序呢?其实很简单了,有时间再写吧!

原文始发于微信公众号(MicroPest):PE数字签名的移植

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月7日19:03:28
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   PE数字签名的移植https://cn-sec.com/archives/1970037.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息