The TCP handler

A guide to using the lower-level TLS-over-TCP handler

The TCP handler performs manual serialisation and de-serialisation of request and response objects. The key differences between it and the HTTP(S) handlers are:

  • TLS is enabled by default. To verify the server certificate, embed the certificate authority's PEM-encoded certificate into your agent's configuration for manual validation.

  • TCP sessions don't timeout like HTTP sessions, because they don't use JWTs.

  • Data is sent in a raw byte structure that needs to be parsed manually.

This is not a tutorial on serialisation. For a technical guide on how to develop your implant to interact with the TCP handler, you may want to read this blog post made by the developer themselves.

Important

  • Packets work using 'prepended size' - the size of the data sent over the connection must be prepended to the data itself.

  • All sizes and numeric values use big-endian notation (i.e. network byte order) and are of type uint32 - unsigned, 4-byte integer. This includes the opcode.

  • Response status and dest(ination) are each 1 byte long, and either 1 or 0.

  • All fields with non-fixed lengths must have their sizes prepended to the field data itself as part of the packet. Fixed-length fields are as follows: 1. Agent ID (length as bytes: 8, length as string: 16) 2. Request ID (length as string: 36) The diagrams below provide neat visualisations for object structures.

  • TEST THOROUGHLY! Use the install local feature for quick and convenient integration testing.

Empress, a POC agent for Monarch, includes several functions related to parsing and serialising valid request and response structures. It is recommended to draw from the examples contained in its source code.

Object structures

The next sections provide diagrams for each structure that an implant using the TCP handler will have to work with. Pay attention to the offsets in the diagrams. The invalid hex numbers (e.g. 0xG ) represent unknown offsets.

Registration

  • Usage: serialise

{
	"agent_id": "string",
	"os": "string",
	"arch": "string",
	"username": "string",
	"hostname": "string",
	"uid": "string",
	"gid": "string",
	"pid": "string",
	"home_dir": "string",
}

Here is our registration object, for reference. To register an implant, we would send a packet with the same structure as the one shown below. Notice that each field is dependent on its order above.

Operator Requests

  • Usage: parse / unserialise

The following diagram shows how requests from the C2 to the implant are structured.

Implant responses

  • Usage: serialise

The following diagram shows how a response to an operator request should be structured.

Despite the complexity, once a set of TCP-compliant routines have been implemented once, you won't need to implement them again!

Last updated