C2 and agent communication protocol
This document describes TLV structures exchanged between C2 and Tuoni agent. There are currently two ways to get
them to the agent:
- patch them into the payload file (exe, dll, shellcode) so they are handled right after execution
- send them over listener connection.
Top Level TLV Parent (TLV[1]) map
| ID | TYPE | DESCRIPTION |
|---|---|---|
| 0x01 | PARENT | Executable code (legacy shellcode or ExecUnit) |
| 0x03 | PARENT | Built-in command |
| 0x04 | PARENT | Command result |
| 0x05 | PARENT | Agent command control |
| 0x0C | PARENT | Agent configuration |
| 0x11 (currently 0x1) | PARENT | Agent metadata |
| 0x12 | PARENT | Encrypted metadata |
| 0x13 | PARENT | Encrypted data |
Table Of Contents
- 0x01 Shellcode TLV structure
- 0x03 built-in command TLV structure
- 0x04 Command result TLV structure
- 0x05 Agent Command control TLV structure
- 0x0C Agent configuration TLV structure
- 0x11(0x1) Agent metadata TLV structure
- 0x12 Encrypted metadata TLV structure
- 0x13 Encrypted data TLV structure
Structures
Shellcode TLV structure
The 0x01 top-level structure is historically named Shellcode in the protocol and code, but it now carries either legacy native shellcode or an ExecUnit. Existing anchors keep the old name for compatibility.
- ID:
0x01
TYPE:PARENT
VALUE: structure contains executable code and metadata- ID:
0x01
TYPE:BYTE
required: YES
VALUE: Executable-code wrapper type [0x01forlistener|0x02forcommand] - ID:
0x02
TYPE:PARENT
required: no (default is same process context and pipe based communication)
VALUE: execution policy [same process|new process|existing process]- ID:
0x01
TYPE:BYTE
required: no
VALUE: In what context the code is executed - 0 (self), 1 (existing), 2(new) - ID:
0x02
TYPE:BYTE
required: no
VALUE: Communication channel - 0 (none), 1 (pipe) - ID:
0x03
TYPE:STR_UTF8
required: no
VALUE: In case of "new process" context, what executable to use - ID:
0x03
TYPE:INT32
required: no
VALUE: In case of "existing process" context, what process to target - ID:
0x04
TYPE:BYTE
required: no
VALUE: In case of "new process" context, should process be suspended - ID:
0x05
TYPE:BYTE
required: no
VALUE: In case of "new process" context, should executable window be hidden - ID:
0x06
TYPE:STR_UTF8
required: no
VALUE: In case of "new process" context, what username to use for runas type of execution - ID:
0x07
TYPE:STR_UTF8
required: no
VALUE: In case of "new process" context, what password to use for runas type of execution - ID:
0x08
TYPE:INT32
required: no
VALUE: In case of "new process" context, value of the PPID
- ID:
- ID:
0x03
TYPE:BLOB
required: YES
VALUE: Executable code bytes. If0x07is absent, the bytes are treated as legacySHELLCODE_NATIVE. - ID:
0x04
TYPE:UNDEFINED
required: no
VALUE: IPC configuration. For named-pipe IPC this is the pipe name. - ID:
0x05
TYPE:BLOB
required: no
VALUE: Configuration sent to the executable code - ID:
0x06
TYPE:UNDEFINED
required: no
VALUE: Wrapper typeTLV[1.1]specific configuration. For command wrappers this is the command ID. - ID:
0x07
TYPE:PARENT
required: no (required for ExecUnit; absent for legacy shellcode)
VALUE: ExecUnit configuration- ID:
0x01
TYPE:BYTE
required: YES
VALUE: ExecUnit format: 0=SHELLCODE_NATIVE, 1=DOTNET_EXE, 2=DOTNET_DLL, 3=NATIVE_LIB - ID:
0x02
TYPE:STR_UTF8
required: no
VALUE: Entrypoint, method, or exported function name - ID:
0x03
TYPE:STR_UTF8
required: no
VALUE: Command/listener-specific type identifier - ID:
0x04
TYPE:INT32
required: no
VALUE: Command/listener-specific version
- ID:
- ID:
Shellcode TLV structure listener
TLV[1.1] ==
0x01
- ID:
0x01
TYPE:PARENT
VALUE: structure contains listener executable code and metadata- ID:
0x01
TYPE:BYTE
required: YES
VALUE:0x01 - ID:
0x02
TYPE:PARENT
required: no (default is same process context and pipe based communication)
VALUE: execution policy [same process|new process|existing process]- ID:
0x01
TYPE:BYTE
required: no
VALUE: In what context the code is executed - 0 (self), 1 (existing), 2(new) - ID:
0x02
TYPE:BYTE
required: no
VALUE: Communication channel - 0 (none), 1 (pipe) - ID:
0x03
TYPE:STR_UTF8
required: no
VALUE: In case of "new process" context, what executable to use - ID:
0x03
TYPE:INT32
required: no
VALUE: In case of "existing process" context, what process to target - ID:
0x04
TYPE:BYTE
required: no
VALUE: In case of "new process" context, should process be suspended - ID:
0x05
TYPE:BYTE
required: no
VALUE: In case of "new process" context, should executable window be hidden - ID:
0x06
TYPE:STR_UTF8
required: no
VALUE: In case of "new process" context, what username to use for runas type of execution - ID:
0x07
TYPE:STR_UTF8
required: no
VALUE: In case of "new process" context, what password to use for runas type of execution - ID:
0x08
TYPE:INT32
required: no
VALUE: In case of "new process" context, value of the PPID
- ID:
- ID:
0x03
TYPE:BLOB
required: YES
VALUE: Listener executable code bytes. If0x07is absent, the bytes are treated as legacySHELLCODE_NATIVE. - ID:
0x04
TYPE:UNDEFINED
required: YES
VALUE: IPC configuration. For named-pipe IPC this is the pipe name. - ID:
0x05
TYPE:BLOB
required: YES
VALUE: Configuration sent to the listener code. Should contain instructions for communicating with the listener. - ID:
0x07
TYPE:PARENT
required: no (required for ExecUnit listeners; absent for legacy shellcode listeners)
VALUE: ExecUnit configuration- ID:
0x01
TYPE:BYTE
required: YES
VALUE: ExecUnit format: 0=SHELLCODE_NATIVE, 1=DOTNET_EXE, 2=DOTNET_DLL, 3=NATIVE_LIB - ID:
0x02
TYPE:STR_UTF8
required: no
VALUE: Entrypoint, method, or exported function name - ID:
0x03
TYPE:STR_UTF8
required: no
VALUE: Listener-specific type identifier - ID:
0x04
TYPE:INT32
required: no
VALUE: Listener-specific version
- ID:
- ID:
Shellcode TLV structure command
TLV[1.1] ==
0x2
- ID:
0x01
TYPE:PARENT
VALUE: structure contains command executable code and metadata- ID:
0x01
TYPE:BYTE
required: YES
VALUE:0x02 - ID:
0x02
TYPE:PARENT
required: no (default is same process context and pipe based communication)
VALUE: execution policy [same process|new process|existing process]- ID:
0x01
TYPE:BYTE
required: no
VALUE: In what context the code is executed - 0 (self), 1 (existing), 2(new) - ID:
0x02
TYPE:BYTE
required: no
VALUE: Communication channel - 0 (none), 1 (pipe) - ID:
0x03
TYPE:STR_UTF8
required: no
VALUE: In case of "new process" context, what executable to use - ID:
0x03
TYPE:INT32
required: no
VALUE: In case of "existing process" context, what process to target - ID:
0x04
TYPE:BYTE
required: no
VALUE: In case of "new process" context, should process be suspended - ID:
0x05
TYPE:BYTE
required: no
VALUE: In case of "new process" context, should executable window be hidden - ID:
0x06
TYPE:STR_UTF8
required: no
VALUE: In case of "new process" context, what username to use for runas type of execution - ID:
0x07
TYPE:STR_UTF8
required: no
VALUE: In case of "new process" context, what password to use for runas type of execution - ID:
0x08
TYPE:INT32
required: no
VALUE: In case of "new process" context, value of the PPID
- ID:
- ID:
0x03
TYPE:BLOB
required: YES
VALUE: Command executable code bytes. If0x07is absent, the bytes are treated as legacySHELLCODE_NATIVE. - ID:
0x04
TYPE:UNDEFINED
required: no
VALUE: IPC configuration. For named-pipe IPC this is the pipe name. - ID:
0x05
TYPE:BLOB
required: YES
VALUE: Configuration sent to the command code - ID:
0x06
TYPE:INT32
required: YES
VALUE: Command ID - ID:
0x07
TYPE:PARENT
required: no (required for ExecUnit commands; absent for legacy shellcode commands)
VALUE: ExecUnit configuration- ID:
0x01
TYPE:BYTE
required: YES
VALUE: ExecUnit format: 0=SHELLCODE_NATIVE, 1=DOTNET_EXE, 2=DOTNET_DLL, 3=NATIVE_LIB - ID:
0x02
TYPE:STR_UTF8
required: no
VALUE: Entrypoint, method, or exported function name - ID:
0x03
TYPE:STR_UTF8
required: no
VALUE: Command-specific type identifier - ID:
0x04
TYPE:INT32
required: no
VALUE: Command-specific version
- ID:
- ID:
Built-in command TLV structure
- ID:
0x03
TYPE:PARENT
VALUE: structure contains built-in command and metadata- ID:
0x01
TYPE:INT32
required: YES
VALUE: Command ID, required for result correlation - ID:
0x02
TYPE:INT32
required: YES
VALUE: Command control code - determining what type of functionality it triggers - for example0x01is "DIE" command for the Agent - ID:
0x03
TYPE:UNDEFINED
required: no
VALUE: Configuration for command
- ID:
Command result TLV structure
- ID:
0x04
TYPE:PARENT
VALUE: structure contains result data- ID:
0x01
TYPE:INT32
required: YES
VALUE: ID of the task - ID:
0x02
TYPE:BLOB
required: YES
VALUE: Result data - ID:
0x03
TYPE:BYTE
required: no
VALUE: Status of the result :[ 0x00 = failed | 0x01 = ongoing | 0x02 = success] - ID:
0x04
TYPE:BLOB
required: no
VALUE: Error data
- ID:
Agent command control TLV structure
- ID:
0x05
TYPE:PARENT
VALUE: structure contains settings to control running command in agent- ID:
0x01
TYPE:INT32
required: YES
VALUE: ID of the command to be controlled in the agent - ID:
0x02
TYPE:BYTE
required: YES
VALUE: Type of the command (task) manipulation -0x01means that there is new data (next value) provided for the command,0xDDmeans that this task should be canceled/stopped - ID:
0x03
TYPE:UNDEFINED
required: no
VALUE: Configuration for manipulation, depends on the previous type (if TLV[1.2]==0x01, then this will contain data relayed to the running command code)
- ID:
Agent configuration TLV structure
- ID:
0x0C
TYPE:PARENT
VALUE: structure contains settings for agent (none of the values inside are mandatory, they just replace existing ones if they are there)- ID:
0x01
TYPE:BLOB
required: no
VALUE: Public key to use, [NOT IMPLEMENTED BY C2 YET] - ID:
0x02
TYPE:BLOB
required: no
VALUE: GUID of the public key used, [NOT IMPLEMENTED BY AGENT OR C2 YET]
- ID:
Relayed Data Structures
Agent metadata TLV structure
NB: The outer TLV type is currently 0x01 for backward compatibility with existing deployments. It is slated to change to 0x11 in a future revision of the specification. Until that revision is adopted, implementations must use 0x01 for the outer TLV type.
-
ID:
0x1(in future will be0x11)
TYPE:PARENT
VALUE: structure contains metadata about the agent- ID:
0x01
TYPE:GUID
required: YES
VALUE: GUID of the agent - ID:
0x02
TYPE:STR_UTF8
required: no
VALUE: Username of the agent process - ID:
0x03
TYPE:STR_UTF8
required: no
VALUE: Process name of the agent process - ID:
0x04
TYPE:INT32
required: no
VALUE: PID of the agent process - ID:
0x05
TYPE:STR_UTF8
required: no
VALUE: Working directory of the agent - ID:
0x06
TYPE:BYTE
required: no
VALUE: OS type (1=WINDOWS, 2=LINUX, 3=BSD, 4=MAC) - ID:
0x07
TYPE:BYTE
required: no
VALUE: Major version of the OS - ID:
0x08
TYPE:BYTE
required: no
VALUE: Minor version of the OS - ID:
0x09
TYPE:STR_ASCII
required: no
VALUE: IPv4 addresses of the agent machine - ID:
0x0A
TYPE:STR_ASCII
required: no
VALUE: Hostname of the agent machine - ID:
0x0B
TYPE:BYTE
required: no
VALUE: Architecture of the process (0=x86, 1=x64) - ID:
0x0C
TYPE:BYTE
required: no
VALUE: Architecture of the OS (0=x86, 1=x64) - ID:
0x0D
TYPE:INT32
required: no
VALUE: Agent OS ANSI code page - ID:
0x0E
TYPE:STR_UTF8
required: no
VALUE: Process integrity level (e.g. System, High, Medium, Low) - ID:
0x10
TYPE:BLOB
required: YES
VALUE: 16-byte AES key for encryption - ID:
0x11
TYPE:BYTE
required: no
VALUE: Encryption algorithm (0=none, 1=aes128-cbc [default], 2=aes128-gcm) - ID:
0x40
TYPE:STR_UTF8
required: no
VALUE: Codename / type identifier of the agent - ID:
0x41
TYPE:INT32
required: no
VALUE: Build version of the agent - ID:
0x42
TYPE:LIST<STR_UTF8>
required: no
VALUE: List of agent feature strings (agent-defined capability flags) - ID:
0x43
TYPE:INT32orLONG
required: no
VALUE: ID of the payload used to generate this agent. Sent as INT32 for legacy agents; newer agents may send LONG. The server accepts both. - ID:
0x44
TYPE:BLOB
required: no
VALUE: Capabilities bitmap. Byte at index 8 advertises supported ExecUnit formats for self-process execution; byte at index 10 advertises supported formats for new/existing-process execution. Bit flags in both bytes are: 0x01=SHELLCODE_NATIVE, 0x02=DOTNET_EXE, 0x04=DOTNET_DLL, 0x08=NATIVE_LIB. - ID:
0x45
TYPE:BLOB
required: no
VALUE: Preferred ExecUnit format order for self-process execution. This does not add support by itself; it orders the supported formats from0x44. Each byte is an ExecUnitType: 0x00=SHELLCODE_NATIVE, 0x01=DOTNET_EXE, 0x02=DOTNET_DLL, 0x03=NATIVE_LIB. Earlier entries are preferred. - ID:
0x46
TYPE:BLOB
required: no
VALUE: Preferred ExecUnit format order for new/existing-process execution. Same encoding and support/preference separation as 0x45.
Note:
0x44uses bitmask encoding for supported formats;0x45and0x46use ordered ordinal ExecUnitType byte values. - ID:
Encrypted metadata TLV structure
- ID:
0x12
TYPE:PARENT
VALUE: structure contains encrypted metadata- ID:
0x01
TYPE:BYTE
required: YES
VALUE: Is metadata encrypted[ no = 0x00 | yes = 0x01 ] - ID:
0x02
TYPE:GUID
required: no
VALUE: Encryption key GUID - ID:
0x03
TYPE:PARENT
required: no
VALUE: Encryption configuration (not used yet) - ID:
0x10
TYPE:BLOB
required: no VALUE: Encrypted metadata TLV
- ID:
Encrypted data TLV structure
(in both direction between C2 and Agent core)
- ID:
0x13
TYPE:PARENT
VALUE: structure contains encrypted data- ID:
0x01
TYPE:BYTE
required: YES
VALUE: Is data encrypted[ no = 0x00 | yes = 0x01 ] - ID:
0x03
TYPE:PARENT
required: no
VALUE: Encryption configuration- ID:
0x01
TYPE:BYTE
required: no
VALUE: Encryption algorithm (1=aes128-cbc [default as of now], 2=aes128-gcm)
- ID:
- ID:
0x04
TYPE:BLOB
required: no
VALUE: IV value, if not present then null IV is used - ID:
0x10
TYPE:BLOB
required: no
VALUE: Encrypted data
- ID: