Source code for dissect.cobaltstrike.c_c2

"""
Structure definitions and classes for dealing with Cobalt Strike C2 packets.
Mainly used by :mod:`dissect.cobaltstrike.c2`.
"""
from enum import IntEnum

from dissect import cstruct


[docs] class BeaconCommand(IntEnum):
[docs] COMMAND_SPAWN = 1
[docs] COMMAND_SHELL = 2
[docs] COMMAND_DIE = 3
[docs] COMMAND_SLEEP = 4
[docs] COMMAND_CD = 5
[docs] COMMAND_KEYLOG_START = 6
[docs] COMMAND_NOOP = 6
[docs] COMMAND_KEYLOG_STOP = 7
[docs] COMMAND_CHECKIN = 8
[docs] COMMAND_INJECT_PID = 9
[docs] COMMAND_UPLOAD = 10
[docs] COMMAND_DOWNLOAD = 11
[docs] COMMAND_EXECUTE = 12
[docs] COMMAND_SPAWN_PROC_X86 = 13
[docs] COMMAND_CONNECT = 14
[docs] COMMAND_SEND = 15
[docs] COMMAND_CLOSE = 16
[docs] COMMAND_LISTEN = 17
[docs] COMMAND_INJECT_PING = 18
[docs] COMMAND_CANCEL_DOWNLOAD = 19
[docs] COMMAND_PIPE_ROUTE = 22
[docs] COMMAND_PIPE_CLOSE = 23
[docs] COMMAND_PIPE_REOPEN = 24
[docs] COMMAND_TOKEN_GETUID = 27
[docs] COMMAND_TOKEN_REV2SELF = 28
[docs] COMMAND_TIMESTOMP = 29
[docs] COMMAND_STEAL_TOKEN = 31
[docs] COMMAND_PS_LIST = 32
[docs] COMMAND_PS_KILL = 33
[docs] COMMAND_PSH_IMPORT = 37
[docs] COMMAND_RUNAS = 38
[docs] COMMAND_PWD = 39
[docs] COMMAND_JOB_REGISTER = 40
[docs] COMMAND_JOBS = 41
[docs] COMMAND_JOB_KILL = 42
[docs] COMMAND_INJECTX64_PID = 43
[docs] COMMAND_SPAWNX64 = 44
[docs] COMMAND_INJECT_PID_PING = 45
[docs] COMMAND_INJECTX64_PID_PING = 46
[docs] COMMAND_PAUSE = 47
[docs] COMMAND_LOGINUSER = 49
[docs] COMMAND_LSOCKET_BIND = 50
[docs] COMMAND_LSOCKET_CLOSE = 51
[docs] COMMAND_STAGE_PAYLOAD = 52
[docs] COMMAND_FILE_LIST = 53
[docs] COMMAND_FILE_MKDIR = 54
[docs] COMMAND_FILE_DRIVES = 55
[docs] COMMAND_FILE_RM = 56
[docs] COMMAND_STAGE_PAYLOAD_SMB = 57
[docs] COMMAND_WEBSERVER_LOCAL = 59
[docs] COMMAND_ELEVATE_PRE = 60
[docs] COMMAND_ELEVATE_POST = 61
[docs] COMMAND_JOB_REGISTER_IMPERSONATE = 62
[docs] COMMAND_SPAWN_POWERSHELLX86 = 63
[docs] COMMAND_SPAWN_POWERSHELLX64 = 64
[docs] COMMAND_INJECT_POWERSHELLX86_PID = 65
[docs] COMMAND_INJECT_POWERSHELLX64_PID = 66
[docs] COMMAND_UPLOAD_CONTINUE = 67
[docs] COMMAND_PIPE_OPEN_EXPLICIT = 68
[docs] COMMAND_SPAWN_PROC_X64 = 69
[docs] COMMAND_JOB_SPAWN_X86 = 70
[docs] COMMAND_JOB_SPAWN_X64 = 71
[docs] COMMAND_SETENV = 72
[docs] COMMAND_FILE_COPY = 73
[docs] COMMAND_FILE_MOVE = 74
[docs] COMMAND_PPID = 75
[docs] COMMAND_RUN_UNDER_PID = 76
[docs] COMMAND_GETPRIVS = 77
[docs] COMMAND_EXECUTE_JOB = 78
[docs] COMMAND_PSH_HOST_TCP = 79
[docs] COMMAND_DLL_LOAD = 80
[docs] COMMAND_REG_QUERY = 81
[docs] COMMAND_LSOCKET_TCPPIVOT = 82
[docs] COMMAND_ARGUE_ADD = 83
[docs] COMMAND_ARGUE_REMOVE = 84
[docs] COMMAND_ARGUE_LIST = 85
[docs] COMMAND_TCP_CONNECT = 86
[docs] COMMAND_JOB_SPAWN_TOKEN_X86 = 87
[docs] COMMAND_JOB_SPAWN_TOKEN_X64 = 88
[docs] COMMAND_SPAWN_TOKEN_X86 = 89
[docs] COMMAND_SPAWN_TOKEN_X64 = 90
[docs] COMMAND_INJECTX64_PING = 91
[docs] COMMAND_BLOCKDLLS = 92
[docs] COMMAND_SPAWNAS_X86 = 93
[docs] COMMAND_SPAWNAS_X64 = 94
[docs] COMMAND_INLINE_EXECUTE = 95
[docs] COMMAND_RUN_INJECT_X86 = 96
[docs] COMMAND_RUN_INJECT_X64 = 97
[docs] COMMAND_SPAWNU_X86 = 98
[docs] COMMAND_SPAWNU_X64 = 99
[docs] COMMAND_INLINE_EXECUTE_OBJECT = 100
[docs] COMMAND_JOB_REGISTER_MSGMODE = 101
[docs] COMMAND_LSOCKET_BIND_LOCALHOST = 102
[docs] class BeaconCallback(IntEnum):
[docs] CALLBACK_OUTPUT = 0
[docs] CALLBACK_KEYSTROKES = 1
[docs] CALLBACK_FILE = 2
[docs] CALLBACK_SCREENSHOT = 3
[docs] CALLBACK_CLOSE = 4
[docs] CALLBACK_READ = 5
[docs] CALLBACK_CONNECT = 6
[docs] CALLBACK_PING = 7
[docs] CALLBACK_FILE_WRITE = 8
[docs] CALLBACK_FILE_CLOSE = 9
[docs] CALLBACK_PIPE_OPEN = 10
[docs] CALLBACK_PIPE_CLOSE = 11
[docs] CALLBACK_PIPE_READ = 12
[docs] CALLBACK_POST_ERROR = 13
[docs] CALLBACK_PIPE_PING = 14
[docs] CALLBACK_TOKEN_STOLEN = 15
[docs] CALLBACK_TOKEN_GETUID = 16
[docs] CALLBACK_PROCESS_LIST = 17
[docs] CALLBACK_POST_REPLAY_ERROR = 18
[docs] CALLBACK_PWD = 19
[docs] CALLBACK_JOBS = 20
[docs] CALLBACK_HASHDUMP = 21
[docs] CALLBACK_PENDING = 22
[docs] CALLBACK_ACCEPT = 23
[docs] CALLBACK_NETVIEW = 24
[docs] CALLBACK_PORTSCAN = 25
[docs] CALLBACK_DEAD = 26
[docs] CALLBACK_SSH_STATUS = 27
[docs] CALLBACK_CHUNK_ALLOCATE = 28
[docs] CALLBACK_CHUNK_SEND = 29
[docs] CALLBACK_OUTPUT_OEM = 30
[docs] CALLBACK_ERROR = 31
[docs] CALLBACK_OUTPUT_UTF8 = 32
[docs] C2_DEF = """ // Callback data from: Beacon -> Team Server typedef struct CallbackPacket { uint32 counter; uint32 size; BeaconCallback callback; char data[size]; }; // Task from: Team Server -> Beacon typedef struct TaskPacket { uint32 epoch; uint32 total_size; BeaconCommand command; uint32 size; char data[size]; }; struct BeaconMetadata { uint32 magic; uint32 size; char aes_rand[16]; uint16 ansi_cp; // GetACP uint16 oem_cp; // GetOEMCP uint32 bid; uint32 pid; uint16 port; uint8 flag; uint8 ver_major; uint8 ver_minor; uint16 ver_build; uint32 ptr_x64; // for x64 addressing uint32 ptr_gmh; // GetModuleHandle uint32 ptr_gpa; // GetProcAddress uint32 ip; char info[size - 51]; }; """
[docs] c2struct = cstruct.cstruct(endian=">")
[docs] def typedef_for_enum(enum_class: IntEnum, int_type: str = "uint32") -> str: """Return C compatible typedef string for `enum_class`.""" header = f"typedef enum {enum_class.__name__} : {int_type} {{" defs = (f" {e.name} = {e.value}," for e in enum_class) footer = "};" return "\n".join([header, *defs, footer])
c2struct.load(typedef_for_enum(BeaconCommand)) c2struct.load(typedef_for_enum(BeaconCallback)) c2struct.load(C2_DEF) # Some wrapper classes for some dissect.cstruct structs, mainly so we can use `isinstance()`
[docs] class BeaconMetadata(cstruct.Instance):
[docs] magic: int
[docs] size: int
[docs] aes_rand: bytes
[docs] ansi_cp: int
[docs] oem_cp: int
[docs] bid: int
[docs] pid: int
[docs] port: int
[docs] flag: int
[docs] ver_major: int
[docs] ver_minor: int
[docs] ver_build: int
[docs] ptr_x64: int
[docs] ptr_gmh: int
[docs] ptr_gpa: int
[docs] ip: int
[docs] info: bytes
def __init__(self, *args, **kwargs): instance = c2struct.BeaconMetadata(*args, **kwargs) super().__init__(instance._type, instance._values, instance._sizes)
[docs] def __eq__(self, other): return self._values == other._values
[docs] def __hash__(self): return hash(tuple(self._values.items()))
[docs] class CallbackPacket(cstruct.Instance):
[docs] counter: int
[docs] size: int
[docs] callback: BeaconCallback
[docs] data: bytes
def __init__(self, *args, **kwargs): instance = c2struct.CallbackPacket(*args, **kwargs) super().__init__(instance._type, instance._values, instance._sizes)
[docs] def __eq__(self, other): return self._values == other._values
[docs] def __hash__(self): return hash(tuple(self._values.items()))
[docs] class TaskPacket(cstruct.Instance):
[docs] epoch: int
[docs] total_size: int
[docs] command: BeaconCommand
[docs] size: int
[docs] data: bytes
def __init__(self, *args, **kwargs): instance = c2struct.TaskPacket(*args, **kwargs) super().__init__(instance._type, instance._values, instance._sizes)
[docs] def __eq__(self, other): return self._values == other._values
[docs] def __hash__(self): return hash(tuple(self._values.items()))