Skip to content

SigFlip使用和原理

字数
1174 字
阅读时间
5 分钟
更新日期
8/10/2021

SigFlip原理:将数据隐写到已签名的PE文件上

Github地址: https://github.com/med0x2e/SigFlip

可以怎么玩呢,可以白加黑当冲锋马的时候,白文件写入shellcode,黑文件加载白文件的shellcode。

也可以做维权使用,将shellcode注入到系统的白文件中,dll劫持或者loader加到启动项里面。

使用

两个目录BofDotNet,DotNet是c#写的用来可行性测试,包含注入代码,loader加载功能,Bof是C写的,也包含注入代码和loader加载功能,主要是可以编译成bof文件给Cobalt Strike使用。

c#代码loader的部分直接CreateRemoteThread就运行shellcode了,而bof的loader部分使用Early Bird,启动一个新进程 pac注入执行。

c#和Bof会写入"\xFE\xED\xFA\xCE\xFE\xED\xFA\xCE" 当作标记,在读取shellcode时通过这个字符就可以直接定位到shellcode了。

注入shellcode到签名的PE文件

c:\> SigFlip.exe -i C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe -s C:\Temp\x86.bin -o C:\Temp\MSbuild.exe -e TestKey

loader执行shellcode

c:\> SigLoader.exe -f C:\Temp\MSBuild.exe -e TestKey -pid <PROCESS_ID>

说说原理,一句话就是将shellcode写到了签名时不计算的区域。

签名的位置

https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-data-directories-image-only

image-20210809175208347

_IMAGE_DATA_DIRECTORY 第4个偏移的位置(从0开始)。

签名信息的结构

https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-attribute-certificate-table-image-only

签名位置

灰色背景的部分,不参与签名的hash计算。粗体的部分,就是签名的相关内容。

SigFlip的原理就是将数据隐写到灰色的部分。

数字签名结构

WIN_CERTIFICATE

c++
typedef struct _WIN_CERTIFICATE {
    DWORD       dwLength;
    WORD        wRevision;
    WORD        wCertificateType;   // WIN_CERT_TYPE_xxx
    BYTE        bCertificate[ANYSIZE_ARRAY];
} WIN_CERTIFICATE, *LPWIN_CERTIFICATE;

dwLength:此结构体的长度。

信息Win32 SDK中的宏定义名
0x0100Win_Certificate的老版本WIN_CERT_REVISION_1_0
0x0200Win_Certificate的当前版本WIN_CERT_REVISION_2_0

wCertificateType:证书类型,有如下表格中的类型:

信息Win32 SDK中的宏定义名
0x0001X.509证书WIN_CERT_TYPE_X509
0x0002包含PKCS#7的SignedData的结构WIN_CERT_TYPE_PKCS_SIGNED_DATA
0x0003保留WIN_CERT_TYPE_RESERVED_1
0x0004终端服务器协议堆栈证书签名WIN_CERT_TYPE_TS_STACK_SIGNED

bCertificate:包含一个或多个证书,一般来说这个证书的内容一直到安全表的末尾。

具体的WIN_CERT_TYPE_PKCS_SIGNED_DATA结构参考 https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/Authenticode_PE.docx

最值得注意的是bCertificate的字节大小要求8字节对齐。

image-20210810143903467

修改要做的步骤

根据_IMAGE_DATA_DIRECTORY 获取 WIN_CERTIFICATE 的RVA和大小,添加数据到bCertificate后面,再注意8字节对齐即可。

Ps:为什么添加数据在bCertificate后面不影响证书的校验呢,我原本想找找PKCS#7证书的结构看看的,搜了一圈,也没找到比较好的。但是可以猜测,既然有8位对齐的校验,说明后面添加几个字符是没有影响,再可以反推出,每个字段都有一个长度字段控制。所以后面无论我们添加多少字段,对证书的校验都不会影响。

再 更新 dwLength 大小

更新 _IMAGE_DATA_DIRECTORY[WIN_CERTIFICATE ]的size。

更新PE头的CheckSum (这个可选)

手动修改

有了上面的描述,我们可以手动修改试试,以“微信”为例,用它的主程序,数字签名也都正常。

image-20210810151212409

CFF Explore打开wechat.exe,定位到证书表的选项

image-20210810151336872

可以知道证书的位置在文件偏移的000EA800,大小是000035F8

010 Editor跳转到这个地方

image-20210810151722788

头部对应上数据结构的值

typedef struct _WIN_CERTIFICATE {
    DWORD       dwLength;
    WORD        wRevision;
    WORD        wCertificateType;   // WIN_CERT_TYPE_xxx
    BYTE        bCertificate[ANYSIZE_ARRAY];
} WIN_CERTIFICATE, *LPWIN_CERTIFICATE;

dwLength = 0x35f8

wRevision=0x0200

wCertificateType=0x02

后面即证书的字节了,跳转到最后可以看到有七个字节用作了对齐

image-20210810151911438

我们可以在后面添加自己需要的字节(要是8的倍数),例如我添加16个。

image-20210810152151990

所以新的长度就是0x35f8+16 = 0x3608 ,新的长度更新到两个地方

更新 dwLength 大小

更新 _IMAGE_DATA_DIRECTORY[WIN_CERTIFICATE ]的size。

最后它的证书也是正常的。

image-20210810152502566

防御手法

检查是否安装了 MS13-098 KB2893294 (一般默认不安装)

检查注册表

  • HKLM:\Software\Microsoft\Cryptography\Wintrust\Config
  • HKLM:\Software\Wow6432Node\Microsoft\Cryptography\Wintrust\Config

历史

早在2013年,就有人发现chrome的安装包会在证书处写自己的安装信息。

增强对抗

loader就可以按shellcode的加载方式进行了,通常一个CreareRemoteThread就可以启动了。在对抗中执行可以更复杂一点,对于白加黑运行,运行shellcode可以劫持返回地址,或者注入到主程序的入口来执行。

撰写

布局切换

调整 VitePress 的布局样式,以适配不同的阅读习惯和屏幕环境。

全部展开
使侧边栏和内容区域占据整个屏幕的全部宽度。
全部展开,但侧边栏宽度可调
侧边栏宽度可调,但内容区域宽度不变,调整后的侧边栏将可以占据整个屏幕的最大宽度。
全部展开,且侧边栏和内容区域宽度均可调
侧边栏宽度可调,但内容区域宽度不变,调整后的侧边栏将可以占据整个屏幕的最大宽度。
原始宽度
原始的 VitePress 默认布局宽度

页面最大宽度

调整 VitePress 布局中页面的宽度,以适配不同的阅读习惯和屏幕环境。

调整页面最大宽度
一个可调整的滑块,用于选择和自定义页面最大宽度。

内容最大宽度

调整 VitePress 布局中内容区域的宽度,以适配不同的阅读习惯和屏幕环境。

调整内容最大宽度
一个可调整的滑块,用于选择和自定义内容最大宽度。

聚光灯

支持在正文中高亮当前鼠标悬停的行和元素,以优化阅读和专注困难的用户的阅读体验。

ON开启
开启聚光灯。
OFF关闭
关闭聚光灯。

聚光灯样式

调整聚光灯的样式。

置于底部
在当前鼠标悬停的元素下方添加一个纯色背景以突出显示当前鼠标悬停的位置。
置于侧边
在当前鼠标悬停的元素旁边添加一条固定的纯色线以突出显示当前鼠标悬停的位置。