Nimpostor: Bringing the nim language to Mythic C2

research

In the second part of 2022, Lukas Donaubauer, security expert at SEC Consult, came in contact with the programming language Nim and its presence in the infosec community especially concerning Malware Development.

Programming language

One of the very first sources he used to get to know more about Nim in an offensive context, was the really great OffensiveNim repository from Marcello Salvati (byt3bl33d3r). At that time, the Malware Development Essentials Course from Sektor7 founded the basis for getting deeper into writing his own exploits, which would be highly beneficial for our internal Red Team. Hence this blog post came to life, sharing the outcome of writing a custom C2 agent for the open source Mythic C2 framework.

Why Mythic?

At that time a lot of people published fully fledged frameworks (Havoc, Sliver, etc.). But writing a custom C2 server for the agent would mean that much development time would have to be spent creating the server architecture instead of developing only the agent.

Mythic is very unique compared to other frameworks in the sense that it splits up design and functionality into three distinct parts. These parts are the server, the C2 profiles and the C2 agents. Due to this nature, profiles and agents can be developed separately from the server and then integrated into the platform. This design for a C2 framework is where Mythic really excels compared to other platforms. Developers have the freedom to create their own custom agents with unique capabilities for a central server. This allowed us to only focus on the agent aspects without needing to create an own custom framework. The MythicAgents github group contains a whole suite of custom agents ranging from fully featured .NET agents to Mac OS agents. Mythic’s modularity allows for these fully custom payloads and profiles to be developed to work seamlessly with the Mythic server. Looking through the existing agents we recognized that a 3-year-old Nim Agent already existed but was deprecated. This Nim agent has been used as a basis now for the development of this custom agent.

Using Mythic for agent development is ideal when wanting to include custom payload functionality without creating your own server from scratch. Creating the server from scratch though allows for further flexibility on the design of the framework itself.

Directory structure for the agent
Figure 1: Directory structure for the agent

Mythic Payload Development

Mythic payload type development is very well documented in the Mythic documentation. The first stage requires creating a directory structure for the agent. 

There are a few strict rules when it comes to file and directory names.

For example: the name of the directory under Payload_Type/* has to be the name of the payload. The same goes for documentation-payload/* for documentation and agent_icons/*.svg for the icon of the agent.

The example in Figure 1 assumes that the agent’s name is mypayload. Some of the files such as the mythic_service.py and rabbitmq_config.json file need to be pre-populated according to the Mythic documentation or other payload types.

It is really useful to have a look at the already existing agents to get a feeling which configuration options are needed.

Mythic functions are using docker containers. The Payload_Type/mypayload/Dockerfile file is used to define the docker container the payload builder will use. There are docker base images already available which include dependencies for building different types of payloads but a custom one can be defined, which was needed in this case to install all the dependencies for Nim. This docker container is used for building the payload; other functions such as C2 communication are handled in profile containers.

The Payload_Type/mypayload/mythic/agent_functions/builder.py file includes metadata about the payload along with the implementation for building each payload. The Mythic documentation for this file includes a very in-depth guide on what to include in this file in order to define your agent in Mythic along with how to compile build parameters into the payload.

One can think of payload type development as containing “payload” code and “mythic” code. The payload code is the code for the agent itself and lives in the Payload_Type/mypayload/agent_code/ directory. The actual development of the agent and its features occur here. The other part of the agent is the mythic code which is in the Payload_Type/mypayload/mythic/agent_functions/ directory. Here is where various commands are defined for the agent. This will define the commands and their parameters along with any other pre-tasking before sending it down to the agent.

HTTP is a very common C2 communication transport and is one of the easiest to implement. Mythic already includes an HTTP C2 profile which can be used with an agent for C2 communications. This is a fairly straight forward profile which uses HTTP GET/POST requests and base64-encoded JSON data. The initial check-in for an agent consists of an HTTP request including several data fields which the mythic server uses to identify the agent respectively the system the agent runs on.

Each agent has a unique PayloadUUID that is generated at compile time. An HTTP POST request with this in the body of the request will register an initial check-in with Mythic in the callbacks page. Encryption can be included in the request payload by following the format specified in the documentation.

From here, an agent is periodically beaconing back to the Mythic server to get tasking and sending the results of completed tasking back.

That is all that’s needed for building a basic Mythic payload. Creating more advanced commands can be found through the Mythic documentation. The example does not go into depth about all of the other great capabilities included with Mythic. A good source of possibilities are the already existing agents. Mythic also supports a structure for peer-to-peer communications between agents. An agent can communicate with other agents directly in order to pass on tasking. The Apollo and Poseidon agents support p2p functionality through SMB and/or TCP.

Why Nim?

One of the greatest advantages Nim offers is that it’s a compiled, statically typed language with syntax that feels like a scripting language. Much of the syntax exactly matches or is very similar to Python’s. This was a huge advantage as many little tools that were developed for internal use are based on Python.

Additionally, since Nim is an ahead-of-time compiled language, it’s probably a more sensible choice for developing C2 implants or other post-exploitation tools than Python would be. While it is possible to compile Python code to an executable using tools like PyInstaller or Py2Exe, those tools seem to have problems with setting off antivirus programs and using them introduces one more step into the development process.

Here’s a quick overview of a few other features that make Nim promising:

  • Cross-compilation support with mingw-64. Languages like Go, which was analyzed in another personal research project, highlight how helpful seamless cross-compilation is for offensive tool development. Being able to compile agents for Windows as well as for Linux clients brings more flexibility.
  • The binaries Nim emits are fairly small, in comparison to binaries emitted by Go, which is crucial for initial deployment of the agent.
  • Nim offers support for calling backend code like the Windows API using its Foreign Function Interface. This seems like a particularly promising feature for anyone interested in developing post-exploitation tools for Windows in Nim.
  • The documentation is very detailed and there are a lot of tutorials to get starting.

Nimpostor Functions

To get a feeling which functions are essential, other agents from the MythicAgents github were analyzed. Especially the Apollo, Medusa and Poseidon agents are very advanced and have a great overview of functions. Furthermore, the code snippets from the OffensiveNim repository gave some more inspiration.

Currently the proof-of-concept payload is very basic and doesn’t have advanced capabilities implemented. It focuses on simple file system tasks like cd, ls, download, upload and the more advanced execute_assembly function that allows for execution of .NET files directly in memory.

Conclusion

The main goal of this research was to get to know the language Nim and see if it is suitable for internal tool development. This can be confirmed 100% and the topics mentioned in “Why Nim?” make it the new favorite for inhouse tooling for red teaming projects.

Although the agent is in what you could call a beta stage at the moment, it will definitely be developed further, so that it can be used in future Red Team projects.

The very next steps to be included are a bof_loader to be able to execute Beacon Object Files directly in memory, a socks proxy and the p2p functionality for inter-agent communication via SMB or TCP.

If you want to have a look at the code and test the agent yourself, you can do so at the SEC Consult Github Page.

 

This blogpost was written by Lukas Donaubauer and published on behalf of the SEC Consult Vulnerability Lab.

Are you interested in working at SEC Consult?

SEC Consult is always searching for talented security professionals to work in our team.