在之前的文章中,我们已经看过了一些基本的PowerShell概念我们已经构建了一些用于导出和比较数据的基本命令

我们通过使用一个由恶意软件转储到“不可信”类别的证书的例子来做到这一点。这一次,我们将尝试编写一个可以撤销这些更改的程序。

请记住,在运行PowerShell脚本时,与单个命令不同,您必须删除现有的任何执行限制。这个命令将允许当前会话的所有内容:

Set-ExecutionPolicy无限制的

目标

每种脚本语言的基本技能之一是文本操作。我将需要一些这些操作,在我能够使用我们上次创建的html导出,作为一个源的注册表项列表,我需要删除。但我们知道它们都存在于导出中,所以让我们开始吧。

要了解我们是如何创建compare .html文件的,请查看这个迷你系列的前一篇文章.首先,我们需要去除在制作表格和转换为HTML过程中添加的一些不必要的文本。

html头

我们想要去掉的其中一行是header。我们可以采取简单的方法,简单地删除它,但我想建立一些额外的安全,所以我将尝试删除所有不包含的行@{拇指指纹=因为这些都是我们感兴趣的条目。

我们怎么做呢?

Get-Content c:\users\public\desktop\comparison.html | Select-String -pattern "@{Thumbprint=" | Out-File c:\ certain\ceficates1.txt

该命令过滤掉所有不包含@{拇指指纹=字符串,并将HTML返回到文本文件,因为TXT文件更容易处理。

现在我们需要一个步骤来去除表上的化妆品。

表布局代码

点击放大

(Get-Content C:\certain\ceficates1.txt) -replace "\<.*?Out-File C:\certain\ceficates2.txt

这个看起来有点复杂,因为正则表达式.正则表达式(regex)本身就值得作为一个主题讨论,因为它很复杂,也很有用。也许另一天。这个函数查找一个“<”并删除它以及直到并包括结束的“>”的所有内容。这样就消除了表之前需要的所有、、和位。的获取内容调用需要在括号中,否则PowerShell会考虑——取代作为该调用的参数并抛出错误,如取代没有定义为该cmdlet的参数。

现在,为了方便起见,我想删除所有的SideIndicator箭头。注意,在文本文件中,它们看起来像这样:=比;其中>为“>”的HTML代码。

(Get-Content C:\certain\certificates2.txt) -replace "=>","" | Out-File C:\certain\certificates3.txt

现在我们已经清理了文件,我们可以使用下一个循环来删除注册表项。使用这些密钥,我们可以有效地删除证书。

$List = Get-Content certificates.txt
foreach ($Line in $List) {
$First, $Second, $Third = $Line -split ';'
拇指指纹=第一次取代美元(“@{拇指指纹=”、“HKLM: \微软软件\ \ SystemCertificates \ \不允许\证书”)
如果($拇指指纹。长度-eq 108) {
= $ $ path拇指指纹
$acl = Get-Acl
$rule = New-Object System.Security.AccessControl.RegistryAccessRule ("Everyone","FullControl","Allow")
(acl.SetAccessRule美元规则)
$acl |Set-Acl -Path $path
美元Remove-Item路径路径
Write-Host($路径,“删除”)



解释这个循环的作用:

  • 它逐行读取文本文件,并使用“;”作为分隔符将每行分开。
  • 每一行的第一部分包含Thumbprint,所以我们可以忽略其余部分,只使用第一部分。
  • 我们将Get-ChildItem(即" @{Thumbprint= ")添加的文本替换为所需的注册表项的路径(" HKCR:\SOFTWARE\Microsoft\SystemCertificates\Disallowed\Certificates\ ")
  • 作为额外的安全措施,我们检查字符串的长度是否等于108(包含Thumbprint的密钥的长度)。我们不想因为文本文件中的一些侥幸而删除随机注册表项。作为练习:请考虑如果有人在证书的Subject部分中使用“<”会发生什么情况。
  • 然后我们让自己完全控制同一个注册表项并删除它。
  • 然后程序将删除的键写入PowerShell终端。

之后

当把程序放在一起时,我发现移动过滤出没有的行的命令效果更好@{拇指指纹=因为它捕获了一些由意外的换行问题创建的行。程序的最终版本是这样的:

Get-ChildItem -Path cert:\currentuser\disallowed -Recurse | select Thumbprint, FriendlyName, Subject| Set-Content c:\users\public\desktop\certificatesafter.txt
get- object (get-content c:\users\public\desktop\certificatesbefore.txt) (get-content c:\users\public\desktop\certificatesafter.txt
Get-Content c:\users\public\desktop\comparison.html | Select-String -pattern "@{Thumbprint=" | Out-File c:\ certain\certificates1.txt
(Get-Content C:\certain\certificates1.txt) -replace "\<.*?| Out-File C:\certain\certificates2.txt
(Get-Content C:\certain\certificates2.txt) -replace "=>","" | Out-File C:\certain\certificates3.txt
Get-Content C:\certain\certificates3.txt | Select-String -pattern "@{Thumbprint=" | Out-File C:\certain\certificates3.txt
$List = Get-Content certificates.txt
foreach ($Line in $List) {
$First, $Second, $Third = $Line -split ';'
拇指指纹=第一次取代美元(“@{拇指指纹=”、“HKLM: \微软软件\ \ SystemCertificates \ \不允许\证书”)
如果($拇指指纹。长度-eq 108) {
= $ $ path拇指指纹
$acl = Get-Acl
$rule = New-Object System.Security.AccessControl.RegistryAccessRule ("Everyone","FullControl","Allow")
(acl.SetAccessRule美元规则)
$acl |Set-Acl -Path $path
美元Remove-Item路径路径
Write-Host($路径,“删除”)


德尔C: \ \ certificates1.txt
德尔C: \ \ certificates2.txt
德尔C: \ \ certificates3.txt
德尔C: \ \ certificates.txt

使用它

如果你对如何使用这个感兴趣。

理论上,我们应该创建一个文件夹C:\certain来保存脚本(直接上面的那个),然后它也被用作所有不同文本文件的临时存储。

在公共桌面中,有一个保存“Before”证书集的文本文件。该虚拟机可能是快照的一部分。

所以,我们所要做的是在html中获得一个概述,并在同一时间删除它们:

  • 以管理员身份运行Powershell
  • 命令:Set-ExecutionPolicy无限制的
  • 确认与Y
  • 命令:cd c: \确定更改目录
  • 命令:。\ certsfinal.ps1运行脚本

看,我们将有c:\users\public\desktop\comparison.html和我们添加的证书列表,以及在终端中确认它们被删除的列表。

对于那些想要在自己的VM上重复此操作的人,有一个警告:请确保终止certsdropper进程,因为如果它仍然处于活动状态,它将重新添加证书。并确保只在VM上尝试它,因为证书并不是它所做的唯一更改。

我希望这对你有用。我很清楚有更有效的方法来做到这一点,但欢迎您在评论中提出所有可能的改进

链接:

PowerShell中的字符串——替换、比较、连接、分割、子字符串

正则表达式

Pieter Arntz