自《取证实录》登了此文后,多人来要电子档,现这里发出来。这篇文章,也是将以前的几个进行了充实整合删减,考虑了文章的阅读适宜度、条理清晰度、理解通畅度,降低了知识点的晦涩难懂度。
对数学一直敬畏害怕,但这些涉数学类知识点,用途广泛,作用重要,影响深远,不过关、避而不谈是不行的;下定决心、沉下心来,如小虫般慢慢啃;当有了一些懵懂地进展了解时,也惭惭能领略到它的美妙,如饮酿酒,醉。
也感谢编辑同志们帮我耐心地排版校验完!!
全文附上。
领略数字签名的天才构思
------by 小虫
数字签名的事,网上有很多;对我而言,因涉及到数学,故对它望而生畏,那怕十几年前就用过了微软的数字签名api也不行。躲避不是办法,多年屡试不爽的经验让我这样解决:要么写一篇关于它的文章搞清楚它,or要么办一起关于它的案件了解它,这里采用前者。
虽然“心魔”难解,但随着学习了解,还是被大师们的天才构想所折服,“大师们设计的数字签名的公私钥验证非常有智慧,环环相扣,缜密绵绵”,只能深深地膜拜。
下面,让我们一起感受下大师们天才般的构思。
一、概念
1、数字签名是一种用于确保数字信息的完整性和身份验证的技术。它通过在数字信息上应用加密算法来创建一个唯一的标识符,该标识符称为数字签名。数字签名通常用于验证数字文档、电子邮件、软件和其他类型的数字信息。数字签名相当于人类的“手印”。
举个例子来理解:A发一个有A签名的文件给B,如何保证这个文件是安全的呢?B在打开文件前会验证A签名是否属于A(怎么验证?B用A公钥来解密A签名,如果能解开,就说明签名是A的)。那A签名怎么生成的呢?A用A私钥对文件算出的Hash(摘要)进行加密生成了一串字符就是A签名。那怎么保证A的公钥安全,这就要到一个有公信力的CA机构了,由它来给A的公钥作签名保护。
“签名和验证”如下图:
“CA验证A公钥签名”如下图:
用一句话总结:公钥验签,私钥签名。
2、常见规范:是x509、PKCS7和PKCS12等。
x509是数字证书的规范,是基本规范;P7和P12是两个实现规范,是两种封装形式;P7是数字信封,P12是带有私钥的证书规范。P7一般是把证书分成两个文件,一个公钥一个私钥,有PEM(纯文本编码)和DER(二进制编码)两种编码方式。P7一般是分发公钥用,看到的就是一串可见字符串,扩展名经常是.crt,.cer,.key等。P12是把证书压成一个文件,.pfx 主要是考虑分发证书,私钥是要绝对保密的,不能随便以文本方式散播。所以P7格式不适合分发。.pfx中可以加密码保护,所以相对安全些。
3、目前主流的数字签名算法包括:
.RSA:基于大数因子分解问题,适用于加密和数字签名。
.DSA(数字签名算法):基于离散对数问题,仅适用于数字签名。
.ECDSA(椭圆曲线数字签名算法):基于椭圆曲线密码学,具有更短的密钥长度和更高的安全性。
4、目前主流应用:
.电子邮件签名:电子邮件客户端(如Outlook)支持S/MIME标准,允许用户使用数字签名对邮件进行签名,确保邮件的完整性和发件人身份。
.代码签名:软件开发者为其发布的软件应用数字签名,以确保应用的完整性和开发者的身份。例如,微软的Authenticode技术允许开发者为Windows应用程序添加数字签名。
.网络安全协议:HTTPS协议使用SSL/TLS证书对网站进行加密,同时也包含了数字签名技术,确保网站的安全性和完整性。
.文档签名:Adobe Acrobat等PDF阅读器允许用户对PDF文档进行数字签名,确保文档的完整性和签署者的身份。
.区块链技术:区块链技术的核心之一是对交易进行数字签名,以确保交易的完整性、认证和不可否认性。例如,比特币使用ECDSA算法进行交易签名。
.数字证书:数字证书是由权威的证书颁发机构(CA)签发的,用于证明实体的身份和公钥。数字证书中包含了实体的公钥和一些其他信息,这些信息都是通过CA的私钥进行数字签名的,用户可以使用CA的公钥进行验证。
二、证书结构
证书的详细结构:
蓝色部分为tbsCertificate;
红色部分为signatureValue;
signatureAlogrithm没有体现在上图中;它表示使用的是哪个hash函数对tbsCertificate的数据进行的hash计算;
第一部分证书的关系验证
通过这个验证,我们能了解到父、子证书之间是如何实现继承并制约这种巧妙关系的。
1、总体思路
1)提取该证书的父证书公钥;
2)使用公钥解密子证书中的signatureValue(红色部分),对照PKCS#7结构,提取出Hash1;
3)使用signatureAlgorithm中相同哈希算法对tbsCertificate数据(蓝色部分)做哈希,得到Hash2;
4)如果Hash1 = Hash2,则证书有效。
2、实例讲解
我们以卡巴斯基avpui.exe文件为例, 依次查看其数字签名与证书信息如下:
它的数字签名使用的是sha256算法,证书链为:
DigiCert High Assurance EV Root CA->DigiCert EVCode Signing CA(SHA2)->Kaspersky Lab JSC
avpui.exe它的父证书是上面的红色部分;我们选择“详细信息”下的“复制到文件”就可以导出该证书用于研究(导出时选择DER格式):
1)首先需要获得父证书的公钥,可以使用openssl命令将avpui.exe的父证书(avpuiParent.cer)公钥输出到了avpuiParentPublicKey.pem文件中:
openssl x509 -inform DER -in avpuiParent.cer -pubkey -noout > avpuiParentPublicKey.pem
得到avpuiParentPublicKey.pem;
2)父证书的公钥拿到了,下面来分离avpui证书的tbsCertificate和signatureValue部分。
导出avpui.exe的证书为avpui.cer; 看一下其内容:
openssl x509 -inform DER -in ./avpui.exe.cer -noout -text
上述Signature Algorithm: sha256WithRSAEncryption下面的即为signatureValue部分,把他复制到任意的二进制编辑器中,然后另存为avpuiExeSignatureValue.bin,
上面是提取的签名数据, 使用下面的命令解密, 解密后的文件保存到avpuiExeSignatureValueDecrypted.bin:
openssl rsautl -inkey avpuiParentPublicKey.pem -pubin -in avpuiExeSignatureValue.bin >avpuiExeSignatureValueDecrypted.bin
3)继续解析下:
openssl asn1parse -i -inform DER -in avpuiExeSignatureValueDecrypted.bin
至此,我们得到了第一个哈希值,该哈希值是一个SHA256值:9C007EDD7E089CB84373A053CB9030DC2444D256F3A5B06C74BAFDA30792147C
4)我们需要提取avpui.exe证书的tbsCertificate部分, 可以使用如下openssl命令先查看其证书的结构
上述结果中,每一行冒号开始前的数字代表在数据中的偏移,hl代表头长度,l代表实际的数据长度。根据上文中证书的ASN1结构定义,我们需要从offset 4开始提取4+1161=1165长度的数据,
然后, 我们对提取的这部分tbsCertificate数据做sha256,得到第二个哈希值,
可以看到,第二个sha256值 = 第一个sha256值。
3、回顾总结
1)从信任证书DigiCert EV Code Signing CA(SHA2)中提取了此(父)证书的公钥;
2)使用此公钥解密了avpui.exe证书中的signatureValue部分,得到第一个sha256值;
3)提取avpui.exe证书的tbsCertificate部分数据做sha256运算,得到第二个sha256值;
4)第一个sha256值与第二个sha256相等;
因此,avpui.exe使用的证书是合法有效且没有经过篡改的。
第二部分PE数字签名的移植
了解了上面的基础知识,我们来作更深一步的学习,加深实战理解。
工具准备:
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
生成了“test.cer(数字证书文件)、test.PVK(数字签名的私钥文件)”;
2、安装证书:
双击test.cer,输入密码,下一步...,成功安装;(略)
3、signtool进行签名
复制一个test.exe为test02.exe,对test02.exe进行数字签名;test.exe方便和test02.exe进行比对;
这里为test03.exe,因为02已经签名成功了,以03为例吧。
注意,这里的散列算法选择“SHA1”。这里的散列算法是PE文件的签名信息, 而之前makecert.exe设置的md5是证书的散列算法。
打开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”,
从而得知,在文件偏移“BD8000h”处,大小为1176(498h);
我们比较下 无签名 的此处位置值:
都为0;
2、偏移处BD8000h的Certificate Table:
可以看到Certificate Table存储相关签名信息:
文件开始位置:BD8000h
表项长度:4字节,头部和签名数据的总长度498h;
证书版本:2字节,常见0x0200表示WIN_CERT_REVISION_2;
证书类型:2字节,常见0x0002表示包含PKCS#7的SignData结构
SignedData:包含PE文件Hash值的签名数据、软件发布者公钥,选用的签名及散列算法等。(在文件中为ASN.1编码)
3、提取签名数据
可以用010editor来提取,也可以用dd工具来提取;
Certificate Table从第9个字节开始后为签名信息,存为文件“test02Pkcs7Data.bin”;
这里我们用dd工具:
ddif=./test02.exe of=./test02Pkcs7Data.bin skip=12419080 bs=1 count=1168
BD8000h转换为十进制为12419072+8,498h为1176-8,(减去8个字节的版本号和证书类型);
如果导出正确了,可以用asn1dump正常打开,
三、PE签名数据分析
上图中左半部分为PE结构。右半部分,微软对PKCS#7格式的数字签名数据部分做了一个大概的结构介绍,实际的结构对应SignedData。
1、PKCS#7 微软官方文档
一个PKCS#7 SignedData结构包括PE文件的哈希值,一个被软件出版厂商的私钥创建的签名、将软件出版厂商的签名密钥和法人代表进行绑定的(系列)X.509 v3证书。PKCS#7 1.5版本规范定义了如下关于SignedData 的 ASN.1(抽象语法符号)结构:
SignedData的定义:
注意,导出的“test02Pkcs7Data.bin”签名数据为ASN.1抽象结构,需要用ASN1View或ASN1Dump进行解析,
如果不方便,可以将hex导出,放入这个网站https://holtstrom.com/michael/tools/asn1decoder.php将hex转换成asn1:
在这里对应的flag,如:指定SignedData结构值为“1.2.840.113549.1.7.2”,表示采用PKCS#7结构;生成签名的哈希算法MD5SHA1SHA256签名属性SPC证书颁发者信息(包括md5withRSA签名、证书颁发者YXZ、组织WHU、国家及省份)等。核心数据包括:散列算法摘要数据公钥数据签名后数据;
所有的对应最后显示成这张图;
2、分析Contentinfo部分数据。
该部分主要存储PE文件的hash值、以及标记变量、散列算法等。
比如上面的sha1算法。
3、分析Certificates部分数据。
该部分主要存储证书相关信息,包括证书发布者、证书时间戳等信息。注意,该部分内容可以直接导出,再和“test02.exe”的数字证书 进行对比。
比如省份“AnHui”。
4、采用010Editor导出证书部分数据,并进行对比实验。
我们从“30 82”开始复制。这里采用010Editor工具复制。
保存为h.cer,和test02.exe中的证书对比下,
对比从010Editor导出的“h.cer”证书和“test02.exe”数字签名信息,发现是一致的(包括公钥),该实验也证明了签名数据的 第二部分为证书信息。
四、数字签名的移植
将数字签名移植到无数字签名的程序上,移花接木。
步骤如下:
1、有签名程序开展,找到PE头的struct IMAGE_DATA_DIRECTORY Security,取出其签名的偏移和大小长度,移到偏移处,取大小长度的内容;
2、将以上长度的内容复制到无签名程序的尾部,修改struct IMAGE_DATA_DIRECTORY Security处的偏移和长度值,指向Certificates;
3、完工。
虽然洋洋洒洒,但其核心就那么几行字。精妙绝伦,大道至简。
感想:写完这篇文章,对数字签名有了更深的认识。发明创造这个规则的人是个天才!当深入了解一个安全体系时,你才发觉其中的精妙之处。安全体系是保护信息和系统免受潜在威胁的框架,而其设计和实施往往要考虑到复杂的技术、人员和流程因素。当深入了解一个安全体系时,你会发现它不仅仅是一堆技术的堆砌,更是一门科学,需要全方位的考虑和综合应对各种潜在威胁。安全体系的设计和运维是一个不断演进的过程,需要持续学习和适应不断变化的威胁环境。
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...