I’ve been sitting on this for a while and thought I’d do a brief write up.
I’m calling this tactic "Drop the Shields"
What is Device Guard? Good read here:
The basic idea is we want to lock down the system to only execute approved binaries, etc…
What I am about to describe is a method I use to disarm Device Guard in order to execute some .NET code that has not been approved. This post assumes you already have access to the system.
We will disarm Device Guard by removing PowerShell Constrained Language Mode as a normal user , normal privileges, using no exploitation.
Constrained Language Mode is on once a system is locked down with Device Guard. Details about the impact of that here:
Please, this doesn’t mean Device Guard is no good or not a strong defense…
I leave it up to the reader on how you might gain a shell on a Device Guard protected system in the first place.
First, lets review some tasks that a normal user can perform.
1. Map a network drive to a url. example: "net use s: https://live.sysinternals.com"
I like this because its proxy aware, and works over SSL/TLS. All you need is to have your tool set on a WebDAV share which is trivial.
2. Debug a process that I own.
3. Change Memory in a Process I can debug.
4. Load Binaries Signed by MS – Example – cdb.exe, and SOS.dll
Ok, Here we go. First verification that the system is indeed under Device Guard Protection.
So, we can’t invoke methods, we can’t load unapproved binaries.
Step 1: We need to drop cdb.exe on this system. An MS signed binary. Distributed with Windows debugging tools. This will/should be able to execute on a System, even after the Device Guard Policies have been set.
Step 2: Attach to your own PowerShell process –
For details on various options see this: cdb.exe Command-Line Options
Step 3: Load the SOS.dll which is useful for debugging .NET apps. Which PowerShell is.
This should already be on the system, and approved, so we aren’t actually adding anything new.
Step 4: Locate the object that contains the setting for Constrained Language Mode
!DumpHeap -type System.Management.Automation.ExecutionContext -short -min 100
Here we just scan the address space for an object of a particular size.
This will return a reference to the location of that object in memory
Step 5: Edit the _languageMode property, setting it from 3 to 0. This removes the restrictions.
Here’s what it looks like putting steps 1-5 together.
|cdb.exe -p $PID -pvr|
|.load C:/Windows/Microsoft.Net/Framework64/v4.0.30319/SOS.dll !DumpHeap -type System.Management.Automation.ExecutionContext -short -min 100|
|ed [Address]+148 0|
Now that is done, we have effectively removed the constraints. You are now clear to move about the process.
Ok. So this was really just an experiment.
A PowerShell Constrained Language bypass can degrade the effectiveness of Device Guard.
Of course this entire process can be automated, I leave that to you for experimenting.
Does this mean you should not consider Device Guard. – NO. Device Guard is a powerful tool in the defender arsenal.
It was just bugging me that I could get past it. And even still this isn’t exactly a world class bypass….
So, whats the point of this post?
Well, I wanted to prove a concept that Constrained Language Bypasses will affect defenders who rely on Device Guard.
Feel free to test this. Your mileage may vary.
Remember again, this was not an exploit. Operating as a standard user, I can attach a debugger to a process I own and manipulate its address space. But I needed to bring a debugger to the system to do that.
I was really just curious as to where the Language Mode setting was held in memory and could it be altered.
Its not great, but it does pique my curiosity for Constrained Language bypasses.
Ok, that is all I have today.