Mythic v3.2 has Push C2, Interactive Async Tasking, TypedArray parameters, new graphing libraries in the UI, database migrations, dynamic file browser groupings, and more!
It’s been a few months since the last Mythic update, so it’s time to release a new version! This version has many major updates from the past quarter that I’m excited to share. The next few sections highlight some of the more major updates, but a detailed breakdown can be found on the Mythic repo’s changelog.
Asynchronous communications in command and control (C2) platforms have many great benefits, but sometimes it can be really helpful to drop into an interactive shell on the target. Historically, if you wanted to do this, you needed to do something like sleep 0 and combine it with something like socks to allow proxying in a local SSH connection. Going to sleep 0 on a callback can have severe penalties to performance and can increase possibilities of detection. There’s no reason we must do that though. Mythic 3.1 allows you to add a supported_ui_featureof task_response:interactive, which effectively means that this task opens a streaming channel for follow-on inputs.
Mythic can open a sub-shell within your response output that allows you to submit follow-on input. Not only that, but you can use the controls to send non-text inputs too like escape, CtrlC, CtrlZ, etc. You can also adjust what kind of line endings get sent with your input (ex: LineFeed (n), CarriageReturn (r), None). The interesting piece here is being able to specify None because it allows you to, from the web UI, control interactive shell commands like less or man that expect a single character ( q, space, n, etc) without additional line endings.
You can also toggle the ability for the web UI to process ANSI terminal colors, line wrapping, and even task statuses. Every input you pass in through the web UI for interactive tasking is tracked as a proper Task within Mythic. This makes it easy to go back and find what things were issued interactively as well as giving the operator some indication as to which tasks the agent has picked up so far or not.
With the MythicRPCProxyStart call, you can also open up a port associated with this interactive task. This port allows you to have a normal full terminal TTY that you use instead of going through the web UI. It’s important to note though that if you do this, the inputs you pass in will NOT be tracked as normal tasks within Mythic. The output will still be streamed to the web UI and saved in the database, but your inputs are not tracked.
As part of interactive tasking, or anything where you ideally want rapid responses such as SOCKS or reverse port forwards, it’s helpful to reduce latency as much as possible without adding additional overheads. The traditional format is to do something like sleep 0 so that your agent checks for messages from the C2 platform with only milliseconds of time between each message. This does allow a higher throughput of traffic but comes at a cost. Most of those messages from the agent are going to be the same — empty messages back that there’s nothing new. There is no benefit, and you have a lot of added overhead reprocessing that same request for messages repeatedly, complete with database lookups, encryption/decryption, and additional processing. A better way to do this would be to have the C2 platform notify the agent that there’s new data — this is Push C2.
This is nothing new overall. Many peer-to-peer (P2P) agents use this style of connection already so that they don’t cause a massive build-up of requests waiting for the final egress agent to pass along their messages to the C2 platform. The only potential downside to Push C2 vs Polling is that you have a held open connection to your redirector. This can look less suspicious if you do this connection via something like Websockets instead of a raw TCP connection outbound, but that highly depends on the environment. On the back end, the C2 profile holds open a connection to Mythic via gRPC to allow the streaming of messages.
The performance improvements for this can be astounding. The poseidon agent at sleep 0 spiked the mythic_server Docker container to 40% to provide a download speed test of 186 Mb/s. Swapping that poseidon agent to a Push C2 with websockets spiked the mythic_server Docker container to 1% with the same throughput.
Split Tasking View & New Graphing Library
The Mythic UI had a facelift with Mythic 3.1, an upgrade to React 18, and a new graphing library, react-flow. This library is a huge improvement on the raw SVG drawing that Mythic 3.0 used.
This library makes it easier to perform updates, provides speed improvements, and enables dynamic graph tweaks such as the above image showing two egress channels from callback 500. This comes with the ability to zoom in/out more easily, re-center the graph, and even save what you can see to PNG or SVG. The bottom-right side even has a mini-map of what you’re seeing that you can use to scroll your view if your map is quite large more quickly.
Along with this new library, I wanted a better way to view and interact with tasking. The image below shows this new “Split Tasking” view that’s available for any callback as part of the dropdown actions:
Instead of having individual tasks as accordions that expand down, potentially causing a weird double scrollbar issue, this SplitTasking view allows only a single task to open at a time, but with a bigger view. You can see which task we’re looking at on the side due to the blue border, and you can see the same task in the middle of the screen. Both of these sections can be expanded or shrunk to meet you needs; you can hide all of the tasks, the middle section, and the callbacks at the top to have a single view of a task that takes up the whole screen. This gives operators a lot more flexibility in how they work with their callbacks. The middle view of the task is meant to provide a better picture about what’s going on when you have a single task that spins up a lot of subtasks and subtask groups.
Starting with Mythic 3.1, there are now database migrations for the PostgreSQL database. This means that if you’re upgrading from Mythic 3.0 to Mythic 3.1 or Mythic 3.0 to Mythic 3.2, you’ll automatically use the migrations and won’t have to wipe your database anymore. This has been a long time coming but will be here as we go forward.
A common question for Mythic is if it supports things like beacon object files (BOFs). While support for this sort of thing doesn’t really make sense within Mythic’s server, it does make sense to support the core functionality of this for the various agents. The best course of action for an agent to support a BOF is to make a new command file so that you can explicitly define the parameter names and types. This helps operators with the help command and allows them to tab-complete the various parameters. However, this sort of flow might not always be possible ahead of time. So, Mythic now has support for TypedArrays:
The above screenshot shows an example of a TypedArray command parameter called Arguments. The developer of the command can define the choices that appear on the left as a dropdown list, and the operator can pick the appropriate type to add to their array element. This gets sent down to the payload container as an array of arrays — [ ["NSString", "some value"], ["char*", "my char* string"] ]. Not only does this declaration convention help with executing arbitrary BOFs, but it can be used to call arbitrary functions with DLLs/Dylibs as well. This provides a much more robust way to provide arguments to functions instead of just requiring a properly escaped string that then gets double and triple processed.
Another common request in Mythic is the ability to host an arbitrary file (typically a payload) through a C2 profile. Due to Mythic’s microservice architecture, it’s impossible for Mythic itself to know how to do this. However, each C2 profile is the most knowledgeable on how it works, so it makes sense to simply ask the C2 profile to host the file on your behalf.
In Mythic 3.2, whenever there’s a file that can be hosted there will be a blue globe icon. Clicking that button will open a small dialog for the operator to specify which C2 profile they want to ask to host the file and at what URL. That information, along with the UUID of the file, gets passed along to the C2 profile for it to determine the best way to specify the route and host it.
Dynamic File Browser Grouping
Mythic has a few different GitHub issues about people encountering environments where hostnames are repeated (either CTFs, CCDCs, or even containerized environments). Mythic used the hostname field to aggregate data for the file browser and process browser to display a unified view of data across all callbacks. However, if you have multiple (different) hosts with the same name, this causes an issue where multiple host’s data gets merged and lost.
Some solutions to this try to find a way to uniquely identify the host based on a large variety of factors that hopefully don’t change. That’s kind of error prone and also might lose context between things like a reboot or vm clones. It also doesn’t handle instances where you have data from a remote system since you’re not on that host to fingerprint it. From Mythic’s perspective, all it knows that’s unique is each callback — so, that’s what Mythic now uses to allow you, the operator, to make informed decisions about what should and should not be grouped together. Below is an example of the file browser data split out amongst a few different groups:
Clicking any of the group names on the left allows you to see which callbacks are feeding data into that view and clicking the top-right button from here allows you to see how all the callbacks are grouped.
This grouping can be modified at any time by clicking the dropdown next to a callback and selecting to “Modify Groupings”. These groupings also persist for process data as seen below:
Because this data is stored per-callback, you can freely modify these groups as much as you want. Each time you make a modification, simply close and re-open the file browser or process browser tab to adjust historic data. Mythic then streams data related to the new groups.
If you’re using Mythic’s scripting, you can get notified of new callbacks and automatically adjust the callback’s groups. This makes it easy to group like-hosts or ranges for CCDC events based on something you know is unique to that range (ex: IP subnets, domains, or even based on which payload was used to generate the callback).
Mythic v3.2 Highlights: Interactive Tasking, Push C2, and Dynamic File Browser was originally published in Posts By SpecterOps Team Members on Medium, where people are continuing the conversation by highlighting and responding to this story.