Skip to content

Commit

Permalink
Add support for SETTING_HTTP_DATA_REQUIRED beacon setting (#71)
Browse files Browse the repository at this point in the history
Introduced in Cobalt Strike 4.10
  • Loading branch information
yunzheng authored Oct 15, 2024
1 parent dcb009d commit a532957
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 0 deletions.
1 change: 1 addition & 0 deletions dissect/cobaltstrike/beacon.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@
SETTING_DATA_STORE_SIZE = 76,
// CobaltStrike version >= 4.10 (Jul 16, 2024)
SETTING_HTTP_DATA_REQUIRED = 77,
SETTING_BEACON_GATE = 78,
};
Expand Down
5 changes: 5 additions & 0 deletions dissect/cobaltstrike/c2profile.lark
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ start: value*
| "process-inject" "{" process_inject_options* "}" -> process_inject
| "post-ex" "{" postex_options* "}" -> post_ex
| "dns-beacon" "{" dns_beacon_options* "}" -> dns_beacon
| "http-beacon" "{" http_beacon_options* "}" -> http_beacon

OPTION: "sample_name"
| "data_jitter"
Expand Down Expand Up @@ -214,6 +215,10 @@ dns_beacon_options: "set" "dns_idle" string ";" -> dns_idle
| "set" "ns_response" string ";" -> ns_response
| "#" "dns_resolver" string ";" -> comment_dns_resolver

http_beacon_options: "set" "library" string ";" -> library // introduced in Cobalt Strike 4.9
| "set" "data_required" string ";" -> data_required // introduced in Cobalt Strike 4.10
| "set" "data_required_length" string ";" -> data_required_length // introduced in Cobalt Strike 4.10

header: string
string: STRING
variant: string
Expand Down
10 changes: 10 additions & 0 deletions dissect/cobaltstrike/c2profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,12 @@ class DnsBeaconBlock(ConfigBlock):
__name__ = "dns_beacon"


class HttpBeaconBlock(ConfigBlock):
"""`.http-beacon` block"""

__name__ = "http_beacon"


class ExecuteOptionsBlock(ConfigBlock):
"""`.process-inject.execute` block"""

Expand Down Expand Up @@ -446,6 +452,7 @@ def from_beacon_config(cls, config: BeaconConfig) -> "C2Profile":
http_post_client = HttpOptionsBlock()
proc_inj = ProcessInjectBlock()
dns_beacon = DnsBeaconBlock()
http_beacon = HttpBeaconBlock()
# http_get_server = HttpOptionsBlock()

for setting, value in config.settings_by_index.items():
Expand Down Expand Up @@ -668,6 +675,8 @@ def from_beacon_config(cls, config: BeaconConfig) -> "C2Profile":
proc_inj.set_option("bof_allocator", value)
elif setting == BeaconSetting.SETTING_DATA_STORE_SIZE:
stage.set_option("data_store_size", value)
elif setting == BeaconSetting.SETTING_HTTP_DATA_REQUIRED and value:
http_beacon.set_option("data_required", "true")
elif setting == BeaconSetting.SETTING_BEACON_GATE and value:
block = BeaconGateBlock.from_beacon_gate_option_strings(value)
stage.set_config_block("beacon_gate", block)
Expand All @@ -681,6 +690,7 @@ def from_beacon_config(cls, config: BeaconConfig) -> "C2Profile":
profile.set_non_empty_config_block("stage", stage)
profile.set_non_empty_config_block("process_inject", proc_inj)
profile.set_non_empty_config_block("dns_beacon", dns_beacon)
profile.set_non_empty_config_block("http_beacon", http_beacon)
return profile

def __str__(self) -> str:
Expand Down
22 changes: 22 additions & 0 deletions tests/test_c2profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,25 @@ def test_c2profile_beacon_gate():
bconfig = beacon.BeaconConfig(data)
profile = c2profile.C2Profile.from_beacon_config(bconfig)
assert "stage.beacon_gate" not in profile.properties


@pytest.mark.parametrize(
("http_data_required",),
[
(True,),
(False,),
],
)
def test_c2profile_http_data_required(http_data_required: bool):
data = beacon.Setting(
index=beacon.BeaconSetting.SETTING_HTTP_DATA_REQUIRED,
type=beacon.SettingsType.TYPE_SHORT,
length=0x2,
value=beacon.cs_struct.uint16(http_data_required).dumps(),
).dumps()
bconfig = beacon.BeaconConfig(data)
profile = c2profile.C2Profile.from_beacon_config(bconfig)
if not http_data_required:
assert "http-beacon.data_required" not in profile.properties
else:
assert profile.properties["http-beacon.data_required"] == ["true"]

0 comments on commit a532957

Please sign in to comment.