Commands
This document outlines the implementation of commands in Tuoni. From a broad perspective, there are two types of commands: native commands and plugin-based commands. We will begin our explanation with native commands as they represent the simpler category.
Native commands
Native commands in Tuoni are those implemented directly within the agent. They consistently operate within the agent's process and are primarily associated with managing the agent's configuration or handling tasks that are impractical to implement as plugins. A prime example is the "die" command. This command terminates the agent process and, under no circumstances, should it be associated with any external processes or functionalities.
Plugin based commands
In Tuoni, the majority of commands are implemented as plugin-based commands, which bear a significant resemblance in structure to the listener plugin. These commands are composed of two essential parts:
-
The C2 Plugin Part: This component is responsible for integrating with the Command and Control (C2) system. It manages the configuration of the implemented command(s), parses results, and handles other related tasks.
-
Shellcode part: This portion is executed either within the agent or in a different process on the agent's machine. It is the actual implementation of the command, carrying out the intended operations.
How it works in practice
- Through the C2 API, the GUI or script selects a command for the agent and configures it.
- The command's name, agent GUI, and configuration are transmitted to the C2 via the C2 API.
-
The C2 forwards the configuration to the command's plugin, which then converts it into a format understandable by the shellcode. The plugin returns this configuration along with the shellcode itself to the C2.
-
The C2 dispatches all this information to the agent through the listener plugin-shellcode connection.
- The agent's core initiates the received shellcode in itself or another process (as configured) and establishes a connection to it (typically using named pipes).
- The agent's core sends the command's configuration to the shellcode via this connection and waits for the outcome.
- The command's shellcode executes its designated function and sends the result back to the agent's core.
- The agent's core then transmits these results back to the C2.
- The C2 utilizes the command plugin to interpret the result. The plugin provides the parsed result to the C2 in a specified format (which could be a file, a string, etc.).
- The command's results are now accessible through the C2 API.
Visual representation
Step 1
User tasks C2 to send command to the agent via C2 API. This can be done with GUI or script. User provides command configuration.
Step 2
C2 gives command configuration received via API to command plugin.
Step 3
Command plugin parses the provided configuration and gives C2 back the command shellcode and the configuration (in format shellcode understands) that should be relayed to the shellcode upon execution
Step 4
Shellcode and configuration is sent to the agent
Step 5
Agent core parses the information sent to it and separates the shellcode and configuration
Step 6
Agent core executes provided shellcode
Step 7
Agent core and executed shellcode create a data channel (named pipes usually) and agent core relays to it the configuration
Step 8
Command shellcode returns command results to the agent core
Step 9
Result is sent to the C2
Step 10
C2 core provides result to command plugin to parse
Step 11
Command plugin gives C2 core the parsed result
Step 12
User can now ask for command results from the C2 via API