> For the complete documentation index, see [llms.txt](https://bc-security.gitbook.io/empire-wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bc-security.gitbook.io/empire-wiki/listeners/malleable-c2.md).

# Malleable C2

The Malleable C2 Listener gives control to operators to customize their beacons to match specific threats. It does this through profiles, which are simple scripts that instruct the listener how to store, interpret, and extract data.

Malleable C2 is not a new concept, having been employed by Cobalt Strike for several years and is one of the most valuable features for the platform. Profiles allow users to change various settings within a beacon to truly customize its footprint. This post is not going to be a deep dive into Malleable Profiles, since Empire leverages the same profiles used in Cobalt Strike. If you are interested in learning more, we highly encourage checking out [Joe Vest’s post](https://posts.specterops.io/a-deep-dive-into-cobalt-strike-malleable-c2-6660e33b0e0b) or [Cobalt Strike’s Malleable C2 documentation](https://www.cobaltstrike.com/help-malleable-c2).

This project originated from [Johneiser’s Malleable C2 Parser](https://github.com/johneiser/MalleableC2Parser), which is a Python 2.7 implementation that parses the profile for the listener. Unfortunately, the project was no longer maintained and required a [refactor](https://github.com/BC-SECURITY/MalleableC2Parser) to work with Empire.

The parser takes the profile and executes the set of transforms that were scripted. The transformation order is extremely important, since both directions have to produce the same result. Currently, Empire can ingest the Global Options, HTTP/S, `http-config`, and `https-certificate` blocks. Other Cobalt Strike 4.0 blocks (e.g. `stage`, `process-inject`, `post-ex`) are not yet ingested. In the future, we hope to incorporate this additional functionality.

As of 7.0, the `http-config` block is enforced by the malleable HTTP listener: `trust_x_forwarded_for` (default `false`) enables validated `X-Forwarded-For` parsing, `block_useragents` rejects requests from matching user agents (fnmatch globs) with the shared IIS 7.5 404, and `header` is merged into every response. `set headers` ordering is parsed but not yet enforced. The `https-certificate` block is **parse-only** — Empire still loads the certificate from the listener's `CertPath` and logs a startup warning; runtime certificate generation from the block's fields is deferred.

7.0 also adds a `host_stage` directive (`set host_stage "false";`) to disable the listener's stager URI entirely; it defaults to `true` so existing profiles keep serving stagers unchanged. Serialized profiles carry a schema version that the C# (Sharpire) and Go (Gopire) agents validate before parsing, so an agent build expecting a newer/older schema will refuse a mismatched profile instead of misparsing it.

As of 6.0 malleable profiles can be easily managed from the **Malleable Profiles** entry in the sidebar. Here you can manually enter a profile by clicking on create and pasting in the profile configuration. You can also directly edit profiles by clicking on loaded profile and making changes then hitting **submit**

![](https://1910080187-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MM2c5FycSJH9sASPLaA%2Fuploads%2Fgit-blob-a4d269def05035e4c4782813ed54dd099e154513%2Fmalleable_profiles.png?alt=media)

Launching a Malleable C2 Listener can be simply done by selecting http\_malleable from the dropdown options when selecting a listener. The info page should look familiar since it uses similar settings as the standard HTTP listener, just with the addition **Profiles** dropdown:

![](https://1910080187-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MM2c5FycSJH9sASPLaA%2Fuploads%2Fgit-blob-a842dd8a8d3a575efda977b81ac24a60aff4974f%2Fmalleable_listener.png?alt=media)

One of the areas that still needs some improvement is when the listener tries to ingest serialized profiles. Occasionally Empire will successfully start the listener, but the agent will fail to properly stage when using a launcher. We are always trying to improve Empire functionality, so please [submit any issues](https://github.com/BC-SECURITY/Empire/issues) to our Github, since we heavily rely on users to help us identify areas for improvement.

The bundled profiles live in `empire/server/data/profiles` and ship with Empire, and we will continue to update them as new threat profiles are generated. This is also an opportunity for everyone to submit and share their profiles (assuming they work with Empire) — open a pull request against [Empire](https://github.com/BC-SECURITY/Empire) adding your profile under the appropriate category directory.

Similar to Cobalt Strike, Empire can only load a single profile per instance (for now). You can always spin up another instance of Empire if you want to run multiple Malleable Listeners at once. Otherwise, other listener types will still work while you have an active Malleable C2 Listener.
