Decoding encoded Powershell commands using Securonix SNYPR

Madhukar Raina
Securonix Tech Blog
6 min readAug 11, 2021

Why decode PowerShell commands?

PowerShell is a powerful scripting language and shell framework that comes built-in in Windows systems and is used by system administrators to automate their work and for legitimate administration tasks. However, threat actors are increasingly leveraging tools that are already there on the targeted systems and PowerShell is heavily used by them to download executables from the Internet and to execute in memory (for example — Mimikatz).

Adversaries use PowerShell for obfuscation and execution and to create new tasks on remote hosts, identify misconfigurations, exfiltrate data, and execute other commands. While performing hunts on endpoint logs in SNYPR, our security analytics platform, we see a high number of PowerShell commands in logs that are encoded and require an analyst to decode them to see what’s behind them. In this blog, we’ll see how we can use SNYPR to decode a lot of the encoded PowerShell commands in Spotter.

Let’s look into the process creation logs, where we see the source process name, destination process name, command-line, and other important fields. In windows, Process creation is logged into the Security events as event ID 4688 or in the case of Sysinternals tool Sysmon, Process Creation is logged as event ID 1.

There are cases where the destination process is powershell.exe and the command-line contains encoded commands. To manually decode the PowerShell encoded commands and understand the command, an analyst usually copies the encoded part of the command and decode it using base64 utility in Linux:

 echo <ENCODED-POWERSHELL-STRING> | base64 -d 
Fig 1: PowerShell command decoded from base64

Or it can also be done using the below command in PowerShell:

[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String(‘ENCODED-POWERSHELL-STRING’))
Fig 2: PowerShell command decoded using PowerShell

The problem here is that we have a lot of PowerShell encoded strings in logs, so it becomes difficult to decode all the encoded commands manually. Let’s see how we can do it in SNYPR using the existing functions.

Finding PowerShell encoded commands

In SNYPR, while performing hunting on endpoint logs, we usually see a high number of PowerShell commands in the logs that are encoded and require an analyst to decode those to see what’s the actual command. Let’s take an example of Crowdstrike logs where we have encoded PowerShell commands.

For the resource group “Crowdstrike Falcon”, the field that has the command line arguments is “resourcecustomfield1”, so we’ll apply a filter for “resourcecustomfield1” with *EncodedCommand* string and it’ll show results with PowerShell encoded commands like below:

Fig 3: Crowdstrike alerts with encoded PowerShell commands

In this scenario, the PowerShell commands displayed in the results are encoded; and an analyst would have to go and decode the commands manually to find what’s happening.

Decoding the commands

Instead of manually decoding each command and getting the results to find out what’s happening, we’ll use SNYPR to decode the commands for us. To do that, we’ll need to know below:

  1. The field containing the encoded command
  2. The length of the field
  3. The length of the non-encoded string

We’ll use the EVAL operator to evaluate the above.

Our objective is to extract the encoded PowerShell command from the command-line field (mapped to resourcecustomfield1). Let’s first calculate the total length of the command-line using SNYPR’s LEN function, and then subtract the non-encoded initial part (using SUBSTR function) to get only the encoded command. We’ll store it in a new field and decode it later using SNYPR’s inbuilt function UNBASE64.

Get the length of the field having encoded PowerShell command

Consider the following example which shows the command-line parameters of PowerShell execution using encoded PowerShell commands:

powershell.exe -NoProfile -EncodedCommand VwByAGkAdABlAC0ASABvAHMAdAAgACgARwBlAHQALQBXAG0AaQBPAGIAagBlAGMAdAAgAC0ATgBhAG0AZQBzAHAAYQBjAGUAIAByAG8AbwB0AFwAdwBtAGkAIAAtAEMAbABhAHMAcwAgAE0AUwBpAFMAQwBTAEkASQBuAGkAdABpAGEAdABvAHIAXwBNAGUAdABoAG8AZABDAGwAYQBzAHMAK

We shall use the EVAL operator with the LEN() function to calculate the overall length of the command line:

EVAL x=LEN(resourcecustomfield1)
Fig 4: Using the EVAL operator with LEN()

The total length of the command-line field is now stored in new field x.

Subtract the part which is not encoded string

Now that we have the total length of the command-line in x, the next step is to subtract the non-encoded part from the whole string.

To do this, we’ll use the SUBSTR function of the EVAL operator to extract only the encoded string:

EVAL <store-field> = <SUBSTR> < field > < start-position > <endposition>

Let’s name the store field as y and use the SUBSTR function on the command-line field:

EVAL y=SUBSTR(resourcecustomfield1,42,x)
Fig 5: Using SUBSTR with EVAL to extract the encoded string

We added 42 in the start position because 42 is the count of the non-encoded characters in the PowerShell command i.e. “powershell -NoProfile -Encodedcommand “ (including the space before the encoded part). In cases where the non-encoded part is different i.e. its PowerShell -enc or -e or other parameters are added, then this value will change.

This will return the substring of the actual field value which is encoded and store it in y, which contains the encoded command. Let’s see how to decode it further in SYNPR.

Decode the encoded string

Now that we have the encoded string in the variable y, we can use the UNBASE64 function to decode the encoded string to plain text.

 EVAL (store-field) = (UNBASE64) ( field )

Let’s name the store-field as decodedcmd and pass y to it to decode the encoded command:

 EVAL decodedcmd = UNBASE64(y)

This will result in adding a new field decodedcmd in the results, which will show the decoded PowerShell command as shown in the screenshot below:

Fig 6: Adding the decoded PowerShell command as a new field

Once the encoded string is decoded, we can do a STATS on the new field that we created along with the other important fields that are required to correlate it with the important data.

Fig 7: Using STATS for correlation with important data

Conclusion

SNYPR can be really helpful in decoding the bulk of encoded PowerShell commands by making use of the built-in functionalities (i.e. EVAL, UNBASE64 function) which come in handy while dealing with bulk encoded commands in the threat hunting programs. For visibility over the PowerShell activity, the best practice is to always turn on the Module logging, Script Block logging for PowerShell, which records the deobfuscated commands and outputs.

Fig 8: Turning on Module Logging for PowerShell

These events with decoded commands and script blocks are logged under event ID 4103 and 4104.

Securonix Threats Labs researches cutting-edge security topics to drive our industry-leading security analytics and operations platform. Check out Securonix Threat Labs for up to date advisories and alerts for emerging threats

--

--