【实战】验证可执行文件可靠性| Windows 应急响应

0x01 简介

相信部分朋友已经看过我们的 《Windows 应急响应手册》了,我们这边也得到部分朋友的正向反馈,包括工具、方法等。

Windows 版的应急响应手册中常规安全检查部分第一版就包含了 30 多个检查项目,按照我们的风格,每个检查项基本都给出了 Windows 默认的情况(书中以 Windows Server 2016 为例),对于存在大量检查项的(例如大量的 dll 文件需要检查),基本也都给出了 Powershell 脚本。

如果大家详细看了这些 Powershell 脚本或者看我们的描述可以发现,其实就是找到检查项,进而找到可执行文件(exedll 等),之后验证签名是否通过,这个做法仔细想是存在问题的:恶意程序也可以拥有有效的签名,所以只检查是否验证通过是不可靠的

0x02 目的说明

单纯验证每个可执行文件是否为恶意,这不是我们的工作,这是主机/终端管理程序、杀毒软件、沙箱软件的工作,对某一个可执行文件如何进行分析也不是这篇文章的目的,这是部分恶意软件/代码分析师的工作

这篇文章的目的是在应急响应过程中,面对中等数量的可执行文件等待验证,如何快速将可疑文件挑选出来

我选择的方法是先验证签名,签名通过后再验证发布者或者叫签名者 (Publisher) 名称是否为微软官方,如果两者有一个不满足,则认为是可疑文件

如果大家有更好的方法,欢迎根据应急手册上的联系方式联系我们讨论

0x03 弃用方案

为什么不采用杀毒软件对要检查的文件进行查杀?

首先是在应急响应手册的常规检查阶段包含了全盘查杀,其次并不是所有应急场景都包含杀毒程序并且杀毒程序的病毒库能够及时 联网/不联网 更新

为什么不采用沙箱进行检查?

这是出于保密要求,很多场景下客户内部没有沙箱,如果将可执行文件等直接放在互联网上的沙箱进行检查,可能会导致文件泄漏

为什么不用 Hash 验证?

Windows 升级可能会涉及部分程序,导致 Hash 变化

为什么不收集起来,人工分析?

有些时候量比较大,对于应急响应场景不现实,而且导出文件也可能造成文件泄漏

先验签名再验证发布者的方法会导致误杀吧?

是的,可以说除了微软的都会被列为可疑文件,这是我们在应急响应场景下优于杀毒软件的地方,我们检查的地方都是可以被用来做权限维持等操作的地方,第三方软件不会很多,我们的目的也是找出它们,之后进行针对性的分析

先验证签名再验证发布者的方法检验通过的程序是不是完全问题?

并不是完全是

首先得保证验证本身是没问题的,这里就涉及两个部分:1. 系统存储的证书没问题,2. 验证过程没有被篡改;

其次私钥可能会被盗嘛,或者因为漏洞绕过验证;

需要注意的是还有一种情况:对于嵌入式签名,签名本身存储位置是可以被放置 payload 的,但是默认不会执行,想要执行得有额外的加载器,文章后面部分会详细说这个事,这里拿出来说是担心部分用户在非常规安全检查阶段验证某个程序的时候被这种隐藏 payload 的方法给欺骗了

0x04 Windows 签名简介

Windows 签名一般有两种形式,一种是针对文件的;一种是针对文件集合(.cat文件)的,我们接下来简单介绍一下这两种形式

1. 针对文件集合签名

微软官方叫针对目录文件进行签名,如果看过之前关于 Linux 更新源那期文章的朋友应该还记得,Linux 是将某个文件夹中文件的 hash 等信息集中到一个文件中,之后对该文件进行签名的,而不是对某个应用程序单独签名,Windows 中针对文件集合(某个目录内的所有文件)的签名也是一个道理

这个过程都是大同小异,无非就是收集 hash 等信息,之后使用私钥配合各种算法进行签名,之后操作系统通过分发的公钥验证签名

2. 针对文件签名

针对文件的签名就聚焦到单个文件了,也就是上面提到的方案的验证对象

简单来说就是将可执行文件进行 Hash 运算(可采用不同的 Hash 算法)后,生成一个值,之后通过私钥对该值进行签名,最后将签名相关内容存储到可执行文件中的一个段(或者叫一个部分吧)

图片

图片

这里大家可以思考一下,是不是存在一些逻辑悖论:

我要计算一个文件的 Hash 之后再将计算的结果处理后塞到文件里,那文件的 Hash 是不是就变了,这样的话,操作系统在校验的时候是不是就得忽略签名相关的这个段(其实还有部分要去掉的),采用和签名是一样的算法进行 Hash 计算,之后比对值是否一致

这样一来,签名这个部分本身的校验就被忽略了,所以之前就有安全研究人员提出在这部分添加 payload ,但值得注意的是,这部分不属于可执行部分,只能用来存储 payload ,需要额外的加载器才能运行,除非文件本身可实现加载器的功能

因此,经过 先验证签名,后验证发布者 的方式验证通过的程序不一定与官方程序一模一样,不一定是完全无害的,这里费这么多口舌是为了提醒大家这个问题,有点黑加白的意思,而不是白加黑

0x05 针对文件签名详述

大家可能会觉得奇怪,你刚刚简述了,为什么又来个详述,这是因为看网络上的文章以及各种GPT 时有个问题我觉得不太对,困扰我2天了


图片

http://p7.qhimg.com/t01fc41fe42a2a5e702.png

来自 https://www.anquanke.com/post/id/84470

图片

img

来自 https://www.wosign.com/column/ssl_20220222.htm

图片

img

来自 https://cloud.tencent.com/developer/article/2185414


还有来自官方的系列文章

https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/digital-signatures

这些内容都是在描述 Windows 签名验证过程,按照他们的描述,以及网络上的文章描述大致如下

  1. 开发者生成密钥对以及证书请求文件

  2. 向证书颁发机构(以下简称CA)

  3. CA 核验开发者身份没问题后,用 CA 自己的私钥签名一张证书,颁发给开发者,证书内容是开发者的公钥以及开发者部分信息

  4. 开发者对二进制程序进行 Hash 运算,之后通过开发者的私钥进行加密也就是数字签名并嵌入到二进制文件中

  5. 将二进制分发给用户,用户的操作系统获取文件后,解密签名,采用签名同样的方法计算 Hash

  6. 对比一致则验证通过

这是最开始看到的,这里产生的疑问是,操作系统是怎么得到开发者的公钥的?没有描述单独下载的过程嘛,证书好像没用上啊?之后带着疑问开始找资料,这时候看的资料就包括上面的几个了

这时候就搞清楚了,原来数字证书和数字签名都是被嵌入到二进制文件中的,这就很好理解为什么操作系统能够获取到开发者的公钥了

  1. 开发者生成密钥对以及证书请求文件

  2. 向证书颁发机构(以下简称CA)

  3. CA 核验开发者身份没问题后,用 CA 自己的私钥签名一张证书,颁发给开发者,证书内容是开发者的公钥以及开发者部分信息

  4. 开发者对二进制程序进行 Hash 运算,之后通过开发者的私钥进行加密也就是数字签名并嵌入到二进制文件中

  5. 同时,将CA签名过的数字证书也嵌入到二进制文件中

  6. 将二进制分发给用户,用户的操作系统获取文件后,验证证书签名,获取开发者公钥,解密数字签名,采用签名同样的方法计算 Hash

  7. 对比一致则验证通过

这个时候流程就和上面的图片里一致了,文章介绍本来到这里就应该结束了,但是我有一个疑问:

操作系统是如何验证开发者证书的签名的呢?要知道开发者证书的签名是 CA (证书颁发机构) 私钥签名的

这时候可能很多朋友说了,Windows 操作系统或者浏览器等都会内置部分证书的,搞过 Burpsuite 的都见过,这部分证书是根证书,不就可以用来验证开发者证书的签名

这应该是在几年前我参加面试的时候,有个面试官就问过我这个问题:离线的操作系统是如何验证签名的,他给出的答案就是系统内置根证书。没想到多年以后,这个问题也成了回旋镖

当然了,熟悉我们的小伙伴肯定明白,如果这样就解决了问题,我肯定不会出来写,我们先看一下 Windows 内置的证书

Windows + r 输入mmc

图片

图片

图片

图片

图片

可以看到,操作系统确实是内置了根证书颁发机构的证书,我细数了一下,这里共有 20 个,第三方根证书颁发机构都包含在这里了,全世界这么多人要申请证书,如果仅仅由这 20 个受信任根证书的颁发机构私钥签名,颁发,吊销,那可能都得忙到冒火星,这还不是最主要的,最关键的受信任的根证书的私钥这么频繁地使用,如果其中一张根证书颁发机构的私钥泄漏了,那影响是非同小可的

所以详细看应用程序的签名,可以看到并不是直接由上面系统内置的根证书签的

图片

颁发者是 Microsoft Code Signing PCA 2011 , 这并不在 Windows 操作系统内置受信任的根证书存储中

证书是证书,存储是存储,这个也说一下,简单来说上面那些像文件夹一样的都是存储,里面存的是证书,这里说是希望大家看别人文章的时候不会混淆

那问题来了,难道说某个根证书的公钥能解密这个根证书下面的所有的CA私钥签名的证书吗?公私钥不是一对一的吗???难道调兵遣将的虎符不止一个?

所以这不得不引起疑问对吧,这个时候又开始查询资料,把官方资料都看了好几遍了,没提这事,官方的知识平台确实比较次,看了很多文章后,有些人提出了一个概念 —— 证书链

图片

可以看到证书是有一个链的, Microsoft Corporation 证书是由 Microsoft Code Signing PCA 2011 签名的,Microsoft Code Signing PCA 2011 是由 Microsoft Root Certificate Authority 2011 签名的

证书链是如何验证的呢?

在  Microsoft Corporation 证书中会记录是哪个 CA 将证书签名后颁布给开发者的

图片

之后操作系统会发起网络请求,寻找包含 Microsoft Code Signing PCA 2011 公钥的证书,当然这个证书是被上一级 CA 的私钥签名的,直到最终到达根证书颁发机构

抓包并测试验证某个程序的签名

图片

确实会发起相关请求,再次测试验证某个程序的签名就不会再次发起请求了

图片

应该是证书公钥被缓存了,准确地说, Microsoft Code Signing PCA 2011 这张证书叫做中间证书,这样就可以层层校验,最终验证开发者的证书中的公钥是否可以使用


本来一切又该结束了,可恶的是咱们又是搞安全的,比较严谨,如果验证开发者证书的时候没有网络怎么办呢?

这是个好问题,带着这个问题我们测试一下

图片

图片

还是能够验证成功,是不是软件的问题,用 Powershell 测试一下

图片

Powershell 也验证成功,说明软件没问题

难道是刚才的缓存问题?重启系统,再次验证

图片

重启后还是验证成功了,会不会是 Wireshark 的中间证书也被系统内置了,在根证书或中间证书那里

图片

它这个还多一层,我们去查查吧

图片

第二层就没查到,这个时候大家得明白,按理说没有网络,这个证书链最多也就找到上一层,甚至上一层的详细情况都看不到,只能看到个名字

难道说刚才的缓存还在吗?

为了验证这个问题,我们在无网络的情况下(直接不分配网卡)新建一个 Windows Server 2016 系统,通过虚拟机工具映射文件夹的方式将二进制文件传递进去

图片

图片

重新安装系统的情况下,完全离线都能够还原证书链,并且验证成功

这个时候又开始查资料了,在官方的资料里发现了一个叫交叉证书的东西,看了几遍,也没有完全理解,但好在似乎在 21 年就已经停止了,于是我们在无网络的情况下(不分配网卡)安装了一个 Windows Server 2022 ,这样总能验证了吧

图片

得,不是交叉证书的事

这个时候有开始找各种资料,并且各种 GPT 问,GPT们给出的答案中比较可信的还是证书缓存,但是如何查看缓存,GPT 没有给出

在系统安装以及启动过程中会涉及到很多签名校验,如果不能获取到证书缓存,就很难确定是不是真的因为证书缓存,关键似乎也没有其他可能了

这怎么办呢?千山鸟飞绝,万径人踪灭呀,我想到一个办法,你能缓存 Windows 自己的那些程序中间签名不奇怪,缓存 Wireshark 的也算是可以接受,你不至于在系统安装和启动过程中把所有软件的中间证书都缓存了吧

于是我们从腾讯管家平台下载了大量的软件进行测试,我就不信你能把这些软件的中间证书都缓存了

图片

结果有签名的程序大部分能够签名通过,欣喜若狂发现几个没通过的,结果放到可联网的 Windows Server 2016 中也是一样不通过,测试了一定数量以后,实在是测试不动了,关键是没有找到任何一个案例

现在还有一种办法,我们自己伪造一整套证书,包括根证书、中间证书、开发者证书,将根证书和中间证书都放到操作系统中,这样就可以模拟正常的签名验证过程,之后再将中间证书删除掉,再次验证,看看能不能通过

如果还是能够通过验证,找出完整的证书链,说明是由缓存导致的验证成功,你听我这个词,“导致的”, 但这也有一个问题,如果没有验证成功,也可能是因为操作系统在删除证书的时候直接把缓存也删除掉了

最关键的是,这个过程也挺复杂的,于是放弃这个方案


到这里本来又应该结束了,因为通过案例证明,其实我们的验证方案是有效且可靠的,但是吧,不搞清楚我会一直想着这个事,而且把没有完全验证过的方法写入到应急响应手册里也不太妥当

于是我打算研究研究 Windows 二进制文件结果,之后详细看看签名和证书部分到底是什么情况,能不能找到一些关键字,之后找到 Windows 的签名验证的程序,大不了再搞一下逆向,看看能不能发现蛛丝马迹

关于 Windows 二进制格式,官方还是有详细资料的

https://learn.microsoft.com/zh-cn/windows/win32/debug/pe-format#the-attribute-certificate-table-image-only

这里面找到 属性证书表(Attribute Certificate Table)

图片

图片

这部分引用了一个 docx 文件  —— Windows 验证码可移植可执行签名格式

https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/Authenticode_PE.docx

建议大家用 word 而不是 wps 打开,不然里面的图可能会有些问题

图片

这就直接交给有道翻译吧,感谢有道翻译的文档翻译功能,一点一点儿看的时候发现了一个问题

图片

哎呀!!!原来微软官方文档里都写清楚了,属性证书表里不只是开发者证书,还有所有中间证书

GPT 都白学习了呀,没学透啊!不过总算是解释清楚了

正好一个学弟专门写过相关的论文,我的这个结论其实就是他论文中的一部分,感谢学弟

要是早知道就好了,但探究一圈过来以后,对这个过程印象就比较深了,当然本篇文章介绍的也不是全部细节,如果大家感兴趣可以去实践一下

0x06  Powershell 实现验证方案

$file = 'c:\windows\system32\cmd.exe'$microsoftCNS = @('Microsoft Corporation', 'Microsoft Windows')# 获取可执行文件的数字签名
$signature = Get-AuthenticodeSignature -FilePath $fileif ($signature.Status -eq 'Valid') {Write-Output "文件的数字签名有效。"# 获取签名的发布者信息$publisher = $signature.SignerCertificate.Subject# $publisher = "CN=Microsoft Windows, CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"# 解析发布者信息以提取 CN 字段的值$cnValues = @(($publisher -split ', ' | Where-Object { $_ -like 'CN=*' }).Substring(3))# 验证 CN 字段数量if ($cnValues.Count -eq 1) {$cnValue = $cnValues[0]Write-Output "CN 字段的值: $cnValue"# 判断 CN 字段是否为微软官方if ($microsoftCNS -contains $cnValue) {Write-Output "CN 字段值为微软官方。"} else {Write-Output "CN 字段值不是微软官方。"}} elseif ($cnValues.Count -gt 1) {Write-Output "错误:找到多个 CN 字段。"} else {Write-Output "错误:未找到 CN 字段。"}
} else {Write-Output "文件的数字签名无效。"
}

这是一个 demo ,经过测试发现微软的官方签名发布者(CN) 还不止一个,所以这里使用了数组,方便大家后续添加新的微软官方签名或者大家认可的非微软签名

图片

尝试测试非微软官方的程序

图片

这两个微软官方的签名发布者是通过 system32 文件夹以及 SysinternalsSuite 对比提取出来的,如何才能获取操作系统默认的所有已签名的应用程序的签名发布者信息呢?

我的电脑只有一个 C 盘,通过 Powershell 帮我们来完成

$rootPath = "C:\"# 用于存储已发现的 CN 值和对应的文件地址
$cnFileMap = @{}# 处理文件,获取 CN 值并记录对应的文件地址
function Process-File($file) {try {# 获取可执行文件的数字签名$signature = Get-AuthenticodeSignature -FilePath $file.FullName -ErrorAction Stopif ($signature -ne $null -and $signature.Status -eq 'Valid') {# 获取签名的发布者信息$publisher = $signature.SignerCertificate.Subject# 解析发布者信息以提取 CN 字段的值$cnValue = ($publisher -split ', ' | Where-Object { $_ -like 'CN=*' }).Substring(3)if ($cnValue) {if (-not $cnFileMap.ContainsKey($cnValue)) {# 添加新的 CN 值到映射表$cnFileMap[$cnValue] = $file.FullName}}}} catch {Write-Host "无法访问文件: $($file.FullName)"}
}# 递归遍历目录并处理每个文件
Get-ChildItem -Path $rootPath -Recurse -ErrorAction SilentlyContinue | ForEach-Object {$item = $_if ($item.PSIsContainer) {# 如果是目录,则继续递归遍历其中的文件Get-ChildItem -Path $item.FullName -File -ErrorAction SilentlyContinue | ForEach-Object {Process-File $_}} else {# 如果是文件,则直接处理Process-File $item}
}# 打印所有的 CN 值
$cnValues = $cnFileMap.Keys
Write-Host "所有的 CN 值:"
Write-Host "-----------------------------------------------"
foreach ($cn in $cnValues) {Write-Host $cn
}
Write-Host "-----------------------------------------------"
Write-Host ""# 打印每个 CN 值对应的文件地址
foreach ($cn in $cnValues) {Write-Host "CN 值: $cn"Write-Host "文件地址:"Write-Host "- $($cnFileMap[$cn])"Write-Host ""
}

这个脚本会将所有可以访问的文件验证成功的签名提取出来,之后进行保存,每一个新签名都会记录第一个发现的使用该签名的文件地址

图片

所有的 CN 值:
-----------------------------------------------
Microsoft Windows Hardware Compatibility Publisher
Microsoft Corporation
Microsoft Windows
Microsoft Update
-----------------------------------------------CN 值: Microsoft Windows Hardware Compatibility Publisher
文件地址:
- C:\Windows\System32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\windows-legacy-whql.catCN 值: Microsoft Corporation
文件地址:
- C:\Windows\System32\MpSigStub.exeCN 值: Microsoft Windows
文件地址:
- C:\Windows\bfsvc.exeCN 值: Microsoft Update
文件地址:
- C:\Windows\SoftwareDistribution\SIH\eng\SIHEng.dll

其中 Microsoft Windows Hardware Compatibility Publisher 对应的文件 C:\Windows\System32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\windows-legacy-whql.cat 就是我们上面提到的针对文件集合(目录文件)签名

图片

最终的 demo 为

$file = 'c:\windows\system32\cmd.exe'$microsoftCNS = @('Microsoft Corporation', 'Microsoft Windows', 'Microsoft Windows Hardware Compatibility Publisher', 'Microsoft Update')# 获取可执行文件的数字签名
$signature = Get-AuthenticodeSignature -FilePath $fileif ($signature.Status -eq 'Valid') {Write-Output "文件的数字签名有效。"# 获取签名的发布者信息$publisher = $signature.SignerCertificate.Subject# $publisher = "CN=Microsoft Windows, CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"# 解析发布者信息以提取 CN 字段的值$cnValues = @(($publisher -split ', ' | Where-Object { $_ -like 'CN=*' }).Substring(3))# 验证 CN 字段数量if ($cnValues.Count -eq 1) {$cnValue = $cnValues[0]Write-Output "CN 字段的值: $cnValue"# 判断 CN 字段是否为微软官方if ($microsoftCNS -contains $cnValue) {Write-Output "CN 字段值为微软官方。"} else {Write-Output "CN 字段值不是微软官方。"}} elseif ($cnValues.Count -gt 1) {Write-Output "错误:找到多个 CN 字段。"} else {Write-Output "错误:未找到 CN 字段。"}
} else {Write-Output "文件的数字签名无效。"
}

0x07 COM劫持检查实战

应急响应手册v1.0 给出的版本,大家主要看 Verify-FileSignature 函数就好,这也是当时想到的,把验证步骤单独做一个函数,方便后期调整

# 定义函数来进行签名校验
function Verify-FileSignature {param ([Parameter(Mandatory=$true)][ValidateScript({Test-Path $_ -PathType Leaf})][string]$FilePath)if (Test-Path -Path $FilePath -PathType Leaf) {$signature = Get-AuthenticodeSignature -FilePath $FilePathif ($signature.Status -eq 'Valid') {return "Valid"} else {return "Invalid"}} else {return "File Not Found"}
}# 定义函数来检查注册表地址
function Check-RegistryPaths {param ([Parameter(Mandatory=$true)][string[]]$RegistryPaths)$invalidSignatures = @()foreach ($registryPath in $RegistryPaths) {if (Test-Path -Path $registryPath) {$subkeys = Get-ChildItem -Path $registryPathforeach ($subkey in $subkeys) {$inprocServer32Path = Join-Path -Path $subkey.PSPath -ChildPath "InprocServer32"if (Test-Path -Path $inprocServer32Path) {$defaultPropertyValue = (Get-ItemProperty -Path $inprocServer32Path -Name "(default)" -ErrorAction SilentlyContinue)."(default)"if ($defaultPropertyValue) {# 此处加 Trim('"') 是为了防止类似于 Defender 这种“有个性”的软件胡乱设置注册表$binaryFilePath = $defaultPropertyValue.Trim().Trim('"')$binaryFilePath = [Environment]::ExpandEnvironmentVariables($binaryFilePath)if (Test-Path $binaryFilePath) {$result = Verify-FileSignature -FilePath $binaryFilePathif ($result -eq "Invalid") {$invalidSignatures += @{RegistryPath = $subkeyBinaryFilePath = $binaryFilePath} Write-Host "Signature is invalid for file: $binaryFilePath" -ForegroundColor Red} elseif ($result -eq "Valid") {Write-Host "Signature is valid for file: $binaryFilePath " -ForegroundColor Green}} else {$dllFileName = Split-Path -Leaf $binaryFilePath$found = $false$searchPaths = @((Join-Path -Path $env:SystemRoot -ChildPath $dllFileName),(Join-Path -Path $env:SystemRoot -ChildPath "System32\$dllFileName"))foreach ($path in $searchPaths) {if (Test-Path $path) {$found = $true$result = Verify-FileSignature -FilePath $pathif ($result -eq "Invalid") {$invalidSignatures += @{RegistryPath = $subkeyBinaryFilePath = $path}Write-Host "Signature is invalid for file: $path" -ForegroundColor Red} elseif ($result -eq "Valid") {Write-Host "Signature is valid for file: $path " -ForegroundColor Green}break}}if (-not $found) {Write-Host "Could not find file '$dllFileName' in default search paths. Skipping signature verification."  -ForegroundColor Yellow}}} else {Write-Host "Binary file path is empty for subkey $($subkey.PSChildName)."  -ForegroundColor Yellow}}}}}# 打印不通过的签名验证信息if ($invalidSignatures.Count -gt 0) {Write-Output ""Write-Output ""Write-Output "--------------------------------------------------------"Write-Host "Invalid signatures:" -ForegroundColor Redforeach ($invalidSignature in $invalidSignatures) {$registryPath = $invalidSignature.RegistryPath$binaryFilePath = $invalidSignature.BinaryFilePathWrite-Host "Registry path: $registryPath" -ForegroundColor YellowWrite-Host "Binary file path: $binaryFilePath" -ForegroundColor YellowWrite-Output ""}Write-Output "--------------------------------------------------------"}
}# 要检查的注册表地址数组
$registryPaths = @("Registry::HKEY_CURRENT_USER\Software\Classes\CLSID","Registry::HKEY_CLASSES_ROOT\CLSID","Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Objects\"
)# 调用函数进行检查
Write-Host "Starting signature verification..."Check-RegistryPaths -RegistryPaths $registryPathsWrite-Host "Signature verification completed."

增加验证步骤后的版本,大家还是主要看 Verify-FileSignature 函数

$microsoftCNS = @('Microsoft Corporation', 'Microsoft Windows', 'Microsoft Windows Hardware Compatibility Publisher', 'Microsoft Update')# 定义函数来进行签名校验
function Verify-FileSignature {param ([Parameter(Mandatory=$true)][ValidateScript({Test-Path $_ -PathType Leaf})][string]$FilePath)if (Test-Path -Path $FilePath -PathType Leaf) {$signature = Get-AuthenticodeSignature -FilePath $FilePathif ($signature.Status -eq 'Valid') {$publisher = $signature.SignerCertificate.Subject# 解析发布者信息以提取 CN 字段的值$cnValues = @(($publisher -split ', ' | Where-Object { $_ -like 'CN=*' }).Substring(3))if ($cnValues.Count -eq 1) {$cnValue = $cnValues[0]# Write-Output "CN 字段的值: $cnValue"# 判断 CN 字段是否为微软官方if ($microsoftCNS -contains $cnValue) {# Write-Output "CN 字段值为微软官方。"return "Valid"} } } return "Invalid"} return "File Not Found"}# 定义函数来检查注册表地址
function Check-RegistryPaths {param ([Parameter(Mandatory=$true)][string[]]$RegistryPaths)$invalidSignatures = @()foreach ($registryPath in $RegistryPaths) {if (Test-Path -Path $registryPath) {$subkeys = Get-ChildItem -Path $registryPathforeach ($subkey in $subkeys) {$inprocServer32Path = Join-Path -Path $subkey.PSPath -ChildPath "InprocServer32"if (Test-Path -Path $inprocServer32Path) {$defaultPropertyValue = (Get-ItemProperty -Path $inprocServer32Path -Name "(default)" -ErrorAction SilentlyContinue)."(default)"if ($defaultPropertyValue) {# 此处加 Trim('"') 是为了防止类似于 Defender 这种“有个性”的软件胡乱设置注册表$binaryFilePath = $defaultPropertyValue.Trim().Trim('"')$binaryFilePath = [Environment]::ExpandEnvironmentVariables($binaryFilePath)if (Test-Path $binaryFilePath) {$result = Verify-FileSignature -FilePath $binaryFilePathif ($result -eq "Invalid") {$invalidSignatures += @{RegistryPath = $subkeyBinaryFilePath = $binaryFilePath} Write-Host "Signature is invalid for file: $binaryFilePath" -ForegroundColor Red} elseif ($result -eq "Valid") {Write-Host "Signature is valid for file: $binaryFilePath " -ForegroundColor Green}} else {$dllFileName = Split-Path -Leaf $binaryFilePath$found = $false$searchPaths = @((Join-Path -Path $env:SystemRoot -ChildPath $dllFileName),(Join-Path -Path $env:SystemRoot -ChildPath "System32\$dllFileName"))foreach ($path in $searchPaths) {if (Test-Path $path) {$found = $true$result = Verify-FileSignature -FilePath $pathif ($result -eq "Invalid") {$invalidSignatures += @{RegistryPath = $subkeyBinaryFilePath = $path}Write-Host "Signature is invalid for file: $path" -ForegroundColor Red} elseif ($result -eq "Valid") {Write-Host "Signature is valid for file: $path " -ForegroundColor Green}break}}if (-not $found) {Write-Host "Could not find file '$dllFileName' in default search paths. Skipping signature verification."  -ForegroundColor Yellow}}} else {Write-Host "Binary file path is empty for subkey $($subkey.PSChildName)."  -ForegroundColor Yellow}}}}}# 打印不通过的签名验证信息if ($invalidSignatures.Count -gt 0) {Write-Output ""Write-Output ""Write-Output "--------------------------------------------------------"Write-Host "Invalid signatures:" -ForegroundColor Redforeach ($invalidSignature in $invalidSignatures) {$registryPath = $invalidSignature.RegistryPath$binaryFilePath = $invalidSignature.BinaryFilePathWrite-Host "Registry path: $registryPath" -ForegroundColor YellowWrite-Host "Binary file path: $binaryFilePath" -ForegroundColor YellowWrite-Output ""}Write-Output "--------------------------------------------------------"}
}# 要检查的注册表地址数组
$registryPaths = @("Registry::HKEY_CURRENT_USER\Software\Classes\CLSID","Registry::HKEY_CLASSES_ROOT\CLSID","Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Objects\"
)# 调用函数进行检查
Write-Host "Starting signature verification..."Check-RegistryPaths -RegistryPaths $registryPathsWrite-Host "Signature verification completed."

图片

发现的四个程序其中三个是 PD 虚拟机的组件,一个是 Python 组件,这是因为我的虚拟机中安装了PD虚拟机工具和Python

【 Windows Server 2016 】默认情况

图片

红队知识库icon-default.png?t=N7T8https://pc.fenchuan8.com/#/index?forum=70943&yqm=5XBP8

高质量安全学习圈子

下方详情,扫码加入

图片

免责声明

由于传播、利用本公众号所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本公众号及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2905909.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

备忘录删除了怎么恢复?解锁4个简单方法

误删除苹果备忘录是一个常见的问题,而且很容易导致我们遗失重要信息的情况。但是,如果您不幸误删了备忘录,也不必过分担心,因为有几种简单的方法可以帮助您恢复这些备忘录。备忘录删除了怎么恢复?在本文中,…

R语言使用dietaryindex包计算NHANES数据多种营养指数(2)

健康饮食指数 (HEI) 是评估一组食物是否符合美国人膳食指南 (DGA) 的指标。Dietindex包提供用户友好的简化方法,将饮食摄入数据标准化为基于指数的饮食模式,从而能够评估流行病学和临床研究中对这些模式的遵守情况,从而促进精准营养。 该软件…

2023年财报大揭秘:下一个倒闭的新势力呼之欲出

3月25日,零跑汽车公布了他们2023年的财报。财报数据显示,零跑亏损了42亿元。恰逢近段时间众多新势力车企皆公布了年报,而亏损也成了大家避不开的话题。那今天就让我们一起盘点一下各个车企的财报吧! 2023年财报大揭秘:…

Sip-6002D 双按键SIP对讲求助终端

Sip-6002D 双按键SIP对讲求助终端 一、描述 SV-6002TP是我司的一款壁挂式一键求助对讲终端,具有10/100M以太网接口,支持G.711、G.722音频解码,其接收SIP网络的音频数据,实时解码播放,还配置了麦克风输入和扬声器输出…

UI的设计

一、RGB888的显示 即红色,绿色,蓝色都为8位,即通常说的24位色。可以很好显示各种过渡颜色。从硬件上,R、G、B三基色的连接线各需要有8根,即24根数据线;软件上存储的数据量也需要24位,即3个字节&…

led驱动恒流电源0-10v可控硅调光电源控制芯片SM2318EA

LED驱动恒流电源、0-10V可控硅调光电源以及控制芯片是LED照明系统中重要的组成部分。它们共同协作,实现对LED灯的亮度、颜色等特性的精确控制。 1. LED驱动恒流电源:由于LED的伏安特性是非线性的,且其亮度与电流直接相关,因此需要…

Keil MDK如何主题美化和代码美化

目录 概要 下载地址:Keil MDK主题美化和代码美化 保存插件 配置MDK 使用方法 MDK配色 概要 编写代码时,缩进和括号的使用对于代码的清晰度和可读性至关重要。手动调整这些格式细节不仅费时,还容易出错。幸运的是,有许多工具…

python如何获取word文档的总页数

最近在搞AI. 遇到了一个问题,就是要进行doc文档的解析。并且需要展示每个文档的总页数。 利用AI. 分别尝试了chatGPT, 文心一言, github copilot,Kimi 等工具,给出来的答案都不尽如人意。 给的最多的查询方式就是下面这种。 这个…

JVM篇详细分析

JVM总体图 程序计数器: 线程私有的,每个线程一份,内部保存字节码的行号,用于记录正在执行字节码指令的地址。(可通过javap -v XX.class命令查看) java堆: 线程共享的区域,用来保存对…

Codeforces Round #818 (Div. 2) A-C

人类智慧 A. 题意&#xff1a;求满足1<a,b<n且lcm(a,b)/gcd(a,b)<3的(a,b)的个数 转化 a/gcd*b*gcd<3 可以划归为1*2 1*1 2*1 3*1 1*3 则可以转变成一个统计倍数问题 #include<bits/stdc.h> using namespace std; using ll long long; using pii pair&…

电脑最高可以装多少内存?电脑内存怎么装?

大家好&#xff0c;我是来自兼容性之家的&#xff01; 通常我们的家用电脑主机有8到16GB的运行内存。 极少数高端用户会使用32至64GB内存。 比较高端的工作站的内存在128GB左右。 同时&#xff0c;家用电脑的硬盘容量约为1TB。 那么你有没有想过一台电脑可以拥有的最大内存量…

Spring Boot 工程开发常见问题解决方案,日常开发全覆盖

本文是 SpringBoot 开发的干货集中营&#xff0c;涵盖了日常开发中遇到的诸多问题&#xff0c;通篇着重讲解如何快速解决问题&#xff0c;部分重点问题会讲解原理&#xff0c;以及为什么要这样做。便于大家快速处理实践中经常遇到的小问题&#xff0c;既方便自己也方便他人&…

氮气柜常用的制作材质有哪些?

氮气柜主要用于存储对湿度敏感或需要在低氧环境中保存的精密部件、电子元器件、化学品、文物等&#xff0c;需要确保柜体的密闭性和内部环境的稳定&#xff0c;以防止氧化、受潮或变质。 常见的材质有冷轧钢板&#xff0c;冷轧钢板通过冷轧工艺使钢材组织更紧密&#xff0c;从而…

代码随想录算法训练营 Day31 贪心算法1

Day31 贪心算法1 理论基础 贪心算法的本质&#xff1a;找到每个阶段的局部最优&#xff0c;从而去推导全局最优 贪心的两个极端&#xff1a;要么觉得特别简单&#xff0c;要么觉得特别难 贪心无套路 不像二叉树、递归&#xff0c;有固定模式 贪心题目的思考方式 做题的时候…

漏洞挖掘 | SRC中信息收集姿势分享

前言 前前后后挖了四个月的EDUSRC&#xff0c;顺利从路人甲升到了网络安全专家&#xff0c;从提交的内容来看大部分还是以中低危为主&#xff0c;主打的就是弱口令和未授权。 在这过程中还是比较浮躁的&#xff0c;因此接下来的时间还是要好好沉淀一下自身的技术&#xff0c;学…

全局UI方法-弹窗二-列表选择弹窗(ActionSheet)

1、描述 定义列表弹窗 2、接口 ActionSheet.show(value:{ title: string | Resource, message: string | Resource, autoCancel?: boolean, confrim?: {value: string | Resource, action: () > void }, cancel?: () > void, alignment?: DialogAlignment, …

ubuntu下安装minconda

1.搜索清华源 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 2.搜索conda 3.选一个合适自己的下载到本地 4.将下载的文件传入到ubuntu中 bash Miniconda3-py311_23.11.0-1-Linux-x86_64.sh 安装 5.source ~/.bashrc 激活即可&#xff08;必要步骤&#xff09;

论文笔记:分层问题-图像共注意力问答

整理了2017 Hierarchical Question-Image Co-Attention for Visual Question Answering&#xff09;论文的阅读笔记 背景模型问题定义模型结构平行共注意力交替共注意力 实验可视化 背景 视觉问答(VQA)的注意力模型在此之前已经有了很多工作&#xff0c;这种模型生成了突出显示…

Ubuntu 系统下安装 Nginx

目录 一、Nginx是什么 ​二、Ubuntu 系统下安装 Nginx 1、安装包下载 2、上传服务器并解压缩 3、依赖配置安装 4、生成编译脚本 ​5、编译 6、开始安装 7、设置为随机自启动 7.1、创建 nginx.service 文件&#xff0c;将以下内容粘贴到文件中 7.2、将 nginx.service…

JAVA的NIO和BIO底层原理分析

文章目录 一、操作系统底层IO原理1. 简介2. 操作系统进行IO的流程 二、BIO底层原理1. 什么是Socket2. JDK原生编程的BIO 三、Java原生编程的NIO1. 简介2. NIO和BIO的主要区别3. Reactor模式4. NIO的三大核心组件5. NIO核心源码分析 一、操作系统底层IO原理 1. 简介 IO&#x…