{"id":8583,"date":"2017-08-04T11:10:29","date_gmt":"2017-08-04T19:10:29","guid":{"rendered":"http:\/\/www.palada.net\/index.php\/2017\/08\/04\/news-2356\/"},"modified":"2017-08-04T11:10:29","modified_gmt":"2017-08-04T19:10:29","slug":"news-2356","status":"publish","type":"post","link":"https:\/\/www.palada.net\/index.php\/2017\/08\/04\/news-2356\/","title":{"rendered":"Learning PowerShell: basic programs"},"content":{"rendered":"<p><strong>Credit to Author: Pieter Arntz| Date: Fri, 04 Aug 2017 18:00:35 +0000<\/strong><\/p>\n<p>In the previous posts we have looked at <a href=\"https:\/\/blog.malwarebytes.com\/101\/how-tos\/2017\/07\/learning-powershell-the-basics\/\" target=\"_blank\" rel=\"noopener\">some elementary PowerShell concepts<\/a> and we have constructed some <a href=\"https:\/\/blog.malwarebytes.com\/101\/2017\/08\/learning-powershell-some-basic-commands\/\" target=\"_blank\" rel=\"noopener\">basic commands to export and compare data<\/a>.<\/p>\n<p>We did this by using an example of certificates being dumped in the \u201cUntrusted\u201d category by some malware. This time we will try to write a program that can undo these changes.<\/p>\n<p>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:<\/p>\n<p><code>Set-ExecutionPolicy Unrestricted<\/code><\/p>\n<h2>Objectives<\/h2>\n<p>One of the basic skills in each scripting language is text manipulation. I will need a few of those manipulations, before I\u2019m 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\u2019s get to it.<\/p>\n<p>To read how we created the comparison.html file have a look at the <a href=\"https:\/\/blog.malwarebytes.com\/101\/2017\/08\/learning-powershell-some-basic-commands\/\" target=\"_blank\" rel=\"noopener\">previous post in this mini-series<\/a>. First we need to get rid of some unnecessary text that was added during the process of making tables and converting to HTML.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-19161\" src=\"https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/header.png\" alt=\"html header\" width=\"709\" height=\"84\" srcset=\"https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/header.png 709w, https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/header-300x36.png 300w, https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/header-600x71.png 600w\" sizes=\"auto, (max-width: 709px) 100vw, 709px\" \/><\/p>\n<p>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 <strong>@{Thumbprint= <\/strong>since those are the entries we are interested in anyways.<\/p>\n<p>So how do we do that?<\/p>\n<p><code>Get-Content c:userspublicdesktopcomparison.html | Select-String -pattern \"@{Thumbprint=\" | Out-File C:certainceficates1.txt<\/code><\/p>\n<p>That command filters out all the lines that do not contain the <strong>@{Thumbprint= <\/strong>string and brings the html back to a text file, because txt files are a bit easier to work with.<\/p>\n<p>Now we will need a step to get rid of the table make-up.<\/p>\n<div id=\"attachment_19162\" style=\"width: 610px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/tablemakeup.png\" data-rel=\"lightbox-0\" title=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-19162 size-large\" src=\"https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/tablemakeup-600x57.png\" alt=\"table layout code\" width=\"600\" height=\"57\" srcset=\"https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/tablemakeup-600x57.png 600w, https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/tablemakeup-300x29.png 300w, https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/tablemakeup.png 1440w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/a><\/p>\n<p class=\"wp-caption-text\">click to enlarge<\/p>\n<\/div>\n<p><code>(Get-Content C:certainceficates1.txt) -replace \"&lt;.*?&gt;\",\"\" | Out-File C:certainceficates2.txt<\/code><\/p>\n<p>This one looks a bit more complicated because of the <a href=\"http:\/\/www.regular-expressions.info\/\" target=\"_blank\" rel=\"noopener\">regular expression<\/a>. 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 \u201c&lt;\u201d and deletes that and everything up to and including the closing \u201c&gt;\u201d.\u00a0 That got rid of all the &lt;tr&gt;, &lt;td&gt;, &lt;\/td&gt;, and &lt;\/tr&gt; bits that were previously needed for the table. The <em>Get-Content<\/em> call needs to be in parentheses or PowerShell would regard <em>\u2013 replace<\/em> as an argument for that call and throw an error, as <em>-replace<\/em> is not defined as an argument for that cmdlet.<\/p>\n<p>Now, just for good measure I want to delete all the <strong>SideIndicator<\/strong> arrows as well. Note that in the text file they look like this: <strong>=&amp;gt; <\/strong>where \u201c&amp;gt;\u201d is the html code for \u201c&gt;\u201d.<\/p>\n<p><code>(Get-Content C:certaincertificates2.txt) -replace \"=&amp;gt;\",\"\" | Out-File C:certaincertificates3.txt<\/code><\/p>\n<p>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.<br \/> <code><br \/> $List = Get-Content certificates.txt<br \/> foreach ($Line in $List) {<br \/> $First, $Second, $Third = $Line -split ';'<br \/> $Thumbprint= $First -replace(\"@{Thumbprint=\",\"HKLM:SOFTWAREMicrosoftSystemCertificatesDisallowedCertificates\")<br \/> If ($Thumbprint.length -eq 108) {<br \/> $path = $Thumbprint<br \/> $acl = Get-Acl $path<br \/> $rule = New-Object System.Security.AccessControl.RegistryAccessRule (\"Everyone\",\"FullControl\",\"Allow\")<br \/> $acl.SetAccessRule($rule)<br \/> $acl |Set-Acl -Path $path<br \/> Remove-Item \u2013Path $path<br \/> Write-Host ($path,\"removed\")<br \/> }<br \/> }<br \/> <\/code><br \/> Explanation of what this loop does:<\/p>\n<ul>\n<li>It reads the text file line by line and splits each line up using the \u201c;\u201d as a delimiter.<\/li>\n<li>The first part of each line contains the Thumbprint, so we can ignore the rest and use only the first part.<\/li>\n<li>We replace the text added by the Get-ChildItem ( which is &#8220;@{Thumbprint=&#8221;) by the path to the registry key that we need (&#8220;HKCR:SOFTWAREMicrosoftSystemCertificatesDisallowedCertificates&#8221;)<\/li>\n<li>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 \u201c&lt;\u201d in the Subject part of the certificate.<\/li>\n<li>Then we give ourselves full control over that same registry key and remove it.<\/li>\n<li>Then the program writes to the PowerShell terminal which keys were removed.<\/li>\n<\/ul>\n<h2>Aftermath<\/h2>\n<p>When putting the program together I found out that it worked better to move the command that filters out the lines without the <strong>@{Thumbprint= <\/strong>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:<br \/> <code><br \/> Get-ChildItem -Path cert:currentuserdisallowed -Recurse | select Thumbprint, FriendlyName, Subject| Set-Content c:userspublicdesktopcertificatesafter.txt<br \/> compare-object (get-content c:userspublicdesktopcertificatesbefore.txt) (get-content c:userspublicdesktopcertificatesafter.txt)| ConvertTo-Html | Set-Content c:userspublicdesktopcomparison.html<br \/> Get-Content c:userspublicdesktopcomparison.html | Select-String -pattern \"@{Thumbprint=\" | Out-File C:certaincertificates1.txt<br \/> (Get-Content C:certaincertificates1.txt) -replace \"&lt;.*?&gt;\",\"\" | Out-File C:certaincertificates2.txt<br \/> (Get-Content C:certaincertificates2.txt) -replace \"=&amp;gt;\",\"\" | Out-File C:certaincertificates3.txt<br \/> Get-Content C:certaincertificates3.txt | Select-String -pattern \"@{Thumbprint=\" | Out-File C:certaincertificates.txt<br \/> $List = Get-Content certificates.txt<br \/> foreach ($Line in $List) {<br \/> $First, $Second, $Third = $Line -split ';'<br \/> $Thumbprint= $First -replace(\"@{Thumbprint=\",\"HKLM:SOFTWAREMicrosoftSystemCertificatesDisallowedCertificates\")<br \/> If ($Thumbprint.length -eq 108) {<br \/> $path = $Thumbprint<br \/> $acl = Get-Acl $path<br \/> $rule = New-Object System.Security.AccessControl.RegistryAccessRule (\"Everyone\",\"FullControl\",\"Allow\")<br \/> $acl.SetAccessRule($rule)<br \/> $acl |Set-Acl -Path $path<br \/> Remove-Item \u2013Path $path<br \/> Write-Host ($path,\"removed\")<br \/> }<br \/> }<br \/> del C:certaincertificates1.txt<br \/> del C:certaincertificates2.txt<br \/> del C:certaincertificates3.txt<br \/> del C:certaincertificates.txt<br \/> <\/code><\/p>\n<h2>Using it<\/h2>\n<p>In case you are interested how to use this.<\/p>\n<p>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.<\/p>\n<p>On the public desktop there is the text file that holds the \u201cBefore\u201d set of certificates. On a VM that could be a part of the snapshot.<\/p>\n<p>So, all we have to do to get an overview in html off the added certificates and remove them at the same time:<\/p>\n<ul>\n<li>Run Powershell as Administrator<\/li>\n<li>Command: <strong>Set-ExecutionPolicy Unrestricted<\/strong><\/li>\n<li>Confirm with a <strong>Y<\/strong><\/li>\n<li>Command:<strong> cd c:certain <\/strong>to change the directory<\/li>\n<li>Command: <strong>.certsfinal.ps1 <\/strong>to run the script<\/li>\n<\/ul>\n<p>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.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-19163\" src=\"https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/RemovedList.png\" alt=\"\" width=\"877\" height=\"738\" srcset=\"https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/RemovedList.png 877w, https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/RemovedList-300x252.png 300w, https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/08\/RemovedList-600x505.png 600w\" sizes=\"auto, (max-width: 877px) 100vw, 877px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>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\u2019s still active. And make sure only to try it on a VM as the certificates are not the only changes it makes.<\/p>\n<p>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<\/p>\n<h3>Links:<\/h3>\n<p><a href=\"https:\/\/4sysops.com\/archives\/strings-in-powershell-replace-compare-concatenate-split-substring\/\" target=\"_blank\" rel=\"noopener\">Strings in PowerShell &#8211; Replace, compare, concatenate, split, substring<\/a><\/p>\n<p><a href=\"https:\/\/www.computerhope.com\/jargon\/r\/regex.htm\" target=\"_blank\" rel=\"noopener\">Regex<\/a><\/p>\n<p>Pieter Arntz<\/p>\n<p>The post <a rel=\"nofollow\" href=\"https:\/\/blog.malwarebytes.com\/101\/2017\/08\/learning-powershell-basic-programs\/\">Learning PowerShell: basic programs<\/a> appeared first on <a rel=\"nofollow\" href=\"https:\/\/blog.malwarebytes.com\">Malwarebytes Labs<\/a>.<\/p>\n<p><a href=\"https:\/\/blog.malwarebytes.com\/101\/2017\/08\/learning-powershell-basic-programs\/\" target=\"bwo\" >https:\/\/blog.malwarebytes.com\/feed\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><strong>Credit to Author: Pieter Arntz| Date: Fri, 04 Aug 2017 18:00:35 +0000<\/strong><\/p>\n<table cellpadding='10'>\n<tr>\n<td valign='top' align='center'><a href='https:\/\/blog.malwarebytes.com\/101\/2017\/08\/learning-powershell-basic-programs\/' title='Learning PowerShell: basic programs'><img src='https:\/\/blog.malwarebytes.com\/wp-content\/uploads\/2017\/07\/Powershellhero.jpg' border='0'  width='300px'  \/><\/a><\/td>\n<\/tr>\n<tr>\n<td valign='top' align='left'>In this last part of the short series about the basics of PowerShell we  assemble a small script from scratch and explain how it works. <\/p>\n<p>Categories: <\/p>\n<ul class=\"post-categories\">\n<li><a href=\"https:\/\/blog.malwarebytes.com\/category\/101\/\" rel=\"category tag\">101<\/a><\/li>\n<li><a href=\"https:\/\/blog.malwarebytes.com\/category\/101\/how-tos\/\" rel=\"category tag\">How-tos<\/a><\/li>\n<\/ul>\n<p>Tags: <a href=\"https:\/\/blog.malwarebytes.com\/tag\/certificates\/\" rel=\"tag\">certificates<\/a><a href=\"https:\/\/blog.malwarebytes.com\/tag\/pieter-arntz\/\" rel=\"tag\">Pieter Arntz<\/a><a href=\"https:\/\/blog.malwarebytes.com\/tag\/powershell\/\" rel=\"tag\">powershell<\/a><a href=\"https:\/\/blog.malwarebytes.com\/tag\/program\/\" rel=\"tag\">program<\/a><a href=\"https:\/\/blog.malwarebytes.com\/tag\/script\/\" rel=\"tag\">script<\/a><\/p>\n<table width='100%'>\n<tr>\n<td align=right>\n<p><b>(<a href='https:\/\/blog.malwarebytes.com\/101\/2017\/08\/learning-powershell-basic-programs\/' title='Learning PowerShell: basic programs'>Read more&#8230;<\/a>)<\/b><\/p>\n<\/td>\n<\/tr>\n<\/table>\n<\/td>\n<\/tr>\n<\/table>\n<p>The post <a rel=\"nofollow\" href=\"https:\/\/blog.malwarebytes.com\/101\/2017\/08\/learning-powershell-basic-programs\/\">Learning PowerShell: basic programs<\/a> appeared first on <a rel=\"nofollow\" href=\"https:\/\/blog.malwarebytes.com\">Malwarebytes Labs<\/a>.<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[10488,10378],"tags":[10519,13240,11171,10523,11191,13348,13349],"class_list":["post-8583","post","type-post","status-publish","format-standard","hentry","category-malwarebytes","category-security","tag-10519","tag-certificates","tag-how-tos","tag-pieter-arntz","tag-powershell","tag-program","tag-script"],"_links":{"self":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/8583","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/comments?post=8583"}],"version-history":[{"count":0,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/8583\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/media?parent=8583"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/categories?post=8583"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/tags?post=8583"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}