Is PowerShell the ultimate malware authoring tool?

I will never forget being in Redmond when Microsoft announced PowerShell to the world. PowerShell, which was at that time called Monad, was to be a new administrative tool for Windows. During the question-and-answer portion of the event, I told the panel that in spite of its potential as a system’s management tool, Monad sounded like a malware author’s dream come true. I then went on to ask what Microsoft was doing to keep Monad from being exploited. I have to admit that I can’t really remember the answer that I received, aside from the fact that it contained vague references to built-in security.

About a decade has passed since that press briefing, and Monad has evolved into Windows PowerShell, which is baked into every modern Windows operating system. However, my question still remains: What is to stop PowerShell from being used in the creation of malware?

If you were to ask Microsoft this question, the answer would probably reference execution policies. For the uninitiated, execution policies are a PowerShell mechanism that is designed to prevent an unauthorized script from running.

Execution policies seem to work really well. Although I was not able to dedicate an extensive amount of time, I spent about half an hour trying to circumvent PowerShell’s execution policies. Unfortunately, or fortunately, depending on how you choose to look at it, I had no luck breaking the execution policies. It would seem that a malicious PowerShell script simply cannot run unless an execution policy allows it to do so. So that’s the end of the story, right? Not quite. It took me less than an hour to come up with another method that allowed me to run a malicious PowerShell script.

Before I tell you how I did it, I want to take a step back and answer a question that is fundamental to my approach. Why use PowerShell? Why not just use some other method?

The reason why I wanted to attempt a PowerShell exploit is because PowerShell has really deep integration into the Windows operating system. With a few exceptions, PowerShell can interact with every Windows role, feature, service, and process. PowerShell can access the Windows registry, the Windows Event Log, and pretty much anything else that a malware author might want to tamper with. Furthermore, PowerShell is a part of Windows, which means that a malicious PowerShell script could theoretically attack any modern Windows deployment, including those running on Azure.

As previously mentioned, the execution policy stops malicious PowerShell scripts cold in their tracks, and there doesn’t seem to be an easy way to use an automated script (which the execution policy prevents from running in the first place) to change the execution policy. I’m pretty sure that given enough time, I could probably find a way use a script to change PowerShell’s execution policy, but there is an easier way to make malicious PowerShell code run.

What if the Windows operating system contained a hidden, and completely unprotected, version of PowerShell? And what if there was a way to run a script on this secondary PowerShell environment? Because the secondary PowerShell environment is completely separate from the “normal” PowerShell environment, the execution policies would be completely oblivious to any scripts that you might choose to run.

Now I’m sure that some of you are thinking, “Wait a minute, Posey, that type of environment doesn’t exist. Microsoft would never allow a PowerShell backdoor that circumvents PowerShell’s security.” Well, you would be right. Such an environment does not exist in Windows. You have to download it from Microsoft.

Yes, you read that correctly. Microsoft freely provides an insecure PowerShell environment that can be used to defy PowerShell’s execution policies. It would be logical to assume that you would have to find a way to install this environment onto a victim’s computer before you could run PowerShell malware, but you don’t. The insecure PowerShell environment is completely portable, and can be easily bundled with the malicious script. Do I have your attention yet?

OK, I know that I have made some really outlandish claims, so let me show you just how easy it is to run malicious PowerShell code on a protected system. For this demonstration, I am going to be using Windows 10.

I started my experiment by setting my computer’s execution policy to Restricted, as shown below. This should keep any PowerShell scripts from running on the computer. As you can see in the screencap, I have used the Get-ExecutionPolicy cmdlet to confirm that the execution policy is indeed set to restricted.

PowerShell Execution Policy

OK, so remember that unprotected PowerShell environment that I mentioned? Well, as it turns out, Microsoft doesn’t offer it as a malware authoring tool. Imagine that. Instead, insecure PowerShell environment exists within a utility called PS2EXE.

PS2EXE is a free tool for converting PowerShell scripts into executable files. However, there isn’t really a way to compile a PowerShell script into an EXE file. Since PS2EXE can’t do a true conversion, it encapsulates the PowerShell script into an EXE file, along with a lightweight (and insecure) PowerShell environment. This means that when you run the EXE file, the PowerShell script executes in a completely separate PowerShell environment.

It is worth noting that PS2EXE can’t handle every PowerShell script. This is especially true for scripts that call .NET or that use certain modules. Even so, PS2EXE does allow a PowerShell script to run in spite of a computer’s execution policies.

The first step in the process is to create the PowerShell script that you want to run. For my first attempt, I made a simple script called Payload.ps1. This script simply displays the words “Hello World” and then waits for a key press.

The second step in the process is to use PS2EXE to convert the script into an EXE file. To do that, enter the PS2EXE command, followed by the -Inputfile parameter, the name of your script, and the name of the EXE file that you want to create. You can see how this works below.

Compile code with PS2EXE

Once I created my executable that was based on a “malicious” script, I tried running it. Upon doing so, my antimalware software immediately kicked in and identified the executable as a potential threat, as shown in the screencap below. After a few seconds however, my antimalware software dismissed the threat, and the script was allowed to run.

Run PowerShell code regardless of Execution Policy

As you can see in the next screencap below, I ran a PowerShell script on my system in spite of an execution policy forbidding it.

Run PowerShell code regardless of Execution Policy

OK, I will be the first to admit that there is a big difference between a “Hello World” script and a virus. Even so, I have illustrated a proof of concept.

I decided to try taking things to the next level, so I modified my Payload.ps1 script so that it would exhibit behavior that was a bit more virus-like. I didn’t want to do anything destructive, but I designed to script to create a file named Evil Trojan, and place the file onto the computer’s hard drive. Here is what the code looks like:

$A = “Insert Malicious Code Here”

$A | Out-File “C:\data\Evil-Trojan.txt”

After modifying my payload file, I re-created my EXE file, and then set the restriction policy back to Restricted. You can see the proof below.

Modified PowerShell payload

When I ran the EXE file, my antimalware software detected a potential problem, but let the script execute. The “Evil-Trojan” file was created on my hard drive as predicted.

File created by "malicious" PowerShell script

The takeaway: Be prepared

It is a little bit unnerving to think that the PS2EXE utility can be used to circumvent PowerShell security. The best defense against this sort of attack is to use application whitelisting to prevent unauthorized EXE files from running. You can use Windows AppLocker, or any of the third-party utilities.

6 thoughts on “Is PowerShell the ultimate malware authoring tool?”

  1. come on, brien… powershell process is just a normal process… if a user is allowed to run an .exe file, it runs with user’s security privileges…

    if you consider running a powershell script within “insecured” powershell engine a security threat, why don’t you include a story about ability to write a .net program that instantiates a powershell script engine and run any script within it… you do not need to download anything “insecure” from microsoft, god forbid 🙂

    for example, try program like this, a very very basic console program, which runs while execution policy is set to RESTRICTED:

    Imports System.Management.Automation

    Dim ps = PowerShell.Create()
    ps.AddCommand(“Get-Process”)
    Console.WriteLine(“Process Id”)
    Console.WriteLine(“—————————-“)
    For Each result As PSObject In ps.Invoke()
    Console.WriteLine(“{1,10} {0,-24} {2, 12}”,
    result.Members(“ProcessName”).Value,
    result.Members(“Id”).Value,
    result.Members(“WorkingSet”).Value)
    Next

    1. Yeah, I think this entry is part honest, part FUD. I will admit that I was captivated by the article title when it came through this morning.

      In addition to allowing users to run unrecognized/unknown .EXE files the other thing that caught me off-guard was the comment that “Microsoft makes this available”. At best that is a half-truth. The tool was written and shared by an independent “Partner” and was uploaded to Microsoft’s TechNet Gallery (similar in concept to GitHub or SourceForge).
      I suppose Microsoft makes it “Available” as it is hosted on a Microsoft service, but it is neither written-by nor endorsed-by Microsoft.

      An interesting find, absolutely, but the presentation I feel is skewed.

  2. You are correct in that a PowerShell process is a normal process, and that if a user is allowed to run an EXE file, then that EXE file could exploit anything that the user has access to. I made that point The last second to last sentence of the article addressed this… “The best defense against this sort of attack is to use application whitelisting to prevent unauthorized EXE files from running. “. I also addressed the issue of what the big deal is about PowerShell, as opposed to .NET, in the 5th or 6th paragraph.

    As for the code sample that you have provided, it that code is written to a PS1 file then a PowerShell execution policy of Restricted will prevent it from running. The whole point of the article is that execution policies are designed to prevent malicious scripts from running, but can be circumvented.

  3. I’m more likely to share Gjuro’s opinion.
    Moreover, the Powershell team have always said, Execution Policy is Not a security tool. Looks logic , why would they otherwise include -EP Bypass. Besides the runspace example above, there are enough ways to circumvent EP without downloading any exe..anything Base64 encoded for example will happily pass and not yet to speak of NPS or the many obfuscation techniques in use today. As a general security measure I agree app whitelisting is the way to go.

  4. > If you were to ask Microsoft this question, the answer would probably reference execution policies.

    OMG NO!

    I wanted to name the Cmdlet
    Set-ExecutionPolicyAndIAcknowledgeThisIsntASecurityFeatureAndPromiseNeverToThinkOfItAsOneSoHelpMeGod

    I got overruled on that one but I was right and they were wrong.

    We’ve been SUPER clear on this point from the very beginning but
    as clear as we were about this, people continued to get that wrong so at some point we updated it with a new value to make it event more clear:

    Set-ExecutionPolicy BYPASS

    ExecutionPolicy is essentially the equivalent of UAC and is what allowed us to ship in Windows.

    Why?

    If you recall ILuvYou.VBS – scripting languages almost destroyed the internet. We needed to ship PowerShell in a way that if people weren’t explicitly using it, it didn’t reduce the security of the system. ExecutionPolicy was one of a wide set of configuration controls that we put in place to support this (another one is that when you double-click on a script -it EDITs the script – it doesn’t EXECUTE it).

    Your original point is spot on. PowerShell is POWERFUL and it is powerful for bad guys as much as it is for good guys. Anyone in the mgmt business will tell you that the only difference between Malware and Mgmt is intent.

    It is important to note that PowerShell is used by the bad guys as a POST-EXPLOITATION tool. They crack the system using a vuln in some other feature and then, when they can use any tool using any language they want, then they use PowerShell. Why? Because PowerShell is awesome and makes them more productive. The same reasons admins use it.

    We’ve always been super attentive to security and if you look at what we did in PowerShell V5 . Lee Holmes lead the charge here and he changed the game: https://blogs.msdn.microsoft.com/powershell/2015/06/09/powershell-the-blue-team/
    At the recently BlackHat/Defcon conferences, we heard a number of security researchers are moving away from using PowerShell because it is too easy to get caught if you use it. PowerShell has become a malware honeypot.

    The great thing is that just as PowerShell benefited from the great work of other shells, other dynamic languages are beginning benefiting from the great security work of PowerShell. https://twitter.com/jsnover/status/900891304120295424

    If people are interested in PowerShell security, they might want to watch the DerbyCon keynote that Lee Holmes and I gave on this topic:
    https://www.youtube.com/watch?v=BMreZZ1cgFI

    I hope this additional background helps.

    Jeffrey Snover
    Microsoft Technical Fellow

Leave a Comment

Your email address will not be published.

Scroll to Top