In the previous posts we have looked at some elementary PowerShell concepts and we have constructed some basic commands to export and compare data.
We did this by using an example of certificates being dumped in the “Untrusted” category by some malware. This time we will try to write a program that can undo these changes.
Remember when running PowerShell scripts, unlike single commands, that you will have to remove any execution restrictions that are in place. This command will allow everything for the current session:
Set-ExecutionPolicy Unrestricted
Objectives
One of the basic skills in each scripting language is text manipulation. I will need a few of those manipulations, before I’m able to use the html export we created last time, as a source for the list of registry keys that I need to remove. But we know they are all present in that export, so let’s get to it.
To read how we created the comparison.html file have a look at the previous post in this mini-series. First we need to get rid of some unnecessary text that was added during the process of making tables and converting to HTML.
One of the lines we want to get rid off is the header. We could take the easy route and simply delete it, but I want to build in some extra safety, so I will try to remove all the lines that do NOT contain @{Thumbprint= since those are the entries we are interested in anyways.
So how do we do that?
Get-Content c:userspublicdesktopcomparison.html | Select-String -pattern "@{Thumbprint=" | Out-File C:certainceficates1.txt
That command filters out all the lines that do not contain the @{Thumbprint= string and brings the html back to a text file, because txt files are a bit easier to work with.
Now we will need a step to get rid of the table make-up.
click to enlarge
(Get-Content C:certainceficates1.txt) -replace "<.*?>","" | Out-File C:certainceficates2.txt
This one looks a bit more complicated because of the regular expression. Regular expressions (regex) are worthy of a topic all by themselves, because of their complexity and usefulness. Maybe another day. This one looks for a “<” and deletes that and everything up to and including the closing “>”. That got rid of all the
Now, just for good measure I want to delete all the SideIndicator arrows as well. Note that in the text file they look like this: => where “>” is the html code for “>”.
(Get-Content C:certaincertificates2.txt) -replace "=>","" | Out-File C:certaincertificates3.txt
Now that we have cleaned up the file we can use the next loop to delete the registry keys. And with those keys we effectively delete the certificates. $List = Get-Content certificates.txt foreach ($Line in $List) { $First, $Second, $Third = $Line -split ';' $Thumbprint= $First -replace("@{Thumbprint=","HKLM:SOFTWAREMicrosoftSystemCertificatesDisallowedCertificates") If ($Thumbprint.length -eq 108) { $path = $Thumbprint $acl = Get-Acl $path $rule = New-Object System.Security.AccessControl.RegistryAccessRule ("Everyone","FullControl","Allow") $acl.SetAccessRule($rule) $acl |Set-Acl -Path $path Remove-Item –Path $path Write-Host ($path,"removed") } }
Explanation of what this loop does:
- It reads the text file line by line and splits each line up using the “;” as a delimiter.
- The first part of each line contains the Thumbprint, so we can ignore the rest and use only the first part.
- We replace the text added by the Get-ChildItem ( which is “@{Thumbprint=”) by the path to the registry key that we need (“HKCR:SOFTWAREMicrosoftSystemCertificatesDisallowedCertificates”)
- As an extra security measure we check if the length of the string equals 108 (the length of the key including the Thumbprint. We do not want to delete random registry keys because of some fluke in the text-files. As an exercise: think what could happen if someone used the “<” in the Subject part of the certificate.
- Then we give ourselves full control over that same registry key and remove it.
- Then the program writes to the PowerShell terminal which keys were removed.
Aftermath
When putting the program together I found out that it worked better to move the command that filters out the lines without the @{Thumbprint= string further down, because it caught some lines that were created by some unexpected word-wrap issue. So the final version of my program looks like this:
Get-ChildItem -Path cert:currentuserdisallowed -Recurse | select Thumbprint, FriendlyName, Subject| Set-Content c:userspublicdesktopcertificatesafter.txt compare-object (get-content c:userspublicdesktopcertificatesbefore.txt) (get-content c:userspublicdesktopcertificatesafter.txt)| ConvertTo-Html | Set-Content c:userspublicdesktopcomparison.html Get-Content c:userspublicdesktopcomparison.html | Select-String -pattern "@{Thumbprint=" | Out-File C:certaincertificates1.txt (Get-Content C:certaincertificates1.txt) -replace "<.*?>","" | Out-File C:certaincertificates2.txt (Get-Content C:certaincertificates2.txt) -replace "=>","" | Out-File C:certaincertificates3.txt Get-Content C:certaincertificates3.txt | Select-String -pattern "@{Thumbprint=" | Out-File C:certaincertificates.txt $List = Get-Content certificates.txt foreach ($Line in $List) { $First, $Second, $Third = $Line -split ';' $Thumbprint= $First -replace("@{Thumbprint=","HKLM:SOFTWAREMicrosoftSystemCertificatesDisallowedCertificates") If ($Thumbprint.length -eq 108) { $path = $Thumbprint $acl = Get-Acl $path $rule = New-Object System.Security.AccessControl.RegistryAccessRule ("Everyone","FullControl","Allow") $acl.SetAccessRule($rule) $acl |Set-Acl -Path $path Remove-Item –Path $path Write-Host ($path,"removed") } } del C:certaincertificates1.txt del C:certaincertificates2.txt del C:certaincertificates3.txt del C:certaincertificates.txt
Using it
In case you are interested how to use this.
In theory we would have created a folder C:certain that holds the script (the one directly above) which is then also in use as a temporary storage for all the different text files.
On the public desktop there is the text file that holds the “Before” set of certificates. On a VM that could be a part of the snapshot.
So, all we have to do to get an overview in html off the added certificates and remove them at the same time:
- Run Powershell as Administrator
- Command: Set-ExecutionPolicy Unrestricted
- Confirm with a Y
- Command: cd c:certain to change the directory
- Command: .certsfinal.ps1 to run the script
And behold, we will have c:userspublicdesktopcomparison.html with our list of added certificates and the list in the terminal to confirm that they were removed.
A word of warning for those who want to repeat this on their own VM: make sure to kill the certsdropper process as it will re-add the certificates if it’s still active. And make sure only to try it on a VM as the certificates are not the only changes it makes.
I hope you found this useful. I am well aware there are more efficient ways to do this, but all your possible improvements are welcome in the comments
Links:
Strings in PowerShell – Replace, compare, concatenate, split, substring
Pieter Arntz