From ab91f993a52e916e2d1f9a88aa74b4e3bb661ccc Mon Sep 17 00:00:00 2001 From: Archer Bowen Date: Fri, 9 Aug 2024 12:45:15 +0100 Subject: [PATCH] #2689 Initial Implementation of multi-port listeners. --- src/primaite/game/agent/actions.py | 4 +- .../Command-&-Control-E2E-Demonstration.ipynb | 130 ++++++++++++++++++ .../red_applications/c2/abstract_c2.py | 5 +- 3 files changed, 134 insertions(+), 5 deletions(-) diff --git a/src/primaite/game/agent/actions.py b/src/primaite/game/agent/actions.py index 5f045ccb..92b175a9 100644 --- a/src/primaite/game/agent/actions.py +++ b/src/primaite/game/agent/actions.py @@ -1107,8 +1107,8 @@ class ConfigureC2BeaconAction(AbstractAction): config = ConfigureC2BeaconAction._Opts( c2_server_ip_address=config["c2_server_ip_address"], keep_alive_frequency=config["keep_alive_frequency"], - masquerade_port=config["masquerade_protocol"], - masquerade_protocol=config["masquerade_port"], + masquerade_port=config["masquerade_port"], + masquerade_protocol=config["masquerade_protocol"], ) ConfigureC2BeaconAction._Opts.model_validate(config) # check that options adhere to schema diff --git a/src/primaite/notebooks/Command-&-Control-E2E-Demonstration.ipynb b/src/primaite/notebooks/Command-&-Control-E2E-Demonstration.ipynb index 10077cd4..bbe29cd6 100644 --- a/src/primaite/notebooks/Command-&-Control-E2E-Demonstration.ipynb +++ b/src/primaite/notebooks/Command-&-Control-E2E-Demonstration.ipynb @@ -133,6 +133,15 @@ " action: C2_SERVER_RANSOMWARE_LAUNCH\n", " options:\n", " node_id: 1\n", + " 7:\n", + " action: CONFIGURE_C2_BEACON\n", + " options:\n", + " node_id: 0\n", + " config:\n", + " c2_server_ip_address: 192.168.10.21\n", + " keep_alive_frequency: 10\n", + " masquerade_protocol: TCP\n", + " masquerade_port: DNS\n", "\n", "\n", "\n", @@ -1045,6 +1054,127 @@ "source": [ "display_obs_diffs(pre_blue_action_obs, post_blue_action_obs, blue_env.game.step_counter)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Command and Control** | C2 Beacon Actions\n", + "\n", + "Before any C2 Server commands is able to accept any commands, it must first establish connection with a C2 beacon.\n", + "\n", + "This can be done by installing, configuring and then executing a C2 Beacon. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Command and Control** | Configurability \n", + "\n", + "TODO: Fleshout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open(data_manipulation_config_path()) as f:\n", + " cfg = yaml.safe_load(f)\n", + " # removing all agents & adding the custom agent.\n", + " cfg['agents'] = {}\n", + " cfg['agents'] = c2_agent_yaml\n", + " \n", + "\n", + "c2_config_env = PrimaiteGymEnv(env_config=cfg)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Installing the C2 Server" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "client_1: Computer = c2_config_env.game.simulation.network.get_node_by_hostname(\"client_1\")\n", + "client_1.software_manager.install(C2Server)\n", + "c2_server: C2Server = client_1.software_manager.software[\"C2Server\"]\n", + "c2_server.run()\n", + "client_1.software_manager.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Installing the C2 Beacon via NODE_APPLICATION_INSTALL" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "c2_config_env.step(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Configuring the C2 Beacon using different parameters:\n", + "\n", + "``` yaml\n", + " action: CONFIGURE_C2_BEACON\n", + " options:\n", + " node_id: 0\n", + " config:\n", + " c2_server_ip_address: 192.168.10.21\n", + " keep_alive_frequency: 10\n", + " masquerade_protocol: TCP\n", + " masquerade_port: DNS\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "c2_config_env.step(7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Establishing connection to the C2 Server.\n", + "c2_config_env.step(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "web_server: Server = c2_config_env.game.simulation.network.get_node_by_hostname(\"web_server\")\n", + "c2_beacon: C2Beacon = web_server.software_manager.software[\"C2Beacon\"]\n", + "c2_beacon.show()\n", + "c2_server.show()" + ] } ], "metadata": { diff --git a/src/primaite/simulator/system/applications/red_applications/c2/abstract_c2.py b/src/primaite/simulator/system/applications/red_applications/c2/abstract_c2.py index 47944633..c7b0d32c 100644 --- a/src/primaite/simulator/system/applications/red_applications/c2/abstract_c2.py +++ b/src/primaite/simulator/system/applications/red_applications/c2/abstract_c2.py @@ -87,11 +87,10 @@ class AbstractC2(Application, identifier="AbstractC2"): """ return super().describe_state() - # TODO: Update this post application/services requiring to listen to multiple ports def __init__(self, **kwargs): """Initialise the C2 applications to by default listen for HTTP traffic.""" kwargs["listen_on_ports"] = {Port.HTTP, Port.FTP, Port.DNS} - kwargs["port"] = Port.HTTP + kwargs["port"] = Port.NONE kwargs["protocol"] = IPProtocol.TCP super().__init__(**kwargs) @@ -242,7 +241,7 @@ class AbstractC2(Application, identifier="AbstractC2"): ) return False - # Setting the Ports + # Setting the masquerade_port/protocol attribute: self.current_masquerade_port = payload.masquerade_port self.current_masquerade_protocol = payload.masquerade_protocol