https://www.cobaltstrike.com/help-malleable-c2

Overview

Beacon's HTTP indicators are controlled by a Malleable C2 profile. A Malleable C2 profile is a simple program that specifies how to transform data and store it in a transaction. The same profile that transforms and stores data, interpreted backwards, also extracts and recovers data from a transaction.

To use a custom profile, you must start a Cobalt Strike team server and specify your profile file at that time.

./teamserver [external IP] [password] [/path/to/my.profile]

You may only load one profile per Cobalt Strike instance. If you need multiple profiles during an engagement, start multiple team servers [each with its own profile] and connect to them from one Cobalt Strike client.

Checking for Errors

Cobalt Strike's Linux package includes a c2lint program. This program will check the syntax of a communication profile, apply a few extra checks, and even unit test your profile with random data. It's highly recommended that you check your profiles with this tool before you load them into Cobalt Strike.

./c2lint [/path/to/my.profile]

Profile Language

The best way to create a profile is to modify an existing one. Take a look at the examples on Github.

When you open a profile, here is what you will see:

# this is a comment
set global_option "value";

protocol-transaction {
	set local_option "value";

	client {
		# customize client indicators
	}

	server {
		# customize server indicators
	}
}

Comments begin with a # and go until the end of the line. The set statement is a way to assign a value to an option. Profiles use { curly braces } to group statements and information together. Statements always end with a semi-colon.

To help all of this make sense, here's a partial profile:

http-get {
        set uri "/foobar";
        client {
                metadata {
                        base64;
                        prepend "user=";
                        header "Cookie";
                }
        }

This partial profile defines indicators for an HTTP GET transaction. The first statement, set uri, assigns the URI that the client and server will reference during this transaction. This set statement occurs outside of the client and server code blocks because it applies to both of them.

The client block defines indicators for the client that performs an HTTP GET. The client, in this case, is Cobalt Strike's Beacon.

When Cobalt Strike's Beacon "phones home" it sends metadata about itself to Cobalt Strike. In this profile, we have to define how this metadata is encoded and sent with our HTTP GET request.