From 7584285ecf1b37ddf40c3f8b690bc18875c53dd2 Mon Sep 17 00:00:00 2001 From: spenceradolph Date: Wed, 17 Apr 2024 15:42:11 +0000 Subject: [PATCH] progress on 'generate' command --- .../sliverapi/SliverRequests/SliverAPI.py | 7 +- .../sliverapi/agent_functions/builder.py | 1 + .../sliverapi/agent_functions/generate.py | 97 +++++++++++++++++++ .../sliverimplant/agent_functions/builder.py | 63 +++++++----- README.md | 6 +- 5 files changed, 141 insertions(+), 33 deletions(-) create mode 100644 Payload_Type/sliverapi/sliverapi/agent_functions/generate.py diff --git a/Payload_Type/sliverapi/sliverapi/SliverRequests/SliverAPI.py b/Payload_Type/sliverapi/sliverapi/SliverRequests/SliverAPI.py index e30a02a..a2dc4c8 100644 --- a/Payload_Type/sliverapi/sliverapi/SliverRequests/SliverAPI.py +++ b/Payload_Type/sliverapi/sliverapi/SliverRequests/SliverAPI.py @@ -1,7 +1,7 @@ from tabulate import tabulate from mythic_container.MythicCommandBase import * from mythic_container.MythicRPC import SendMythicRPCFileGetContent, MythicRPCFileGetContentMessage -from sliver import SliverClientConfig, SliverClient +from sliver import SliverClientConfig, SliverClient, client_pb2 from mythic_container.MythicCommandBase import * from mythic_container.MythicRPC import * from mythic_container.PayloadBuilder import * @@ -115,7 +115,6 @@ async def version(taskData: PTTaskMessageAllData): return f"{version_results}" - async def jobs_kill(taskData: PTTaskMessageAllData, job_id: int): client = await create_sliver_client(taskData) kill_response = await client.kill_job(job_id=job_id) @@ -186,14 +185,14 @@ async def use(taskData: PTTaskMessageAllData, sliver_id: int): payload_type="sliverimplant", uuid=sliver_id, selected_os=sliver_os_table[implant_info.OS], - description=f"sliver {'beaconing' if isBeacon else 'interactive'} implant for {sliver_id}", + description=f"(no download) using sliver {'beaconing' if isBeacon else 'interactive'} implant for {sliver_id}", build_parameters=[], c2_profiles=[], # TODO: figure out if possible to not specify these manually commands=['ifconfig', 'download', 'upload', 'ls', 'ps', 'ping', 'whoami', 'screenshot', 'netstat', 'getgid', 'getuid', 'getpid', 'cat', 'cd', 'pwd', 'info', 'execute', 'mkdir', 'shell', 'terminate', 'rm'] ), ) - await SendMythicRPCPayloadCreateFromScratch(new_payload) + scratchBuild = await SendMythicRPCPayloadCreateFromScratch(new_payload) # create the callback extra_info = json.dumps({ diff --git a/Payload_Type/sliverapi/sliverapi/agent_functions/builder.py b/Payload_Type/sliverapi/sliverapi/agent_functions/builder.py index a4b0d1f..060878a 100644 --- a/Payload_Type/sliverapi/sliverapi/agent_functions/builder.py +++ b/Payload_Type/sliverapi/sliverapi/agent_functions/builder.py @@ -40,6 +40,7 @@ async def build(self) -> BuildResponse: Host="SliverAPI", Ip=ip, IntegrityLevel=3, + ExtraInfo=self.uuid, )) if not create_callback.Success: logger.info(create_callback.Error) diff --git a/Payload_Type/sliverapi/sliverapi/agent_functions/generate.py b/Payload_Type/sliverapi/sliverapi/agent_functions/generate.py new file mode 100644 index 0000000..25d1121 --- /dev/null +++ b/Payload_Type/sliverapi/sliverapi/agent_functions/generate.py @@ -0,0 +1,97 @@ +from ..SliverRequests import SliverAPI + +from mythic_container.MythicCommandBase import * +from mythic_container.PayloadBuilder import * +from mythic_container.MythicRPC import MythicRPCPayloadCreateFromScratchMessage, MythicCommandBase, SendMythicRPCPayloadCreateFromScratch, SendMythicRPCResponseCreate, MythicRPCResponseCreateMessage + +from mythic_container.MythicGoRPC.send_mythic_rpc_payload_create_from_scratch import MythicRPCPayloadConfiguration + +class GenerateArguments(TaskArguments): + def __init__(self, command_line, **kwargs): + super().__init__(command_line, **kwargs) + self.args = [ + CommandParameter( + name="os", + cli_name="os", + display_name="os", + description="operating system", + default_value='windows', + type=ParameterType.ChooseOne, + choices=["linux", "windows"] + ), + CommandParameter( + name="mtls", + cli_name="mtls", + display_name="mtls", + description="mtls ip:port to use", + type=ParameterType.String, + ), + ] + + async def parse_arguments(self): + self.load_args_from_json_string(self.command_line) + + +class Generate(CommandBase): + cmd = "generate" + needs_admin = False + help_cmd = "generate" + description = "Generate a new sliver binary" + version = 1 + author = "Spencer Adolph" + argument_class = GenerateArguments + attackmapping = [] + + async def create_go_tasking(self, taskData: MythicCommandBase.PTTaskMessageAllData) -> MythicCommandBase.PTTaskCreateTaskingMessageResponse: + # TODO: paste all the config options here + + os = taskData.args.get_arg('os') + mtls = taskData.args.get_arg('mtls') + + sliverconfig_file_uuid = taskData.BuildParameters[0].Value + + sliver_os_table = { + 'linux': 'Linux' + } + + createMessage = MythicRPCPayloadCreateFromScratchMessage( + TaskID=taskData.Task.ID, + PayloadConfiguration=MythicRPCPayloadConfiguration( + PayloadType="sliverimplant", + SelectedOS=sliver_os_table[os], + Description="generated payload: sliver implant", + BuildParameters=[ + MythicRPCPayloadConfigurationBuildParameter( + name='sliverconfig_file_uuid', + value=sliverconfig_file_uuid + ), + MythicRPCPayloadConfigurationBuildParameter( + name='os', + value=os + ), + MythicRPCPayloadConfigurationBuildParameter( + name='mtls', + value=mtls + ), + ], + C2Profiles=[], + Commands=['ifconfig', 'download', 'upload', 'ls', 'ps', 'ping', 'whoami', 'screenshot', 'netstat', 'getgid', 'getuid', 'getpid', 'cat', 'cd', 'pwd', 'info', 'execute', 'mkdir', 'shell', 'terminate', 'rm'] + ), + ) + await SendMythicRPCPayloadCreateFromScratch(createMessage) + + await SendMythicRPCResponseCreate(MythicRPCResponseCreateMessage( + TaskID=taskData.Task.ID, + Response="generated implant".encode("UTF8"), + )) + + taskResponse = MythicCommandBase.PTTaskCreateTaskingMessageResponse( + TaskID=taskData.Task.ID, + Success=True, + Completed=True + ) + return taskResponse + + async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: + resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) + return resp diff --git a/Payload_Type/sliverimplant/sliverimplant/agent_functions/builder.py b/Payload_Type/sliverimplant/sliverimplant/agent_functions/builder.py index e74f219..d5589ab 100644 --- a/Payload_Type/sliverimplant/sliverimplant/agent_functions/builder.py +++ b/Payload_Type/sliverimplant/sliverimplant/agent_functions/builder.py @@ -2,7 +2,7 @@ from mythic_container.PayloadBuilder import * from mythic_container.MythicCommandBase import * from mythic_container.MythicRPC import * -from sliver import SliverClientConfig, SliverClient +from sliver import SliverClientConfig, SliverClient, client_pb2 class SliverImplant(PayloadType): @@ -24,38 +24,49 @@ class SliverImplant(PayloadType): build_steps = [] build_parameters = [ BuildParameter( - name="name", - description="name", + name="sliverconfig_file_uuid", + description="sliverconfig_file_uuid", + parameter_type=BuildParameterType.String, + ), + BuildParameter( + name="os", + description="os", + parameter_type=BuildParameterType.String, + ), + BuildParameter( + name="mtls", + description="mtls", parameter_type=BuildParameterType.String, ), ] async def build(self) -> BuildResponse: - # Just hope they have this setup already, and not have multiple - # sliverapi_payloads = await SendMythicRPCPayloadSearch(MythicRPCPayloadSearchMessage( - # PayloadTypes=['sliverapi'], - # )) - # sliver_config_uuid = sliverapi_payloads.Payloads[0].BuildParameters[0].Value - # filecontent = await SendMythicRPCFileGetContent(MythicRPCFileGetContentMessage( - # AgentFileId=sliver_config_uuid - # )) - # config = SliverClientConfig.parse_config(filecontent.Content) - # client = SliverClient(config) - # await client.connect() + os = self.get_parameter('os') + mtls = self.get_parameter('mtls') + sliverconfig_file_uuid = self.get_parameter('sliverconfig_file_uuid') - # self.build_parameters + if (os == ''): + return BuildResponse(status=BuildStatus.Success) + + filecontent = await SendMythicRPCFileGetContent(MythicRPCFileGetContentMessage( + AgentFileId=sliverconfig_file_uuid + )) + config = SliverClientConfig.parse_config(filecontent.Content) + client = SliverClient(config) + await client.connect() - # implant_config = client_pb2.ImplantConfig( - # IsBeacon=self.build_parameters[''], - # Name="sliver-pytest-1", - # GOARCH="amd64", - # GOOS="linux", - # Format=client_pb2.OutputFormat.EXECUTABLE, - # ObfuscateSymbols=False, - # C2=[client_pb2.ImplantC2(Priority=0, URL="http://localhost:80")], - # ) + implant_config = client_pb2.ImplantConfig( + IsBeacon=False, + Name=f"{self.uuid}", + GOARCH="amd64", + GOOS=os, + Format=client_pb2.OutputFormat.EXECUTABLE, + ObfuscateSymbols=False, + C2=[client_pb2.ImplantC2(Priority=0, URL=f"mtls://{mtls}")], + ) - # implant = await client.generate_implant(implant_config) + implant = await client.generate_implant(implant_config) + implant_bytes = implant.File.Data - resp = BuildResponse(status=BuildStatus.Success) + resp = BuildResponse(status=BuildStatus.Success, payload=implant_bytes) return resp diff --git a/README.md b/README.md index 90b06fc..9ba54e7 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ sudo ./mythic-cli install github https://github.com/MythicAgents/sliver - Interactive Tasking (shell) 🚧🐞 (buggy) - Beacon checkin status - Documentation-payload -- Build implants through Mythic ('generate' + UI) +- Build implants through Mythic ('generate' + UI)✅ - Sliver 3rd party integrations - Stretch Goal: Ability to run the sliver server within mythic - Stretch Goal: V2 everything in go💙 (match sliver official client code) @@ -67,7 +67,7 @@ sudo ./mythic-cli install github https://github.com/MythicAgents/sliver - cursed - dns - env - - generate + - generate✅ - hosts - http - https @@ -86,7 +86,7 @@ sudo ./mythic-cli install github https://github.com/MythicAgents/sliver - tasks - update - use✅ - - version + - version✅ - websites - wg - operators