From 7fe4915f4280c4431ac83dcc1255fe6fb8707174 Mon Sep 17 00:00:00 2001 From: Charlie Crane Date: Wed, 26 Feb 2025 15:31:03 +0000 Subject: [PATCH] Revisions to make the how-to guides show in navigation pane --- .pre-commit-config.yaml | 12 +- docs/index.rst | 12 + docs/source/how_to.rst | 10 + docs/source/how_to_guides/custom_actions.rst | 12 +- .../how_to_guides/custom_environments.rst | 6 +- docs/source/how_to_guides/custom_software.rst | 2 +- .../how_to_guides/extensible_actions.rst | 3 +- ...ommand-and-Control-E2E-Demonstration.ipynb | 1780 +++++++++++++++-- ...ege-Escalation-and-Data-Loss-Example.ipynb | 407 +++- 9 files changed, 2045 insertions(+), 199 deletions(-) create mode 100644 docs/source/how_to.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d004dd6c..4100f8b2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,10 +1,10 @@ repos: - # - repo: local - # hooks: - # - id: ensure-copyright-clause - # name: ensure copyright clause - # entry: python copyright_clause_pre_commit_hook.py - # language: python + - repo: local + hooks: + - id: ensure-copyright-clause + name: ensure copyright clause + entry: python copyright_clause_pre_commit_hook.py + language: python - repo: http://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: diff --git a/docs/index.rst b/docs/index.rst index aa7d16e0..53d2e1b3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -17,6 +17,18 @@ What is PrimAITE? source/dependencies source/glossary +.. toctree:: + :maxdepth: 8 + :caption: How To + :hidden: + + source/how_to + source/how_to_guides/custom_actions + source/how_to_guides/custom_environments + source/how_to_guides/custom_rewards + source/how_to_guides/custom_software + source/how_to_guides/using_dev_cli + .. toctree:: :caption: Usage: :hidden: diff --git a/docs/source/how_to.rst b/docs/source/how_to.rst new file mode 100644 index 00000000..e6ea0d10 --- /dev/null +++ b/docs/source/how_to.rst @@ -0,0 +1,10 @@ +.. only:: comment + + © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK + +How-To Guides +============= + +These how-to guides aim to provide a starting point for development within PrimAITE, creating your own custom components and environments for use when training agents. More detailed information for each section can be found within the documentation. + +There are also some additional notebooks which provide a walkthrough of established content. It's encouraged to reference these when developing for PrimAITE. diff --git a/docs/source/how_to_guides/custom_actions.rst b/docs/source/how_to_guides/custom_actions.rst index ae865b3d..4b51e76a 100644 --- a/docs/source/how_to_guides/custom_actions.rst +++ b/docs/source/how_to_guides/custom_actions.rst @@ -7,13 +7,15 @@ Creating Custom Actions in PrimAITE *********************************** -PrimAITE contains a selection of available actions that can be exercised within a training session, listed within ``actions.py``. `Note`: Agents are only able to perform the actions listed within it's action_map, defined within it's configuration YAML. See :ref:`custom_environment` for more information. +PrimAITE contains a selection of possible actions that can be exercised within a training environment. Actions provided as a part of PrimAITE can be seen within `src/primaite/game/agent/actions`. `Note`: Agents are only able to perform the actions listed within it's action_map, defined within it's configuration YAML. See :ref:`custom_environment` for more information. Developing Custom Actions -============================ +========================= Actions within PrimAITE follow a default format, as seen below and in ``actions.py``. It's important that they have an identifier when declared, as this is used when creating the training environment. +An example of a custom action is seen below, with key information about what is required for new actions in :ref:`extensible_actions`. + .. code:: Python class ExampleActionClass(AbstractAction, identifier="ExampleActions"): @@ -24,7 +26,7 @@ Actions within PrimAITE follow a default format, as seen below and in ``actions. class ConfigSchema(AbstractAction.ConfigSchema) node_name: str - + @classmethod def form_request(cls, config: ConfigSchema) -> RequestFormat: return [config.node_name, "example_action"] @@ -36,9 +38,9 @@ Any custom actions should then be added to the `ActionManager` class, and the `a Interaction with the PrimAITE Request Manager -============================================== +============================================= -Where an action would cause a request to be sent through the PrimAITE RequestManager, a `form_request` method is expected to be defined within the Action Class. This should format the action into a format that can be ingested by the `RequestManager`. Examples of this include the `NodeFolderCreateAction`, which sends a formed request to create a folder on a given node (seen below). +Where an action would cause a request to be sent through the PrimAITE RequestManager, a `form_request` method is expected to be defined within the Action Class. This should format the action into a format that can be ingested by the `RequestManager`. Examples of this include the `NodeFolderCreateAction`, which sends a formed request to create a folder on a given node (seen below): .. code:: Python diff --git a/docs/source/how_to_guides/custom_environments.rst b/docs/source/how_to_guides/custom_environments.rst index 928fc101..23c70d85 100644 --- a/docs/source/how_to_guides/custom_environments.rst +++ b/docs/source/how_to_guides/custom_environments.rst @@ -25,7 +25,9 @@ You configuration file should follow the hierarchy seen below: simulation: ... +MetaData Tag +============ + It's important to include the metadata tag within your YAML file, as this is used to ensure PrimAITE can interpret the configuration correctly. This should also include any plugins that are required for the defined environment, along with their respective version. -For detailed information about each configuration item found within the configuration file, see :ref:`Configurable Items`. - +For detailed information about the remaining configuration items found within the configuration file, see :ref:`Configurable Items`. diff --git a/docs/source/how_to_guides/custom_software.rst b/docs/source/how_to_guides/custom_software.rst index fa0671d7..e10bcf1f 100644 --- a/docs/source/how_to_guides/custom_software.rst +++ b/docs/source/how_to_guides/custom_software.rst @@ -12,7 +12,7 @@ This page aims to provide a how-to guide on how to create your own custom softwa PrimAITE has a base software class which should be inherited from when building custom software. Examples of this can be seen in the ``IOSoftware`` and ``Process`` classes. It's important that any new software created within PrimAITE has the ``identifier`` attribute defined, for use when generating the environment. -Some default attributes may need to be adjusted to align with the intended application of the custom software. +Some default attributes may need to be adjusted to align with the intended application of the custom software. .. code:: Python diff --git a/docs/source/how_to_guides/extensible_actions.rst b/docs/source/how_to_guides/extensible_actions.rst index 4a7ed35c..fe61949b 100644 --- a/docs/source/how_to_guides/extensible_actions.rst +++ b/docs/source/how_to_guides/extensible_actions.rst @@ -7,7 +7,6 @@ Extensible Actions ****************** - Changes to Actions class Structure. =================================== @@ -33,7 +32,7 @@ The ConfigSchema sub-class of the action must contain all `configurable` variabl Unique discriminator -################# +#################### When declaring a custom class, it must have a unique discriminator string, that allows PrimAITE to generate the correct action when needed. diff --git a/src/primaite/notebooks/Command-and-Control-E2E-Demonstration.ipynb b/src/primaite/notebooks/Command-and-Control-E2E-Demonstration.ipynb index 7e64c3c5..9f4923df 100644 --- a/src/primaite/notebooks/Command-and-Control-E2E-Demonstration.ipynb +++ b/src/primaite/notebooks/Command-and-Control-E2E-Demonstration.ipynb @@ -13,9 +13,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 12:09:23,996: Performing the PrimAITE first-time setup...\n", + "2025-02-26 12:09:23,996: Building the PrimAITE app directories...\n", + "2025-02-26 12:09:23,996: Building primaite_config.yaml...\n", + "2025-02-26 12:09:23,996: Rebuilding the demo notebooks...\n", + "2025-02-26 12:09:24,029: Rebuilding the example notebooks...\n", + "2025-02-26 12:09:24,029: PrimAITE setup complete!\n" + ] + } + ], "source": [ "!primaite setup" ] @@ -36,7 +49,8 @@ "from primaite.simulator.system.applications.red_applications.c2.abstract_c2 import C2Command\n", "from primaite.simulator.system.applications.red_applications.ransomware_script import RansomwareScript\n", "from primaite.simulator.network.hardware.nodes.host.computer import Computer\n", - "from primaite.simulator.network.hardware.nodes.host.server import Server" + "from primaite.simulator.network.hardware.nodes.host.server import Server\n", + "from primaite.game.agent.interface import ProxyAgent" ] }, { @@ -52,7 +66,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -138,9 +152,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 12:09:31,270: PrimaiteGymEnv RNG seed = None\n" + ] + } + ], "source": [ "with open(data_manipulation_config_path()) as f:\n", " cfg = yaml.safe_load(f)\n", @@ -166,9 +188,35 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------------------------------------------------------------------------------+\n", + "| client_1 Software Manager |\n", + "+-----------------------+-------------+-----------------+--------------+------+----------+\n", + "| Name | Type | Operating State | Health State | Port | Protocol |\n", + "+-----------------------+-------------+-----------------+--------------+------+----------+\n", + "| arp | Service | RUNNING | GOOD | 219 | udp |\n", + "| icmp | Service | RUNNING | GOOD | None | icmp |\n", + "| dns-client | Service | RUNNING | GOOD | 53 | tcp |\n", + "| ntp-client | Service | RUNNING | GOOD | 123 | udp |\n", + "| web-browser | Application | RUNNING | GOOD | 80 | tcp |\n", + "| nmap | Application | RUNNING | GOOD | None | none |\n", + "| user-session-manager | Service | RUNNING | GOOD | None | none |\n", + "| user-manager | Service | RUNNING | GOOD | None | none |\n", + "| terminal | Service | RUNNING | GOOD | 22 | tcp |\n", + "| ftp-client | Service | RUNNING | GOOD | 21 | tcp |\n", + "| data-manipulation-bot | Application | RUNNING | GOOD | None | none |\n", + "| database-client | Application | RUNNING | GOOD | 5432 | tcp |\n", + "| c2-server | Application | RUNNING | GOOD | None | tcp |\n", + "+-----------------------+-------------+-----------------+--------------+------+----------+\n" + ] + } + ], "source": [ "client_1: Computer = env.game.simulation.network.get_node_by_hostname(\"client_1\")\n", "client_1.software_manager.install(C2Server)\n", @@ -218,9 +266,34 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+---------------------------------------------------------------------------------------+\n", + "| web_server Software Manager |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "| Name | Type | Operating State | Health State | Port | Protocol |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "| arp | Service | RUNNING | GOOD | 219 | udp |\n", + "| icmp | Service | RUNNING | GOOD | None | icmp |\n", + "| dns-client | Service | RUNNING | GOOD | 53 | tcp |\n", + "| ntp-client | Service | RUNNING | GOOD | 123 | udp |\n", + "| web-browser | Application | RUNNING | GOOD | 80 | tcp |\n", + "| nmap | Application | RUNNING | GOOD | None | none |\n", + "| user-session-manager | Service | RUNNING | GOOD | None | none |\n", + "| user-manager | Service | RUNNING | GOOD | None | none |\n", + "| terminal | Service | RUNNING | GOOD | 22 | tcp |\n", + "| web-server | Service | RUNNING | GOOD | 80 | tcp |\n", + "| database-client | Application | RUNNING | GOOD | 5432 | tcp |\n", + "| c2-beacon | Application | INSTALLING | GOOD | None | tcp |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n" + ] + } + ], "source": [ "env.step(1)\n", "web_server: Computer = env.game.simulation.network.get_node_by_hostname(\"web_server\")\n", @@ -255,9 +328,41 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+---------------------------------------------------------------------------------------+\n", + "| web_server Software Manager |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "| Name | Type | Operating State | Health State | Port | Protocol |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "| arp | Service | RUNNING | GOOD | 219 | udp |\n", + "| icmp | Service | RUNNING | GOOD | None | icmp |\n", + "| dns-client | Service | RUNNING | GOOD | 53 | tcp |\n", + "| ntp-client | Service | RUNNING | GOOD | 123 | udp |\n", + "| web-browser | Application | RUNNING | GOOD | 80 | tcp |\n", + "| nmap | Application | RUNNING | GOOD | None | none |\n", + "| user-session-manager | Service | RUNNING | GOOD | None | none |\n", + "| user-manager | Service | RUNNING | GOOD | None | none |\n", + "| terminal | Service | RUNNING | GOOD | 22 | tcp |\n", + "| web-server | Service | RUNNING | GOOD | 80 | tcp |\n", + "| database-client | Application | RUNNING | GOOD | 5432 | tcp |\n", + "| c2-beacon | Application | RUNNING | GOOD | None | tcp |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "+----------------------------------------------------------------------------------------------------------------------------------------------------+\n", + "| c2-beacon Running Status |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Keep Alive Inactivity | Keep Alive Frequency | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| False | 192.168.10.21 | 0 | 5 | tcp | 80 |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n" + ] + } + ], "source": [ "env.step(2)\n", "c2_beacon: C2Beacon = web_server.software_manager.software[\"c2-beacon\"]\n", @@ -288,18 +393,54 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(0,\n", + " 0.0,\n", + " False,\n", + " False,\n", + " {'agent_actions': {'CustomC2Agent': AgentHistoryItem(timestep=2, action='node-application-execute', parameters={'node_name': 'web_server', 'application_name': 'c2-beacon'}, request=['network', 'node', 'web_server', 'application', 'c2-beacon', 'execute'], response=RequestResponse(status='success', data={}), reward=0.0, reward_info={})}})" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "env.step(3)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------------------------------------------------------------------------------------------------------------------------------------------+\n", + "| c2-beacon Running Status |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Keep Alive Inactivity | Keep Alive Frequency | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| True | 192.168.10.21 | 1 | 5 | tcp | 80 |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "+-----------------------------------------------------------------------------------------------------+\n", + "| c2-server Running Status |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n", + "| True | 192.168.1.12 | tcp | 80 |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n" + ] + } + ], "source": [ "c2_beacon.show()\n", "c2_server.show()" @@ -354,18 +495,59 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(0,\n", + " 0.0,\n", + " False,\n", + " False,\n", + " {'agent_actions': {'CustomC2Agent': AgentHistoryItem(timestep=3, action='c2-server-terminal-command', parameters={'node_name': 'client_1', 'ip_address': None, 'username': 'admin', 'password': 'admin', 'commands': [['software_manager', 'application', 'install', 'ransomware-script']]}, request=['network', 'node', 'client_1', 'application', 'c2-server', 'terminal_command', {'commands': [['software_manager', 'application', 'install', 'ransomware-script']], 'ip_address': None, 'username': 'admin', 'password': 'admin'}], response=RequestResponse(status='success', data={0: RequestResponse(status='success', data={})}), reward=0.0, reward_info={})}})" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "env.step(4)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------------------------------------------------------------------------------+\n", + "| client_1 Software Manager |\n", + "+-----------------------+-------------+-----------------+--------------+------+----------+\n", + "| Name | Type | Operating State | Health State | Port | Protocol |\n", + "+-----------------------+-------------+-----------------+--------------+------+----------+\n", + "| arp | Service | RUNNING | GOOD | 219 | udp |\n", + "| icmp | Service | RUNNING | GOOD | None | icmp |\n", + "| dns-client | Service | RUNNING | GOOD | 53 | tcp |\n", + "| ntp-client | Service | RUNNING | GOOD | 123 | udp |\n", + "| web-browser | Application | RUNNING | GOOD | 80 | tcp |\n", + "| nmap | Application | RUNNING | GOOD | None | none |\n", + "| user-session-manager | Service | RUNNING | GOOD | None | none |\n", + "| user-manager | Service | RUNNING | GOOD | None | none |\n", + "| terminal | Service | RUNNING | GOOD | 22 | tcp |\n", + "| ftp-client | Service | RUNNING | GOOD | 21 | tcp |\n", + "| data-manipulation-bot | Application | RUNNING | GOOD | None | none |\n", + "| database-client | Application | RUNNING | GOOD | 5432 | tcp |\n", + "| c2-server | Application | RUNNING | GOOD | None | tcp |\n", + "+-----------------------+-------------+-----------------+--------------+------+----------+\n" + ] + } + ], "source": [ "client_1.software_manager.show()" ] @@ -396,18 +578,66 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(0,\n", + " 0.0,\n", + " False,\n", + " False,\n", + " {'agent_actions': {'CustomC2Agent': AgentHistoryItem(timestep=4, action='c2-server-ransomware-configure', parameters={'node_name': 'client_1', 'server_ip_address': '192.168.1.14', 'payload': 'ENCRYPT'}, request=['network', 'node', 'client_1', 'application', 'c2-server', 'ransomware_configure', {'server_ip_address': '192.168.1.14', 'server_password': None, 'payload': 'ENCRYPT'}], response=RequestResponse(status='success', data={}), reward=0.0, reward_info={})}})" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "env.step(5)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+---------------------------------------------------------------------------------------+\n", + "| web_server Software Manager |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "| Name | Type | Operating State | Health State | Port | Protocol |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "| arp | Service | RUNNING | GOOD | 219 | udp |\n", + "| icmp | Service | RUNNING | GOOD | None | icmp |\n", + "| dns-client | Service | RUNNING | GOOD | 53 | tcp |\n", + "| ntp-client | Service | RUNNING | GOOD | 123 | udp |\n", + "| web-browser | Application | RUNNING | GOOD | 80 | tcp |\n", + "| nmap | Application | RUNNING | GOOD | None | none |\n", + "| user-session-manager | Service | RUNNING | GOOD | None | none |\n", + "| user-manager | Service | RUNNING | GOOD | None | none |\n", + "| terminal | Service | RUNNING | GOOD | 22 | tcp |\n", + "| web-server | Service | RUNNING | GOOD | 80 | tcp |\n", + "| database-client | Application | RUNNING | GOOD | 5432 | tcp |\n", + "| c2-beacon | Application | RUNNING | GOOD | None | tcp |\n", + "| ransomware-script | Application | RUNNING | GOOD | None | none |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "+------------------------------------+\n", + "| ransomware-script Running Status |\n", + "+--------------------------+---------+\n", + "| Target Server IP Address | Payload |\n", + "+--------------------------+---------+\n", + "| 192.168.1.14 | ENCRYPT |\n", + "+--------------------------+---------+\n" + ] + } + ], "source": [ "ransomware_script: RansomwareScript = web_server.software_manager.software[\"ransomware-script\"]\n", "web_server.software_manager.show()\n", @@ -445,18 +675,48 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(0,\n", + " 0.0,\n", + " False,\n", + " False,\n", + " {'agent_actions': {'CustomC2Agent': AgentHistoryItem(timestep=5, action='c2-server-data-exfiltrate', parameters={'node_name': 'client_1', 'target_file_name': 'database.db', 'target_folder_name': 'database', 'exfiltration_folder_name': 'spoils', 'target_ip_address': '192.168.1.14', 'username': 'admin', 'password': 'admin'}, request=['network', 'node', 'client_1', 'application', 'c2-server', 'exfiltrate', {'target_file_name': 'database.db', 'target_folder_name': 'database', 'exfiltration_folder_name': 'spoils', 'target_ip_address': '192.168.1.14', 'username': 'admin', 'password': 'admin'}], response=RequestResponse(status='success', data={}), reward=0.0, reward_info={})}})" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "env.step(6)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+--------------------------------------------------------------------------------+\n", + "| client_1 File System |\n", + "+--------------------+---------+---------------+-----------------------+---------+\n", + "| File Path | Size | Health status | Visible health status | Deleted |\n", + "+--------------------+---------+---------------+-----------------------+---------+\n", + "| root | 0 B | GOOD | NONE | False |\n", + "| spoils/database.db | 4.77 MB | GOOD | NONE | False |\n", + "+--------------------+---------+---------------+-----------------------+---------+\n" + ] + } + ], "source": [ "client_1: Computer = env.game.simulation.network.get_node_by_hostname(\"client_1\")\n", "client_1.software_manager.file_system.show(full=True)" @@ -464,9 +724,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+---------------------------------------------------------------------------------+\n", + "| web_server File System |\n", + "+---------------------+---------+---------------+-----------------------+---------+\n", + "| File Path | Size | Health status | Visible health status | Deleted |\n", + "+---------------------+---------+---------------+-----------------------+---------+\n", + "| primaite/index.html | 15.0 KB | GOOD | NONE | False |\n", + "| root | 0 B | GOOD | NONE | False |\n", + "| spoils/database.db | 4.77 MB | GOOD | NONE | False |\n", + "+---------------------+---------+---------------+-----------------------+---------+\n" + ] + } + ], "source": [ "web_server: Computer = env.game.simulation.network.get_node_by_hostname(\"web_server\")\n", "web_server.software_manager.file_system.show(full=True)" @@ -496,18 +772,48 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(0,\n", + " 0.0,\n", + " False,\n", + " False,\n", + " {'agent_actions': {'CustomC2Agent': AgentHistoryItem(timestep=6, action='c2-server-ransomware-launch', parameters={'node_name': 'client_1'}, request=['network', 'node', 'client_1', 'application', 'c2-server', 'ransomware_launch'], response=RequestResponse(status='success', data={}), reward=0.0, reward_info={})}})" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "env.step(7)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------------------------------------------------------------------------+\n", + "| database_server File System |\n", + "+----------------------+---------+---------------+-----------------------+---------+\n", + "| File Path | Size | Health status | Visible health status | Deleted |\n", + "+----------------------+---------+---------------+-----------------------+---------+\n", + "| database/database.db | 4.77 MB | CORRUPT | NONE | False |\n", + "| root | 0 B | GOOD | NONE | False |\n", + "+----------------------+---------+---------------+-----------------------+---------+\n" + ] + } + ], "source": [ "database_server: Server = env.game.simulation.network.get_node_by_hostname(\"database_server\")\n", "database_server.software_manager.file_system.show(full=True)" @@ -526,7 +832,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ @@ -654,9 +960,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 12:09:32,087: PrimaiteGymEnv RNG seed = None\n" + ] + } + ], "source": [ "with open(data_manipulation_config_path()) as f:\n", " cfg = yaml.safe_load(f)\n", @@ -670,7 +984,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ @@ -713,9 +1027,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 12:09:32,894: Resetting environment, episode 0, avg. reward: 0.0\n", + "2025-02-26 12:09:32,898: Saving agent action log to C:\\Users\\CharlieCrane\\primaite\\4.0.0a1-dev\\sessions\\2025-02-26\\12-09-25\\agent_actions\\episode_0.json\n" + ] + } + ], "source": [ "# Resetting the environment and capturing the default observation space.\n", "blue_env.reset()\n", @@ -724,9 +1047,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Setting up the C2 Suite via the simulation API.\n", "\n", @@ -747,7 +1081,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": {}, "outputs": [], "source": [ @@ -757,9 +1091,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 2\n", + "root['nodes']['HOST0']['APPLICATIONS'][1]['operating_status']: 0 -> 1\n", + "root['nodes']['HOST1']['NICS'][1]['TRAFFIC']['tcp'][21]['inbound']: 1 -> 0\n", + "root['nodes']['HOST1']['NICS'][1]['TRAFFIC']['tcp'][21]['outbound']: 4 -> 0\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 1 -> 0\n", + "root['LINKS'][5]['PROTOCOLS']['ALL']: 4 -> 0\n", + "root['LINKS'][6]['PROTOCOLS']['ALL']: 4 -> 0\n" + ] + } + ], "source": [ "display_obs_diffs(default_obs, c2_configuration_obs, blue_env.game.step_counter)" ] @@ -779,9 +1130,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={0: RequestResponse(status='success', data={})})" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Installing RansomwareScript via C2 Terminal Commands\n", "ransomware_install_command = {\"commands\":[[\"software_manager\", \"application\", \"install\", \"ransomware-script\"]],\n", @@ -792,9 +1154,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={})" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Configuring the RansomwareScript\n", "ransomware_config = {\"server_ip_address\": \"192.168.1.14\", \"payload\": \"ENCRYPT\"}\n", @@ -803,7 +1176,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -813,9 +1186,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 29, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 7\n", + "root['nodes']['HOST0']['APPLICATIONS'][1]['operating_status']: 0 -> 1\n", + "root['nodes']['HOST0']['APPLICATIONS'][2]['operating_status']: 0 -> 3\n", + "root['nodes']['HOST0']['users']['local_login']: 0 -> 1\n", + "root['nodes']['HOST1']['NICS'][1]['TRAFFIC']['tcp'][21]['inbound']: 1 -> 0\n", + "root['nodes']['HOST1']['NICS'][1]['TRAFFIC']['tcp'][21]['outbound']: 4 -> 0\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 1 -> 0\n", + "root['LINKS'][5]['PROTOCOLS']['ALL']: 4 -> 0\n", + "root['LINKS'][6]['PROTOCOLS']['ALL']: 4 -> 0\n" + ] + } + ], "source": [ "display_obs_diffs(default_obs, c2_ransomware_obs, env.game.step_counter)" ] @@ -831,7 +1223,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 30, "metadata": {}, "outputs": [], "source": [ @@ -847,16 +1239,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 31, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={})" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "c2_server.send_command(given_command=C2Command.DATA_EXFILTRATION, command_options=exfil_options)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "metadata": {}, "outputs": [], "source": [ @@ -865,9 +1268,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 33, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 7\n", + "root['nodes']['HOST0']['APPLICATIONS'][2]['operating_status']: 3 -> 1\n", + "root['nodes']['HOST1']['users']['remote_sessions']: 0 -> 1\n" + ] + } + ], "source": [ "display_obs_diffs(c2_ransomware_obs, c2_exfil_obs, env.game.step_counter)" ] @@ -883,9 +1299,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 34, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={})" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Configuring the RansomwareScript\n", "ransomware_config = {\"server_ip_address\": \"192.168.1.14\", \"payload\": \"ENCRYPT\"}\n", @@ -894,9 +1321,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={})" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Waiting for the ransomware to finish installing and then launching the RansomwareScript.\n", "blue_env.step(0)\n", @@ -905,7 +1343,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "metadata": {}, "outputs": [], "source": [ @@ -915,9 +1353,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 37, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 6\n", + "root['nodes']['HOST0']['APPLICATIONS'][2]['operating_status']: 3 -> 1\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['nodes']['HOST1']['users']['remote_sessions']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][2]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][4]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][8]['PROTOCOLS']['ALL']: 0 -> 1\n" + ] + } + ], "source": [ "display_obs_diffs(c2_ransomware_obs, c2_final_obs, blue_env.game.step_counter)" ] @@ -933,7 +1392,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "metadata": {}, "outputs": [], "source": [ @@ -965,16 +1424,200 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 12:09:33,561: Resetting environment, episode 1, avg. reward: 0.0\n", + "2025-02-26 12:09:33,561: Saving agent action log to C:\\Users\\CharlieCrane\\primaite\\4.0.0a1-dev\\sessions\\2025-02-26\\12-09-25\\agent_actions\\episode_1.json\n" + ] + }, + { + "data": { + "text/plain": [ + "({'nodes': {'HOST0': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 1,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'HOST1': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 1,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'HOST2': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 0,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'HOST3': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 0,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'ROUTER0': {'ACL': {1: {'position': 0,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 2: {'position': 1,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 3: {'position': 2,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 4: {'position': 3,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 5: {'position': 4,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 6: {'position': 5,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 7: {'position': 6,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 8: {'position': 7,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 9: {'position': 8,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 10: {'position': 9,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0}},\n", + " 'PORTS': {1: {'operating_status': 1},\n", + " 2: {'operating_status': 1},\n", + " 3: {'operating_status': 2}},\n", + " 'users': {'local_login': 0, 'remote_sessions': 0}}},\n", + " 'LINKS': {1: {'PROTOCOLS': {'ALL': 1}},\n", + " 2: {'PROTOCOLS': {'ALL': 1}},\n", + " 3: {'PROTOCOLS': {'ALL': 0}},\n", + " 4: {'PROTOCOLS': {'ALL': 1}},\n", + " 5: {'PROTOCOLS': {'ALL': 1}},\n", + " 6: {'PROTOCOLS': {'ALL': 1}},\n", + " 7: {'PROTOCOLS': {'ALL': 1}},\n", + " 8: {'PROTOCOLS': {'ALL': 1}},\n", + " 9: {'PROTOCOLS': {'ALL': 1}},\n", + " 10: {'PROTOCOLS': {'ALL': 0}}},\n", + " 'ICS': 0},\n", + " {})" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "blue_env.reset()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 40, "metadata": {}, "outputs": [], "source": [ @@ -993,7 +1636,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 41, "metadata": {}, "outputs": [], "source": [ @@ -1010,9 +1653,33 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 42, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+---------------------------------------------------------------------------------------+\n", + "| web_server Software Manager |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "| Name | Type | Operating State | Health State | Port | Protocol |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "| arp | Service | RUNNING | GOOD | 219 | udp |\n", + "| icmp | Service | RUNNING | GOOD | None | icmp |\n", + "| dns-client | Service | RUNNING | GOOD | 53 | tcp |\n", + "| ntp-client | Service | RUNNING | GOOD | 123 | udp |\n", + "| web-browser | Application | RUNNING | GOOD | 80 | tcp |\n", + "| nmap | Application | RUNNING | GOOD | None | none |\n", + "| user-session-manager | Service | RUNNING | GOOD | None | none |\n", + "| user-manager | Service | RUNNING | GOOD | None | none |\n", + "| terminal | Service | RUNNING | GOOD | 22 | tcp |\n", + "| web-server | Service | RUNNING | GOOD | 80 | tcp |\n", + "| database-client | Application | RUNNING | GOOD | 5432 | tcp |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n" + ] + } + ], "source": [ "blue_env.step(0)\n", "web_server.software_manager.show()" @@ -1020,9 +1687,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 43, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 3\n", + "root['nodes']['HOST0']['APPLICATIONS'][1]['operating_status']: 1 -> 0\n", + "root['nodes']['HOST1']['NICS'][1]['TRAFFIC']['tcp'][21]['inbound']: 1 -> 0\n", + "root['nodes']['HOST1']['NICS'][1]['TRAFFIC']['tcp'][21]['outbound']: 4 -> 0\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 1 -> 0\n", + "root['LINKS'][5]['PROTOCOLS']['ALL']: 4 -> 0\n", + "root['LINKS'][6]['PROTOCOLS']['ALL']: 4 -> 0\n" + ] + } + ], "source": [ "display_obs_diffs(pre_blue_action_obs, post_blue_action_obs, blue_env.game.step_counter)" ] @@ -1036,9 +1720,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 44, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='failure', data={'Reason': 'Command sent to the C2 Beacon but no response was ever received.'})" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Attempting to install the C2 RansomwareScript\n", "ransomware_install_command = {\"commands\":[[\"software_manager\", \"application\", \"install\", \"RansomwareScript\"]],\n", @@ -1060,16 +1755,200 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 45, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 12:09:33,856: Resetting environment, episode 2, avg. reward: 0.0\n", + "2025-02-26 12:09:33,856: Saving agent action log to C:\\Users\\CharlieCrane\\primaite\\4.0.0a1-dev\\sessions\\2025-02-26\\12-09-25\\agent_actions\\episode_2.json\n" + ] + }, + { + "data": { + "text/plain": [ + "({'nodes': {'HOST0': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 1,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'HOST1': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 1,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'HOST2': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 0,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'HOST3': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 0,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'ROUTER0': {'ACL': {1: {'position': 0,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 2: {'position': 1,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 3: {'position': 2,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 4: {'position': 3,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 5: {'position': 4,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 6: {'position': 5,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 7: {'position': 6,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 8: {'position': 7,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 9: {'position': 8,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 10: {'position': 9,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0}},\n", + " 'PORTS': {1: {'operating_status': 1},\n", + " 2: {'operating_status': 1},\n", + " 3: {'operating_status': 2}},\n", + " 'users': {'local_login': 0, 'remote_sessions': 0}}},\n", + " 'LINKS': {1: {'PROTOCOLS': {'ALL': 1}},\n", + " 2: {'PROTOCOLS': {'ALL': 1}},\n", + " 3: {'PROTOCOLS': {'ALL': 0}},\n", + " 4: {'PROTOCOLS': {'ALL': 1}},\n", + " 5: {'PROTOCOLS': {'ALL': 1}},\n", + " 6: {'PROTOCOLS': {'ALL': 1}},\n", + " 7: {'PROTOCOLS': {'ALL': 1}},\n", + " 8: {'PROTOCOLS': {'ALL': 1}},\n", + " 9: {'PROTOCOLS': {'ALL': 1}},\n", + " 10: {'PROTOCOLS': {'ALL': 0}}},\n", + " 'ICS': 0},\n", + " {})" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "blue_env.reset()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 46, "metadata": {}, "outputs": [], "source": [ @@ -1088,7 +1967,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 47, "metadata": {}, "outputs": [], "source": [ @@ -1105,9 +1984,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NodeOperatingState.SHUTTING_DOWN\n" + ] + } + ], "source": [ "web_server = blue_env.game.simulation.network.get_node_by_hostname(\"web_server\")\n", "print(web_server.operating_state)" @@ -1115,18 +2002,48 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 49, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 2\n", + "root['nodes']['HOST0']['operating_status']: 1 -> 4\n", + "root['nodes']['HOST0']['APPLICATIONS'][1]['operating_status']: 1 -> 0\n", + "root['nodes']['HOST0']['NICS'][1]['nic_status']: 1 -> 0\n", + "root['nodes']['HOST1']['NICS'][1]['TRAFFIC']['tcp'][21]['inbound']: 1 -> 0\n", + "root['nodes']['HOST1']['NICS'][1]['TRAFFIC']['tcp'][21]['outbound']: 4 -> 0\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 1 -> 0\n", + "root['LINKS'][5]['PROTOCOLS']['ALL']: 4 -> 0\n", + "root['LINKS'][6]['PROTOCOLS']['ALL']: 4 -> 0\n" + ] + } + ], "source": [ "display_obs_diffs(pre_blue_action_obs, post_blue_action_obs, blue_env.game.step_counter)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 50, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='failure', data={'Reason': 'Command sent to the C2 Beacon but no response was ever received.'})" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Attempting to install the C2 RansomwareScript\n", "ransomware_install_command = {\"commands\":[\"software_manager\", \"application\", \"install\", \"RansomwareScript\"],\n", @@ -1150,16 +2067,200 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 51, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 12:09:34,093: Resetting environment, episode 3, avg. reward: 0.0\n", + "2025-02-26 12:09:34,093: Saving agent action log to C:\\Users\\CharlieCrane\\primaite\\4.0.0a1-dev\\sessions\\2025-02-26\\12-09-25\\agent_actions\\episode_3.json\n" + ] + }, + { + "data": { + "text/plain": [ + "({'nodes': {'HOST0': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 1,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'HOST1': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 1,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'HOST2': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 0,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'HOST3': {'APPLICATIONS': {1: {'operating_status': 0,\n", + " 'health_status': 0,\n", + " 'num_executions': 0},\n", + " 2: {'operating_status': 0, 'health_status': 0, 'num_executions': 0}},\n", + " 'FOLDERS': {1: {'health_status': 0,\n", + " 'FILES': {1: {'health_status': 0, 'num_access': 0}}}},\n", + " 'NICS': {1: {'nic_status': 1,\n", + " 'TRAFFIC': {'icmp': {'inbound': 0, 'outbound': 0},\n", + " 'tcp': {80: {'inbound': 0, 'outbound': 0},\n", + " 53: {'inbound': 0, 'outbound': 0},\n", + " 21: {'inbound': 0, 'outbound': 0}}}}},\n", + " 'num_file_creations': 0,\n", + " 'num_file_deletions': 0,\n", + " 'users': {'local_login': 0, 'remote_sessions': 0},\n", + " 'operating_status': 1},\n", + " 'ROUTER0': {'ACL': {1: {'position': 0,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 2: {'position': 1,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 3: {'position': 2,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 4: {'position': 3,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 5: {'position': 4,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 6: {'position': 5,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 7: {'position': 6,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 8: {'position': 7,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 9: {'position': 8,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0},\n", + " 10: {'position': 9,\n", + " 'permission': 0,\n", + " 'source_ip_id': 0,\n", + " 'source_wildcard_id': 0,\n", + " 'source_port_id': 0,\n", + " 'dest_ip_id': 0,\n", + " 'dest_wildcard_id': 0,\n", + " 'dest_port_id': 0,\n", + " 'protocol_id': 0}},\n", + " 'PORTS': {1: {'operating_status': 1},\n", + " 2: {'operating_status': 1},\n", + " 3: {'operating_status': 2}},\n", + " 'users': {'local_login': 0, 'remote_sessions': 0}}},\n", + " 'LINKS': {1: {'PROTOCOLS': {'ALL': 1}},\n", + " 2: {'PROTOCOLS': {'ALL': 1}},\n", + " 3: {'PROTOCOLS': {'ALL': 0}},\n", + " 4: {'PROTOCOLS': {'ALL': 1}},\n", + " 5: {'PROTOCOLS': {'ALL': 1}},\n", + " 6: {'PROTOCOLS': {'ALL': 1}},\n", + " 7: {'PROTOCOLS': {'ALL': 1}},\n", + " 8: {'PROTOCOLS': {'ALL': 1}},\n", + " 9: {'PROTOCOLS': {'ALL': 1}},\n", + " 10: {'PROTOCOLS': {'ALL': 0}}},\n", + " 'ICS': 0},\n", + " {})" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "blue_env.reset()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 52, "metadata": {}, "outputs": [], "source": [ @@ -1178,7 +2279,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 53, "metadata": {}, "outputs": [], "source": [ @@ -1195,9 +2296,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 54, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+------------------------------------------------------------------------------------------------------------------------+\n", + "| router_1 Access Control List |\n", + "+-------+--------+----------+---------------+--------------+----------+--------------+--------------+----------+---------+\n", + "| Index | Action | Protocol | Src IP | Src Wildcard | Src Port | Dst IP | Dst Wildcard | Dst Port | Matched |\n", + "+-------+--------+----------+---------------+--------------+----------+--------------+--------------+----------+---------+\n", + "| 1 | DENY | ANY | 192.168.10.21 | 0.0.0.1 | 80 | 192.168.1.12 | 0.0.0.1 | 80 | 0 |\n", + "| 18 | PERMIT | ANY | ANY | ANY | 5432 | ANY | ANY | 5432 | 0 |\n", + "| 19 | PERMIT | ANY | ANY | ANY | 53 | ANY | ANY | 53 | 0 |\n", + "| 20 | PERMIT | ANY | ANY | ANY | 21 | ANY | ANY | 21 | 0 |\n", + "| 21 | PERMIT | ANY | ANY | ANY | 80 | ANY | ANY | 80 | 4 |\n", + "| 22 | PERMIT | ANY | ANY | ANY | 219 | ANY | ANY | 219 | 10 |\n", + "| 23 | PERMIT | icmp | ANY | ANY | ANY | ANY | ANY | ANY | 0 |\n", + "| 24 | DENY | ANY | ANY | ANY | ANY | ANY | ANY | ANY | 0 |\n", + "+-------+--------+----------+---------------+--------------+----------+--------------+--------------+----------+---------+\n" + ] + } + ], "source": [ "router_1: Router = blue_env.game.simulation.network.get_node_by_hostname(\"router_1\")\n", "router_1.acl.show()" @@ -1212,9 +2334,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 55, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='failure', data={'Reason': 'Command sent to the C2 Beacon but no response was ever received.'})" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "blue_env.step(0)\n", "\n", @@ -1225,9 +2358,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 56, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+------------------------------------------------------------------------------------------------------------------------+\n", + "| router_1 Access Control List |\n", + "+-------+--------+----------+---------------+--------------+----------+--------------+--------------+----------+---------+\n", + "| Index | Action | Protocol | Src IP | Src Wildcard | Src Port | Dst IP | Dst Wildcard | Dst Port | Matched |\n", + "+-------+--------+----------+---------------+--------------+----------+--------------+--------------+----------+---------+\n", + "| 1 | DENY | ANY | 192.168.10.21 | 0.0.0.1 | 80 | 192.168.1.12 | 0.0.0.1 | 80 | 2 |\n", + "| 18 | PERMIT | ANY | ANY | ANY | 5432 | ANY | ANY | 5432 | 0 |\n", + "| 19 | PERMIT | ANY | ANY | ANY | 53 | ANY | ANY | 53 | 0 |\n", + "| 20 | PERMIT | ANY | ANY | ANY | 21 | ANY | ANY | 21 | 0 |\n", + "| 21 | PERMIT | ANY | ANY | ANY | 80 | ANY | ANY | 80 | 4 |\n", + "| 22 | PERMIT | ANY | ANY | ANY | 219 | ANY | ANY | 219 | 10 |\n", + "| 23 | PERMIT | icmp | ANY | ANY | ANY | ANY | ANY | ANY | 0 |\n", + "| 24 | DENY | ANY | ANY | ANY | ANY | ANY | ANY | ANY | 0 |\n", + "+-------+--------+----------+---------------+--------------+----------+--------------+--------------+----------+---------+\n" + ] + } + ], "source": [ "router_1.acl.show()" ] @@ -1241,18 +2395,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 57, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+---------------------------------------------------------------------------------------+\n", + "| web_server Software Manager |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "| Name | Type | Operating State | Health State | Port | Protocol |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n", + "| arp | Service | RUNNING | GOOD | 219 | udp |\n", + "| icmp | Service | RUNNING | GOOD | None | icmp |\n", + "| dns-client | Service | RUNNING | GOOD | 53 | tcp |\n", + "| ntp-client | Service | RUNNING | GOOD | 123 | udp |\n", + "| web-browser | Application | RUNNING | GOOD | 80 | tcp |\n", + "| nmap | Application | RUNNING | GOOD | None | none |\n", + "| user-session-manager | Service | RUNNING | GOOD | None | none |\n", + "| user-manager | Service | RUNNING | GOOD | None | none |\n", + "| terminal | Service | RUNNING | GOOD | 22 | tcp |\n", + "| web-server | Service | RUNNING | GOOD | 80 | tcp |\n", + "| database-client | Application | RUNNING | GOOD | 5432 | tcp |\n", + "| c2-beacon | Application | RUNNING | GOOD | None | tcp |\n", + "+----------------------+-------------+-----------------+--------------+------+----------+\n" + ] + } + ], "source": [ "web_server.software_manager.show()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 58, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------------------------------------------------------------------------+\n", + "| database_server File System |\n", + "+----------------------+---------+---------------+-----------------------+---------+\n", + "| File Path | Size | Health status | Visible health status | Deleted |\n", + "+----------------------+---------+---------------+-----------------------+---------+\n", + "| database/database.db | 4.77 MB | GOOD | NONE | False |\n", + "| root | 0 B | GOOD | NONE | False |\n", + "+----------------------+---------+---------------+-----------------------+---------+\n" + ] + } + ], "source": [ "database_server: Server = blue_env.game.simulation.network.get_node_by_hostname(\"database_server\")\n", "database_server.software_manager.file_system.show(full=True)" @@ -1260,9 +2454,33 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 59, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 3\n", + "root['nodes']['HOST1']['NICS'][1]['TRAFFIC']['tcp'][21]['inbound']: 1 -> 0\n", + "root['nodes']['HOST1']['NICS'][1]['TRAFFIC']['tcp'][21]['outbound']: 4 -> 0\n", + "root['nodes']['ROUTER0']['ACL'][1]['permission']: 0 -> 2\n", + "root['nodes']['ROUTER0']['ACL'][1]['source_ip_id']: 0 -> 7\n", + "root['nodes']['ROUTER0']['ACL'][1]['source_wildcard_id']: 0 -> 2\n", + "root['nodes']['ROUTER0']['ACL'][1]['source_port_id']: 0 -> 2\n", + "root['nodes']['ROUTER0']['ACL'][1]['dest_ip_id']: 0 -> 3\n", + "root['nodes']['ROUTER0']['ACL'][1]['dest_wildcard_id']: 0 -> 2\n", + "root['nodes']['ROUTER0']['ACL'][1]['dest_port_id']: 0 -> 2\n", + "root['nodes']['ROUTER0']['ACL'][1]['protocol_id']: 0 -> 1\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 1 -> 0\n", + "root['LINKS'][5]['PROTOCOLS']['ALL']: 4 -> 0\n", + "root['LINKS'][6]['PROTOCOLS']['ALL']: 4 -> 0\n" + ] + } + ], "source": [ "display_obs_diffs(pre_blue_action_obs, post_blue_action_obs, blue_env.game.step_counter)" ] @@ -1328,9 +2546,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 60, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 12:09:34,725: PrimaiteGymEnv RNG seed = None\n" + ] + } + ], "source": [ "with open(data_manipulation_config_path()) as f:\n", " cfg = yaml.safe_load(f)\n", @@ -1351,7 +2577,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 61, "metadata": {}, "outputs": [], "source": [ @@ -1379,9 +2605,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 62, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------------------------------------------------------------------------------------------------------------------------------------------+\n", + "| c2-beacon Running Status |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Keep Alive Inactivity | Keep Alive Frequency | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| False | None | 0 | 5 | tcp | 80 |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "+-----------------------------------------------------------------------------------------------------+\n", + "| c2-server Running Status |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n", + "| False | None | tcp | 80 |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n" + ] + } + ], "source": [ "env.step(2) # Agent Action Equivalent to c2_beacon.configure(c2_server_ip_address=\"192.168.10.21\")\n", "env.step(3) # Agent action Equivalent to c2_beacon.establish()\n", @@ -1398,9 +2645,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 63, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------------------------------------------------------------------------------------------------------------------------------------------+\n", + "| c2-beacon Running Status |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Keep Alive Inactivity | Keep Alive Frequency | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| False | None | 0 | 5 | tcp | 80 |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "+-----------------------------------------------------------------------------------------------------+\n", + "| c2-server Running Status |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n", + "| False | None | tcp | 80 |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n" + ] + } + ], "source": [ "env.step(9) # Equivalent of to c2_beacon.configure(c2_server_ip_address=\"192.168.10.22\")\n", "env.step(3)\n", @@ -1418,9 +2686,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 64, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+-----------------------------------------------------------------------------------------------------+\n", + "| c2-server Running Status |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n", + "| False | None | tcp | 80 |\n", + "+----------------------+----------------------+-----------------------------+-------------------------+\n" + ] + } + ], "source": [ "for i in range(6):\n", " env.step(0)\n", @@ -1443,9 +2725,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 65, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 12:09:35,057: PrimaiteGymEnv RNG seed = None\n" + ] + } + ], "source": [ "with open(data_manipulation_config_path()) as f:\n", " cfg = yaml.safe_load(f)\n", @@ -1461,7 +2751,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 66, "metadata": {}, "outputs": [], "source": [ @@ -1485,9 +2775,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 67, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------------------------------------------------------------------------------------------------------------------------------------------+\n", + "| c2-beacon Running Status |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Keep Alive Inactivity | Keep Alive Frequency | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| True | 192.168.10.21 | 0 | 5 | tcp | 80 |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n" + ] + } + ], "source": [ "c2_beacon.configure(c2_server_ip_address=\"192.168.10.21\")\n", "c2_beacon.establish()\n", @@ -1505,9 +2809,72 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 68, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 4\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 5\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 6\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 7\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 8\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][2]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][4]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][8]['PROTOCOLS']['ALL']: 0 -> 1\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 9\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 10\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 11\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 12\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 13\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][2]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][4]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][8]['PROTOCOLS']['ALL']: 0 -> 1\n" + ] + } + ], "source": [ "for i in range(10):\n", " keep_alive_obs, _, _, _, _ = blue_config_env.step(0)\n", @@ -1523,9 +2890,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 69, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------------------------------------------------------------------------------------------------------------------------------------------+\n", + "| c2-beacon Running Status |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Keep Alive Inactivity | Keep Alive Frequency | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| True | 192.168.10.21 | 0 | 1 | tcp | 80 |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n" + ] + } + ], "source": [ "c2_beacon.configure(c2_server_ip_address=\"192.168.10.21\", keep_alive_frequency=1)\n", "c2_beacon.establish()\n", @@ -1541,9 +2922,40 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 70, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 14\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][2]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][4]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][8]['PROTOCOLS']['ALL']: 0 -> 1\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 15\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][2]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][4]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][8]['PROTOCOLS']['ALL']: 0 -> 1\n" + ] + } + ], "source": [ "# Comparing the OBS of the default frequency to a timestep frequency of 1\n", "for i in range(2):\n", @@ -1562,9 +2974,52 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 71, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 16\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 17\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 18\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 19\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 20\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 21\n", + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 22\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][2]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][4]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][8]['PROTOCOLS']['ALL']: 0 -> 1\n" + ] + } + ], "source": [ "c2_beacon.configure(c2_server_ip_address=\"192.168.10.21\", keep_alive_frequency=7)\n", "\n", @@ -1601,9 +3056,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 72, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 12:09:35,703: Resetting environment, episode 0, avg. reward: 0.0\n", + "2025-02-26 12:09:35,704: Saving agent action log to C:\\Users\\CharlieCrane\\primaite\\4.0.0a1-dev\\sessions\\2025-02-26\\12-09-25\\agent_actions\\episode_0.json\n" + ] + } + ], "source": [ "blue_config_env.reset()\n", "\n", @@ -1625,9 +3089,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 73, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 5\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 0 -> 1\n", + "root['LINKS'][1]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][2]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][4]['PROTOCOLS']['ALL']: 0 -> 1\n", + "root['LINKS'][8]['PROTOCOLS']['ALL']: 0 -> 1\n" + ] + } + ], "source": [ "# Capturing default C2 Traffic\n", "for i in range(3):\n", @@ -1645,9 +3128,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 74, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------------------------------------------------------------------------------------------------------------------------------------------+\n", + "| c2-beacon Running Status |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| C2 Connection Active | C2 Remote Connection | Keep Alive Inactivity | Keep Alive Frequency | Current Masquerade Protocol | Current Masquerade Port |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n", + "| True | 192.168.10.21 | 0 | 5 | udp | 53 |\n", + "+----------------------+----------------------+-----------------------+----------------------+-----------------------------+-------------------------+\n" + ] + } + ], "source": [ "from primaite.utils.validation.ip_protocol import PROTOCOL_LOOKUP\n", "from primaite.utils.validation.port import PORT_LOOKUP\n", @@ -1660,9 +3157,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 75, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Observation space differences\n", + "-----------------------------\n", + "Step 10\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 1 -> 0\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 1 -> 0\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['udp'][53]['inbound']: 0 -> 1\n", + "root['nodes']['HOST0']['NICS'][1]['TRAFFIC']['udp'][53]['outbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['inbound']: 1 -> 0\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['tcp'][80]['outbound']: 1 -> 0\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['udp'][53]['inbound']: 0 -> 1\n", + "root['nodes']['HOST2']['NICS'][1]['TRAFFIC']['udp'][53]['outbound']: 0 -> 1\n" + ] + } + ], "source": [ "# Capturing UDP C2 Traffic\n", "for i in range(5):\n", diff --git a/src/primaite/notebooks/Privilege-Escalation-and-Data-Loss-Example.ipynb b/src/primaite/notebooks/Privilege-Escalation-and-Data-Loss-Example.ipynb index deb38eea..284cd9fd 100644 --- a/src/primaite/notebooks/Privilege-Escalation-and-Data-Loss-Example.ipynb +++ b/src/primaite/notebooks/Privilege-Escalation-and-Data-Loss-Example.ipynb @@ -53,16 +53,37 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C:\\Users\\CharlieCrane\\primaite\\4.0.0a1-dev\\notebooks\\example_notebooks\\Privilege-Escalation-and-Data-Loss-Example.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-02-26 14:11:04,193: Performing the PrimAITE first-time setup...\n", + "2025-02-26 14:11:04,193: Building the PrimAITE app directories...\n", + "2025-02-26 14:11:04,193: Building primaite_config.yaml...\n", + "2025-02-26 14:11:04,193: Rebuilding the demo notebooks...\n", + "2025-02-26 14:11:04,226: Reset example notebook: C:\\Users\\CharlieCrane\\primaite\\4.0.0a1-dev\\notebooks\\example_notebooks\\Privilege-Escalation-and-Data-Loss-Example.ipynb\n", + "2025-02-26 14:11:04,246: Rebuilding the example notebooks...\n", + "2025-02-26 14:11:04,251: PrimAITE setup complete!\n" + ] + } + ], "source": [ "!primaite setup" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "tags": [] }, @@ -90,7 +111,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "tags": [] }, @@ -113,7 +134,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "tags": [] }, @@ -140,33 +161,73 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+--------------------------------------------------------------------+\n", + "| some_tech_storage_srv File System |\n", + "+-----------+------+---------------+-----------------------+---------+\n", + "| File Path | Size | Health status | Visible health status | Deleted |\n", + "+-----------+------+---------------+-----------------------+---------+\n", + "| root | 0 B | GOOD | NONE | False |\n", + "+-----------+------+---------------+-----------------------+---------+\n" + ] + } + ], "source": [ "some_tech_storage_srv.file_system.show(full=True)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "some_tech_db_service.backup_database()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+--------------------------------------------------------------------------------------------------------------+\n", + "| some_tech_storage_srv File System |\n", + "+--------------------------------------------------+---------+---------------+-----------------------+---------+\n", + "| File Path | Size | Health status | Visible health status | Deleted |\n", + "+--------------------------------------------------+---------+---------------+-----------------------+---------+\n", + "| ed8587f2-7100-4837-bfbb-2a06bfafa8db/database.db | 4.77 MB | GOOD | NONE | False |\n", + "| root | 0 B | GOOD | NONE | False |\n", + "+--------------------------------------------------+---------+---------------+-----------------------+---------+\n" + ] + } + ], "source": [ "some_tech_storage_srv.file_system.show(full=True)" ] @@ -180,11 +241,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "'ed8587f2-7100-4837-bfbb-2a06bfafa8db'" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "db_backup_folder = [folder.name for folder in some_tech_storage_srv.file_system.folders.values() if folder.name != \"root\"][0]\n", "db_backup_folder" @@ -203,11 +275,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='failure', data={})" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "caos_action = [\n", " \"network\", \"node\", \"some_tech_jnr_dev_pc\", \n", @@ -227,11 +310,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={})" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "caos_action = [\"network\", \"node\", \"some_tech_jnr_dev_pc\", \"application\", \"web-browser\", \"execute\"]\n", "game.simulation.apply_request(caos_action)" @@ -252,20 +346,42 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "game.get_sim_state()[\"network\"][\"nodes\"][\"some_tech_rt\"][\"services\"][\"user-session-manager\"][\"active_remote_sessions\"]" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={'ip_address': '10.10.2.1', 'username': 'admin'})" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "caos_action = [\n", " \"network\", \"node\", \"some_tech_jnr_dev_pc\", \n", @@ -276,11 +392,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "['ee4b75dc-1f70-4f93-a25f-d0466afecfd9']" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "game.get_sim_state()[\"network\"][\"nodes\"][\"some_tech_rt\"][\"services\"][\"user-session-manager\"][\"active_remote_sessions\"]" ] @@ -296,22 +423,59 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+---------------------------------------------------------------------------------------------------------------------+\n", + "| some_tech_rt Access Control List |\n", + "+-------+--------+----------+-------------+--------------+----------+-------------+--------------+----------+---------+\n", + "| Index | Action | Protocol | Src IP | Src Wildcard | Src Port | Dst IP | Dst Wildcard | Dst Port | Matched |\n", + "+-------+--------+----------+-------------+--------------+----------+-------------+--------------+----------+---------+\n", + "| 11 | PERMIT | ANY | 94.10.180.6 | 0.0.0.0 | 5432 | 10.10.1.11 | 0.0.0.0 | 5432 | 2 |\n", + "| 12 | PERMIT | ANY | 10.10.1.11 | 0.0.0.0 | 5432 | 94.10.180.6 | 0.0.0.0 | 5432 | 2 |\n", + "| 13 | DENY | ANY | 10.10.2.12 | 0.0.0.0 | 21 | 10.10.1.12 | 0.0.0.0 | 21 | 0 |\n", + "| 14 | DENY | ANY | 10.10.2.12 | 0.0.0.0 | 22 | 10.10.1.12 | 0.0.0.0 | 22 | 1 |\n", + "| 15 | PERMIT | ANY | 10.10.2.0 | 0.0.0.255 | ANY | 10.10.1.0 | 0.0.0.255 | ANY | 0 |\n", + "| 16 | PERMIT | ANY | 10.10.1.0 | 0.0.0.255 | ANY | 10.10.2.0 | 0.0.0.255 | ANY | 0 |\n", + "| 17 | PERMIT | ANY | ANY | ANY | 80 | ANY | ANY | 80 | 2 |\n", + "| 18 | PERMIT | ANY | 10.10.0.0 | 0.0.255.255 | 219 | ANY | ANY | ANY | 7 |\n", + "| 19 | PERMIT | icmp | 10.10.0.0 | 0.0.255.255 | ANY | ANY | ANY | ANY | 0 |\n", + "| 21 | PERMIT | ANY | 94.10.180.6 | 0.0.0.0 | 80 | 10.10.0.0 | 0.0.255.255 | 80 | 0 |\n", + "| 22 | PERMIT | ANY | ANY | ANY | 53 | ANY | ANY | 53 | 2 |\n", + "| 23 | PERMIT | ANY | ANY | ANY | 22 | ANY | ANY | 22 | 1 |\n", + "| 24 | DENY | ANY | ANY | ANY | ANY | ANY | ANY | ANY | 0 |\n", + "+-------+--------+----------+-------------+--------------+----------+-------------+--------------+----------+---------+\n" + ] + } + ], "source": [ "some_tech_rt.acl.show()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={})" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "caos_action = [\n", " \"network\", \"node\", \"some_tech_jnr_dev_pc\", \n", @@ -340,11 +504,38 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+---------------------------------------------------------------------------------------------------------------------+\n", + "| some_tech_rt Access Control List |\n", + "+-------+--------+----------+-------------+--------------+----------+-------------+--------------+----------+---------+\n", + "| Index | Action | Protocol | Src IP | Src Wildcard | Src Port | Dst IP | Dst Wildcard | Dst Port | Matched |\n", + "+-------+--------+----------+-------------+--------------+----------+-------------+--------------+----------+---------+\n", + "| 1 | PERMIT | tcp | 10.10.2.12 | 0.0.0.0 | 22 | 10.10.1.12 | 0.0.0.0 | 22 | 0 |\n", + "| 11 | PERMIT | ANY | 94.10.180.6 | 0.0.0.0 | 5432 | 10.10.1.11 | 0.0.0.0 | 5432 | 2 |\n", + "| 12 | PERMIT | ANY | 10.10.1.11 | 0.0.0.0 | 5432 | 94.10.180.6 | 0.0.0.0 | 5432 | 2 |\n", + "| 13 | DENY | ANY | 10.10.2.12 | 0.0.0.0 | 21 | 10.10.1.12 | 0.0.0.0 | 21 | 0 |\n", + "| 14 | DENY | ANY | 10.10.2.12 | 0.0.0.0 | 22 | 10.10.1.12 | 0.0.0.0 | 22 | 1 |\n", + "| 15 | PERMIT | ANY | 10.10.2.0 | 0.0.0.255 | ANY | 10.10.1.0 | 0.0.0.255 | ANY | 0 |\n", + "| 16 | PERMIT | ANY | 10.10.1.0 | 0.0.0.255 | ANY | 10.10.2.0 | 0.0.0.255 | ANY | 0 |\n", + "| 17 | PERMIT | ANY | ANY | ANY | 80 | ANY | ANY | 80 | 2 |\n", + "| 18 | PERMIT | ANY | 10.10.0.0 | 0.0.255.255 | 219 | ANY | ANY | ANY | 7 |\n", + "| 19 | PERMIT | icmp | 10.10.0.0 | 0.0.255.255 | ANY | ANY | ANY | ANY | 0 |\n", + "| 21 | PERMIT | ANY | 94.10.180.6 | 0.0.0.0 | 80 | 10.10.0.0 | 0.0.255.255 | 80 | 0 |\n", + "| 22 | PERMIT | ANY | ANY | ANY | 53 | ANY | ANY | 53 | 2 |\n", + "| 23 | PERMIT | ANY | ANY | ANY | 22 | ANY | ANY | 22 | 2 |\n", + "| 24 | DENY | ANY | ANY | ANY | ANY | ANY | ANY | ANY | 0 |\n", + "+-------+--------+----------+-------------+--------------+----------+-------------+--------------+----------+---------+\n" + ] + } + ], "source": [ "some_tech_rt.acl.show()" ] @@ -360,11 +551,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={})" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "caos_action = [\n", " \"network\", \"node\", \"some_tech_jnr_dev_pc\", \n", @@ -382,9 +584,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "game.get_sim_state()[\"network\"][\"nodes\"][\"some_tech_rt\"][\"services\"][\"user-session-manager\"][\"active_remote_sessions\"]" ] @@ -400,9 +613,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={'ip_address': '10.10.1.12', 'username': 'admin'})" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "caos_action = [\n", " \"network\", \"node\", \"some_tech_jnr_dev_pc\", \n", @@ -413,11 +637,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={})" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "caos_action = [\n", " \"network\", \"node\", \"some_tech_jnr_dev_pc\", \n", @@ -441,11 +676,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+--------------------------------------------------------------------------------------------------------------+\n", + "| some_tech_storage_srv File System |\n", + "+--------------------------------------------------+---------+---------------+-----------------------+---------+\n", + "| File Path | Size | Health status | Visible health status | Deleted |\n", + "+--------------------------------------------------+---------+---------------+-----------------------+---------+\n", + "| ed8587f2-7100-4837-bfbb-2a06bfafa8db/database.db | 4.77 MB | GOOD | NONE | True |\n", + "| root | 0 B | GOOD | NONE | False |\n", + "+--------------------------------------------------+---------+---------------+-----------------------+---------+\n" + ] + } + ], "source": [ "some_tech_storage_srv.file_system.show(full=True)" ] @@ -470,11 +720,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='success', data={})" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "caos_action = [\"network\", \"node\", \"some_tech_jnr_dev_pc\", \"application\", \"web-browser\", \"execute\"]\n", "game.simulation.apply_request(caos_action)" @@ -489,11 +750,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "DatabaseClientConnection(connection_id='cb712d1e-68d2-4504-94a2-8c67d3652ccd', is_active=True)" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "some_tech_jnr_dev_db_client.server_ip_address = some_tech_db_srv.network_interface[1].ip_address\n", "some_tech_jnr_dev_db_connection = some_tech_jnr_dev_db_client.get_new_connection()\n", @@ -511,11 +783,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "some_tech_jnr_dev_db_connection.query(\"DELETE\")" ] @@ -529,11 +812,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "RequestResponse(status='failure', data={})" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "caos_action = [\"network\", \"node\", \"some_tech_jnr_dev_pc\", \"application\", \"web-browser\", \"execute\"]\n", "game.simulation.apply_request(caos_action)" @@ -550,11 +844,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "some_tech_db_service.restore_backup()" ] @@ -595,7 +900,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": ".venv", "language": "python", "name": "python3" }, @@ -609,7 +914,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.11" } }, "nbformat": 4,