Empire 4.2 was just finalized over the weekend and we are excited to share some of the new features. This version has added some new capabilities to keep our threat emulation capabilities in line with current adversary TTPs. We have added a brand new IronPython stager, which can be compiled to an executable or shellcode via donut integration. Next, we added a C# VNC server that is compatible with noVNC. Finally, we added proxy chain pivots for Python and IronPython agents.
IronPython Stager
There has been a lot of interest in expanding Empire to be more than just Python/PowerShell. The first “phase” of this was the implementation of an entirely C# based agent. This was accomplished back in 4.0 when we introduced the integrated Roslyn compiler based on Covenant’s compiler. Next, we updated the Python agent’s staging to detect IronPython and load a compatible agent. But, there was a minor issue with the initial implementation. Not many users had a copy of IronPython 3 floating around on their networks. Especially in the rare instance that we found IronPython, it would be a 2.7 implementation since 3.4 is still in “development.”
So how do we solve having to download the C# files to compile an executable to launch an IronPython agent? Luckily, we already had our Roslyn compiler integrated into Empire. We can write a stager that embeds the IronPython DLLs and Standard Library files to bring along everything we need to run in memory. The best part is that our yamls are cross-compatible with Covenant, so you can (theoretically at least) integrate an IronPython runtime into Covenant.
We don’t want this blog to get too much into IronPython TTPs, so Cx01N will expand on that more in our next blog post.
// Load Python Std Lib from embedded resources
Assembly asm = Assembly.GetExecutingAssembly();
dynamic sysScope = engine.GetSysModule();
var importer = new ResourceMetaPathImporter(asm, "Lib.zip");
sysScope.meta_path.append(importer);
sysScope.path.append(importer);
// Load DLLs from embedded resources
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
String resourceName = new AssemblyName(args.Name).Name + ".dll";
// Load embedded resources
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
Byte[] assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
};
C# Stager for PowerShell
Not to be confused with Sharpire, the fully C# Empire agent. The other C# stager for PowerShell has been around for quite some time now. But a limitation is that the original implementation was based on having to compile your own executable external to Empire. With all the changes going in, we figured now would be a good time to update the code and have it compile all internal to Empire. So if you really want to run PowerShell inside of C#, this is the stager for you.
Donut Integration
If you were thinking of Krispy Kreme, then you are wrong. We have completely removed the old shellcode method in this release and replaced it with the Roslyn compiler and Donut. For those not familiar with Donut, it creates position-independent code that enables in-memory execution of VBScript, JScript, EXE, DLLs, and .NET assemblies. It has the option of being encrypted using the Chaskey block cipher and a 128-bit randomly generated key. After the file is loaded and executed in memory, the original reference is erased to deter memory scanners.
ReverseShell & Cmd Stagers
I’ve wanted to do this for a while, mostly out of curiosity. The ReverseShell and Cmd are used when you need a tiny shellcode payload (<1000 Bytes) to get an initial foothold, such as exploiting Eternal Blue or SMBGhost. Actually, these stagers were initially created for just those things within some of our sponsor plugins.
These stagers create a Stage 0, which uses our server information and passes it to MSFVenom to compile a reverseshell/cmd. That shellcode can then be delivered to the target machine, calling back to a server that serves the rest of the Empire payload.
C# VNC Server
We have been searching for a while to get an entirely C# implementation of a VNC server and we came across NVNC, an archived project that met our needs. We were able to make some updates and compile them on the fly through the Roslyn compiler. Just like the IronPython stager, the C# VNC server uses the same yamls as Covenant. So this module should also be cross-compatible with Covenant if someone decides to give it a try.
- To use the C# VNC Server, type “usemodule csharp/VNC/VNCServer”. The default options should meet most needs, but we recommend updating the password if using this in a production environment.
- Websockify creates a bridge between WebSocket traffic and normal traffic and allows us to receive the VNC connection from the agent on the Empire Server and pass it to another client since the server may not be on the same box as the client in multi-user engagements.
- For our VNC client, we will be using noVNC, which allows us to run a client window directly from a web browser. Also, this package allows for integration into Starkiller (hint, hint…). Use the source host address for the system. In this case, it’s ‘localhost’ since the server, client, and noVNC are all on the same virtual machine.
- noVNC will prompt for a password which the default is “password” (very secure).
- Finally, we are in and have a VNC session with the target.
Proxy Pivots
Proxy pivots allow us to push C2 traffic through additional servers/infrastructure to mask our presence further. Each hop of the proxy chain can be set within the agent. To deploy a proxy pivot, you must be using either a Python or IronPython agent. This feature is not supported by C# or PowerShell yet.
- Once you are interacting with the agent from the CLI Client, you will have the option to open the proxy menu.
- Once in the proxy menu, you will be given a list of the current chained proxies and you can view the available commands.
- To add a proxy to the list, you will set the required options in a similar fashion as in Modules/Listeners/Stagers.
- The Proxy Type option has a drop down list of the available proxy types that the proxy chain supports. Currently this supports SOCKS 4/4a/5, HTTP/S, SSL, and TOR.
- To add the proxy chain to the list, you will use the command “add”. This command has the optional argument of setting a position, in case you need to insert a new proxy into the list.
Note: Do not accidentally use the command “Execute” as that is used to deploy the proxy chain to the agent.
- The last step is deploying the proxy chain to the agent by using the command “execute”.
Obviously, there are a lot of Pros/Cons on when you would want to use this that we are not going to dive into, but feel free to try it out and let us know how you think it can be improved in the future. The proxy pivots is a POC at the moment and will be greatly expanded upon when our team completes a brand-new Peer-to-Peer infrastructure for agents.
So what’s next?
We have some big plans on the horizon that we are excited to share. Empire 5.0 is expected to drop in 2022 with these new features. API v2 includes a consistent naming convention, automated tests, and will make integration with other platforms better. Plugins are still one of the biggest hidden gems in Empire, which gives you the ability to build custom tools. We will continue to expand this functionality with Plugins v2. Some other features to watch out for are peer-to-peer comms, new agent types, logging v2, and much more.