Tuoni 0.14.0 introduces support for ExecUnit, a new execution abstraction for plugin commands and listener-side code. The short version: an ExecUnit is the agent executable part of a Tuoni plugin, packaged in a format the agent can load and run at task time.
That sounds simple, but it changes a lot. Previously, plugin code was mostly treated as shellcode. Shellcode is still supported, but it is no longer the only shape that plugin code can take. With ExecUnit, the C2 and agent can negotiate the best available format for the command, payload, and execution context.
What is an ExecUnit?
An ExecUnit is a small package of executable code produced by a Tuoni plugin and delivered to an agent. It contains:
- the executable bytes,
- the declared ExecUnit format,
- an optional entrypoint,
- plugin-specific configuration,
- and the IPC information needed for the agent and ExecUnit to communicate.
In practice, this means a plugin command is split into two clear halves. The C2-side plugin handles user input, command configuration, result parsing, and API integration. The ExecUnit is the agent-side implementation that actually performs the operation on the endpoint and returns the result.
Tuoni 0.14.0 supports these ExecUnit formats:
| Format | What it means |
|---|---|
SHELLCODE_NATIVE |
Native shellcode executed by the agent. |
DOTNET_EXE |
A .NET executable loaded and invoked in memory. |
DOTNET_DLL |
A .NET DLL loaded in memory, with a method invoked by reflection. |
NATIVE_LIB |
A native library loaded with an in-memory mapping technique, then called through an export. |
The goal is not to force every command into one preferred format. The goal is to let Tuoni choose a compatible format automatically, while still giving advanced users control when they need it.
How ExecUnit execution works
When a user sends a plugin command, the flow looks like this:
- The user chooses a command in the GUI, terminal, REST API, or TSE script.
- The C2 passes the command configuration to the command plugin.
- The plugin prepares the agent-side ExecUnit and the configuration that belongs to it.
- The C2 sends the ExecUnit package to the selected agent.
- The agent checks the requested execution context and loads the ExecUnit using the selected format.
- The agent provides configuration to the ExecUnit, usually over a named pipe in Windows or tmp file in Linux.
- The ExecUnit runs the command logic and returns output to the agent.
- The agent sends the result back to the C2.
- The C2-side plugin parses the result and presents it through the normal Tuoni command result flow.
The important detail is capability matching. Not every agent supports every ExecUnit format, and the available formats can differ between self-process execution and remote-process execution. Agents report the formats they support and the order they prefer. The C2 intersects that with what the command supports and selects the first compatible option.
If a user explicitly asks for a format that the command or agent cannot support, the C2 rejects the command instead of silently falling back to something unexpected.
Execution contexts
ExecUnit support also fits into Tuoni's execution context model. Plugin commands can run in three broad ways:
- Self process: the ExecUnit runs inside the current agent process. This is the default when no execution configuration is provided.
- New process: the agent starts another process and runs the ExecUnit there.
- Existing process: the agent runs the ExecUnit inside an already running process, when the agent and selected ExecUnit format support that mode and the operator has sufficient permissions.
Native commands are different: they are built directly into the agent and run in the agent's own process. ExecUnit applies to plugin-based commands and listener-side plugin code.
This separation keeps the core agent smaller while allowing plugin functionality to grow. The agent does not need every possible command compiled into it. Instead, the C2 can deliver only the code needed for the task being run.
How users can use it
Most users do not need to think about ExecUnit during normal operation. Send the command as usual and Tuoni will select a compatible format automatically.
Advanced users get control at two levels.
First, the payload can advertise its own preferred ExecUnit order. Commercial payload configuration exposes
execUnitTypeOrder, an ordered list of ExecUnit formats the agent should prefer for self-process
command execution. For example, a payload can prefer managed-code formats first, native libraries next, and
shellcode last, or use a different order that better matches the lab, engagement, or compatibility
requirements.
Second, individual command execution can still request a specific ExecUnit format when the user needs predictable behavior for testing or troubleshooting. The request is not treated as a blind override. Tuoni still checks that the selected command supports the requested format and that the target agent can execute it in the chosen execution context. If the combination is not valid, the command is rejected instead of silently falling back to another format.
The supported ExecUnit format names are:
SHELLCODE_NATIVEDOTNET_EXEDOTNET_DLLNATIVE_LIB
When no specific format is requested for a command, Tuoni uses the command's supported formats, the agent's advertised capabilities, and the agent's preferred order to choose automatically. That is the recommended default for day-to-day use.
Why it matters for operations
ExecUnit gives Tuoni a cleaner boundary between "what the command does" and "how the command is delivered and executed." That has several practical benefits:
- More flexible plugins: plugin authors can ship the most suitable implementation format for a task.
- Better compatibility: commands can support multiple execution formats instead of depending on a single loader path.
- More predictable testing: operators can pin a format when validating behavior in a lab.
This also gives teams a better way to reason about stability. A command that is risky to run in the agent process can be moved to another process. A command that needs minimal process creation can run in the self-process context. A command that works best as managed code can be delivered as a .NET ExecUnit instead of being converted into another representation first.
What this means for EDR testing and bypass research
ExecUnit is useful for authorized red-team, purple-team, and detection engineering work because it gives operators more than one execution shape to test. EDR products do not observe "a command" in the abstract. They observe concrete behavior: process creation, module loading, memory allocation, thread creation, CLR loading, named pipe activity, parent-child process relationships, and other endpoint signals.
By supporting multiple ExecUnit formats and execution contexts, Tuoni makes it easier to test how those controls respond to different legitimate implementation paths. A team can compare how a command behaves as native shellcode, a .NET executable, a .NET DLL, or a native library. They can also evaluate whether running in the current agent process, a newly created process, or a permitted existing process changes the telemetry produced by the same high-level task.
This is where ExecUnit helps with EDR bypassing in the responsible, engagement-scoped sense: it reduces dependence on one predictable execution pattern. If a control is tuned only for one loader style or one command shape, ExecUnit makes that assumption visible during testing. That helps red teams adapt within the rules of engagement, and it helps blue teams close detection gaps by validating coverage across more execution paths.
It is not a magic "bypass EDR" switch. Modern EDRs correlate behavior across many signals, and changing the packaging format alone does not make activity invisible. The practical value is control, repeatability, and format diversity. Those qualities let teams test detections honestly, document what changed, and understand which signals are tied to the operation itself versus the execution method used to deliver it.
Summary
ExecUnit support in Tuoni 0.14.0 makes plugin execution more flexible, more explicit, and easier to reason about. Commands are no longer tied to a single shellcode-centric model. Instead, Tuoni can deliver plugin code as native shellcode, .NET EXE, .NET DLL, or native library, then execute it in the context that best matches the command, payload, and operator intent.
For everyday users, the default automatic selection is enough. For advanced users, payload-level format preference and per-command execution settings provide precise control. For red teams and defenders, ExecUnit adds a practical way to test endpoint detection coverage across multiple execution paths without changing the high-level command being exercised.
In short: ExecUnit gives Tuoni a more capable command execution model, and it gives users a clearer way to balance compatibility, stability, operational control, and detection testing.