dissect.cobaltstrike 1.2.1.dev5__tar.gz → 1.2.1.dev7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/PKG-INFO +6 -2
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/README.rst +5 -1
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/_version.py +2 -2
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/beacon.py +90 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/c2profile.lark +31 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/c2profile.py +49 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/installation.rst +13 -4
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tutorials/decrypt_cobaltstrike_pcaps.rst +1 -1
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tutorials/minimal_beacon_client.rst +1 -1
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/tests/test_c2profile.py +57 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/.github/workflows/dissect-ci.yml +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/.gitignore +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/.lfs-assets-id +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/.pre-commit-config.yaml +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/.readthedocs.yml +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/LICENSE +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/codecov.yml +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/__init__.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/artifact.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/c2.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/c_c2.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/client.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/pcap.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/pe.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/utils.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/version.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/xordecode.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/Makefile +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/c2profile-grammar.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/codespell-ignore-words.txt +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/conf.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/examples.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/images/beacon-client.png +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/images/teamserver-echoclient.png +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/images/teamserver_ls.png +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/images/vt-cobaltstrike-43-zip.png +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/index.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/license.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/scripts/checksum8-accesslogs.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/scripts/dump_beacon_keys.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/scripts/example_client.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/scripts/index.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/structures/c2_def.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/structures/cs_def.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/structures/index.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/structures/pe_def.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/beacon-artifact.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/beacon-client.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/beacon-dump.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/beacon-pcap.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/beacon-xordecode.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/c2profile-dump.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tutorials/index.rst +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/pyproject.toml +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/scripts/checksum8-accesslogs.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/scripts/dump_beacon_keys.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/scripts/example_client.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/tests/conftest.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/tests/test_beacon.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/tests/test_c2.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/tests/test_client.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/tests/test_pe.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/tests/test_utils.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/tests/test_version.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/tests/test_xordecode.py +0 -0
- {dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dissect.cobaltstrike
|
|
3
|
-
Version: 1.2.1.
|
|
3
|
+
Version: 1.2.1.dev7
|
|
4
4
|
Summary: a Python library for dissecting Cobalt Strike related data
|
|
5
5
|
Project-URL: Homepage, https://github.com/fox-it/dissect.cobaltstrike
|
|
6
6
|
Project-URL: Documentation, https://dissect-cobaltstrike.readthedocs.io/
|
|
@@ -93,7 +93,11 @@ The library is available on `PyPI <https://pypi.org/project/dissect.cobaltstrike
|
|
|
93
93
|
|
|
94
94
|
Or install using the ``full`` extra to automatically install dependencies for C2 and PCAP support::
|
|
95
95
|
|
|
96
|
-
$ pip install dissect.cobaltstrike[full]
|
|
96
|
+
$ pip install 'dissect.cobaltstrike[full]'
|
|
97
|
+
|
|
98
|
+
If you want to install the latest pre-release version, use the ``--pre`` flag::
|
|
99
|
+
|
|
100
|
+
$ pip install --pre dissect.cobaltstrike
|
|
97
101
|
|
|
98
102
|
**dissect.cobaltstrike** requires Python 3.9 or later.
|
|
99
103
|
|
|
@@ -21,7 +21,11 @@ The library is available on `PyPI <https://pypi.org/project/dissect.cobaltstrike
|
|
|
21
21
|
|
|
22
22
|
Or install using the ``full`` extra to automatically install dependencies for C2 and PCAP support::
|
|
23
23
|
|
|
24
|
-
$ pip install dissect.cobaltstrike[full]
|
|
24
|
+
$ pip install 'dissect.cobaltstrike[full]'
|
|
25
|
+
|
|
26
|
+
If you want to install the latest pre-release version, use the ``--pre`` flag::
|
|
27
|
+
|
|
28
|
+
$ pip install --pre dissect.cobaltstrike
|
|
25
29
|
|
|
26
30
|
**dissect.cobaltstrike** requires Python 3.9 or later.
|
|
27
31
|
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/_version.py
RENAMED
|
@@ -12,5 +12,5 @@ __version__: str
|
|
|
12
12
|
__version_tuple__: VERSION_TUPLE
|
|
13
13
|
version_tuple: VERSION_TUPLE
|
|
14
14
|
|
|
15
|
-
__version__ = version = '1.2.1.
|
|
16
|
-
__version_tuple__ = version_tuple = (1, 2, 1, '
|
|
15
|
+
__version__ = version = '1.2.1.dev7'
|
|
16
|
+
__version_tuple__ = version_tuple = (1, 2, 1, 'dev7')
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/beacon.py
RENAMED
|
@@ -170,6 +170,12 @@ enum BeaconSetting: uint16 {
|
|
|
170
170
|
|
|
171
171
|
// CobaltStrike version >= 4.7 (Aug 17, 2022)
|
|
172
172
|
SETTING_MASKED_WATERMARK = 74,
|
|
173
|
+
|
|
174
|
+
// CobaltStrike version >= 4.9 (Sep 19, 2023)
|
|
175
|
+
SETTING_DATA_STORE_SIZE = 76,
|
|
176
|
+
|
|
177
|
+
// CobaltStrike version >= 4.10 (Jul 16, 2024)
|
|
178
|
+
SETTING_BEACON_GATE = 78,
|
|
173
179
|
};
|
|
174
180
|
|
|
175
181
|
enum DeprecatedBeaconSetting: uint16 {
|
|
@@ -253,6 +259,33 @@ enum BofAllocator: uint16 {
|
|
|
253
259
|
MapViewOfFile = 1,
|
|
254
260
|
HeapAlloc = 2,
|
|
255
261
|
};
|
|
262
|
+
|
|
263
|
+
// https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/beacon-gate.htm
|
|
264
|
+
struct BeaconGateOptions {
|
|
265
|
+
uint8 InternetOpenA; // commms
|
|
266
|
+
uint8 InternetConnectA;
|
|
267
|
+
uint8 VirtualAlloc; // core
|
|
268
|
+
uint8 VirtualAllocEx;
|
|
269
|
+
uint8 VirtualProtect;
|
|
270
|
+
uint8 VirtualProtectEx;
|
|
271
|
+
uint8 VirtualFree;
|
|
272
|
+
uint8 GetThreadContext;
|
|
273
|
+
uint8 SetThreadContext;
|
|
274
|
+
uint8 ResumeThread;
|
|
275
|
+
uint8 CreateThread;
|
|
276
|
+
uint8 CreateRemoteThread;
|
|
277
|
+
uint8 OpenProcess;
|
|
278
|
+
uint8 OpenThread;
|
|
279
|
+
uint8 CloseHandle;
|
|
280
|
+
uint8 CreateFileMappingA;
|
|
281
|
+
uint8 MapViewOfFile;
|
|
282
|
+
uint8 UnmapViewOfFile;
|
|
283
|
+
uint8 VirtualQuery;
|
|
284
|
+
uint8 DuplicateHandle;
|
|
285
|
+
uint8 ReadProcessMemory;
|
|
286
|
+
uint8 WriteProcessMemory;
|
|
287
|
+
uint8 ExitThread; // cleanup
|
|
288
|
+
};
|
|
256
289
|
"""
|
|
257
290
|
|
|
258
291
|
cs_struct = cstruct.cstruct(endian=">")
|
|
@@ -269,6 +302,7 @@ ProxyServer = cs_struct.ProxyServer
|
|
|
269
302
|
InjectAllocator = cs_struct.InjectAllocator
|
|
270
303
|
InjectExecutor = cs_struct.InjectExecutor
|
|
271
304
|
BofAllocator = cs_struct.BofAllocator
|
|
305
|
+
BeaconGateOptions = cs_struct.BeaconGateOptions
|
|
272
306
|
|
|
273
307
|
DEFAULT_XOR_KEYS: List[bytes] = [b"\x69", b"\x2e", b"\x00"]
|
|
274
308
|
""" Default XOR keys used by Cobalt Strike for obfuscating Beacon config bytes """
|
|
@@ -581,6 +615,61 @@ def parse_pivot_frame(data: bytes) -> bytes:
|
|
|
581
615
|
return p.read(length - 4)
|
|
582
616
|
|
|
583
617
|
|
|
618
|
+
def parse_beacon_gate(data: bytes) -> BeaconGateOptions:
|
|
619
|
+
"""Parse ``SETTING_BEACON_GATE`` (`.stage.beacon_gate`) data"""
|
|
620
|
+
return BeaconGateOptions(data)
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
def beacon_gate_options_string(bgo: BeaconGateOptions) -> list[str]:
|
|
624
|
+
"""Return the enabled BeaconGate WinAPI's as a list of strings"""
|
|
625
|
+
options = {k for k, v in bgo._values.items() if v}
|
|
626
|
+
|
|
627
|
+
comms = {"InternetOpenA", "InternetConnectA"}
|
|
628
|
+
core = {
|
|
629
|
+
"VirtualAlloc",
|
|
630
|
+
"VirtualAllocEx",
|
|
631
|
+
"VirtualProtect",
|
|
632
|
+
"VirtualProtectEx",
|
|
633
|
+
"VirtualFree",
|
|
634
|
+
"GetThreadContext",
|
|
635
|
+
"SetThreadContext",
|
|
636
|
+
"ResumeThread",
|
|
637
|
+
"CreateThread",
|
|
638
|
+
"CreateRemoteThread",
|
|
639
|
+
"OpenProcess",
|
|
640
|
+
"OpenThread",
|
|
641
|
+
"CloseHandle",
|
|
642
|
+
"CreateFileMappingA",
|
|
643
|
+
"MapViewOfFile",
|
|
644
|
+
"UnmapViewOfFile",
|
|
645
|
+
"VirtualQuery",
|
|
646
|
+
"DuplicateHandle",
|
|
647
|
+
"ReadProcessMemory",
|
|
648
|
+
"WriteProcessMemory",
|
|
649
|
+
}
|
|
650
|
+
cleanup = {"ExitThread"}
|
|
651
|
+
|
|
652
|
+
ret = []
|
|
653
|
+
if options.issuperset(comms | core | cleanup):
|
|
654
|
+
ret.append("All")
|
|
655
|
+
options -= comms | core | cleanup
|
|
656
|
+
|
|
657
|
+
if options.issuperset(comms):
|
|
658
|
+
ret.append("Comms")
|
|
659
|
+
options -= comms
|
|
660
|
+
|
|
661
|
+
if options.issuperset(core):
|
|
662
|
+
ret.append("Core")
|
|
663
|
+
options -= core
|
|
664
|
+
|
|
665
|
+
if options.issuperset(cleanup):
|
|
666
|
+
ret.append("Cleanup")
|
|
667
|
+
options -= cleanup
|
|
668
|
+
|
|
669
|
+
ret.extend(options)
|
|
670
|
+
return ret
|
|
671
|
+
|
|
672
|
+
|
|
584
673
|
def sha256sum_pubkey(der_data: bytes) -> str:
|
|
585
674
|
"""Return the SHA-256 digest of `der_data`"""
|
|
586
675
|
return hashlib.sha256(der_data.rstrip(b"\x00")).hexdigest()
|
|
@@ -643,6 +732,7 @@ SETTING_TO_PRETTYFUNC: Dict[BeaconSetting, Callable] = {
|
|
|
643
732
|
BeaconSetting.SETTING_WATERMARKHASH: lambda x: null_terminated_bytes(x) if isinstance(x, bytes) else x,
|
|
644
733
|
BeaconSetting.SETTING_MASKED_WATERMARK: lambda x: x.hex(),
|
|
645
734
|
BeaconSetting.SETTING_BOF_ALLOCATOR: lambda x: BofAllocator(x).name,
|
|
735
|
+
BeaconSetting.SETTING_BEACON_GATE: lambda x: beacon_gate_options_string(parse_beacon_gate(x)),
|
|
646
736
|
# BeaconSetting.SETTING_PROTOCOL: lambda x: BeaconProtocol(x).name,
|
|
647
737
|
# BeaconSetting.SETTING_CRYPTO_SCHEME: lambda x: CryptoScheme(x).name,
|
|
648
738
|
# BeaconSetting.SETTING_PROXY_BEHAVIOR: lambda x: ProxyServer(x).name,
|
|
@@ -137,6 +137,8 @@ stage_options: "string" string ";" -> string
|
|
|
137
137
|
| "set" "rich_header" string ";" -> rich_header
|
|
138
138
|
| "set" "checksum" string ";" -> checksum
|
|
139
139
|
| "set" "syscall_method" string ";" -> syscall_method // introduced in Cobalt Strike 4.8
|
|
140
|
+
| "set" "data_store_size" string ";" -> data_store_size // introduced in Cobalt Strike 4.9
|
|
141
|
+
| "beacon_gate" "{" beacon_gate_options* "}" -> beacon_gate // introduced in Cobalt Strike 4.10
|
|
140
142
|
|
|
141
143
|
process_inject_options: "set" "allocator" string ";" -> allocator
|
|
142
144
|
| "set" "min_alloc" string ";" -> min_alloc
|
|
@@ -158,6 +160,35 @@ execute_options: "CreateThread" string ";" -> createthread_special
|
|
|
158
160
|
| "RtlCreateUserThread" ";" -> rtlcreateuserthread
|
|
159
161
|
| "SetThreadContext" ";" -> setthreadcontext
|
|
160
162
|
|
|
163
|
+
beacon_gate_options: "None" ";" -> none
|
|
164
|
+
| "Comms" ";" -> comms
|
|
165
|
+
| "Core" ";" -> core
|
|
166
|
+
| "Cleanup" ";" -> cleanup
|
|
167
|
+
| "All" ";" -> all
|
|
168
|
+
| "InternetOpenA" ";" -> internetopena
|
|
169
|
+
| "InternetConnectA" ";" -> internetconnecta
|
|
170
|
+
| "VirtualAlloc" ";" -> virtualalloc
|
|
171
|
+
| "VirtualAllocEx" ";" -> virtualallocex
|
|
172
|
+
| "VirtualProtect" ";" -> virtualprotect
|
|
173
|
+
| "VirtualProtectEx" ";" -> virtualprotextex
|
|
174
|
+
| "VirtualFree" ";" -> virtualfree
|
|
175
|
+
| "GetThreadContext" ";" -> getthreadcontext
|
|
176
|
+
| "SetThreadContext" ";" -> setthreadcontext
|
|
177
|
+
| "ResumeThread" ";" -> resumethread
|
|
178
|
+
| "CreateThread" ";" -> createthread
|
|
179
|
+
| "CreateRemoteThread" ";" -> createremotethread
|
|
180
|
+
| "OpenProcess" ";" -> openprocess
|
|
181
|
+
| "OpenThread" ";" -> openthread
|
|
182
|
+
| "CloseHandle" ";" -> closehandle
|
|
183
|
+
| "CreateFileMappingA" ";" -> createfilemappinga
|
|
184
|
+
| "MapViewOfFile" ";" -> mapviewoffile
|
|
185
|
+
| "UnmapViewOfFile" ";" -> unmapviewoffile
|
|
186
|
+
| "VirtualQuery" ";" -> virtualquery
|
|
187
|
+
| "DuplicateHandle" ";" -> duplicatehandle
|
|
188
|
+
| "ReadProcessMemory" ";" -> readprocessmemory
|
|
189
|
+
| "WriteProcessMemory" ";" -> writeprocessmemory
|
|
190
|
+
| "ExitThread" ";" -> exitthread
|
|
191
|
+
|
|
161
192
|
postex_options: "set" "spawnto_x86" string ";" -> spawnto_x86
|
|
162
193
|
| "set" "spawnto_x64" string ";" -> spawnto_x64
|
|
163
194
|
| "set" "obfuscate" string ";" -> obfuscate
|
|
@@ -350,6 +350,50 @@ class ExecuteOptionsBlock(ConfigBlock):
|
|
|
350
350
|
return block
|
|
351
351
|
|
|
352
352
|
|
|
353
|
+
class BeaconGateBlock(ConfigBlock):
|
|
354
|
+
"""`.stage.beacon_gate` block"""
|
|
355
|
+
|
|
356
|
+
__name__ = "BeaconGateBlock"
|
|
357
|
+
|
|
358
|
+
none = ConfigBlock._enable
|
|
359
|
+
comms = ConfigBlock._enable
|
|
360
|
+
core = ConfigBlock._enable
|
|
361
|
+
cleanup = ConfigBlock._enable
|
|
362
|
+
all = ConfigBlock._enable
|
|
363
|
+
internetopena = ConfigBlock._enable
|
|
364
|
+
internetconnecta = ConfigBlock._enable
|
|
365
|
+
virtualalloc = ConfigBlock._enable
|
|
366
|
+
virtualallocex = ConfigBlock._enable
|
|
367
|
+
virtualprotect = ConfigBlock._enable
|
|
368
|
+
virtualprotextex = ConfigBlock._enable
|
|
369
|
+
virtualfree = ConfigBlock._enable
|
|
370
|
+
getthreadcontext = ConfigBlock._enable
|
|
371
|
+
setthreadcontext = ConfigBlock._enable
|
|
372
|
+
resumethread = ConfigBlock._enable
|
|
373
|
+
createthread = ConfigBlock._enable
|
|
374
|
+
createremotethread = ConfigBlock._enable
|
|
375
|
+
openprocess = ConfigBlock._enable
|
|
376
|
+
openthread = ConfigBlock._enable
|
|
377
|
+
closehandle = ConfigBlock._enable
|
|
378
|
+
createfilemappinga = ConfigBlock._enable
|
|
379
|
+
mapviewoffile = ConfigBlock._enable
|
|
380
|
+
unmapviewoffile = ConfigBlock._enable
|
|
381
|
+
virtualquery = ConfigBlock._enable
|
|
382
|
+
duplicatehandle = ConfigBlock._enable
|
|
383
|
+
readprocessmemory = ConfigBlock._enable
|
|
384
|
+
writeprocessmemory = ConfigBlock._enable
|
|
385
|
+
exitthread = ConfigBlock._enable
|
|
386
|
+
|
|
387
|
+
@classmethod
|
|
388
|
+
def from_beacon_gate_option_strings(cls, options: list[str]):
|
|
389
|
+
block = cls()
|
|
390
|
+
|
|
391
|
+
for option in options:
|
|
392
|
+
block._enable(option.lower(), True)
|
|
393
|
+
|
|
394
|
+
return block
|
|
395
|
+
|
|
396
|
+
|
|
353
397
|
class C2Profile(ConfigBlock):
|
|
354
398
|
"""A :class:`C2Profile` object represents a parsed Malleable C2 Profile
|
|
355
399
|
|
|
@@ -622,6 +666,11 @@ class C2Profile(ConfigBlock):
|
|
|
622
666
|
proc_inj.set_option("bof_reuse_memory", "true")
|
|
623
667
|
elif setting == BeaconSetting.SETTING_BOF_ALLOCATOR:
|
|
624
668
|
proc_inj.set_option("bof_allocator", value)
|
|
669
|
+
elif setting == BeaconSetting.SETTING_DATA_STORE_SIZE:
|
|
670
|
+
stage.set_option("data_store_size", value)
|
|
671
|
+
elif setting == BeaconSetting.SETTING_BEACON_GATE and value:
|
|
672
|
+
block = BeaconGateBlock.from_beacon_gate_option_strings(value)
|
|
673
|
+
stage.set_config_block("beacon_gate", block)
|
|
625
674
|
|
|
626
675
|
if c2_recover:
|
|
627
676
|
http_get.set_non_empty_config_block("server", HttpOptionsBlock(output=DataTransformBlock(steps=c2_recover)))
|
|
@@ -19,14 +19,23 @@ The following pip `extras` flavours are provided as well:
|
|
|
19
19
|
|
|
20
20
|
.. code-block:: bash
|
|
21
21
|
|
|
22
|
-
$ pip install dissect.cobaltstrike[c2]
|
|
23
|
-
$ pip install dissect.cobaltstrike[pcap]
|
|
24
|
-
$ pip install dissect.cobaltstrike[full]
|
|
22
|
+
$ pip install 'dissect.cobaltstrike[c2]'
|
|
23
|
+
$ pip install 'dissect.cobaltstrike[pcap]'
|
|
24
|
+
$ pip install 'dissect.cobaltstrike[full]'
|
|
25
25
|
|
|
26
26
|
* ``[c2]`` for if you want to communicate with Cobalt Strike Team Servers, eg: :doc:`tools/beacon-client`.
|
|
27
27
|
* ``[pcap]`` for if you want to parse and decrypt PCAPS containing Beacon traffic, eg: :doc:`tools/beacon-pcap`.
|
|
28
28
|
* ``[full]`` provides the above but also installs ``rich`` for prettier console logging.
|
|
29
29
|
|
|
30
|
+
Install the latest pre-release version
|
|
31
|
+
--------------------------------------
|
|
32
|
+
|
|
33
|
+
Every change to the main branch is packaged and uploaded to PyPi as a pre-release version, to install the latest pre-release version use the ``--pre`` flag:
|
|
34
|
+
|
|
35
|
+
.. code-block:: bash
|
|
36
|
+
|
|
37
|
+
$ pip install --pre dissect.cobaltstrike
|
|
38
|
+
|
|
30
39
|
Installing from source
|
|
31
40
|
----------------------
|
|
32
41
|
|
|
@@ -36,7 +45,7 @@ If you want to install ``dissect.cobaltstrike`` from source, you can use the fol
|
|
|
36
45
|
|
|
37
46
|
$ git clone https://github.com/fox-it/dissect.cobaltstrike.git
|
|
38
47
|
$ cd dissect.cobaltstrike
|
|
39
|
-
$ pip install --editable .[full]
|
|
48
|
+
$ pip install --editable '.[full]'
|
|
40
49
|
|
|
41
50
|
Using a virtual environment is recommended. Using the ``--editable`` flag ensures that any changes you make to the source code directly affects the installed package.
|
|
42
51
|
|
|
@@ -26,7 +26,7 @@ First we ensure that we have ``dissect.cobaltstrike`` installed with PCAP suppor
|
|
|
26
26
|
|
|
27
27
|
.. code-block:: bash
|
|
28
28
|
|
|
29
|
-
$ pip install dissect.cobaltstrike[pcap]
|
|
29
|
+
$ pip install 'dissect.cobaltstrike[pcap]'
|
|
30
30
|
|
|
31
31
|
This also installs the ``pyshark`` Python package but it still requires the ``tshark`` binary from Wireshark_ to work.
|
|
32
32
|
Ensure that you have Wireshark_ installed or install the ``tshark`` binary, for example on Ubuntu or Debian systems you can install it with:
|
|
@@ -26,7 +26,7 @@ First we install ``dissect.cobaltstrike`` with the ``[c2]`` extra, as we are goi
|
|
|
26
26
|
|
|
27
27
|
.. code-block:: bash
|
|
28
28
|
|
|
29
|
-
$ pip install dissect.cobaltstrike[c2]
|
|
29
|
+
$ pip install 'dissect.cobaltstrike[c2]'
|
|
30
30
|
|
|
31
31
|
This installs the necessary dependencies such as `PyCryptodome` and `httpx`.
|
|
32
32
|
|
|
@@ -298,6 +298,39 @@ def test_c2profile_v48():
|
|
|
298
298
|
assert profile.properties["stage.syscall_method"] == ["direct"]
|
|
299
299
|
|
|
300
300
|
|
|
301
|
+
def test_c2profile_v49():
|
|
302
|
+
c2profile_fragment = """
|
|
303
|
+
stage {
|
|
304
|
+
set data_store_size "1024";
|
|
305
|
+
}
|
|
306
|
+
"""
|
|
307
|
+
profile = c2profile.C2Profile.from_text(c2profile_fragment)
|
|
308
|
+
assert profile.properties["stage.data_store_size"] == ["1024"]
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def test_c2profile_v410():
|
|
312
|
+
c2profile_fragment = """
|
|
313
|
+
stage {
|
|
314
|
+
beacon_gate {
|
|
315
|
+
All;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
"""
|
|
319
|
+
profile = c2profile.C2Profile.from_text(c2profile_fragment)
|
|
320
|
+
assert profile.properties["stage.beacon_gate"] == ["All"]
|
|
321
|
+
|
|
322
|
+
c2profile_fragment = """
|
|
323
|
+
stage {
|
|
324
|
+
beacon_gate {
|
|
325
|
+
VirtualAlloc;
|
|
326
|
+
WriteProcessMemory;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
"""
|
|
330
|
+
profile = c2profile.C2Profile.from_text(c2profile_fragment)
|
|
331
|
+
assert profile.properties["stage.beacon_gate"] == ["VirtualAlloc", "WriteProcessMemory"]
|
|
332
|
+
|
|
333
|
+
|
|
301
334
|
@pytest.mark.parametrize(
|
|
302
335
|
("allocator_enum", "bof_allocator"),
|
|
303
336
|
[
|
|
@@ -338,3 +371,27 @@ def test_c2profile_bof_reuse_memory(bof_reuse_memory):
|
|
|
338
371
|
assert profile.properties["process-inject.bof_reuse_memory"] == ["true"]
|
|
339
372
|
else:
|
|
340
373
|
assert "project.inject.bof_reuse_memory" not in profile.properties
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def test_c2profile_beacon_gate():
|
|
377
|
+
# beacon gate with all options
|
|
378
|
+
data = beacon.Setting(
|
|
379
|
+
index=beacon.BeaconSetting.SETTING_BEACON_GATE,
|
|
380
|
+
type=beacon.SettingsType.TYPE_PTR,
|
|
381
|
+
length=0x40,
|
|
382
|
+
value=b"\x01" * 0x40,
|
|
383
|
+
).dumps()
|
|
384
|
+
bconfig = beacon.BeaconConfig(data)
|
|
385
|
+
profile = c2profile.C2Profile.from_beacon_config(bconfig)
|
|
386
|
+
assert profile.properties["stage.beacon_gate"] == ["All"]
|
|
387
|
+
|
|
388
|
+
# empty beacon gate should not result into any profile setting
|
|
389
|
+
data = beacon.Setting(
|
|
390
|
+
index=beacon.BeaconSetting.SETTING_BEACON_GATE,
|
|
391
|
+
type=beacon.SettingsType.TYPE_PTR,
|
|
392
|
+
length=0x40,
|
|
393
|
+
value=b"\x00" * 0x40,
|
|
394
|
+
).dumps()
|
|
395
|
+
bconfig = beacon.BeaconConfig(data)
|
|
396
|
+
profile = c2profile.C2Profile.from_beacon_config(bconfig)
|
|
397
|
+
assert "stage.beacon_gate" not in profile.properties
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/.github/workflows/dissect-ci.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/__init__.py
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/artifact.py
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/c2.py
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/c_c2.py
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/client.py
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/pcap.py
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/pe.py
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/utils.py
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/dissect/cobaltstrike/version.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/c2profile-grammar.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/codespell-ignore-words.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/images/beacon-client.png
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/images/teamserver_ls.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/scripts/example_client.rst
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/structures/c2_def.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/structures/cs_def.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/structures/index.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/structures/pe_def.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/beacon-artifact.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/beacon-client.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/beacon-dump.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/beacon-pcap.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/beacon-xordecode.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tools/c2profile-dump.rst
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/docs/tutorials/index.rst
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/scripts/checksum8-accesslogs.py
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/scripts/dump_beacon_keys.py
RENAMED
|
File without changes
|
{dissect_cobaltstrike-1.2.1.dev5 → dissect_cobaltstrike-1.2.1.dev7}/scripts/example_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|