dissect.cobaltstrike.beacon

This module is responsible for extracting and parsing configuration from Cobalt Strike beacon payloads.

Module Contents

Classes

BeaconConfig

A BeaconConfig object represents a single Beacon configuration

Functions

find_beacon_config_bytes(→ Iterator[bytes])

Find and yield (possible) Cobalt Strike configuration bytes from file fh using xorkey (eg: b"x69").

iter_beacon_config_blocks(→ Iterator[Tuple[bytes, dict]])

Yield tuple with found Beacon config_block_bytes from file fobj and extra_info dict

make_byte_list(→ List[bytes])

Return all single-byte bytes as an ordered list, excluding exclude bytes.

iter_settings(→ Iterator[Setting])

Returns an iterator yielding Setting objects by reading data from fobj

grouper(iterable, n[, fillvalue])

Collect data into fixed-length chunks or blocks

parse_recover_binary(→ List[Tuple[str, Union[int, bool]]])

Parse SETTING_C2_RECOVER (.http-get.server.output) data

parse_transform_binary(→ List[Tuple[str, Union[str, ...)

Parse SETTING_C2_{REQUEST,POSTREQ} (http-{get,post}.client) data

parse_execute_list(→ List[str])

Parse SETTING_PROCINJ_EXECUTE (.process-inject.execute) data

parse_process_injection_transform_steps(→ list)

Parse SETTING_PROCINJ_TRANSFORM_X{86,64} (process-inject.transform-x{86,64}) data

parse_gargle(→ list)

Parse SETTING_GARGLE_SECTIONS (.stage.{sleep_mask,obfuscate,userwx}) data

parse_pivot_frame(→ bytes)

Parse SETTING_{TCP,SMB}_FRAME_HEADER (.{tcp,smb}_frame_header) data

sha256sum_pubkey(→ str)

Return the SHA-256 digest of der_data

null_terminated_bytes(→ bytes)

Return null terminated data as bytes.

null_terminated_str(→ str)

Return null terminated data as string. Non ascii characters are ignored.

build_parser()

main()

Entrypoint for beacon-dump.

Attributes

logger

CS_DEF

cs_struct

TransformStep

BeaconSetting

DeprecatedBeaconSetting

SettingsType

Setting

BeaconProtocol

CryptoScheme

ProxyServer

InjectAllocator

InjectExecutor

DEFAULT_XOR_KEYS

Default XOR keys used by Cobalt Strike for obfuscating Beacon config bytes

SETTING_TO_PRETTYFUNC

BeaconSetting enum to pretty function mapping

dissect.cobaltstrike.beacon.logger[source]
dissect.cobaltstrike.beacon.CS_DEF = Multiline-String[source]
Show Value
  1enum BeaconSetting: uint16 {
  2    SETTING_PROTOCOL = 1,
  3    SETTING_PORT = 2,
  4    SETTING_SLEEPTIME = 3,
  5    SETTING_MAXGET = 4,
  6    SETTING_JITTER = 5,
  7    SETTING_MAXDNS = 6,
  8    SETTING_PUBKEY = 7,
  9    SETTING_DOMAINS = 8,
 10    SETTING_USERAGENT = 9,
 11    SETTING_SUBMITURI = 10,
 12    SETTING_C2_RECOVER = 11,
 13    SETTING_C2_REQUEST = 12,
 14    SETTING_C2_POSTREQ = 13,
 15    SETTING_SPAWNTO = 14,       // releasenotes.txt
 16
 17    // CobaltStrike version >= 3.4 (27 Jul, 2016)
 18    SETTING_PIPENAME = 15,
 19    SETTING_KILLDATE_YEAR = 16,
 20    SETTING_KILLDATE_MONTH = 17,
 21    SETTING_KILLDATE_DAY = 18,
 22    SETTING_DNS_IDLE = 19,
 23    SETTING_DNS_SLEEP = 20,
 24
 25    // CobaltStrike version >= 3.5 (22 Sept, 2016)
 26    SETTING_SSH_HOST = 21,
 27    SETTING_SSH_PORT = 22,
 28    SETTING_SSH_USERNAME = 23,
 29    SETTING_SSH_PASSWORD = 24,
 30    SETTING_SSH_KEY = 25,
 31    SETTING_C2_VERB_GET = 26,
 32    SETTING_C2_VERB_POST = 27,
 33    SETTING_C2_CHUNK_POST = 28,
 34    SETTING_SPAWNTO_X86 = 29,
 35    SETTING_SPAWNTO_X64 = 30,
 36
 37    // CobaltStrike version >= 3.6 (8 Dec, 2016)
 38    SETTING_CRYPTO_SCHEME = 31,
 39
 40    // CobaltStrike version >= 3.7 (15 Mar, 2016)
 41    SETTING_PROXY_CONFIG = 32,
 42    SETTING_PROXY_USER = 33,
 43    SETTING_PROXY_PASSWORD = 34,
 44    SETTING_PROXY_BEHAVIOR = 35,
 45
 46    // CobaltStrike version >= 3.8 (23 May 2017)
 47    // DEPRECATED_SETTING_INJECT_OPTIONS = 36,
 48
 49    // Renamed from DEPRECATED_SETTING_INJECT_OPTIONS in CobaltStrike 4.5
 50    SETTING_WATERMARKHASH = 36,
 51
 52    // CobaltStrike version >= 3.9  (Sept 26, 2017)
 53    SETTING_WATERMARK = 37,
 54
 55    // CobaltStrike version >= 3.11 (April 9, 2018)
 56    SETTING_CLEANUP = 38,
 57
 58    // CobaltStrike version >= 3.11 (May 24, 2018)
 59    SETTING_CFG_CAUTION = 39,
 60
 61    // CobaltStrike version >= 3.12 (Sept 6, 2018)
 62    SETTING_KILLDATE = 40,
 63    SETTING_GARGLE_NOOK = 41,       // https://www.youtube.com/watch?v=nLTgWdXrx3U
 64    SETTING_GARGLE_SECTIONS = 42,
 65    SETTING_PROCINJ_PERMS_I = 43,
 66    SETTING_PROCINJ_PERMS = 44,
 67    SETTING_PROCINJ_MINALLOC = 45,
 68    SETTING_PROCINJ_TRANSFORM_X86 = 46,
 69    SETTING_PROCINJ_TRANSFORM_X64 = 47,
 70    SETTING_PROCINJ_ALLOWED = 48,
 71
 72    // CobaltStrike version >= 3.13 (Jan 2, 2019)
 73    SETTING_BINDHOST = 49,
 74
 75    // CobaltStrike version >= 3.14 (May 4, 2019)
 76    SETTING_HTTP_NO_COOKIES = 50,
 77    SETTING_PROCINJ_EXECUTE = 51,
 78    SETTING_PROCINJ_ALLOCATOR = 52,
 79    SETTING_PROCINJ_STUB = 53,      // .self = MD5(cobaltstrike.jar)
 80
 81    // CobaltStrike version >= 4.0 (Dec 5, 2019)
 82    SETTING_HOST_HEADER = 54,
 83    SETTING_EXIT_FUNK = 55,
 84
 85    // CobaltStrike version >= 4.1 (June 25, 2020)
 86    SETTING_SSH_BANNER = 56,
 87    SETTING_SMB_FRAME_HEADER = 57,
 88    SETTING_TCP_FRAME_HEADER = 58,
 89
 90    // CobaltStrike version >= 4.2 (Nov 6, 2020)
 91    SETTING_HEADERS_REMOVE = 59,
 92
 93    // CobaltStrike version >= 4.3 (Mar 3, 2021)
 94    SETTING_DNS_BEACON_BEACON = 60,
 95    SETTING_DNS_BEACON_GET_A = 61,
 96    SETTING_DNS_BEACON_GET_AAAA = 62,
 97    SETTING_DNS_BEACON_GET_TXT = 63,
 98    SETTING_DNS_BEACON_PUT_METADATA = 64,
 99    SETTING_DNS_BEACON_PUT_OUTPUT = 65,
100    SETTING_DNSRESOLVER = 66,
101    SETTING_DOMAIN_STRATEGY = 67,
102    SETTING_DOMAIN_STRATEGY_SECONDS = 68,
103    SETTING_DOMAIN_STRATEGY_FAIL_X = 69,
104    SETTING_DOMAIN_STRATEGY_FAIL_SECONDS = 70,
105
106    // CobaltStrike version >= 4.5 (Dec 14, 2021)
107    SETTING_MAX_RETRY_STRATEGY_ATTEMPTS = 71,
108    SETTING_MAX_RETRY_STRATEGY_INCREASE = 72,
109    SETTING_MAX_RETRY_STRATEGY_DURATION = 73,
110
111    // CobaltStrike version >= 4.7 (Aug 17, 2022)
112    SETTING_MASKED_WATERMARK = 74,
113};
114
115enum DeprecatedBeaconSetting: uint16 {
116    SETTING_KILLDATE_YEAR = 16,
117    SETTING_INJECT_OPTIONS = 36,
118};
119
120enum TransformStep: uint32 {
121    APPEND = 1,
122    PREPEND = 2,
123    BASE64 = 3,
124    PRINT = 4,
125    PARAMETER = 5,
126    HEADER = 6,
127    BUILD = 7,
128    NETBIOS = 8,
129    _PARAMETER = 9,
130    _HEADER = 10,
131    NETBIOSU = 11,
132    URI_APPEND = 12,
133    BASE64URL = 13,
134    STRREP = 14,
135    MASK = 15,
136    // CobaltStrike version >= 4.0 (Dec 5, 2019)
137    _HOSTHEADER = 16,
138};
139
140enum SettingsType: uint16 {
141    TYPE_NONE = 0,
142    TYPE_SHORT = 1,
143    TYPE_INT = 2,
144    TYPE_PTR = 3,
145};
146
147struct Setting {
148    BeaconSetting index;    // uint16
149    SettingsType type;      // uint16
150    uint16 length;          // uint16
151    char value[length];
152};
153
154flag BeaconProtocol {
155    http = 0,
156    dns = 1,
157    smb = 2,
158    tcp = 4,
159    https = 8,
160    bind = 16
161};
162
163flag ProxyServer {
164    MANUAL = 0,
165    DIRECT = 1,
166    PRECONFIG = 2,
167    MANUAL_CREDS = 4
168};
169
170enum CryptoScheme: uint16 {
171    CRYPTO_LICENSED_PRODUCT = 0,
172    CRYPTO_TRIAL_PRODUCT = 1
173};
174
175enum InjectAllocator: uint8 {
176    VirtualAllocEx = 0,
177    NtMapViewOfSection = 1,
178};
179
180enum InjectExecutor: uint8 {
181    CreateThread = 1,
182    SetThreadContext = 2,
183    CreateRemoteThread = 3,
184    RtlCreateUserThread = 4,
185    NtQueueApcThread = 5,
186    CreateThread_ = 6,
187    CreateRemoteThread_ = 7,
188    NtQueueApcThread_s = 8
189};
dissect.cobaltstrike.beacon.cs_struct[source]
dissect.cobaltstrike.beacon.TransformStep[source]
dissect.cobaltstrike.beacon.BeaconSetting[source]
dissect.cobaltstrike.beacon.DeprecatedBeaconSetting[source]
dissect.cobaltstrike.beacon.SettingsType[source]
dissect.cobaltstrike.beacon.Setting[source]
dissect.cobaltstrike.beacon.BeaconProtocol[source]
dissect.cobaltstrike.beacon.CryptoScheme[source]
dissect.cobaltstrike.beacon.ProxyServer[source]
dissect.cobaltstrike.beacon.InjectAllocator[source]
dissect.cobaltstrike.beacon.InjectExecutor[source]
dissect.cobaltstrike.beacon.DEFAULT_XOR_KEYS :List[bytes] = [b'i', b'.', b'\x00'][source]

Default XOR keys used by Cobalt Strike for obfuscating Beacon config bytes

dissect.cobaltstrike.beacon.find_beacon_config_bytes(fh: BinaryIO, xorkey: bytes) Iterator[bytes][source]

Find and yield (possible) Cobalt Strike configuration bytes from file fh using xorkey (eg: b”x69”).

This is done by scraping the file fh for XOR encoded configuration blocks. A beacon configuration block always (unless modified) starts with:

Setting(index=SETTING_PROTOCOL, type=TYPE_SHORT, length=0x2)

# which translates to the following bytes
b"\x00\x01\x00\x01\x00\x02\x00"

These bytes are used in conjuction with the XOR key for finding the (potential) start of a configuration block.

Parameters
  • fh – file object

  • xorkey – XOR key (as bytes)

Yields

Beacon configuration bytes (4096 bytes), in deobfuscated (un-XOR’d) form.

dissect.cobaltstrike.beacon.iter_beacon_config_blocks(fobj: BinaryIO, xor_keys=None, xordecode=True, all_xor_keys=False) Iterator[Tuple[bytes, dict]][source]

Yield tuple with found Beacon config_block_bytes from file fobj and extra_info dict

It always start seeking from the beginning of fobj. Side effects: file handle position due to seeking

The extra_info dictionary holds some metadata such as if the fobj was xorencoded and which xorkey was used.

Parameters
  • xor_keys – list XOR keys (as bytes), defaults to: DEFAULT_XOR_KEYS if not specified.

  • xordecode – If True it will also try to XorDecode the file object.

  • all_xor_keys – Try ALL single-byte XOR keys if no beacon config is found using the default keys.

Yields

Tuple as (config_block_bytes, extra_info_dict)extra_info dict contains: {"xorkey": bytes, "xorencoded": bool}

dissect.cobaltstrike.beacon.make_byte_list(exclude: List[bytes] = None) List[bytes][source]

Return all single-byte bytes as an ordered list, excluding exclude bytes.

dissect.cobaltstrike.beacon.iter_settings(fobj: Union[bytes, BinaryIO]) Iterator[Setting][source]

Returns an iterator yielding Setting objects by reading data from fobj

The file position will be at the end of the Beacon config after parsing is done. This can be used to determine the exact size of the Beacon configuration block.

Some edge cases are also handled:

  • User-Agent string that exceeds the Setting length.

  • Deprecated setting SETTING_INJECT_OPTIONS

Parameters

fobj – bytes or file-like object with Beacon configuration data

Yields

Setting objects

dissect.cobaltstrike.beacon.grouper(iterable, n, fillvalue=None)[source]

Collect data into fixed-length chunks or blocks

dissect.cobaltstrike.beacon.parse_recover_binary(program: bytes) List[Tuple[str, Union[int, bool]]][source]

Parse SETTING_C2_RECOVER (.http-get.server.output) data

dissect.cobaltstrike.beacon.parse_transform_binary(program: bytes, build: str = 'metadata') List[Tuple[str, Union[str, bytes, bool]]][source]

Parse SETTING_C2_{REQUEST,POSTREQ} (http-{get,post}.client) data

dissect.cobaltstrike.beacon.parse_execute_list(data: bytes) List[str][source]

Parse SETTING_PROCINJ_EXECUTE (.process-inject.execute) data

dissect.cobaltstrike.beacon.parse_process_injection_transform_steps(data: bytes) list[source]

Parse SETTING_PROCINJ_TRANSFORM_X{86,64} (process-inject.transform-x{86,64}) data

dissect.cobaltstrike.beacon.parse_gargle(data: bytes) list[source]

Parse SETTING_GARGLE_SECTIONS (.stage.{sleep_mask,obfuscate,userwx}) data

dissect.cobaltstrike.beacon.parse_pivot_frame(data: bytes) bytes[source]

Parse SETTING_{TCP,SMB}_FRAME_HEADER (.{tcp,smb}_frame_header) data

dissect.cobaltstrike.beacon.sha256sum_pubkey(der_data: bytes) str[source]

Return the SHA-256 digest of der_data

dissect.cobaltstrike.beacon.null_terminated_bytes(data: bytes) bytes[source]

Return null terminated data as bytes.

>>> null_terminated_bytes(b"Hello World\x00\x00Foobar\x00\x00")
b'Hello World'
>>> null_terminated_bytes(b"foo\xffbar\x00\x00\x00baz\x00")
b'foo\xffbar'
dissect.cobaltstrike.beacon.null_terminated_str(data: bytes) str[source]

Return null terminated data as string. Non ascii characters are ignored.

>>> null_terminated_str(b"Hello World\x00\x00foo bar\x00\x00")
'Hello World'
>>> null_terminated_str(b"Goodbye\xffPlanet\x00\x00")
'GoodbyePlanet'
dissect.cobaltstrike.beacon.SETTING_TO_PRETTYFUNC :Dict[BeaconSetting, Callable][source]

BeaconSetting enum to pretty function mapping

class dissect.cobaltstrike.beacon.BeaconConfig(config_block: bytes)[source]

A BeaconConfig object represents a single Beacon configuration

It holds configuration data, parsed settings and other metadata of a Cobalt Strike Beacon and provides useful methods and properties for accessing the Beacon settings. It does not contain the Beacon payload data itself.

It can be directly instantiated using configuration data. Otherwise, use the following constructors:

The from_ constructors automatically tries to extract the configuration data (first candidate only) and also handles xorencoded payloads and XOR decoding of obfuscated configuration blocks that is common with Cobalt Strike.

property setting_enums: list[source]

List of BeaconSetting enum values in the order of appearance within the Beacon configuration. Example value:

[1, 2, 3, 4, 5, 7, ..., 45, 46, 47, 53, 51, 52]
property max_setting_enum: int[source]

The maximum BeaconSetting enum value present in the Beacon configuration.

property raw_settings: Mapping[str, Any][source]

Read-only Beacon settings mapping with raw values, indexed by BeaconSetting name.

The raw bytes of TYPE_SHORT and TYPE_INT values are converted to int. Example value:

mappingproxy({
    'SETTING_PROTOCOL': 8,
    'SETTING_PORT': 443,
    'SETTING_SLEEPTIME': 60000,
    ...
    'SETTING_C2_VERB_POST': b'POST\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
    'SETTING_PROCINJ_STUB': b'\x0c\xe2\xf5TD\xe4y5\x16\xb5\xaf\xe9g\xbe\x92U',
})
property raw_settings_by_index: Mapping[int, Any][source]

Read-only Beacon settings mapping with raw values, indexed by BeaconSetting constant.

The raw bytes of TYPE_SHORT and TYPE_INT values are converted to int. Example value:

mappingproxy({
    1: 8,
    2: 443,
    3: 60000,
    ...
    27: b'POST\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
    53: b'\x0c\xe2\xf5TD\xe4y5\x16\xb5\xaf\xe9g\xbe\x92U',
})
property settings: Mapping[str, Any][source]

Read-only Beacon settings mapping with human readable values, indexed by BeaconSetting name. Example value:

mappingproxy({
    'SETTING_PROTOCOL': 8,
    'SETTING_PORT': 443,
    'SETTING_SLEEPTIME': 60000,
    ...
    'SETTING_C2_VERB_POST': 'POST',
    'SETTING_PROCINJ_STUB': '0ce2f55444e4793516b5afe967be9255',
})
property settings_by_index: Mapping[int, Any][source]

Read-only Beacon settings mapping with human readable values, indexed by BeaconSetting constant. Example value:

mappingproxy({
    1: 8,
    2: 443,
    3: 60000,
    ...
    27: 'POST',
    53: '0ce2f55444e4793516b5afe967be9255',
})
property domain_uri_pairs: List[Tuple[str, str]][source]

List of configured (domain, uri) pairs in the Beacon. Example value:

[
    ('c1.example.com', '/__utm.gif'),
    ('c2.example.com', '/en_US/all.js'),
]
property uris: List[str][source]

List of configured Beacon URIs. Example value:

['/__utm.gif', '/en_US/all.js']
property domains: List[str][source]

List of configured Beacon domains. Example value:

['c1.example.com', 'c2.example.com']
property submit_uri: Optional[str][source]

The submit URI that the beacon uses for sending callback data. Example value:

'/submit.php'
property killdate: Optional[str][source]

Normalized kill date as YYYY-mm-dd string or None if not defined in Beacon.

Note

The reason why the return type is a str instead of a datetime.date object is that the configured killdate in the Beacon can be arbitrary. e.g. 9999-99-99

property protocol: Optional[str][source]

The protocol the Beacon uses for communication, e.g. "http", "dns". None if unknown.

property port: Optional[int][source]

The port the Beacon uses for communication, e.g. 80, 443. None if not defined in config.

property watermark: Optional[int][source]

Beacon watermark (also known as customer or authorization id).

property is_trial: bool[source]

True if Beacon is a trial version (CRYPTO_TRIAL_PRODUCT). Otherwise, False.

property version: dissect.cobaltstrike.version.BeaconVersion[source]

Deduced version of Cobalt Strike as BeaconVersion object.

The version is deduced from the Beacon’s pe_export_stamp when available, otherwise from max_setting_enum.

property public_key: bytes[source]

The RSA public key used by the Beacon in DER format.

property sleeptime: Optional[int][source]

The sleep time in milliseconds the Beacon uses between communication attempts.

property jitter: Optional[int][source]

The jitter in milliseconds the Beacon uses between communication attempts.

config_block :bytes[source]

Raw beacon configuration block bytes

settings_tuple[source]

Tuple containing the Setting objects parsed from config_block

xorkey :Optional[bytes][source]

XOR key that was used to obfuscate the configuration block, None if unknown.

xorencoded :bool = False[source]

True if the beacon was xorencoded, otherwise False

pe_export_stamp :Optional[int][source]

PE export timestamp, None if unknown.

pe_compile_stamp :Optional[int][source]

PE compile timestamp, None if unknown.

architecture :Optional[str][source]

PE architecture, "x86" or "x64" and None if unknown.

classmethod from_file(fobj: BinaryIO, xor_keys: List[bytes] = None, all_xor_keys: bool = False) BeaconConfig[source]

Create a BeaconConfig from file object, or raises ValueError if no beacon config is found.

Parameters
  • fobj – file-like object

  • xor_keys – override the default XOR keys (as bytes) when specified. Default None.

  • all_xor_keys – if True, it will try ALL single-byte XOR keys if the defaults don’t work

Returns

BeaconConfig

Raises

ValueError – If no valid beacon configuration was found

classmethod from_path(path: Union[str, os.PathLike], xor_keys: List[bytes] = None, all_xor_keys: bool = False) BeaconConfig[source]

Create a BeaconConfig from path, or raises ValueError if no beacon config is found.

Parameters
  • path – path to file on disk

  • xor_keys – override the default XOR keys (as bytes) when specified. Default None.

  • all_xor_keys – if True it will try ALL single-byte XOR keys if the defaults don’t work

Returns

BeaconConfig

Raises

ValueError – If no valid beacon configuration was found

classmethod from_bytes(data: bytes, xor_keys: List[bytes] = None, all_xor_keys: bool = False) BeaconConfig[source]

Create a BeaconConfig from bytes, or raises ValueError if no beacon config is found.

Parameters
  • data – configuration bytes

  • xor_keys – override the default XOR keys when specified. Default None.

  • all_xor_keys – if True it will try ALL single-byte XOR keys if the defaults don’t work

Returns

BeaconConfig

Raises

ValueError – If no valid beacon configuration was found

__repr__() str[source]

Return repr(self).

settings_map(index_type='enum', pretty=False, parse=True) types.MappingProxyType[source]

Return a read-only settings mapping indexed by given index_type.

Parameters
  • index_type

    index type of the dictionary, can be one of:

    • name: indexed by BeaconSetting name (str)

    • const: indexed by BeaconSetting constant (int)

    • enum: indexed by BeaconSetting enum (enum object).

  • pretty – if True, apply pretty functions on the values.

  • parse – if True, the raw bytes of TYPE_SHORT and TYPE_INT values are converted to int.

Returns

OrderedDict

dissect.cobaltstrike.beacon.build_parser()[source]
dissect.cobaltstrike.beacon.main()[source]

Entrypoint for beacon-dump.