It seems cliche at this point, but just like every other offensive developer out there, I wanted to try and create my own agent. The problem is, I HATE creating UIs. I find developing the agent fun, I find developing the back-end fun, but making everything look good is something I’m not interested in. So when @its_a_feature released Mythic as an agent agnostic c2 platform, it seemed like just the thing I was looking for. I get all the fun of creating a c2 agent, without having to do any front-end UI work!
When deciding on the agent, I had a few goals in mind. The first was that I wanted the agent to be cross-platform. That way I could use the agent whether I was on a Windows, Linux, or OSX box. Secondly, I wanted it to be modular, that way plugins could be loaded as needed and weren’t directly compiled into the executable. Finally, I wanted it to be easy to develop for, I wanted to make cross-platform red team operations and development more accessible to the average red teamer.
As anyone who knows me will tell you, I’m a big fan of programming in C#. It’s my preferred language, and when possible, I will always choose to write tools in that language. This comes with a pretty big downside however, I’m mostly limited to operating in Windows environments. Luckily for me, Microsoft <3 offsec and their new versions of .NET are all cross-platform! Red Teamers prefer older technologies, whether it’s PowerShell v2, .NET 3.5/4.0 we don’t normally like using the new sexy. New sexy contains security fixes, and those scare us. However, the benefits of the new versions of .NET were too good for me to pass up though, so I decided to stick with what I know, and write my agent in .NET 6.
What is Athena
Athena is a fully-featured cross-platform agent developed in .NET 6. Athena is designed to support Mythic 2.3 versions and will be updated to support new versions as they’re released.
As of this initial release it supports the following C2 Profiles:
- SMB (Beta, Windows Only)
In addition to the usual commands expected of an agent it supports the following:
- SOCKS5 Support (Beta)
- Hot loading of commands
- Cross-Platform execute-assembly functionality
To install Athena on an existing Mythic server, set your current directory to the Mythic folder and run the following command:
./mythic-cli install github https://github.com/MythicAgents/Athena
Once downloaded and installed into the mythic server, run the following command to start the Athena docker and sync with Mythic:
./mythic-cli payload add athena
Athena supports the following commands:
|cat||Return the contents of a file||Yes|
|cd||Change working directory||Yes|
|download||Download a file from the host||No|
|drives||Display connected drives on the host||Yes|
|env||Display environmental variables||Yes|
|execute-assembly||Execute a .net 6.0 assembly in memory on the agent||No|
|exit||Close the agent||No|
|get-clipboard||Get the clipboard contents of the user||Yes|
|hostname||Display the hostname the agent is running on||Yes|
|ifconfig||Display ip configuration information||Yes|
|jobkill||Kill an active job||No|
|jobs||List active jobs||No|
|link||Link to a SMB Athena agent||No|
|load||Load a command||Yes|
|load-assembly||Load a 3rd party assembly into the AssemblyLoadContext||Yes|
|ls||Display the directory listing||Yes|
|mkdir||Make a directory||Yes|
|nslookup||Query the DNS information of a fqdn||Yes|
|pwd||Display the current working directory||Yes|
|reset-assembly-context||Reset the execute-assembly context||No|
|rm||Remove a file||Yes|
|shell||Run a shell command||Yes|
|sleep||Change the sleeptime||No|
|socks||Start the SOCKS5 listener||No|
|upload||Upload a file to the host||No|
|uptime||Get the uptime of the host||Yes|
|whoami||Display the current user context of the agent||Yes|
Commands that are marked
No for loadable, are hardcoded into the agent and are unable to be hot-loaded.
Athena is designed to bring the reflection we all know and love to non-Windows platforms. An operator can create a .NET 6 DLL and compile it from their preferred development machine/pipeline. These DLLs can then be executed on any Athena agent, no matter the platform!
For example: you create an assembly called
Ping.dll that attempts to ping a specified machine, and returns the result. You can develop and compile it on Windows, take the compiled DLL, and run it on your Linux Athena agent! There are some gotchas as certain functionality only supporting certain platforms (e.g. Windows Security Tokens), but for the most part any .NET DLLs coded in .NET Standard 2.0 or .NET 6 will work cross-platform with only a single compilation required!
Assemblies are loaded into their own AssemblyLoadContext which is the .NET 6 version of an AppDomain. This allows required third-party assemblies to be loaded into without interfering with the main agent.
Athena comes with a few recommended DLLs to be loaded out of the box, however any properly compiled 3rd party library can be loaded. Any assemblies that don’t come in the standard Athena executable can be loaded with the
The screenshot below shows an assembly I created quick that makes use of protobufs and
protobuf-net in order to facilitate that. When you try to load the assembly without the libraries being loaded, you’ll see the following:
load-assembly to load the required assemblies, in this case
protobuf-net.Core.dll when running the
execute-assembly command you’ll see it ran succesfully:
When finished, or if you want a fresh start, you can use
reset-assembly-context in order to clear all loaded assemblies:
In order to preserve opsec all assemblies are loaded in-process, this does lead to some caveats which I go over in the
Things You Should Know section.
There are two types of Athena payloads when it comes to SMB. There’s payloads that contain the SMB Forwarder, and ones that don’t. I included this so that operators have the flexibility to shrink down the payload size slightly when deploying agents, and to allow them more flexibility over the capability of their agents. Agents that don’t contain the SMB forwarder will be unable to link up with Athena SMB agents, so if you were to attempt to use the
link command, the agent will return an error.
In order to make use of the Athena SMB C2 profile, you’ll need to generate an Athena payload and specify SMB as your profile. This executable can then be run on a Windows machine, and will wait for a new connection. From an existing egress agent, you can then use the
link command in order to connect to the agent.
link <ip/host> <pipename>
Once connected, you should see a successful check-in with the agent in the UI!
Currently, named pipe communication only works between Windows hosts. But I’d like to explore the possibility of making them work on other platforms, if it’s possible.
Athena comes with the ability to make use of the SOCKS5 functionality provided by the Mythic server and can be started using the following commands:
socks start //Starts SOCKS5 proxy on the default port socks start 999 //Starts SOCKS5 proxy on the specified port (in this case 999)
Note: This functionality is not 100%, it’s likely fine for small things, but may struggle with larger amounts of traffic. Be warned.
Things you should know
This is my first attempt at a fully-featured agent. I’ve attempted to identify and squash as many bugs as possible, however I expect more to be found.
Athena doesn’t currently support some of the Mythic hooking features (e.g. FileBrowser, PS, etc etc). Those will be released in a future update.
In a future update, I plan on flushing out the hot-load functionality of Athena agents so that commands can be properly built-in, making NativeAOT and Trimmed Athena agents more usable.
Long-Running assemblies are unable to be unloaded
Due to the way .NET 6 handles assebly loading, any assembly that never returns will continue running indefinitely. In order to kill the assembly, the entire agent will need to be killed. If you use the
jobkill command, the assembly will continue executing in the background.
execute-assembly command can be run at a time
With most executables, instead of returning a string data type, they print to stdout. Most c2 frameworks get around this limitation by using sacrificial processes and redirecting their output to an SMB pipe. Since everything is run in-process, we only have access to stdout and no way to differentiate between assemblies
.NET 6 is unlikely to be installed on anything by default in the near future. Because of this, I designed Athena to be compiled as a single, self-contained executable, which results in a realatively large executable. In an attempt to mitigate this issue, I’ve provided operators with a few ways to compile Athena, which may result in a file size that’s more reasonable:
- Standard Athena is compiled as a standard executable without merging everything into one file. Useful when .NET 6 is already installed on your target machine
- Self-Contained Athena contains everything it needs to execute, useful when you’re unsure if .NET 6 is already installed on the target machine
- Compressed Compresses the final executable, this can help decrease the file size significantly
- NativeAOT Uses the expiremental NativeAOT compilation method. This allows for Ahead of Time compilation, which allows the executable to run faster and decreases the final executable size, however you lose reflection capabilities
- Trimmed Assemblies that aren’t necessary in order to run Athena are stripped away from the final payload. You will potentially encounter issues with execute-assembly and will need to load any assemblies that are needed manually, but built-in commands should work
The table below provides a few of the common compilation methods along with the estimated compilation size:
|Compilation Method||Description||Estimated Size|
|Standard||No special compilation, requires 3rd party libraries to be included||67kb + 3rd party libraries|
|Self-Contained, Single File, Compressed (Default)||The standard self-contained compilation method, everything is included, final executable is compressed||33mb|
|Self-Contained, Single File, Uncompressed||The standard self-contained compilation method, everything is included||63mb|
|Self-Contained, Trimmed, Uncompressed||Unneeded assemblies are stripped out of final payload||18mb|
|Self-Contained, Trimmed, Compressed||Unneeded assemblies are stripped out of final payload||12.4mb|
|NativeAOT, Uncompressed||Use the experimental NativeAOT compilation method||33mb|
|NativeAOT, Compressed||Use the experimental NativeAOT compilation method, compress final executable||12.4mb|
I have some ideas in the future for these types of compilations, so stay tuned for updates!
If you’ve made it this far, thank you for reading! I’m nervous/excited for the release of Athena, and I’m looking forward to the interesting ways the security community will use/enhance my code.
If there is enough interest, I will release future blog posts which discuss how to create additional c2 profiles and plugins for Athena to further extend its capabilities!