From 2472fe703b67e0b3c221449e1fffc0320136b292 Mon Sep 17 00:00:00 2001 From: Dwight Hohnstein Date: Mon, 16 May 2022 11:54:17 -0700 Subject: [PATCH] 2.2.1 (#107) * Adding ifconfig command * Adding documentation for ifconfig * Updated -Query to provide config information * Updated sc command to extend query and add modify function * updated sc browserscript to include new sc features * Changed upload dialogue from Apfell->Mythic The upload command's modal popup was not updated from Apfell to Mythic. * Adding code for updated sc command * Updated browser script to prevent a value from showing 0 when it should be null * Bumping sc.py version number * adding iphlpapi.dll * adding netstat task * New dev environment, removed MSPSv5 reference assemblies, attempted to reinstall fody for everything * fixing fody for screenshotinject * Adding support for process name on checkin * readding netstat to project * adding scarecrow wrapper * adding legacy call to IsWow64Process back for legacy windows * fixes for it * adding ifconfig to tasks csproj since I'm a big dummy * readme updates * added close handle to tcp peer to force close established connection on unlink with tcp profile (#106) Co-authored-by: spicybyte * moving CloseHandle instantiation to class constructor * Quick fix to services -modify (#103) * Removed some print statements and uploaded correct sc.py... * adding modify to supported ui features Co-authored-by: spicybyte * modifying pth command to respect saved credentials when task is issued. Closes #98 * Updating version number Co-authored-by: spicybyte Co-authored-by: Duane Michael <41414134+subat0mik@users.noreply.github.com> Co-authored-by: thespicybyte <65791900+thespicybyte@users.noreply.github.com> --- .../agent_code/Apollo/Peers/TCP/TCPPeer.cs | 8 + Payload_Type/apollo/agent_code/Tasks/sc.cs | 3 - .../apollo/mythic/agent_functions/builder.py | 2 +- .../apollo/mythic/agent_functions/pth.py | 2 +- .../apollo/mythic/agent_functions/sc.py | 150 +++++++++++++++++- 5 files changed, 157 insertions(+), 8 deletions(-) diff --git a/Payload_Type/apollo/agent_code/Apollo/Peers/TCP/TCPPeer.cs b/Payload_Type/apollo/agent_code/Apollo/Peers/TCP/TCPPeer.cs index ebbfa87d..f119a582 100644 --- a/Payload_Type/apollo/agent_code/Apollo/Peers/TCP/TCPPeer.cs +++ b/Payload_Type/apollo/agent_code/Apollo/Peers/TCP/TCPPeer.cs @@ -16,6 +16,7 @@ using TTasks = System.Threading.Tasks; using ApolloInterop.Enums.ApolloEnums; using System.Net.Sockets; +using ApolloInterop.Classes.Api; using ApolloInterop.Classes.Core; namespace Apollo.Peers.TCP @@ -27,6 +28,10 @@ public class TCPPeer : AI.Classes.P2P.Peer private TTasks.Task _sendTask; private bool _connected = false; private string _partialData = ""; + private IntPtr _socketHandle = IntPtr.Zero; + private delegate void CloseHandle(IntPtr handle); + private CloseHandle _pCloseHandle; + public TCPPeer(IAgent agent, PeerInformation info) : base(agent, info) { C2ProfileName = "tcp"; @@ -34,6 +39,7 @@ public TCPPeer(IAgent agent, PeerInformation info) : base(agent, info) _tcpClient.ConnectionEstablished += OnConnect; _tcpClient.MessageReceived += OnMessageReceived; _tcpClient.Disconnect += OnDisconnect; + _pCloseHandle = _agent.GetApi().GetLibraryFunction(Library.KERNEL32, "CloseHandle"); _sendAction = (object p) => { TcpClient c = (TcpClient)p; @@ -80,6 +86,7 @@ public void OnConnect(object sender, TcpMessageEventArgs args) _sendTask.Start(); _connected = true; _previouslyConnected = true; + _socketHandle = args.Client.Client.Handle; } public void OnDisconnect(object sender, TcpMessageEventArgs args) @@ -184,6 +191,7 @@ public override bool Start() public override void Stop() { _cts.Cancel(); + _pCloseHandle(_socketHandle); _sendTask.Wait(); } } diff --git a/Payload_Type/apollo/agent_code/Tasks/sc.cs b/Payload_Type/apollo/agent_code/Tasks/sc.cs index a3a1f13d..e73ef76d 100644 --- a/Payload_Type/apollo/agent_code/Tasks/sc.cs +++ b/Payload_Type/apollo/agent_code/Tasks/sc.cs @@ -702,9 +702,7 @@ private void ValidateParameters(ScParameters args) throw new Exception("Modify action requires service name to create."); } else if (string.IsNullOrEmpty(args.Binpath) && string.IsNullOrEmpty(args.DisplayName) && string.IsNullOrEmpty(args.RunAs) && string.IsNullOrEmpty(args.ServiceTypeParam) && string.IsNullOrEmpty(args.StartType)) { - Console.WriteLine("all fill ins empty"); if (args.ServiceTypeParam == "SERVICE_NO_CHANGE" && args.StartType == "SERVICE_NO_CHANGE") { - Console.WriteLine("all default"); throw new Exception("Modify action requires parameter to modify."); } } @@ -717,7 +715,6 @@ private void ValidateParameters(ScParameters args) private static bool InstallService(string hostname, string ServiceName, string ServiceDisplayName, string ServiceEXE) { - Console.WriteLine(hostname); try { UninstallService(hostname, ServiceName); diff --git a/Payload_Type/apollo/mythic/agent_functions/builder.py b/Payload_Type/apollo/mythic/agent_functions/builder.py index 0c63da78..747470f5 100644 --- a/Payload_Type/apollo/mythic/agent_functions/builder.py +++ b/Payload_Type/apollo/mythic/agent_functions/builder.py @@ -14,7 +14,7 @@ class Apollo(PayloadType): supported_os = [ SupportedOS.Windows ] - version = "2.2.0" + version = "2.2.1" wrapper = False wrapped_payloads = ["scarecrow_wrapper", "service_wrapper"] note = """ diff --git a/Payload_Type/apollo/mythic/agent_functions/pth.py b/Payload_Type/apollo/mythic/agent_functions/pth.py index 24e029d0..c08038c6 100644 --- a/Payload_Type/apollo/mythic/agent_functions/pth.py +++ b/Payload_Type/apollo/mythic/agent_functions/pth.py @@ -140,7 +140,7 @@ async def parse_arguments(self): cmd += " /run:{}".format(run) cmd = "\\\"{}\\\"".format(cmd) - self.add_arg("command", "mimikatz.exe {}".format(cmd)) + self.add_arg("command", "mimikatz.exe {}".format(cmd), parameter_group_info=[ParameterGroupInfo(group_name=self.get_parameter_group_name())]) else: raise Exception("No mimikatz command given to execute.\n\tUsage: {}".format(PthCommand.help_cmd)) diff --git a/Payload_Type/apollo/mythic/agent_functions/sc.py b/Payload_Type/apollo/mythic/agent_functions/sc.py index f6f60567..09dc20e9 100644 --- a/Payload_Type/apollo/mythic/agent_functions/sc.py +++ b/Payload_Type/apollo/mythic/agent_functions/sc.py @@ -71,6 +71,19 @@ def __init__(self, command_line, **kwargs): group_name="Delete" ), ]), + CommandParameter( + name="modify", + cli_name="Modify", + display_name="Modify", + type=ParameterType.Boolean, + default_value=False, + description="Service controller action to perform.", + parameter_group_info=[ + ParameterGroupInfo( + required=True, + group_name="Modify" + ), + ]), CommandParameter( name="computer", cli_name="Computer", @@ -98,6 +111,10 @@ def __init__(self, command_line, **kwargs): required=False, group_name="Delete" ), + ParameterGroupInfo( + required=False, + group_name="Modify" + ), ]), CommandParameter( name="service", @@ -126,6 +143,10 @@ def __init__(self, command_line, **kwargs): required=True, group_name="Delete" ), + ParameterGroupInfo( + required=True, + group_name="Modify" + ), ]), CommandParameter( name="display_name", @@ -142,6 +163,10 @@ def __init__(self, command_line, **kwargs): required=True, group_name="Create" ), + ParameterGroupInfo( + required=False, + group_name="Modify" + ), ]), CommandParameter( name="binpath", @@ -154,6 +179,101 @@ def __init__(self, command_line, **kwargs): required=True, group_name="Create" ), + ParameterGroupInfo( + required=False, + group_name="Modify" + ), + ]), + CommandParameter( + name="run_as", + cli_name="RunAs", + display_name="Run As", + type=ParameterType.String, + description="Specify the user the service will run as.", + parameter_group_info=[ + ParameterGroupInfo( + required=False, + group_name="Modify" + ), + ]), + CommandParameter( + name="password", + cli_name="Password", + display_name="Password", + type=ParameterType.String, + description="Plaintext password for service.", + parameter_group_info=[ + ParameterGroupInfo( + required=False, + group_name="Modify" + ), + ]), + CommandParameter( + name="service_type", + cli_name="ServiceType", + display_name="Service Type", + type=ParameterType.ChooseOne, + choices= [ + "SERVICE_NO_CHANGE", + "SERVICE_KERNEL_DRIVER", + "SERVICE_FILE_SYSTEM_DRIVER", + "SERVICE_WIN32_OWN_PROCESS", + "SERVICE_WIN32_SHARE_PROCESS", + "SERVICE_INTERACTIVE_PROCESS", + "SERVICE_WIN32", + ], + default_value="SERVICE_NO_CHANGE", + description="Set the service type.", + parameter_group_info=[ + ParameterGroupInfo( + required=False, + group_name="Modify" + ), + ]), + CommandParameter( + name="start_type", + cli_name="StartType", + display_name="Start Type", + type=ParameterType.ChooseOne, + choices= [ + "SERVICE_NO_CHANGE", + "SERVICE_AUTO_START", + "SERVICE_BOOT_START", + "SERVICE_DEMAND_START", + "SERVICE_DISABLED", + "SERVICE_SYSTEM_START" + ], + default_value="SERVICE_NO_CHANGE", + description="Set the service start type.", + parameter_group_info=[ + ParameterGroupInfo( + required=False, + group_name="Modify" + ), + ]), + CommandParameter( + name="dependencies", + cli_name="Dependencies", + display_name="Dependencies", + type=ParameterType.Array, + description="Set a list of dependencies.", + parameter_group_info=[ + ParameterGroupInfo( + required=False, + group_name="Modify" + ), + ]), + CommandParameter( + name="description", + cli_name="Description", + display_name="Description", + type=ParameterType.String, + description="Set the description of a service.", + parameter_group_info=[ + ParameterGroupInfo( + required=False, + group_name="Modify" + ), ]), ] @@ -208,7 +328,7 @@ class ScCommand(CommandBase): author = "@djhohnstein" argument_class = ScArguments attackmapping = ["T1106"] - supported_ui_features = ["sc:start", "sc:stop", "sc:delete"] + supported_ui_features = ["sc:start", "sc:stop", "sc:delete", "sc:modify"] browser_script = BrowserScript(script_name="sc", author="@djhohnstein", for_new_ui=True) async def create_tasking(self, task: MythicTask) -> MythicTask: @@ -216,7 +336,12 @@ async def create_tasking(self, task: MythicTask) -> MythicTask: service_name = task.args.get_arg("service") display_name = task.args.get_arg("display_name") binpath = task.args.get_arg("binpath") - + run_as = task.args.get_arg("run_as") + password = task.args.get_arg("password") + service_type = task.args.get_arg("service_type") + start_type = task.args.get_arg("start_type") + dependencies = task.args.get_arg("dependencies") + description = task.args.get_arg("description") query = task.args.get_arg("query") if query: @@ -233,8 +358,11 @@ async def create_tasking(self, task: MythicTask) -> MythicTask: delete = task.args.get_arg("delete") if delete: task.display_params = "-Delete" + modify = task.args.get_arg("modify") + if modify: + task.display_params = "-Modify" - if not any([query, start, stop, create, delete]): + if not any([query, start, stop, create, delete, modify]): raise Exception("Failed to get a valid action to perform.") if computer is not None and computer is not "": task.display_params += " -Computer {}".format(computer) @@ -248,6 +376,22 @@ async def create_tasking(self, task: MythicTask) -> MythicTask: if binpath is not None and binpath is not "": task.display_params += " -BinPath '{}'".format(binpath) + if run_as is not None and run_as is not "": + task.display_params += " -RunAs '{}'".format(run_as) + + if password is not None and password is not "": + task.display_params += " -Password '{}'".format(password) + + if modify: + task.display_params += " -ServiceType '{}'".format(service_type) + task.display_params += " -StartType '{}'".format(start_type) + + if dependencies is not None and not dependencies: + task.display_params += " -Dependencies '{}'".format(",".join(dependencies)) + + if description is not None and description is not "": + task.display_params += " -Description '{}'".format(description) + return task async def process_response(self, response: AgentResponse):