Skip to content

Commit

Permalink
Merge pull request #110 from its-a-feature/2.2-updates
Browse files Browse the repository at this point in the history
updaing a few pieces of the new ui
  • Loading branch information
its-a-feature authored Aug 4, 2021
2 parents f15ec77 + 8bc514b commit 4f10b1b
Show file tree
Hide file tree
Showing 21 changed files with 232 additions and 167 deletions.
4 changes: 3 additions & 1 deletion mythic-docker/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
mythic_admin_password = str(settings.get("ADMIN_PASSWORD", "mythic_password"))
default_operation_name = str(settings.get("DEFAULT_OPERATION_NAME", "Operation Chimera"))
nginx_port = str(settings.get("NGINX_PORT", 7443))
nginx_host = str(settings.get("NGINX_HOST", "127.0.0.1"))
listen_port = str(settings.get("SERVER_PORT", 17443))
allowed_ip_blocks = settings.get("ALLOWED_IP_BLOCKS", "0.0.0.0/0").split(",")
server_header = settings.get("SERVER_HEADER", "nginx 1.2")
Expand All @@ -40,6 +41,7 @@
"No MYTHIC_JWT_SECRET environment variable found")
sys.exit(1)
redis_port = int(settings.get("REDIS_PORT", 6379))
redis_host = settings.get("REDIS_HOST", "127.0.0.1")
# --------------------------------------------
# --------------------------------------------
# IP to bind to for the server, 0.0.0.0 means all local IPv4 addresses
Expand Down Expand Up @@ -151,7 +153,7 @@ def format(self, record):

mythic = Sanic(__name__, strict_slashes=False, log_config=mythic_logging)

mythic.config["SERVER_IP_ADDRESS"] = "127.0.0.1"
mythic.config["SERVER_IP_ADDRESS"] = nginx_host
mythic.config["SERVER_PORT"] = nginx_port
mythic.config["DB_HOST"] = db_host
mythic.config["DB_PORT"] = db_port
Expand Down
8 changes: 8 additions & 0 deletions mythic-docker/app/api/payloadtype_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,9 +478,17 @@ async def import_payload_type_func(ptype, operator, rabbitmqName):
return {"status": "success", "new": new_payload, **payload_type.to_json()}
except Exception as e:
logger.exception("exception on importing payload type {}".format(payload_type.ptype))
asyncio.create_task(
send_all_operations_message(
message=f"{rabbitmqName}'s sync with Mythic failed:\n" + str(e),
level="warning", source="payload_type_import"))
return {"status": "error", "error": str(e)}
except Exception as e:
logger.exception("failed to import a payload type: " + str(e))
asyncio.create_task(
send_all_operations_message(
message=f"{rabbitmqName}'s sync with Mythic failed:\n" + str(e),
level="warning", source="payload_type_import"))
return {"status": "error", "error": str(e)}


Expand Down
4 changes: 4 additions & 0 deletions mythic-docker/app/api/rabbitmq_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,8 @@ async def create_tasking(self, task: MythicTask) -> MythicTask:
from app.api.task_api import add_all_payload_info

payload_info = await add_all_payload_info(payload)
if payload_info["status"] == "error":
return payload_info
payload_json["commands"] = payload_info["commands"]
payload_json["c2info"] = payload_info["c2info"]
payload_json["build_parameters"] = payload_info["build_parameters"]
Expand Down Expand Up @@ -920,6 +922,8 @@ async def handle_automated_payload_creation_response(task, rsp, data, host):
from app.api.task_api import add_all_payload_info

payload_info = await add_all_payload_info(payload)
if payload_info["status"] == "error":
return payload_info
payload_info = {**payload_info, **payload.to_json()}
return {"status": "success", "response": payload_info}
else:
Expand Down
60 changes: 33 additions & 27 deletions mythic-docker/app/api/response_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,33 +562,39 @@ async def post_agent_response(agent_message, callback):
rabbit_message["task"]["callback"] = task.callback.to_json()
# get the information for the callback's associated payload
payload_info = await add_all_payload_info(task.callback.registered_payload)
rabbit_message["task"]["callback"]["build_parameters"] = payload_info[
"build_parameters"
]
rabbit_message["task"]["callback"]["c2info"] = payload_info["c2info"]
tags = await app.db_objects.execute(
db_model.tasktag_query.where(db_model.TaskTag.task == task))
rabbit_message["task"]["tags"] = [t.tag for t in tags]
rabbit_message["task"]["token"] = task.token.to_json() if task.token is not None else None
rabbit_message["response"] = parsed_response["process_response"]
if app.debugging_enabled:
await send_all_operations_message(
message=f"Sending message to {task.callback.registered_payload.payload_type.ptype}'s container for processing of a 'process_response' message:\n{str(parsed_response['process_container'])}",
level="info", source="debug", operation=task.callback.operation)
status = await send_pt_rabbitmq_message(payload_type=task.callback.registered_payload.payload_type.ptype,
command="process_container",
username="",
reference_id=task.id,
message_body=js.dumps(rabbit_message))
if status["status"] == "error" and "type" in status:
logger.error("response_api.py: sending process_response message: " + status["error"])
await app.db_objects.create(Response, task=task,
response="Container not running, failed to process process_response data, saving here")
await app.db_objects.create(Response, task=task, response=parsed_response["process_response"])
task.callback.registered_payload.payload_type.container_count = 0
await app.db_objects.update(task.callback.registered_payload.payload_type)
if status["status"] == "error":
logger.error("response_api.py: sending process_response message: " + status["error"])
if payload_info["status"] == "error":
asyncio.create_task(
send_all_operations_message(
message=f"Failed to process post_response message for task {task.id}:\n{payload_info['error']}",
level="warning", source=f"task_response_{task.id}"))
else:
rabbit_message["task"]["callback"]["build_parameters"] = payload_info[
"build_parameters"
]
rabbit_message["task"]["callback"]["c2info"] = payload_info["c2info"]
tags = await app.db_objects.execute(
db_model.tasktag_query.where(db_model.TaskTag.task == task))
rabbit_message["task"]["tags"] = [t.tag for t in tags]
rabbit_message["task"]["token"] = task.token.to_json() if task.token is not None else None
rabbit_message["response"] = parsed_response["process_response"]
if app.debugging_enabled:
await send_all_operations_message(
message=f"Sending message to {task.callback.registered_payload.payload_type.ptype}'s container for processing of a 'process_response' message:\n{str(parsed_response['process_container'])}",
level="info", source="debug", operation=task.callback.operation)
status = await send_pt_rabbitmq_message(payload_type=task.callback.registered_payload.payload_type.ptype,
command="process_container",
username="",
reference_id=task.id,
message_body=js.dumps(rabbit_message))
if status["status"] == "error" and "type" in status:
logger.error("response_api.py: sending process_response message: " + status["error"])
await app.db_objects.create(Response, task=task,
response="Container not running, failed to process process_response data, saving here")
await app.db_objects.create(Response, task=task, response=parsed_response["process_response"])
task.callback.registered_payload.payload_type.container_count = 0
await app.db_objects.update(task.callback.registered_payload.payload_type)
elif status["status"] == "error":
logger.error("response_api.py: sending process_response message: " + status["error"])
except Exception as pc:
logger.error("response_api.py: " + str(sys.exc_info()[-1].tb_lineno) + str(pc))
if app.debugging_enabled:
Expand Down
110 changes: 63 additions & 47 deletions mythic-docker/app/api/task_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1017,12 +1017,14 @@ async def issue_dynamic_parameter_call(command: str, parameter_name: str, payloa
rabbitmq_message = callback.to_json()
# get the information for the callback's associated payload
payload_info = await add_all_payload_info(callback.registered_payload)
if payload_info["status"] == "error":
return {"status": "error", "error": payload_info["error"]}
rabbitmq_message["build_parameters"] = payload_info[
"build_parameters"
]
rabbitmq_message["c2info"] = payload_info["c2info"]
except Exception as e:
return {"status": "error", "error": "Failed to get callback and payload information"}, False
return {"status": "error", "error": "Failed to get callback and payload information"}
status, successfully_sent = await payload_rpc.call(message={
"action": parameter_name,
"command": command,
Expand Down Expand Up @@ -1238,6 +1240,8 @@ async def submit_task_to_container(task, username, params: str = None):
rabbit_message["task"]["callback"] = task.callback.to_json()
# get the information for the callback's associated payload
payload_info = await add_all_payload_info(task.callback.registered_payload)
if payload_info["status"] == "error":
return payload_info
rabbit_message["task"]["callback"]["build_parameters"] = payload_info[
"build_parameters"
]
Expand Down Expand Up @@ -1280,6 +1284,8 @@ async def submit_task_callback_to_container(task: Task, function_name: str, user
rabbit_message["task"]["callback"] = task.callback.to_json()
# get the information for the callback's associated payload
payload_info = await add_all_payload_info(task.callback.registered_payload)
if payload_info["status"] == "error":
return payload_info
rabbit_message["task"]["callback"]["build_parameters"] = payload_info[
"build_parameters"
]
Expand Down Expand Up @@ -1308,54 +1314,64 @@ async def submit_task_callback_to_container(task: Task, function_name: str, user


async def add_all_payload_info(payload):
rabbit_message = {}
if payload.uuid in cached_payload_info:
rabbit_message["build_parameters"] = cached_payload_info[payload.uuid][
"build_parameters"
]
rabbit_message["commands"] = cached_payload_info[payload.uuid]["commands"]
rabbit_message["c2info"] = cached_payload_info[payload.uuid]["c2info"]
else:
cached_payload_info[payload.uuid] = {}
build_parameters = {}
build_params = await app.db_objects.execute(
db_model.buildparameterinstance_query.where(db_model.BuildParameterInstance.payload == payload)
)
for bp in build_params:
build_parameters[bp.build_parameter.name] = bp.parameter
rabbit_message["build_parameters"] = build_parameters
# cache it for later
cached_payload_info[payload.uuid]["build_parameters"] = build_parameters
c2_profile_parameters = []
payloadc2profiles = await app.db_objects.execute(
db_model.payloadc2profiles_query.where(db_model.PayloadC2Profiles.payload == payload)
)
for pc2p in payloadc2profiles:
# for each profile, we need to get all of the parameters and supplied values for just that profile
param_dict = {}
c2_param_instances = await app.db_objects.execute(
db_model.c2profileparametersinstance_query.where(
(C2ProfileParametersInstance.payload == payload)
& (C2ProfileParametersInstance.c2_profile == pc2p.c2_profile)
)
rabbit_message = {"status": "success"}
try:
if payload.uuid in cached_payload_info:
rabbit_message["build_parameters"] = cached_payload_info[payload.uuid][
"build_parameters"
]
rabbit_message["commands"] = cached_payload_info[payload.uuid]["commands"]
rabbit_message["c2info"] = cached_payload_info[payload.uuid]["c2info"]
else:
cached_payload_info[payload.uuid] = {}
build_parameters = {}
build_params = await app.db_objects.execute(
db_model.buildparameterinstance_query.where(db_model.BuildParameterInstance.payload == payload)
)
# save all the variables off to a dictionary for easy looping
for instance in c2_param_instances:
param = instance.c2_profile_parameters
param_dict[param.name] = instance.value

c2_profile_parameters.append(
{"parameters": param_dict, **pc2p.c2_profile.to_json()}
for bp in build_params:
build_parameters[bp.build_parameter.name] = bp.parameter
rabbit_message["build_parameters"] = build_parameters
# cache it for later
cached_payload_info[payload.uuid]["build_parameters"] = build_parameters
c2_profile_parameters = []
payloadc2profiles = await app.db_objects.execute(
db_model.payloadc2profiles_query.where(db_model.PayloadC2Profiles.payload == payload)
)
rabbit_message["c2info"] = c2_profile_parameters
cached_payload_info[payload.uuid]["c2info"] = c2_profile_parameters
stamped_commands = await app.db_objects.execute(db_model.payloadcommand_query.where(
db_model.PayloadCommand.payload == payload
))
commands = [c.command.cmd for c in stamped_commands]
rabbit_message["commands"] = commands
cached_payload_info[payload.uuid]["commands"] = commands
return rabbit_message
for pc2p in payloadc2profiles:
# for each profile, we need to get all of the parameters and supplied values for just that profile
param_dict = {}
c2_param_instances = await app.db_objects.execute(
db_model.c2profileparametersinstance_query.where(
(C2ProfileParametersInstance.payload == payload)
& (C2ProfileParametersInstance.c2_profile == pc2p.c2_profile)
)
)
# save all the variables off to a dictionary for easy looping
for instance in c2_param_instances:
param = instance.c2_profile_parameters
param_dict[param.name] = instance.value

c2_profile_parameters.append(
{"parameters": param_dict, **pc2p.c2_profile.to_json()}
)
rabbit_message["c2info"] = c2_profile_parameters
cached_payload_info[payload.uuid]["c2info"] = c2_profile_parameters
stamped_commands = await app.db_objects.execute(db_model.payloadcommand_query.where(
db_model.PayloadCommand.payload == payload
))
commands = [c.command.cmd for c in stamped_commands]
rabbit_message["commands"] = commands
cached_payload_info[payload.uuid]["commands"] = commands
return rabbit_message
except Exception as e:
rabbit_message["status"] = "error"
rabbit_message["error"] = str(e)
from app.api.operation_api import send_all_operations_message
asyncio.create_task(
send_all_operations_message(
message=f"Failed to fetch Payload info for {payload.uuid}:\n{str(e)}",
level="warning"))
return rabbit_message


async def add_command_attack_to_task(task, command):
Expand Down
Loading

0 comments on commit 4f10b1b

Please sign in to comment.