Agent Capabilities
The capabilities bitmap in agent metadata advertises execution contexts, native-command features, and executable-unit (ExecUnit) formats to Command and Control (C2). This reference defines the byte layout, commercial payload reporting, and C2 interpretation at the source revisions documented below.
Metadata fields
Capabilities and format preferences are separate fields in the agent metadata Type-Length-Value (TLV) structure:
| Field ID | Type | Meaning |
|---|---|---|
0x44 |
BLOB |
Capabilities bitmap: each bit advertises support for a specific feature. |
0x45 |
BLOB |
Ordered ExecUnit type IDs for execution in the agent's own process; earlier entries are preferred. |
0x46 |
BLOB |
Ordered ExecUnit type IDs for execution in a new or existing process; earlier entries are preferred. |
These fields are optional in the general protocol for compatibility with other agent implementations. The commercial agent includes 0x44 in its full metadata and emits each preference field when its list is nonempty. Its metadata-field policy keeps capabilities and preferences enabled; Metadata Controls cannot disable them.
The bitmap is separate from the agent-defined feature strings in field 0x42 and from the metadataFields settings that control which optional metadata the agent collects.
Reporting lifecycle
The commercial agent calculates the bitmap and preference lists during metadata initialization at startup and reuses them in later reports. These values come from the build and embedded settings; refreshing metadata does not probe installed runtimes, plugin availability, or command functionality.
Full metadata includes the capability bitmap and any nonempty preference lists. Between full reports, Metadata::getBytes() can return no full metadata body for unchanged metadata; the listener then sends a GUID-only metadata update. A counter also forces full reports at 16-call intervals.
Metadata updates are incremental: a GUID-only update does not withdraw previously reported capabilities or preferences. Retain an existing field value when an update omits that field; if no value has ever been reported, it remains unknown. See the listener metadata interface and server listener integration.
Bitmap encoding
Field 0x44 contains raw bytes, with no additional count or terminator inside the value. The TLV length gives the number of bytes. The current commercial implementation produces 12 bytes, indexed from 0 through 11.
Each byte is an independent bitmask. Bit 0 is the least significant bit (0x01), and bit 7 is the most significant bit (0x80). Combine flags within a byte with bitwise OR. To read a known flag, first check that its byte exists, then test (byte & mask) != 0. Do not interpret the whole blob as a multi-byte integer.
| Byte index | Meaning |
|---|---|
0 |
Supported execution contexts |
1-4 |
Native-command support |
5-7 |
Reserved; currently zero |
8 |
Supported ExecUnit formats in the agent's own process |
9 |
Reserved; currently zero |
10 |
Supported ExecUnit formats in new or existing processes |
11 |
Reserved; currently zero |
Treat undefined bits and additional bytes as unknown extensions. Keep reserved positions when interpreting the bitmap, and check the received length instead of assuming every agent sends the current 12-byte layout.
Execution contexts
Byte 0 reports which execution contexts the agent supports:
| Capability mask | Name | Execution-context ID | Meaning |
|---|---|---|---|
0x01 |
SELF |
0 |
The agent's own process |
0x02 |
NEW |
2 |
A new process |
0x04 |
EXISTING |
1 |
An existing process |
The context IDs are the ExecContextType values used in execution configuration. They are separate from the capability masks: deriving a mask as 1 << context ID would swap NEW and EXISTING. Use the explicit mapping above.
These flags describe contexts; bytes 8 and 10 separately describe the formats supported in those contexts. For example, byte 0 equal to 0x07 advertises all three contexts without implying that every format is supported in each context.
Native commands
Bytes 1-4 use the following flags. Names identify capabilities, not numeric command IDs; see the native-command protocol for command messages.
| Mask | Byte 1 |
Byte 2 |
Byte 3 |
Byte 4 |
|---|---|---|---|---|
0x01 |
BOF |
OVERRIDE_LIST |
RUN_AS |
METADATA_FIELDS_ENABLE |
0x02 |
CD |
OVERRIDE_LOAD |
SH |
METADATA_FIELDS_DISABLE |
0x04 |
CHMOD |
OVERRIDE_SET |
TOKEN_DEL |
METADATA_FIELDS_REPORT |
0x08 |
CMD |
OVERRIDE_UNLOAD |
TOKEN_DEL_ALL |
Reserved |
0x10 |
CONNECTION_CONF |
OVERRIDE_UNSET |
TOKEN_LIST |
Reserved |
0x20 |
DIE |
POWERSHELL |
TOKEN_MAKE |
Reserved |
0x40 |
JOBS |
PS |
TOKEN_STEAL |
Reserved |
0x80 |
LS |
RUN |
TOKEN_USE |
Reserved |
Byte 4 advertises the three metadata-control commands. It does not describe which individual metadata fields are enabled; those are reported by metadata-fields-report.
The override command flags in byte 2 do not describe individual hook functions or DLL callback signatures; see DLL Override Functions.
Several capability names differ from their corresponding protocol command names:
| Capability name | Protocol command |
|---|---|
CONNECTION_CONF |
SET_LISTENER_CONF |
PS |
PROCLIST |
JOBS |
COMMAND_LIST |
OVERRIDE_LOAD |
OVERRIDE_ADD |
OVERRIDE_UNLOAD |
OVERRIDE_REMOVE |
TOKEN_DEL |
TOKEN_DELETE |
TOKEN_DEL_ALL |
TOKEN_DELETE_ALL |
The CMD, POWERSHELL, SH, and RUN_AS flags describe command features; they have no standalone wire-command opcodes in the commercial agent's native-command factory. A capability name therefore does not identify a distinct protocol message. The source constant for RUN_AS is named CAPABILITY_NATIVE_BYTE_3_RUNAS.
The bitmap is not a complete inventory of native commands. SHUTDOWN, TOKEN_FROM_HANDLE, PRIVILEGE_LIST, PRIVILEGE_ENABLE, and PRIVILEGE_DISABLE have protocol command codes but no dedicated bits in this layout. Their availability cannot be determined by testing a corresponding flag. The C2's command-specific eligibility rules must handle these commands separately; see Receiver interpretation.
ExecUnit formats and preferences
Bytes 8 and 10 use the same format masks. Preference fields 0x45 and 0x46 instead contain a sequence of type IDs, one per byte:
Format mask in 0x44 |
Type ID in 0x45 / 0x46 |
ExecUnit type |
|---|---|---|
0x01 |
0x00 |
SHELLCODE_NATIVE |
0x02 |
0x01 |
DOTNET_EXE |
0x04 |
0x02 |
DOTNET_DLL |
0x08 |
0x03 |
NATIVE_LIB |
For example, byte 8 equal to 0x0F advertises all four formats for self-process execution. A preference value of 01 02 03 00 orders those formats as .NET executable, .NET library, native library, then shellcode. The final 00 is a valid type ID, not a terminator.
Preferences do not add support. The C2 also needs a compatible artifact from the command plugin; see Agent capability matching and Formats and Compatibility.
NATIVE_LIB identifies the platform's native library format: a Windows dynamic-link library (DLL), a Linux/FreeBSD Executable and Linkable Format (ELF) shared object, or a macOS Mach-O dynamic library. The implementation's capability constants retain the name NATIVE_DLL for this bit on all platforms.
Receiver interpretation
The following decoding and selection rules were verified against tuoni-server commit 4bdaacbb033569a3564d499026806d2e77085d4a, whose version.yml declares 0.17.1. They describe that implementation of the C2 and its software development kit (SDK); other revisions may differ. Apply the incremental update rules before interpreting an omitted field.
Decoding and metadata updates
| Received data | Verified C2 interpretation |
|---|---|
No new metadata, or 0x44 omitted |
No new bitmap is supplied. Retain any previously reported value; if none exists, support remains unreported. |
0x44 present with a zero-length value |
Every mapped native capability becomes UNSUPPORTED; both format sets become empty. This replaces previously reported support. |
| Nonempty bitmap that does not contain a native capability's byte | That native capability is UNREPORTED. An earlier reported value is retained during metadata merging. |
| Native capability's byte exists and its bit is clear / set | That capability becomes UNSUPPORTED / SUPPORTED, replacing any earlier value. |
0x44 is present, but format byte 8 or 10 is missing |
The corresponding format set becomes empty. It replaces the earlier set rather than retaining it. |
Format byte 8 or 10 is present |
Its known set bits define the corresponding format set, replacing the earlier set. Unknown bits are ignored. |
0x45 or 0x46 omitted |
No new preference list is supplied for that context. Retain any previous list; if none exists, no preference has been reported. Omission does not clear support bits. |
| A preference field is explicitly empty | The TLV decoder treats it as omitted. It does not clear an earlier preference list. |
| A preference list contains only some supported formats | Those formats have an explicit preference order. The remaining support bits are unchanged. |
The verified C2 decoder reads native-command bytes 1-4 and format bytes 8 and 10. It ignores execution-context byte 0, reserved bytes, and unknown bits. The context flags remain part of the payload's advertised layout, but this decoder does not use them to determine context support.
Do not pad a short bitmap with zeroes before decoding native capabilities: that changes missing statuses from UNREPORTED to UNSUPPORTED. Format sets follow different rules, as shown above. Native statuses merge individually, while both format sets come from the latest supplied bitmap.
Nonempty preference fields are decoded in order, preserving duplicates. Unknown type IDs cause preference decoding to fail; they are not silently ignored. An explicit empty preference field is treated as absent, so it cannot be used to clear a cached preference list through this TLV interface.
Native-command eligibility
Built-in native templates using BaseNativeCommandTemplate first check their unconditional requirements, such as applicable listener requirements. The mapped capability then determines eligibility; legacy platform and agent-codename checks apply in the UNREPORTED path:
| Effective native status | Eligibility |
|---|---|
SUPPORTED |
Passes the capability check. |
UNSUPPORTED |
Fails the capability check. |
UNREPORTED |
Uses the template's legacy checks, and only for an agent of SDK type SHELLCODE_AGENT. |
An absent capabilities object also follows the unreported path. Templates based on BaseNativeCommandTemplate without an assigned capability bit follow that same path, including the SDK agent-type restriction and their command-specific legacy checks. A capability check does not guarantee that a custom payload build includes working functionality.
ExecUnit selection and fallback
For an ExecUnitCommand, the selector uses the self-process format set and preference list for self or unspecified context. New and existing contexts share the other-process set and list. The table describes effective SDK metadata after decoding and merging. The rules below assume consistent reports: every preferred format should also be present in the corresponding supported set.
| Effective metadata | Selection behavior |
|---|---|
| Capabilities absent, both format sets empty/absent, or the selected set absent | Treats ExecUnit support as unavailable; legacy fallback may apply. |
| Selected format set empty while the other set is nonempty | Keeps an empty supported set for this context. This differs from unavailable ExecUnit support. |
| Selected set nonempty and its preference list absent/empty | Uses all supported formats in the default SDK order below. |
| Nonempty preference list | Uses listed formats as automatic candidates in preference order. Supported formats omitted from the list are not appended as automatic candidates. |
The default SDK order is SHELLCODE_NATIVE, NATIVE_LIB, DOTNET_DLL, then DOTNET_EXE, restricted to the selected context's supported formats. This is the Java SDK enum order, not the order of the wire type IDs. If an incoming preference field was empty but an earlier list was retained, that retained list still controls selection.
An explicitly requested execUnitType must appear in both the command's supported formats and the agent's selected-context support set. It need not appear in the preference list. Failure is an error; an explicit request does not use legacy fallback.
Without an explicit request, the selector chooses the first preferred type supplied by the command. If no type is selected, it permits legacy shellcode serialization only when the command also implements ShellcodeCommand and either ExecUnit support is unavailable or the effective preference list contains SHELLCODE_NATIVE. Otherwise, selection fails with No compatible execUnitType found. Legacy serialization is a separate path from selecting a typed SHELLCODE_NATIVE ExecUnit.
In particular, an empty bitmap makes both format sets empty and can still allow that legacy fallback, even though all mapped native capabilities are UNSUPPORTED. Native-command eligibility and plugin-command format selection are separate decisions.
Info
The automatic selector in the verified revision assumes capability and preference reports agree; it does not normalize a preference list against the supported set. Contradictory reports can therefore produce an unsupported selection. Explicit execUnitType validation checks the supported set separately. Keep preferred entries within the advertised format set; this is an implementation limitation of the documented revision.
Current commercial payload values
The current initialization code advertises the following bitmap values. Hexadecimal pairs below are the 12 value bytes in order, without a TLV header.
| Build | 0x44 value |
|---|---|
| Windows, native DLL loader enabled | 07 FB FF FD 07 00 00 00 0F 00 01 00 |
| Windows, native DLL loader disabled | 07 FB FF FD 07 00 00 00 07 00 01 00 |
| Linux, FreeBSD, macOS | 01 F6 C0 02 07 00 00 00 08 00 00 00 |
Windows reports all three contexts, with shellcode as the only format advertised for other processes. Linux, FreeBSD, and macOS report self-process execution with NATIVE_LIB. All four platforms advertise the three metadata-control commands in byte 4.
Default preferences are:
| Build | Self-process field 0x45 |
Other-process field 0x46 |
|---|---|---|
| Windows, native DLL loader enabled | 01 02 03 00 |
00 |
| Windows, native DLL loader disabled | 01 02 00 |
00 |
| Linux, FreeBSD, macOS | 03 |
Omitted |
Custom preference lists
On Windows, the payload's execUnitTypeOrder setting can replace the default self-process preference order. This changes field 0x45, not the bitmap or the other-process preference list.
The payload stores the order in the four-byte embedded execUnitTypesOrder array. The native emitter handles that array as follows:
| Embedded configuration | Emitted self-process preferences |
|---|---|
First byte is 0xFF |
Keep the default list. |
First byte is not 0xFF |
Replace the default list with the configured entries, stopping at the first 0xFF or after four entries. |
| Supported format omitted from a custom list | Do not append it automatically; its support bit is unchanged. |
NATIVE_LIB entry with _DISABLE_DLL_LOADER |
Skip the entry. That build also clears NATIVE_LIB support in byte 8. |
The 0xFF sentinel belongs to the embedded configuration, not the emitted preference blob. If filtering leaves no entries, the agent omits 0x45 even though other format support bits can remain set. An absent preference list therefore does not mean that the context supports no formats; see Receiver interpretation.
Apart from the sentinel and disabled-native-library filtering, the native emitter copies the configured bytes without deduplicating or validating type IDs. These are the rules for the embedded array, not a claim that the payload-generation API accepts duplicate or invalid entries; input validation by the generator is a separate contract.
Info
These values describe what the current implementation advertises. The native-command bitmap does not account for the _DISABLE_BOF, _DISABLE_TOKENS, or _DISABLE_OVERRIDES build switches. A custom build using those switches can therefore advertise commands whose functionality is disabled. A capability bit also does not establish that a compatible plugin artifact or runtime dependency is available.
_DISABLE_DLL_LOADER removes NATIVE_LIB support and preference entries, but leaves the OVERRIDE_LOAD capability set even though override loading cannot succeed. The "native DLL loader disabled" examples show the advertised values, not every functional effect of that build switch.
Implementation references
Payload behavior and build-specific examples were checked against payloads_commercial commit 0023aa38439ac06f910c18daac4b4abf99899f15. These examples describe that revision; they are not a guarantee for all releases or custom builds. The source paths below are relative to AgentPower/AgentPower/:
| Source | Responsibility |
|---|---|
Definitions.h |
Metadata field IDs and CAPABILITY_* byte masks |
data_objects/Metadata.cpp |
Metadata::setCapabilitiesAndExecUnitTypes() builds the bitmap and preference lists at startup; Metadata::getBytes() controls full metadata emission. |
Enums.h |
ExecContextType IDs and ExecUnitType ordinal values |
Structs.h |
Four-byte GlobalConfInitial::execUnitTypesOrder array on Windows |
commands/INativeCommand.cpp |
Native-command codes and handler registrations |
listeners/Listener.cpp |
Listener::received_request_metadata() sends GUID-only metadata when no full report is supplied. |
containers/TLV.h |
Byte-vector constructors store the raw blob value. |
specials/DllLoader.cpp, commands/natives/overrides/NativeCommandOverridesUpload.cpp |
Disabled DLL-loader behavior and its effect on override loading |
The receiver rules were checked separately against tuoni-server commit 4bdaacbb033569a3564d499026806d2e77085d4a (version.yml: 0.17.1). The following classes are under each module's src/main/java/com/shelldot/tuoni/ package tree:
| Module directory | Class or enum | Responsibility |
|---|---|---|
server/crypto/impl |
server.crypto.impl.tlv.AgentMetadataTlv |
Bitmap and preference-field decoding |
server/domain |
server.domain.tlv.TlvConstants |
Mapping wire type IDs to SDK ExecUnit types |
server/agent/api |
server.agent.CustomizableAgentMetadata |
Incremental native-status, format-set, and preference updates |
server/native-command |
server.native_command.templates.BaseNativeCommandTemplate |
Native capability checks and legacy eligibility |
server/command/impl |
server.command.impl.CommandExecUnitService |
Format selection, explicit-type validation, and legacy fallback |
plugin/sdk |
plugin.sdk.command.ExecUnitType |
Default SDK format ordering |
The listener integration guide describes incremental metadata updates, and the SDK changelog identifies the capability and preference accessors. Recheck the listed consumer sources before applying these exact fallback rules to a different server revision.