mirror of
https://github.com/Aryma-f4/Ares-mythic.git
synced 2026-06-14 17:24:13 +00:00
refactor(payload): rename apollo to ares and update documentation
This commit renames the Apollo payload type to Ares, moving all associated files and updating documentation accordingly. The change includes: - Renaming directories from `apollo` to `ares` - Updating documentation image references - Maintaining the same code functionality while changing the payload name - Adding new Ares-specific documentation files - Removing old Apollo documentation files The rename is done to reflect the new payload name while preserving all existing functionality.
This commit is contained in:
93
documentation-payload/ares/contributing/C2 Profiles.md
Normal file
93
documentation-payload/ares/contributing/C2 Profiles.md
Normal file
@@ -0,0 +1,93 @@
|
||||
+++
|
||||
title = "Creating C2 Profiles"
|
||||
chapter = false
|
||||
weight = 25
|
||||
+++
|
||||
|
||||
## Creating a New Profile
|
||||
|
||||
New command-and-control profiles for Apollo should be new projects under the Apollo solution. Your new project should be named `C2ChannelProfile`, where `C2Channel` is the means through which the profile will talk to Mythic. For example, if this profile communicates over HTTP, the project name will be `HttpProfile`. If it would communicate over web sockets, the name should be `WebSocketProfile`. This project should be a .NET Framework 4.0 Class library.
|
||||
|
||||
In your new project, create a class that has the same name as your project (e.g., `public class C2ChannelProfile`). This class should inherit from the `C2Profile` abstract class and the `IC2Profile` interface. The constructor of your new C2 profile will take the following parameters:
|
||||
|
||||
- Dictionary<string, string> parameters - C2 Profile specific parameters. For example, things like jitter, urls, host headers, etc. would all be passed via key-value pairs in this dictionary.
|
||||
- ISerializer serializer - This object is used to prepare C# structures into a serialized format that Mythic will receive, and allow the profile to deserialize JSON messages from Mythic into Apollo structures. Currently this variable should not be modified in the agent core.
|
||||
- IAgent agent - Core Apollo agent interface that grants the C2 profile access to other parts of the agent, such as the task manager.
|
||||
|
||||
The new C2 profile should implement the IC2Profile interface, which is as follows:
|
||||
|
||||
```
|
||||
public interface IC2Profile
|
||||
{
|
||||
// Used to connect to Mythic. This function will send the checkinMessage and perform any EKE, if required.
|
||||
// On successful connect, this function will return the value of the onResp function.
|
||||
bool Connect(CheckinMessage checkinMessage, OnResponse<MessageResponse> onResp);
|
||||
|
||||
// The main working loop of the agent. This should perform the periodic checkin of the agent,
|
||||
// dispatch new taskings, and return results.
|
||||
void Start();
|
||||
|
||||
// If the profile, on submission of data, will not receive Mythic's response as a reply,
|
||||
// this function should be used. Example: The data is submitted to a separate url than
|
||||
// where Apollo will receive the response. Used if a one way profile.
|
||||
bool Send<IMythicMessage>(IMythicMessage message);
|
||||
|
||||
// Send the data specified by Message to the server and pass the response of
|
||||
// Mythic ot the onResponse function.
|
||||
bool SendRecv<T, TResult>(T message, OnResponse<TResult> onResponse);
|
||||
|
||||
// Fetch data from Mythic. Used if the profile is a one-way profile.
|
||||
bool Recv(MessageType mt, OnResponse<IMythicMessage> onResp);
|
||||
|
||||
// Tells the caller that this C2 profile is stateful,
|
||||
// and as such it supports only the SendRecv operation.
|
||||
bool IsOneWay();
|
||||
|
||||
// Return whether or not the C2 profile is currently talking to Mythic
|
||||
bool IsConnected();
|
||||
}
|
||||
```
|
||||
|
||||
## Adding Your Profile to Apollo Core
|
||||
|
||||
Once you've created your new C2 profile, you'll need to add it to Apollo as a build option for C2 profiles.
|
||||
|
||||
In the Apollo project under the Apollo solution, add your new C2 profile as a project reference. Then, at the top of the `Apollo/Config.cs` file, add the following lines:
|
||||
|
||||
```
|
||||
using System;
|
||||
...
|
||||
#if C2CHANNEL
|
||||
using C2ChannelProfile;
|
||||
#endif
|
||||
```
|
||||
|
||||
Lastly, in the `EgressProfiles` dictionary, add a new entry for your C2 profile. It shoudl be of the format:
|
||||
```
|
||||
#if C2CHANNEL
|
||||
{ "c2channel", new C2ProfileData()
|
||||
{
|
||||
TC2Profile = typeof(C2ChannelProfile),
|
||||
TCryptography = typeof(PSKCryptography), // do not change
|
||||
TSerializer = typeof(EncryptedJsonSerializer), // do not change
|
||||
Parameters = new Dictionary<string, string>()
|
||||
{
|
||||
#if DEBUG
|
||||
"param1": "debug_val_1",
|
||||
"param2": "debug_val_2",
|
||||
...
|
||||
#else
|
||||
"param1": "param_boilerplate_to_be_filled_in_by_builder.py",
|
||||
"param2": "param_boilerplate_to_be_filled_in_by_builder.py",
|
||||
...
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
To debug your C2 Profile, simply fill in the parameter values in the DEBUG block of your parameters, and add at the top of the file `#define C2CHANNEL` in the `#if DEBUG` block.
|
||||
|
||||
|
||||
### Add to Builder.py
|
||||
|
||||
Lastly, you'll need to modify the builder.py file under `Payload_Type/apollo/mythic/agent_functions`. In that file, add your new profile to the `c2profiles` attribute under Apollo.
|
||||
222
documentation-payload/ares/contributing/Tasks.md
Normal file
222
documentation-payload/ares/contributing/Tasks.md
Normal file
@@ -0,0 +1,222 @@
|
||||
+++
|
||||
title = "Creating a New Task"
|
||||
chapter = false
|
||||
weight = 25
|
||||
+++
|
||||
|
||||
## Creating a New Task
|
||||
|
||||
Tasks fall under two categories: script only tasks, and atomic tasks.
|
||||
|
||||
## Script Only Tasks
|
||||
|
||||
Script only tasks orchestrate one or more tasks that are already built-in to Apollo. For example, think about a `psexec` command. This command would first want to perform an `upload` to a target, then issue an `sc` command to create a new service, then another `sc` command to start the service. All you should need to do is add a new python file under `Payload_Type/apollo/mythic/agent_functions/` named `mycommand.py`. This file should be of the format:
|
||||
|
||||
```
|
||||
// import statements here
|
||||
|
||||
class MyCommandArguments(TaskArguments):
|
||||
|
||||
def __init__(self, command_line, **kwargs):
|
||||
super().__init__(command_line, **kwargs)
|
||||
self.args = [
|
||||
...
|
||||
]
|
||||
|
||||
async def parse_arguments(self):
|
||||
...
|
||||
|
||||
|
||||
class MyCommandCommand(CommandBase):
|
||||
cmd = "my_command"
|
||||
attributes=CommandAttributes(
|
||||
dependencies=["execute_pe"]
|
||||
)
|
||||
... other attributes ...
|
||||
|
||||
async def create_tasking(self, task: MythicTask) -> MythicTask:
|
||||
return task
|
||||
|
||||
async def process_response(self, response: AgentResponse):
|
||||
pass
|
||||
```
|
||||
|
||||
Of note, if your command requires one or more dependencies to be loaded into the agent, you should specify them in the list of `dependencies` that are defined under `MyCommandCommand["attributes"]`. To perform task delegation, see Mythic documentation, or other examples of script only commands in Apollo, such as `pth`, `dcsync`, `mimikatz`, and otherwise.
|
||||
|
||||
## Atomic Tasks
|
||||
|
||||
Atomic tasks are defined as new tasks to be added in the core of the agent. These types of tasks have no dependencies and are discrete taskings in and of themselves. New atomic tasks should be created under the `Tasks` project of the Apollo solution, as `my_command.cs`. This new file should contain a class, `public class my_command`, that inherits from the `Tasking` base class.
|
||||
|
||||
|
||||
### Tasking Base Class
|
||||
|
||||
The `Tasking` base class that all tasks inherit from have the following special variables:
|
||||
1. `IAgent _agent` - Dependency resolver.
|
||||
2. `Task _data` - A .NET representation of the task data sent from Mythic
|
||||
3. `JsonSerializer _jsonSerializer` - An object that can serialize .NET objects to JSON strings and deserialize JSON strings to .NET objects.
|
||||
|
||||
Lastly, all tasks that inherit this class will use the `CreateTaskResponse` function, which is defined as the following:
|
||||
|
||||
```
|
||||
public virtual TaskResponse CreateTaskResponse(
|
||||
object userOutput, // What the user will see
|
||||
bool completed, // If the task is finished executing
|
||||
string status = "completed", // Status of task execution.
|
||||
IEnumerable<IMythicMessage> messages = null // List of additional IMythicMessages
|
||||
)
|
||||
```
|
||||
|
||||
These `TaskResponse` objects are what are added to the queue via the `ITaskManager.AddTaskResponseToQueue` function, which ultimately sends data from the executing task back to Mythic (discussed later). What you should know, as a user, is that:
|
||||
1. `userOutput` is what is sent in the `user_output` field of a task to Mythic.
|
||||
2. `messages` is a list of additional typed messages Mythic can interpret and feed into various parts of it's UI.
|
||||
|
||||
The `messages` variable is a list of `IMythicMessage` types, which can be one of the following:
|
||||
- `CommandInformation` - Information about loaded commands
|
||||
- `EdgeNode` - Updating the P2P nodes this agent knows about or is connected to
|
||||
- `FileBrowser` - Updating data in Mythic's file browser
|
||||
- `Credential` - Adding new credentials to the Mythic store
|
||||
- `RemovedFileInformation` - Tracking file deletions in Mythic
|
||||
- `Artifact` - Artifacts from task execution. Includes process creation events, logons, file deletions, etc.
|
||||
- `UploadMessage` - A special message type telling Mythic you're retrieving a file from it.
|
||||
- `DownloadMessage` - A special message type telling Mythic you're pushing a data to the Mythic server
|
||||
- `ProcessInformation` - Updates information in Mythic's process browser
|
||||
- `KeylogInformation` - Information about a user's keypresses.
|
||||
|
||||
### Example `my_command.cs` File
|
||||
|
||||
```
|
||||
#define COMMAND_NAME_UPPER
|
||||
|
||||
#if DEBUG
|
||||
#define MY_COMMAND
|
||||
#endif
|
||||
|
||||
#if MY_COMMAND
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ApolloInterop.Classes;
|
||||
using ApolloInterop.Interfaces;
|
||||
using ApolloInterop.Structs.MythicStructs;
|
||||
using System.Runtime.Serialization;
|
||||
using ApolloInterop.Serializers;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
|
||||
namespace Tasks
|
||||
{
|
||||
public class my_command : Tasking
|
||||
{
|
||||
[DataContract]
|
||||
public struct MyCommandParameters
|
||||
{
|
||||
[DataMember(Name = "param_name")] public string ParamName;
|
||||
}
|
||||
public my_command(IAgent agent, Task task) : base(agent, task)
|
||||
{
|
||||
/*
|
||||
* Initiliaze any variables that'll be required for task execution, such as
|
||||
* getting function pointers to Win32 APIs through agent.GetApi().GetLibraryFunction,
|
||||
* asynchronous tasks that push data to Mythic if output streaming is required,
|
||||
* etc.
|
||||
*/
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
MyCommandParameters parameters = _jsonSerializer.Deserialize<MyCommandParameters>(_data.Parameters);
|
||||
TaskResponse resp;
|
||||
/*
|
||||
* Do the main bulk of work of the function here. When you want to submit data to Mythic,
|
||||
* create a new TaskResponse, and add it to the response queue.
|
||||
*/
|
||||
_agent.GetTaskManager().AddTaskResponseToQueue(CreateTaskResponse(
|
||||
$"This is the data I want to display to the user",
|
||||
true // Whether or not the task has completed));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
### IAgent Interface
|
||||
|
||||
The IAgent interface is a dependency leveraged heavily throughout the agent. More reading on the interface can be done in the "Available Interfaces" documentation (may or may not be complete at the time of writing). You can use this interface to perform the following:
|
||||
|
||||
1. Get the agent's `IFileManager` interface, responsible for storing, fetching, and sending files to Mythic.
|
||||
2. Get the agent's `IProcessManager` interface, responsible for creating new child processes.
|
||||
3. Get the agent's `IInjectionManager` interface, responsible for injecting shellcode into processes.
|
||||
4. Get the agent's `ITaskManager` interface, responsible for loading commands, dispatching new tasks, and adding output from tasks to the sending queue.
|
||||
|
||||
This is by no means an exhaustive list of interfaces `IAgent` presents nor is it meant as a full list of the capabilities of each of the aforementioned interfaces. The following are just what's most frequently used during Task development.
|
||||
|
||||
### IFileManager Interface
|
||||
|
||||
The IFileManager interface is used by tasking to perform the following.
|
||||
|
||||
1. Get a file from Mythic by its file ID. The result of this operation will yield the file from Mythic in the `fileBytes` variable shown below:
|
||||
```
|
||||
_agent.GetFileManager().GetFile(
|
||||
_cancellation.Token,
|
||||
_data.ID
|
||||
fileId,
|
||||
out byte[] fileBytes
|
||||
)
|
||||
```
|
||||
2. Send a file to Mythic via the `PutFile` call:
|
||||
```
|
||||
_agent.GetFileManager().PutFile(
|
||||
_cancellationToken.Token,
|
||||
_data.ID,
|
||||
fileBytes, // The file you're sending to Mythic
|
||||
filePath, // Where the file originated
|
||||
out string mythicFileId, // The file ID Mythic assigned to your file
|
||||
false, // Whether or not this file is a screenshot
|
||||
parameters.Hostname // The host where this file was found
|
||||
)
|
||||
```
|
||||
3. Retrieve a file from the agent's cache. Some tasks use the file cache to fetch files required for execution, as it reduces latency from task issuance to task execution. Some examples are:
|
||||
- `execute_assembly` - Fetches assemblies previously registered via `register_file` from the file cache to execute in a sacrifical process
|
||||
- `powershell` - Fetches the currently loaded PowerShell script from the file cache.
|
||||
```
|
||||
_agent.GetFileManager().GetFileFromStore(
|
||||
fileName,
|
||||
out byte[] fileBytes)
|
||||
```
|
||||
|
||||
### IProcessManager
|
||||
|
||||
The IProcessManager interface is responsible for:
|
||||
- Spawning new child processes
|
||||
- Setting the parent process ID of child processes (`ppid`)
|
||||
- Blocking non-Microsoft DLL's from being loaded into the process (`block_dlls`)
|
||||
- Setting the default process to spawn used in fork and run tasks (`spawnto_*`)
|
||||
- Retrieving default application startup arguments.
|
||||
|
||||
#### Spawning a Child Process
|
||||
|
||||
Spawning a new child process can be done via:
|
||||
```
|
||||
_agent.GetProcessManager().NewProcess(
|
||||
string lpApplication,
|
||||
string lpArguments,
|
||||
bool startSuspended = false,
|
||||
)
|
||||
```
|
||||
This returns a new `Process` object (defined in `ApolloInterop`) which is distinct from the traditional `System.Diagnostics.Process` object. You can subscribe to this process's stdout and stderr by adding an event handler to the `Process` object's `OutputDataReceived` and `ErrorDataReceived`. Once you have your event handlers configured, you can issue `Process.Start()` to start process execution, and similarily, `WaitForExit` if you wish to wait for the process to exit.
|
||||
|
||||
Should you need to inject shellcode into a process, the `Process.Inject` method will inject arbitrary shellcode into the process using the currently defined injection method in the `IInjectionManager` implementation in use.
|
||||
|
||||
### IInjectionManager
|
||||
|
||||
This interface is responsible for retrieving the loaded injection techniques, changing which technique is in use for post-ex jobs, as well as giving callers the ability to inject into arbitrary processes.
|
||||
|
||||
Namely, `IInjectionManager.CreateInstance` will allow the caller to create an instance of injection to a target process, then a separate call to `InjectionTechnique.Inject` will inject the shellcode.
|
||||
|
||||
### ITaskManager
|
||||
|
||||
The `ITaskManager` interface is what Tasks will most heavily interface with. Notably, this interface will push output from tasks up to Mythic for the user to see, load new taskings, cancel running tasks, and otherwise.
|
||||
|
||||
As a Task developer, you'll mostly look to use `ITaskManager.AddTaskResponseToQueue`, which adds a new `TaskResponse` message to be sent to Mythic. These `TaskResponse` objects should be created via the `Tasking` base class's `Tasking.CreateTaskResponse`, which populates the requisite fields.
|
||||
12
documentation-payload/ares/contributing/_index.md
Normal file
12
documentation-payload/ares/contributing/_index.md
Normal file
@@ -0,0 +1,12 @@
|
||||
+++
|
||||
title = "Contributing"
|
||||
chapter = true
|
||||
weight = 20
|
||||
pre = "<b>4. </b>"
|
||||
+++
|
||||
|
||||
{{% notice info %}}
|
||||
Developer documentation is incomplete at this time. As such, your mileage may vary with the following contents.
|
||||
{{% /notice %}}
|
||||
|
||||
{{% children %}}
|
||||
50
documentation-payload/ares/contributing/apiresolvers.md
Normal file
50
documentation-payload/ares/contributing/apiresolvers.md
Normal file
@@ -0,0 +1,50 @@
|
||||
+++
|
||||
title = "Creating API Resolvers"
|
||||
chapter = false
|
||||
weight = 25
|
||||
+++
|
||||
|
||||
## Creating a New API Resolver
|
||||
|
||||
New API resolvers must be a new .NET 4.0 Class library project under the Apollo solution. This new project should have a new class that follows the naming schema of `XxxxResolver` and inherits from the `IWin32ApiResolver` interface.
|
||||
|
||||
### IWin32ApiResolver
|
||||
|
||||
The `IWin32ApiResolver` must implement three functions (though only one of which is currently leveraged in the Apollo code base).
|
||||
|
||||
```
|
||||
// The most important function to implement - used universally across the code base
|
||||
T GetLibraryFunction<T>(
|
||||
Library library,
|
||||
string functionName,
|
||||
bool canLoadFromDisk = true,
|
||||
bool resolveForwards = true) where T : Delegate
|
||||
|
||||
T GetLibraryFunction<T>(
|
||||
Library library,
|
||||
short ordinal,
|
||||
bool canLoadFromDisk = true,
|
||||
bool resolveForwards = true) where T : Delegate
|
||||
|
||||
T GetLibraryFunction<T>(
|
||||
Library library,
|
||||
string functionHash,
|
||||
long key,
|
||||
bool canLoadFromDisk=true,
|
||||
bool resolveForwards = true) where T : Delegate
|
||||
```
|
||||
|
||||
For the uninitiated, `T` is a generic typing of `Delegate`, meaning that `T` defines an arbitrary function prototype that the API resolver should marshal the resolved function pointer to. For a simple example, we can define a delegate like `CloseHandle` as the following:
|
||||
```
|
||||
private delegate void CloseHandle(IntPtr Handle)
|
||||
```
|
||||
Then, using the resolver, you could do something like the following:
|
||||
```
|
||||
CloseHandle pCloseHandle = MyWin32ApiResolver.GetLibraryFunction<CloseHandle>(Library.KERNEL32, "CloseHandle")
|
||||
```
|
||||
|
||||
Now, the variable `pCloseHandle` is a .NET function representing the `CloseHandle` native Win32 API call.
|
||||
|
||||
{{% notice info %}}
|
||||
The implementation of GetLibraryFunction is truly only important in its first iteration where you specify the cleartext function name. The GetLibraryFunction overloads that use ordinals and function hashes exist as the DInvoke resolver leverages these parameters. If you choose not to implement them and simply raise an error, the agent will still function at this current junction (1/29/2022)
|
||||
{{% /notice %}}
|
||||
Reference in New Issue
Block a user