Examples
Some examples showing how to use the dissect.cobaltstrike
Python API.
Beacon Configuration
The main class for dealing with Cobalt Strike Beacon configuration is BeaconConfig
.
It’s recommended to instantiate the class by using one of the following constructors:
These from_ constructors will handle XorEncoded
beacons
by default and tries the default XOR keys used for obfuscating the beacon configuration. It raises
ValueError if no beacon config was found.
For example to load the configuration of a Beacon payload on disk and access it’s settings:
In [1]: from dissect.cobaltstrike.beacon import BeaconConfig
In [2]: bconfig = BeaconConfig.from_path("beacon_92.bin")
In [3]: bconfig
Out[3]: <BeaconConfig ['londonteea.com']>
In [4]: bconfig.version
Out[4]: <BeaconVersion 'Cobalt Strike 4.2 (Nov 06, 2020)', tuple=(4, 2), date=2020-11-06>
In [5]: hex(bconfig.watermark)
Out[5]: '0x5109bf6d'
In [6]: bconfig.settings["SETTING_C2_REQUEST"]
Out[6]:
[('_HEADER', b'Connection: close'),
('_HEADER', b'Accept-Language: en-US'),
('BUILD', 'metadata'),
('MASK', True),
('BASE64', True),
('PREPEND', b'wordpress_ed1f617bbd6c004cc09e046f3c1b7148='),
('HEADER', b'Cookie')]
If the beacon uses a non standard XOR key it will not find the beacon configuration and will raise ValueError
:
In [7]: %xmode Minimal
Exception reporting mode: Minimal
In [8]: bconfig = BeaconConfig.from_path("beacon_xor.bin")
ValueError: No valid Beacon configuration found
Specify all_xor_keys=True
to automatically try all single-byte XOR keys when the default keys fail:
In [9]: bconfig = BeaconConfig.from_path("beacon_xor.bin", all_xor_keys=True)
In [10]: bconfig
Out[10]: <BeaconConfig ['group.ccb.com.dsa.dnsv1.com']>
In [11]: bconfig.xorkey.hex()
Out[11]: 'cc'
In [12]: bconfig.version
Out[12]: <BeaconVersion 'Cobalt Strike 4.4 (Aug 04, 2021)', tuple=(4, 4), date=2021-08-04>
Or if you want to speed things up and you know a set of candidate XOR keys, just specify them using xor_keys
to
override the DEFAULT_XOR_KEYS
:
In [13]: BeaconConfig.from_path("beacon_xor.bin", xor_keys=[b"\xcc"])
Out[13]: <BeaconConfig ['group.ccb.com.dsa.dnsv1.com']>
In [14]: _.xorkey.hex()
Out[14]: 'cc'
If you have extracted a Beacon configuration block manually, for example via x64dbg, you can pass it directly
to BeaconConfig()
. However, this only works with configuration bytes that is not
obfuscated.
If the configuration block is obfuscated with a single-byte XOR key, use
the BeaconConfig.from_bytes()
constructor:
In [15]: data = '000000000000002e2f2e2f2e2c2e262e2c2e2f2e2c2f952e2d2e2c2e2a2e2ec44e2e2a2e2c2e2a2e3b7b762e2b2e2f2e2c2e302e292e2d2f2e1eafb11e23282704a866a8d9232f2f2f2b2e2dafa32e1eafa72cafaf2e889020f71e85a0e5a8d4e34a3795cda19b92a96ab5def70f62f93df6dc9630a2792be4a072feb87d581c02b171e1f5f869e40ea22cc29f1e77137f46199f49b70467f5f8d0901a7a321e92b6a3e5796ccd898a6b67f99d1861c6a0bf65e28e322f5b48a33edaed42ba921dcd6637560a4f309a8d1a313eeb9e0eae9e05e14cd52c2d2f2e2f2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e262e2d2f2e5d4740475a5b4a4b004d41430201594b4c014d464f5a5c005e415c5a4f422e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e202e2d2e3e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e332e2d2e6e0b5947404a475c0b725d575d594159181a724a424246415d5a004b564b2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e302e2d2e6e0b5947404a475c0b725d575d404f5a47584b724a424246415d5a004b564b2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e312e2f2e2c2e2e2e342e2d2e3e696b7a2e2e2e2e2e2e2e2e2e2e2e2e2e2e352e2d2e3e7e617d7a2e2e2e2e2e2e2e2e2e2e2e2e2e322e2c2e2a2e2e2e2e2e0b2e2c2e2a7f2791432e082e2f2e2c2e2e2e092e2f2e2c2e2e2e272e2d2f2e6341544742424f011b001e0e067947404a41595d0e607a0e18001c070e6f5e5e424b794b4c65475a011b1d19001d180e0665667a6362020e4247454b0e694b4d4541070e6d465c41434b01171e001e001a1a1d1e00161b0e7d4f484f5c47011b1d19001d182e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e242e2d2e6e01594b4c014241494140004f5d5e562e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e252e2d2f2e2e2e2e2a2e2e2e2d2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e222e2d2c2e2e2e2e242e2e2e396d41405a4b405a037a575e4b140e5a4b565a01465a43422e2e2e242e2e2e396d4f4d464b036d41405a5c4142140e4041034d4f4d464b2e2e2e292e2e2e2e2e2e2e262e2e2e222e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e232e2d2c2e2e2e2e242e2e2e0f6d41405a4b405a037a575e4b140e435b425a475e4f5c5a0148415c43034a4f5a4f2e2e2e242e2e2e396d4f4d464b036d41405a5c4142140e4041034d4f4d464b2e2e2e292e2e2e2e2e2e2e252e2e2e222e2e2e292e2e2e2f2e2e2e232e2e2e2a2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e182e2d2eae2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e1c2e2f2e2c2e2e2e0d2e2f2e2c2e2c2e142e2d2eae2e2bbe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e172e2d2eae2e2b5e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e192e2f2e2c2e2e2e062e2c2e2a2e2e2e2e2e072e2c2e2a2e2e2e2e2e052e2f2e2c2e2a2e022e2f2e2c2e0e2e032e2c2e2a2e2e6a722e002e2d2f2e2e2e2e2cbebe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e012e2d2f2e2e2e2e2cbebe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e1b2e2d2e3e22ccdb7a6aca571b389b81c74990bc7b2e1d2e2d2eae282e082e2e2e28405a4a42422e2e2e2e3d7c5a427b5d4b5c7a465c4b4f4a7d5a4f5c5a2e2f26292e7f2e2e2e23454b5c404b421d1c004a42422e2e2e2e2362414f4a62474c5c4f5c576f2e2a2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e1a2e2f2e2c2e2f2e2ea9b00e0f83d6dcebcc255a8257385b0cfcd0b3e396662dbc1dfaa4760f06e45619877b1b8417ed572d4fb9dc3693800c78d5ad9efb6b49101afb1fcce586e1b08bb4bb746dd5114c2707c83b0b3cb571ba5d49ce24d84dc8c719c536d0491107dc284ba6ca8560274d4838c2fb866ef2a1875dead0f249885c0a7b1393dfc3630fb471753e907eef2ffeeb03bba60268453f444d83013fde9e95332e52fb82b1b59ecb31f2b83e90f6738ce1add1def1dddfee14c80445b2e2c5f9318d0efa7082519aa05fe2c3454ccb4950de6a924238bbeb9fe39721719f7ac8092087be5c2de004d6a39acc8135e86a13cac51e3448268a817742493aa3120059a109ef5e1812129f2c6d139a2b8859e8b40bc40eb643583bf993af9c7abaaa37450c426712337b1d18160be90b101698d1fd7b9928f593314b85117713222985f789362cdff09ea88cb167b72d1913961942e0d31ee2c8d256b4e4356d16fd5ea9f6bd42bb2ccb127db061f2003b5fc637873090180c951679a1bf8c8beae3203a6cc3c5638b8c5942bff2f7981b86798023f71d4e9acdd8b39d689c489445e8b9279a078fb6de1b8c527b339ef447039b1903b8b95ef5769502b9d7e0fd81d839c8903ad2244e4690e6839d9869301e0c2c0be9c725d8fb5d6cb96ac9cee3873ec5268c1eeed334317c01'
In [16]: BeaconConfig.from_bytes(bytes.fromhex(data))
Out[16]: <BeaconConfig ['sinitude.com']>
In [17]: config = _
In [18]: config.protocol
Out[18]: 'https'
In [19]: config.domain_uri_pairs
Out[19]: [('sinitude.com', '/web/chatr.portal')]
In [20]: config.settings
Out[20]:
mappingproxy({'SETTING_PROTOCOL': 8,
'SETTING_PORT': 443,
'SETTING_SLEEPTIME': 60000,
'SETTING_MAXGET': 1398104,
'SETTING_JITTER': 30,
'SETTING_PUBKEY': 'a83298f790d9a47e425ce5d67a148ba87498e7ed5eb4b4f4f1e0c5e177b274a2',
'SETTING_DOMAINS': 'sinitude.com,/web/chatr.portal',
'SETTING_SPAWNTO': '00000000000000000000000000000000',
'SETTING_SPAWNTO_X86': '%windir%\\syswow64\\dllhost.exe',
'SETTING_SPAWNTO_X64': '%windir%\\sysnative\\dllhost.exe',
'SETTING_CRYPTO_SCHEME': 0,
'SETTING_C2_VERB_GET': 'GET',
'SETTING_C2_VERB_POST': 'POST',
'SETTING_C2_CHUNK_POST': 0,
'SETTING_WATERMARK': 1359593325,
'SETTING_CLEANUP': 0,
'SETTING_CFG_CAUTION': 0,
'SETTING_USERAGENT': 'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36',
'SETTING_SUBMITURI': '/web/logon.aspx',
'SETTING_C2_RECOVER': [('print', True), ('base64', True)],
'SETTING_C2_REQUEST': [('_HEADER', b'Content-Type: text/html'),
('_HEADER', b'Cache-Control: no-cache'),
('BUILD', 'metadata'),
('NETBIOS', True),
('URI_APPEND', True)],
'SETTING_C2_POSTREQ': [('_HEADER',
b'Content-Type: multipart/form-data'),
('_HEADER', b'Cache-Control: no-cache'),
('BUILD', 'id'),
('NETBIOSU', True),
('URI_APPEND', True),
('BUILD', 'output'),
('BASE64URL', True),
('PRINT', True)],
'SETTING_HOST_HEADER': '',
'SETTING_HTTP_NO_COOKIES': 0,
'SETTING_PROXY_BEHAVIOR': 2,
'SETTING_TCP_FRAME_HEADER': b'\x90',
'SETTING_SMB_FRAME_HEADER': b'p',
'SETTING_EXIT_FUNK': 0,
'SETTING_KILLDATE': 0,
'SETTING_GARGLE_NOOK': 0,
'SETTING_PROCINJ_PERMS_I': 4,
'SETTING_PROCINJ_PERMS': 32,
'SETTING_PROCINJ_MINALLOC': 17500,
'SETTING_PROCINJ_TRANSFORM_X86': [('append', b'\x90\x90'),
('prepend', b'')],
'SETTING_PROCINJ_TRANSFORM_X64': [('append', b'\x90\x90'),
('prepend', b'')],
'SETTING_PROCINJ_STUB': '0ce2f55444e4793516b5afe967be9255',
'SETTING_PROCINJ_EXECUTE': ['CreateThread "ntdll!RtlUserThreadStart+0x26"',
'CreateThread',
'NtQueueApcThread_s',
'CreateRemoteThread "kernel32.dll!LoadLibraryA+0x51"',
'RtlCreateUserThread'],
'SETTING_PROCINJ_ALLOCATOR': 1})
In [21]: config.version
Out[21]: <BeaconVersion 'Cobalt Strike 4.1 (Jun 25, 2020)', tuple=(4, 1), date=2020-06-25>
Memory dumps
While you can use BeaconConfig
to load Beacon payloads directly,
it can also load a memory dump (or any other file) and check for beacon configurations.
However, the default constructors will only return the first found beacon configuration.
If you have a memory dump that could contain multiple beacons,
use iter_beacon_config_blocks()
to iterate over all found beacon
configuration blocks and instantiate BeaconConfig
manually:
import sys
from dissect.cobaltstrike import beacon
with open(sys.argv[1], "rb") as f:
for config_block, extra_data in beacon.iter_beacon_config_blocks(f):
try:
bconfig = beacon.BeaconConfig(config_block)
if not len(bconfig.domains):
continue
except ValueError:
continue
print(bconfig, bconfig.domain_uri_pairs)
This will try to find all beacon config_block bytes in the file and try to instantiate
a BeaconConfig
from it. For verification it will
check if the beacon has a domain to ensure that config_block was not just some random data.
PE Artifacts
Use the dissect.cobaltstrike.pe
module to extract PE artifacts.
If the payload is XorEncoded you need to load it using XorEncodedFile
first.
In [22]: from dissect.cobaltstrike import xordecode
In [23]: from dissect.cobaltstrike import pe
In [24]: import time
In [25]: xf = xordecode.XorEncodedFile.from_path("beacon_93.bin")
In [26]: pe.find_architecture(xf)
Out[26]: 'x64'
In [27]: pe.find_compile_stamps(xf)
Out[27]: (1628256615, 1614696183)
In [28]: compile_stamp, export_stamp = _
In [29]: time.ctime(compile_stamp)
Out[29]: 'Fri Aug 6 13:30:15 2021'
In [30]: pe.find_magic_mz(xf)
Out[30]: b'MZAR'
In [31]: pe.find_magic_pe(xf)
Out[31]: b'PE'
In [32]: pe.find_stage_prepend_append(xf)
Out[32]: (b'\x90\x90\x90\x90\x90\x90\x90\x90', None)
C2 Profiles
Loading Cobalt Strike Malleable C2 Profiles is also supported, to load a profile from disk:
In [33]: from dissect.cobaltstrike.c2profile import C2Profile
In [34]: profile = C2Profile.from_path("amazon.profile")
To access the C2Profile configuration settings use
the C2Profile.as_dict
method or
the C2Profile.properties
attribute. For example:
In [35]: profile.as_dict()
Out[35]:
{'sleeptime': ['5000'],
'jitter': ['0'],
'maxdns': ['255'],
'useragent': ['Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko'],
'http-get.uri': ['/s/ref=nb_sb_noss_1/167-3294888-0262949/field-keywords=books'],
'http-get.client.header': [('Accept', '*/*'), ('Host', 'www.amazon.com')],
'http-get.client.metadata': ['base64',
('prepend', b'session-token='),
('prepend', b'skin=noskin;'),
('append', b'csm-hit=s-24KU11BB82RZSYGJ3BDK|1419899012996'),
('header', b'Cookie')],
'http-get.server.header': [('Server', 'Server'),
('x-amz-id-1', 'THKUYEZKCKPGY5T42PZT'),
('x-amz-id-2',
'a21yZ2xrNDNtdGRsa212bGV3YW85amZuZW9ydG5rZmRuZ2tmZGl4aHRvNDVpbgo='),
('X-Frame-Options', 'SAMEORIGIN'),
('Content-Encoding', 'gzip')],
'http-get.server.output': ['print'],
'http-post.uri': ['/N4215/adj/amzn.us.sr.aps'],
'http-post.client.header': [('Accept', '*/*'),
('Content-Type', 'text/xml'),
('X-Requested-With', 'XMLHttpRequest'),
('Host', 'www.amazon.com')],
'http-post.client.parameter': [('sz', '160x600'),
('oe', 'oe=ISO-8859-1;'),
('s', '3717'),
('dc_ref', 'http%3A%2F%2Fwww.amazon.com')],
'http-post.client.id': [('parameter', b'sn')],
'http-post.client.output': ['base64', 'print'],
'http-post.server.header': [('Server', 'Server'),
('x-amz-id-1', 'THK9YEZJCKPGY5T42OZT'),
('x-amz-id-2',
'a21JZ1xrNDNtdGRsa219bGV3YW85amZuZW9zdG5rZmRuZ2tmZGl4aHRvNDVpbgo='),
('X-Frame-Options', 'SAMEORIGIN'),
('x-ua-compatible', 'IE=edge')],
'http-post.server.output': ['print']}
In [36]: profile.properties["useragent"]
Out[36]: ['Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko']
In [37]: profile.properties["http-get.uri"]
Out[37]: ['/s/ref=nb_sb_noss_1/167-3294888-0262949/field-keywords=books']
In [38]: profile.properties["http-post.client.parameter"]
Out[38]:
[('sz', '160x600'),
('oe', 'oe=ISO-8859-1;'),
('s', '3717'),
('dc_ref', 'http%3A%2F%2Fwww.amazon.com')]
Note
Currently all the values in the dictionary are lists, this might change in the future.
BeaconConfig to C2 Profile
Use C2Profile.from_beacon_config
to load
settings from a BeaconConfig
. This allows for dumping the Beacon Configuration
to a more readable (and reusable) C2 Profile.
In [39]: config
Out[39]: <BeaconConfig ['sinitude.com']>
In [40]: profile = C2Profile.from_beacon_config(config)
In [41]: print(profile)
set sleeptime "60000";
set jitter "30";
set spawnto_x86 "%windir%\syswow64\dllhost.exe";
set spawnto_x64 "%windir%\sysnative\dllhost.exe";
set useragent "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36";
set tcp_frame_header "\x90";
set smb_frame_header "p";
http-get {
set uri "/web/chatr.portal";
set verb "GET";
server {
output {
base64;
print;
}
}
client {
header "Content-Type" "text/html";
header "Cache-Control" "no-cache";
metadata {
netbios;
uri-append;
}
}
}
http-post {
set verb "POST";
set uri "/web/logon.aspx";
client {
header "Content-Type" "multipart/form-data";
header "Cache-Control" "no-cache";
id {
netbiosu;
uri-append;
}
output {
base64url;
print;
}
}
}
stage {
set cleanup "0";
}
process-inject {
set startrwx "false";
set userwx "false";
set min_alloc "17500";
transform-x86 {
append "\x90\x90";
}
transform-x64 {
append "\x90\x90";
}
execute {
CreateThread "ntdll!RtlUserThreadStart+0x26";
CreateThread;
CreateRemoteThread "kernel32.dll!LoadLibraryA+0x51";
RtlCreateUserThread;
}
set allocator "NtMapViewOfSection";
}
Stager URIs and checksum8
checksum8 URIs are used for payload staging and used in Cobalt Strike shellcode stagers for retrieving the final Beacon payload from the Team Server.
Note
Metasploit also uses checksum8, it exists in Cobalt Strike to be compatible with Metasploit.
The following checksum8 values are used by Cobalt Strike:
checksum8 |
architecture |
---|---|
92 |
beacon x86 |
93 |
beacon x64 |
To calculate the checksum8 of an URI:
In [42]: from dissect.cobaltstrike import utils
In [43]: utils.checksum8("/rLEZ")
Out[43]: 93
In [44]: utils.is_stager_x64("/rLEZ")
Out[44]: True
In [45]: utils.is_stager_x86("/yearbook")
Out[45]: True
To easily generate valid Cobalt Strike stager URIs,
use utils.random_stager_uri
:
In [46]: from dissect.cobaltstrike import utils
In [47]: utils.random_stager_uri(x64=True)
Out[47]: '/J6sj'
In [48]: utils.random_stager_uri(length=30)
Out[48]: '/Wt1tX8Yk2ZryVJUl1Ovpw2uIMaWxC3'
Or, a fun script to check a dictionary or word list for valid stager x86 words:
import sys
from dissect.cobaltstrike import utils
for line in sys.stdin:
line = line.strip().lower()
if utils.is_stager_x86(line):
print(line)
$ cat /usr/share/dict/words | python is_stager_x86.py | head -n 10
abortive
abshenry
accommodative
acosmism
acquirer
acroaesthesia
adance
adiposis
adoptive
adulator