{"id":18621,"date":"2022-03-29T11:20:56","date_gmt":"2022-03-29T19:20:56","guid":{"rendered":"https:\/\/www.palada.net\/index.php\/2022\/03\/29\/news-12354\/"},"modified":"2022-03-29T11:20:56","modified_gmt":"2022-03-29T19:20:56","slug":"news-12354","status":"publish","type":"post","link":"https:\/\/www.palada.net\/index.php\/2022\/03\/29\/news-12354\/","title":{"rendered":"Reconstructing PowerShell scripts from multiple Windows event logs"},"content":{"rendered":"<p><strong>Credit to Author: Vikas Singh| Date: Tue, 29 Mar 2022 18:27:50 +0000<\/strong><\/p>\n<div class=\"entry-content lg:prose-lg mx-auto prose max-w-4xl\">\n<p><span data-contrast=\"auto\">Adversaries continue to abuse PowerShell to execute malicious commands and scripts. It is easy to understand its popularity among attackers: Not only is it present on all versions of Windows by default (and crucial to so many Windows applications that few choose to disable it), this powerful interactive CLI and scripting environment can execute code in-memory without malware ever touching the disk. This poses a problem for defenders and researchers alike.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">In a previous post, we <\/span><a href=\"https:\/\/community.sophos.com\/sophos-labs\/b\/blog\/posts\/powershell-command-history-forensics\"><span data-contrast=\"none\">explained<\/span><\/a><span data-contrast=\"auto\"> various forensic artifacts left behind by PowerShell. With the release of PowerShell 5.0 back in 2015, Script Block Logging was enabled by default. This feature records commands and entire scripts in event logs as they execute. If a script is very large, PowerShell breaks it into multiple parts before logging those under <\/span><b><span data-contrast=\"auto\">Event ID 4104, <\/span><\/b><span data-contrast=\"auto\">which will be the focus of this article.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">The open-source community has a variety of effective tools to use when parsing or automatically hunting for suspicious events. In a recent post, we took a step-by-step look at <\/span><a href=\"https:\/\/community.sophos.com\/sophos-labs\/b\/blog\/posts\/decoding-malicious-powershell\"><span data-contrast=\"none\">decoding<\/span><\/a><span data-contrast=\"auto\"> malicious PowerShell activity in a specific incident, using such tools. However, the ability to extract or reconstruct (partially or in full) a very large PowerShell script from multiple event records is still lacking in most of the tools available.\u00a0<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span class=\"NormalTextRun SCXW134189397 BCX0\">W<\/span><span class=\"NormalTextRun SCXW134189397 BCX0\">hen a large PowerShell script runs, it results<\/span><span class=\"NormalTextRun SCXW134189397 BCX0\"> in <\/span><span class=\"NormalTextRun AdvancedProofingIssueV2 SCXW134189397 BCX0\">a number of<\/span><span class=\"NormalTextRun SCXW134189397 BCX0\"> fragmented artifacts deposited across multiple logs. Filtering for event ID 4104 returns a list of those artifacts. <\/span><span class=\"NormalTextRun SCXW134189397 BCX0\">The content<\/span><span class=\"NormalTextRun SCXW134189397 BCX0\"> o<\/span><span class=\"NormalTextRun SCXW134189397 BCX0\">f<\/span><span class=\"NormalTextRun SCXW134189397 BCX0\"> one of these artifacts, contained in the\u00a0 <code>C:WindowsSystem32winevtLogsMicrosoft-Windows-PowerShell%4Operational.evtx<\/code> event log, is shown in the lower portion of the Event Viewer screen in Figure 1.<\/span><\/p>\n<pre class=\"ip iq ir is it iu iv iw\"><span id=\"967b\" class=\"gv ix iy fy iz b dt ja jb s jc\" data-selectable-paragraph=\"\"><\/span><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/02_LargeEvent_121Records.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-80779\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/02_LargeEvent_121Records.png?w=640\" alt=\"\" width=\"640\" height=\"582\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/02_LargeEvent_121Records.png 1489w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/02_LargeEvent_121Records.png?resize=300,273 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/02_LargeEvent_121Records.png?resize=768,698 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/02_LargeEvent_121Records.png?resize=1024,931 1024w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/pre>\n<p><i><span data-contrast=\"auto\">Figure 1: 4104 events in the Operational.evtx log<\/span><\/i><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">The <\/span><b><span data-contrast=\"auto\">ScriptBlock ID <\/span><\/b><span data-contrast=\"auto\">for this fragment, <code>51baf005-40a5-4878-ab90-5ecc51cab9af<\/code>, appears on the right in Figure 2.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/03_ScriptBlockID.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-80780\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/03_ScriptBlockID.png?w=640\" alt=\"\" width=\"640\" height=\"483\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/03_ScriptBlockID.png 1615w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/03_ScriptBlockID.png?resize=300,226 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/03_ScriptBlockID.png?resize=768,579 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/03_ScriptBlockID.png?resize=1024,772 1024w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/03_ScriptBlockID.png?resize=1536,1158 1536w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p><i><span data-contrast=\"auto\">Figure 2: Detail showing ScriptBlock ID for fragment 9<\/span><\/i><span data-contrast=\"auto\">7<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">To create a single PowerShell object containing all the artifacts found with this process, open PowerShell ISE, replace the location of the offline EVTX (in our example, <code>Operational.evtx<\/code>) and ScriptBlock ID (in our example, <code>51baf005-40a5-4878-ab90-5ecc51cab9af<\/code>), and execute the following to create a single PowerShell object as shown in the example below.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<pre class=\"ip iq ir is it iu iv iw\"><span id=\"60cf\" class=\"gv ix iy fy iz b dt ja jb s jc\" data-selectable-paragraph=\"\"><span style=\"color: #b529f7\">#Filtering out all the Event Records associated with the ScriptBlockID into a single PS Object<\/span>  $StoreArrayHere = Get-WinEvent -FilterHashtable @{ Path=\"<span style=\"color: #da3e00\">C:SampleEVTXMicrosoft-Windows-PowerShell%4Operational.evtx<\/span>\"; ProviderName=\u201cMicrosoft-Windows-PowerShell\u201d; Id = 4104 } | Where-Object { $_.Message -like '*<span style=\"color: #da3e00\">51baf005-40a5-4878-ab90-5ecc51cab9af<\/span>*' }  <\/span><span id=\"5d4e\" class=\"gv ix iy fy iz b dt lt lu lv lw lx jb s jc\" data-selectable-paragraph=\"\"><span style=\"color: #b529f7\">#Sorting the objects in the sequence to maintain the order of script.<\/span>  $SortIt = $StoreArrayHere | sort { $_.Properties[0].Value }  <\/span><span class=\"gv ix iy fy iz b dt lt lu lv lw lx jb s jc\" data-selectable-paragraph=\"\"><span style=\"color: #b529f7\">#Display a few columns of interest.<\/span>  $SortIt | select TimeCreated,ActivityId,Id,Message  <\/span><\/pre>\n<p><span class=\"TextRun SCXW238853788 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW238853788 BCX0\">In Figure 3,<\/span><span class=\"NormalTextRun SCXW238853788 BCX0\"> only a <\/span><span class=\"NormalTextRun SCXW238853788 BCX0\">portion<\/span><span class=\"NormalTextRun SCXW238853788 BCX0\"> of the script <\/span><span class=\"NormalTextRun SCXW238853788 BCX0\">is <\/span><span class=\"NormalTextRun SCXW238853788 BCX0\">recorded in the event logs, specifically segments 97 to 121<\/span><span class=\"NormalTextRun SCXW238853788 BCX0\">. D<\/span><span class=\"NormalTextRun SCXW238853788 BCX0\">ue to<\/span><span class=\"NormalTextRun SCXW238853788 BCX0\"> scheduled<\/span><span class=\"NormalTextRun SCXW238853788 BCX0\"> log rotation, <\/span><span class=\"NormalTextRun SCXW238853788 BCX0\">dozens of<\/span><span class=\"NormalTextRun SCXW238853788 BCX0\"> segments are no longer available.<\/span><\/span><span class=\"EOP SCXW238853788 BCX0\" data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><br \/> <a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/04_IncompleteScriptLogged.png\"><br \/> <img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-80781\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/04_IncompleteScriptLogged.png?w=640\" alt=\"\" width=\"640\" height=\"466\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/04_IncompleteScriptLogged.png 1678w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/04_IncompleteScriptLogged.png?resize=300,219 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/04_IncompleteScriptLogged.png?resize=768,560 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/04_IncompleteScriptLogged.png?resize=1024,746 1024w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/04_IncompleteScriptLogged.png?resize=1536,1120 1536w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><em><span class=\"TextRun SCXW32093524 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW32093524 BCX0\">Figure 3: Fragments appearing in the event log<\/span><\/span><\/em><\/p>\n<p id=\"7120\" class=\"ho hp fy hq b hr ii hs ht hu ij hv hw hx ik hy hz ia il ib ic id im ie if ih dn gv\" data-selectable-paragraph=\"\"><span class=\"TextRun SCXW34304681 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW34304681 BCX0\">However, even partial data may be helpful during an incident-response investigation, making this extraction technique useful even when the condition of the log data cannot be <\/span><span class=\"NormalTextRun SCXW34304681 BCX0\">ascertained<\/span><span class=\"NormalTextRun SCXW34304681 BCX0\"> prior to the operation.<\/span><\/span><span class=\"EOP SCXW34304681 BCX0\" data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span class=\"TextRun SCXW229616028 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW229616028 BCX0\">To <\/span><span class=\"NormalTextRun SCXW229616028 BCX0\">attempt<\/span><span class=\"NormalTextRun SCXW229616028 BCX0\"> the <\/span><\/span><span class=\"TextRun SCXW229616028 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW229616028 BCX0\">Listing<\/span><\/span><span class=\"TextRun SCXW229616028 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW229616028 BCX0\"> and <\/span><\/span><span class=\"TextRun SCXW229616028 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW229616028 BCX0\">Extraction <\/span><\/span><span class=\"TextRun SCXW229616028 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW229616028 BCX0\">process <\/span><\/span><a class=\"Hyperlink SCXW229616028 BCX0\" href=\"https:\/\/gist.github.com\/vikas891\/841ac223e69913b49dc2aa9cc8663e34\" target=\"_blank\" rel=\"noreferrer noopener\"><span class=\"TextRun Underlined SCXW229616028 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"none\"><span class=\"NormalTextRun SCXW229616028 BCX0\" data-ccp-charstyle=\"Hyperlink\">via a simple script<\/span><\/span><\/a><span class=\"TextRun SCXW229616028 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW229616028 BCX0\"> available on GitHub, <\/span><\/span>use the PowerShell script <code>ExtractAllScripts.ps1<\/code> by giving it the <code>-List<\/code> parameter<span class=\"TextRun SCXW59836502 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW59836502 BCX0\">, as shown in Figure 4. (As a convenience, we link to and show the full script at the end of this post.)<\/span><\/span><\/p>\n<p><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/06_ScriptedApproach.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-80792\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/06_ScriptedApproach.png?w=640\" alt=\"\" width=\"640\" height=\"233\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/06_ScriptedApproach.png 3159w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/06_ScriptedApproach.png?resize=300,109 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/06_ScriptedApproach.png?resize=768,280 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/06_ScriptedApproach.png?resize=1024,373 1024w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/06_ScriptedApproach.png?resize=1536,559 1536w, https:\/\/news.sophos.com\/wp-content\/uploads\/2021\/12\/06_ScriptedApproach.png?resize=2048,746 2048w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><em>Figure 4: Concatenating the results<\/em><\/p>\n<p>To extract selected scripts, give the <code>ExtractAllScripts.ps1<\/code> script the <code>-ScriptBlockID <strong>[ID]<\/strong><\/code>\u00a0 parameter. An excerpt from the script shows what happens behind the scenes:<\/p>\n<pre class=\"ip iq ir is it iu iv iw\">$StoreArrayHere = Get-WinEvent -FilterHashtable @{ Path=\"<span style=\"color: #da3e00\">C:SampleEVTXMicrosoft-Windows-PowerShell%4Operational.evtx<\/span>\"; ProviderName=\u201cMicrosoft-Windows-PowerShell\u201d; Id = 4104 } | Where-Object { $_.Message -like '*<span style=\"color: #da3e00\">97b04021-6c0b-4fd2-8f57-39ada2599db8<\/span>*' }   $SortIt = $StoreArrayHere | sort { $_.Properties[0].Value }   <span style=\"color: #b529f7\">#Joining the specific property of all event records and exporting to a single file.<\/span>   $MergedScript = -join ($SortIt | % { $_.Properties[2].Value }) | Out-File <span style=\"color: #da3e00\">34CE.  <\/span><\/pre>\n<p>PowerShell\u2019s popularity among attackers stems in part from its ubiquity and its ability to run malicious code in memory. Defenders must therefore examine whatever script traces may be found in logs, even if such traces may be scattered across multiple locations. Since log-rotation intervals and script sizes both vary, the ultimate output of the process detailed in this post may retrieve some, most, or all of the script in question. The technique itself, however, enables defenders to make the most of what is available.<\/p>\n<h3><span class=\"NormalTextRun SCXW40538730 BCX0\">Appendix<\/span><span class=\"NormalTextRun SCXW40538730 BCX0\">: ExtractAllScripts.ps1<\/span><\/h3>\n<p><span class=\"TextRun SCXW75928750 BCX0\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW75928750 BCX0\"><a href=\"https:\/\/gist.github.com\/vikas891\/841ac223e69913b49dc2aa9cc8663e34.js\">https:\/\/gist.github.com\/vikas891\/841ac223e69913b49dc2aa9cc8663e34.js<\/a><\/span><\/span><span class=\"EOP SCXW75928750 BCX0\" data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<pre>#Usage:  #Usage:\u00a0  #\u00a0  #NOTE: Remember to include the path to Microsoft-Windows-PowerShell%4Operational.evtx below.\u00a0\u00a0  #\u00a0  #C:&gt;ExtractAllScripts.ps1\u00a0\u00a0\u00a0  #The default behavior of the script is to assimilate and extract every script\/command to disk.\u00a0  #\u00a0  #C:ExtractAllScripts -List\u00a0  #This will only list Script Block IDs with associated Script Names(if logged.)\u00a0  #\u00a0  #C:&gt;ExtractAllScripts.ps1 -ScriptBlockID aeb8cd23-3052-44f8-b6ba-ff3c083e912d\u00a0  #This will only extract the script corresponding to the user specified ScriptBlock ID\u00a0  #\u00a0  #Twitter: @vikas891\u00a0  \u00a0  param ($ScriptBlockID, [switch]$List)\u00a0  $StoreArrayHere = Get-WinEvent -FilterHashtable @{ Path=\"Microsoft-Windows-PowerShell%4Operational.evtx\"; ProviderName=\u201cMicrosoft-Windows-PowerShell\u201d; Id = 4104 }\u00a0\u00a0  $Desc = $StoreArrayHere | sort -Descending { $_.Properties[1].Value }\u00a0\u00a0  $ArrayofUniqueIDs = @()\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0  if(!$ScriptBlockID)\u00a0  {\u00a0  \u00a0\u00a0\u00a0 $Desc | %{ $ArrayofUniqueIDs += $_.Properties[3].Value }\u00a0  }\u00a0  else\u00a0  {\u00a0  \u00a0\u00a0\u00a0 $Desc | %{ $ArrayofUniqueIDs += $_.Properties[3].Value }\u00a0  \u00a0\u00a0\u00a0 if($ScriptBlockID -in $ArrayofUniqueIDs)\u00a0  \u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0 $ArrayofUniqueIDs = $ScriptBlockID\u00a0  \u00a0\u00a0\u00a0 }\u00a0  \u00a0\u00a0\u00a0 else\u00a0  \u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0 \"\"\u00a0  \u00a0\u00a0\u00a0 Write-Host \"[!] Specified Script Block ID does not exist. Exiting..\" -ForegroundColor Red\u00a0  \u00a0\u00a0\u00a0 break\u00a0  \u00a0\u00a0\u00a0 }\u00a0  }\u00a0  $ArrayofUniqueIDs = $ArrayofUniqueIDs | select -Unique\u00a0  \u00a0  if($List)\u00a0  {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach ($a in $ArrayofUniqueIDs)\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $Temp = $StoreArrayHere | Where-Object { $_.Message -like \"*$a*\" }\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $SortIt = $Temp | sort { $_.Properties[0].Value }\u00a0\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"\"\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if($SortIt[0].Properties[4].Value)\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $OriginalName = Split-Path -Path $SortIt[0].Properties[4].Value -Leaf\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $FileName = \"$($a)_$($OriginalName)\"\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $DisplayName = $SortIt[0].Properties[4].Value\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $OriginalName = ''\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $FileName = $a\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $DisplayName = 'NULL'\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \"Script ID: \"\u00a0\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline $a -ForegroundColor Yellow\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | \" -ForegroundColor White\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \"Script Name:\"\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline $DisplayName -ForegroundColor Magenta\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $NumberOfRecords = $Temp.Count\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $MessageTotal = $Temp[0] | % {$_.Properties[1].Value}\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if($NumberOfRecords -eq $MessageTotal)\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | Complete Script \" -ForegroundColor Green\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | Event Records Logged\"$NumberOfRecords\/$MessageTotal\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"\"\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | InComplete Script Logged\" -ForegroundColor Red\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | Event Records Logged\"$NumberOfRecords\/$MessageTotal\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"\"\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0\u00a0\u00a0\u00a0\u00a0  \u00a0\u00a0\u00a0 }\u00a0  break\u00a0  }\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0  foreach ($a in $ArrayofUniqueIDs)\u00a0  {\u00a0  \u00a0\u00a0\u00a0 $Temp = $StoreArrayHere | Where-Object { $_.Message -like \"*$a*\" }\u00a0  \u00a0\u00a0\u00a0 $SortIt = $Temp | sort { $_.Properties[0].Value }\u00a0\u00a0  \u00a0\u00a0\u00a0 \"\"\u00a0  \u00a0\u00a0\u00a0 if($SortIt[0].Properties[4].Value)\u00a0  \u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $OriginalName = Split-Path -Path $SortIt[0].Properties[4].Value -Leaf\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $FileName = \"$($a)_$($OriginalName)\"\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $DisplayName = $SortIt[0].Properties[4].Value\u00a0  \u00a0\u00a0\u00a0 }\u00a0  \u00a0\u00a0\u00a0 else\u00a0  \u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $OriginalName = ''\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $FileName = $a\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $DisplayName = 'NULL'\u00a0  \u00a0\u00a0\u00a0 }\u00a0  \u00a0\u00a0\u00a0 Write-Host -NoNewline \"Extracting \"\u00a0\u00a0  \u00a0\u00a0\u00a0 Write-Host -NoNewline $a -ForegroundColor Yellow\u00a0  \u00a0\u00a0\u00a0 if ($OriginalName)\u00a0  \u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline _$OriginalName -ForegroundColor Magenta\u00a0  \u00a0\u00a0\u00a0 }\u00a0  \u00a0\u00a0\u00a0 Write-Host -NoNewline \" | \" -ForegroundColor White\u00a0  \u00a0\u00a0\u00a0 Write-Host -NoNewline \"ScriptName:\"\u00a0  \u00a0\u00a0\u00a0 Write-Host -NoNewline $DisplayName -ForegroundColor Magenta\u00a0  \u00a0\u00a0\u00a0 $MergedScript = -join ($SortIt | % { $_.Properties[2].Value }) | Out-File $FileName\u00a0  \u00a0\u00a0\u00a0 $NumberOfRecords = $Temp.Count\u00a0  \u00a0\u00a0\u00a0 $MessageTotal = $Temp[0] | % {$_.Properties[1].Value}\u00a0  \u00a0\u00a0\u00a0 if($NumberOfRecords -eq $MessageTotal)\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | Complete Script Logged\u00a0 \" -ForegroundColor Green\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | Event Records Exported\"$NumberOfRecords\/$MessageTotal\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | Number of lines\" (Get-Content $FileName).Length\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"\"\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0  \u00a0\u00a0\u00a0 else\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | InComplete Script Logged\" -ForegroundColor Red\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ren $FileName \"$FileName.partial\"\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | Event Records Exported\"$NumberOfRecords\/$MessageTotal\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Write-Host -NoNewline \" | Number of lines\" (Get-Content \"$FileName.partial\").Length\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"\"\u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0  \u00a0\u00a0\u00a0 $FileName = ''\u00a0\u00a0\u00a0\u00a0\u00a0  }<\/pre>\n<\/p><\/div>\n<p><a href=\"https:\/\/news.sophos.com\/en-us\/2022\/03\/29\/reconstructing-powershell-scripts-from-multiple-windows-event-logs\/\" target=\"bwo\" >http:\/\/feeds.feedburner.com\/sophos\/dgdY<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2022\/03\/shutterstock_1907723545.jpg\"\/><\/p>\n<p><strong>Credit to Author: Vikas Singh| Date: Tue, 29 Mar 2022 18:27:50 +0000<\/strong><\/p>\n<p>On the trail of malicious PowerShell artifacts too large to be contained in a single log? Help is on the way.<\/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":[10378,10377],"tags":[25539,12749,11191,24552,16771],"class_list":["post-18621","post","type-post","status-publish","format-standard","hentry","category-security","category-sophos","tag-25539","tag-forensics","tag-powershell","tag-security-operations","tag-threat-research"],"_links":{"self":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/18621","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=18621"}],"version-history":[{"count":0,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/18621\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/media?parent=18621"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/categories?post=18621"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/tags?post=18621"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}