Simple Bypass for PowerShell Constrained Language Mode

Edit – I just had this pointed out to me that on Friday 17th March Lee Holmes wrote about this very attack on his blog here – This is a pure coincidence and I was not aware of this blog post by Lee at the time.

We all know that Microsoft has added some nice features to PowerShell v5 to help out the Blue teams, Constrained Language Mode, Deep Scriptblock logging, system wide transcripts and AMSI to name a few.
This blog is not a lesson on each of the features mentioned above, for more information this is a great place to start – Microsoft PowerShell Blue team.
This blog is also not about the awesome bypasses highlighted by Casey Smith, aka @SubTee, again detailed info can be found here – @SubTee Blog.

What I’ve found is probably not even new, but I can’t find anything written about it. This is a very simple and almost too easy a way to bypass Constrained Language Mode. I still can’t believe it myself.

OK, this is it;

PowerShell.exe -Version 2…….insert some code here or just open a shell

There are 2 requirements for this to work,  PowerShell v2.0 has to be enabled in Windows Features so does .NET Framework 2.0, 3.0 and 3.5, these seem to have been already enabled in my testing systems by default, although I have 1 build of Windows 10 where the .NET Framework was not enabled – not sure why yet.


No special access permissions are required, standard user can carry out the bypass and there is no requirement to elevate the PowerShell session.

The screen shots below show the bypass


A before and after series of screenshots to prove its useful, these show powerview.ps1 being imported before and after


Lots of Red errors, denoting Constrained Language Mode is doing its worst.


No Red errors !!

Another really cool part of this is that Deep Scriptblock logging does not pick up the commands after the PowerShell -Version 2 if the bypass is run from an existing PowerShell session as shown above, however if the bypass is passed as part of a standard type payload.bat like the one shown below, (which is an implant from PoshC2), then nothing is shown in the logs.


I’d post a screenshot of the logs but there’s nothing to see, 🙂

To replicate this you should get a copy of PoshC2 and edit the payload.bat to add the -Version 2 or -v 2 and then run it and check the Event Viewer – ‘Microsoft/Windows/PowerShell/Operational’ log for signs of activity.

Also to state the obvious this bypass method falls apart if either, PowerShell V2.0 or the .NET Framework 2.0, 3.0 & 3.5 Windows features are not enabled, this is were @SubTee’s work will come in very handy.

Right now this isn’t part of PoshC2, but it will be added in the near future, you can get a copy of PoshC2 here – PoshC2 Github and visit the wiki page for details on how to install and use PoshC2 – PoshC2 Wiki

Thanks for reading, see you soon.



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s