4. Create Tasking & Comms Format
Manipulate tasking before it's sent to the agent
Create Tasking
All commands must have a create_go_tasking function with a base case like:
create_go_tasking
is new in Mythic v3.0.0. Prior to this, there was the create_tasking
function. The new change supports backwards compatibility, but the new function provides a lot more information and structured context that's not available in the create_tasking
function. The create_go_tasking
function also mirrors the GoLang's create_tasking
function.
When an operator types a command in the UI, whatever the operator types (or whatever is populated based on the popup modal) gets sent to this function after the input is parsed and validated by the TaskArguments and CommandParameters functions mentioned in Commands.
It's here that the operator has full control of the task before it gets sent down to an agent. The task is currently in the "preprocessing" stage when this function is executed and allows you to do many things via Remote Procedure Calls (RPC) back to the Mythic server.
A graphical flow of what goes on is here: tasking flow.
Available Context
So, from this create tasking function, what information do you immediately have available? https://github.com/MythicMeta/MythicContainerPyPi/blob/main/mythic_container/MythicCommandBase.py#L1071-L1088 <-- this class definition provides the basis for what's available.
taskData.Task
- Information about the Task that's issuedtaskData.Callback
- Information about the Callback for this tasktaskData.Payload
- Information about the packing payload for this callbacktaskData.Commands
- A list of the commands currently loaded into this callbacktaskData.PayloadType
- The name of this payload typetaskData.BuildParameters
- The build parameters and their values used when building the payload for this callbacktaskData.C2Profiles
- Information about the C2 Profiles included inside of this callback.taskData.args
- access to the associated arguments class for this command that already has all of the values populated and validated. Let's say you have an argument called "remote_path", you can access it viataskData.args.get_arg("remote_path")
.Want to change the value of that to something else?
taskData.args.add_arg("remote_path", "new value")
.Want to change the value of that to a different type as well?
taskData.args.add_arg("remote_path", 5, ParameterType.Number)
Want to add a new argument entirely for this specific instance as part of the JSON response?
taskData.args.add_arg("new key", "new value")
. Theadd_arg
functionality will overwrite the value if the key exists, otherwise it'll add a new key with that value. The default ParameterType for args isParameterType.String
, so if you're adding something else, be sure to change the type. Note: If you have multiple parameter groups as part of your tasking, make sure you specify which parameter group your new argument belongs to. By default, the argument gets added to theDefault
parameter group. This could result in some confusion where you add an argument, but it doesn't get picked up and sent down to the agent.You can also remove args
taskData.args.remove_arg("key")
, rename argstaskData.args.rename_arg("old key", "new key")
You can also get access to the user's commandline as well via
taskData.args.commandline
Want to know if an arg is in your args?
taskData.args.has_arg("key")
taskData.Task.TokenID
- information about the token that was used with the task. This requires that the callback has at some point returned tokens for Mythic to track, otherwise this will be 0.
In the PTTaskCreateTaskingMessageResponse
, you can set a variety of attributes to reflect changes back to Mythic as a result of your processing: https://github.com/MythicMeta/MythicContainerPyPi/blob/main/mythic_container/MythicCommandBase.py#L820
Success
- did your processing succeed or not? If not, setError
to a string value representing the error you encountered.CommandName
- If you want the agent to see the command name for this task as something other than what the actual command's name is, reflect that change here. This can be useful if you are creating an alias for a command. So, your agent has the commandls
, but you create a script_only commanddir
. During the processing ofdir
you set theCommandName
tols
so that the agent seesls
and processes it as normal.TaskStatus
- If something went wrong and you want to reflect a specific status to the user, you can set that value here. Status that start witherror:
will appearred
in the UI.Stdout
andStderr
- set these if you want to provide some additional stdout/stderr for the task but don't necessarily want it to clutter the user's interface. This is helpful if you're doing additional compliations as part of your tasking and want to store debug or error information for later.Completed
- If this is set toTrue
then Mythic will mark the task as done and won't allow an agent to pick it up.CompletionFunctionName
- if you want to have a specific local function called when the task completes (such as to do follow-on tasking or more RPC calls), then specify that function name here. This requires a matching entry in the command'scompletion_functions
like follows:ParameterGroupName
- if you want to explicitly set the parameter group name instead of letting Mythic figure it out based on which parameters have values, you can specify that here.DisplayParams
- you can set this value to a string that you'd want the user to see instead of thetaskData.Task.OriginalParams
. This allows you to leverage the JSON structure of the popup modals for processing, but return a more human-friendly version of the parameters for operators to view. There's a new menu-item in the UI when viewing a task that you can select to view all the parameters, so on a case-by-case basis an operator can view the original JSON parameters that were sent down, but this provides a nice way to prevent large JSON blobs that are hard to read for operators while still preserving the nice JSON scripting features on the back-end.
RPC Functionality
This additional functionality is broken out into a series of files (https://github.com/MythicMeta/MythicContainerPyPi/tree/main/mythic_container/MythicGoRPC) file that you can import at the top of your Python command file.
They all follow the same format: