9 minute read

Introduction

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

image

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:

  • HTTP
  • Websockets
  • 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

Installation

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

Commands

Athena supports the following commands:

Command Description Loadable?
cat Return the contents of a file Yes
cd Change working directory Yes
cp Copy File 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
ps List processes 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.

Reflection

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!

image

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 load-assembly command.

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:

image

After using load-assembly to load the required assemblies, in this case protobuf-net.dll and protobuf-net.Core.dll when running the execute-assembly command you’ll see it ran succesfully:

image

When finished, or if you want a fresh start, you can use reset-assembly-context in order to clear all loaded assemblies:

image

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.

SMB Usage

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>

image

Once connected, you should see a successful check-in with the agent in the UI!

image

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.

SOCKS5

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

Expect Bugs

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.

Mythic hooking

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.

Command Loading

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.

One 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

Compilation

.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!

Conclusion

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!