Skip to content
8 changes: 5 additions & 3 deletions docs/source/configuration/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ sliver, metasploit and remote attackmate server:
password: password

msf_config:
password: securepassword
server: 127.0.0.1
default:
password: securepassword
server: 127.0.0.1

sliver_config:
config_file: /home/attacker/.sliver-client/configs/attacker_localhost.cfg
default:
config_file: /home/attacker/.sliver-client/configs/attacker_localhost.cfg

remote_config:
remote_server_name:
Expand Down
33 changes: 30 additions & 3 deletions docs/source/configuration/msf_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,40 @@
msf_config
==========

``msf_config`` holds connection settings for the Metasploit RPC daemon (``msfrpcd``).
``msf_config`` holds connection settings for one or more Metasploit RPC daemon (``msfrpcd``)
instances. Each connection is identified by a name. The first defined connection is used by
default when a command does not specify one explicitly.

.. code-block:: yaml

msf_config:
password: securepassword
server: 10.18.3.86
primary:
password: securepassword
server: 10.18.3.86

Multiple servers can be defined and selected per command via the :confval:`connection` field:

.. code-block:: yaml

msf_config:
server1:
password: securepassword
server: 10.18.3.86
server2:
password: anothersecret
server: 10.18.3.87

.. note::

**Backwards compatibility:** The legacy single-server format is still accepted and is
automatically migrated to a named entry called ``default``:

.. code-block:: yaml

# Legacy format (still supported)
msf_config:
password: securepassword
server: 10.18.3.86


.. confval:: server
Expand Down
29 changes: 27 additions & 2 deletions docs/source/configuration/sliver_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,37 @@
sliver_config
=============

``sliver_config`` stores all settings to control the connection to the Sliver API.
``sliver_config`` stores connection settings for one or more Sliver C2 servers.
Each connection is identified by a name. The first defined connection is used by
default when a command does not specify one explicitly.

.. code-block:: yaml

sliver_config:
config_file: /home/attacker/.sliver-client/configs/attacker_localhost.cfg
primary:
config_file: /home/attacker/.sliver-client/configs/attacker_localhost.cfg

Multiple servers can be defined and selected per command via the :confval:`connection` field:

.. code-block:: yaml

sliver_config:
sliver_server1:
config_file: /home/attacker/.sliver-client/configs/attacker_localhost.cfg
sliver_server2:
config_file: /home/attacker/.sliver-client/configs/attacker2_localhost.cfg

.. note::

**Backwards compatibility:** The legacy single-server format is still accepted and is
automatically migrated to a named entry called ``default``:

.. code-block:: yaml

# Legacy format (still supported)
sliver_config:
config_file: /home/attacker/.sliver-client/configs/attacker_localhost.cfg


.. confval:: config_file

Expand Down
2 changes: 1 addition & 1 deletion docs/source/developing/command.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ The factory filters the provided configurations based on the class constructor s
'pm': self.pm,
'varstore': self.varstore,
'cmdconfig': self.pyconfig.cmd_config,
'msfconfig': self.pyconfig.msf_config,
'msf_config': self.pyconfig.msf_config,
'msfsessionstore': self.msfsessionstore,
'sliver_config': self.pyconfig.sliver_config,
'runfunc': self._run_commands,
Expand Down
10 changes: 5 additions & 5 deletions docs/source/developing/integration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,11 @@ Top-level configuration object. All fields have safe defaults, so an empty
- ``CommandConfig``
- Global command execution settings. See below.
* - ``msf_config``
- ``MsfConfig``
- Metasploit RPC connection settings. See below.
- ``dict[str, MsfConfig]``
- Named Metasploit RPC connections. See below.
* - ``sliver_config``
- ``SliverConfig``
- Sliver C2 connection settings. See below.
- ``dict[str, SliverConfig]``
- Named Sliver C2 connections. See below.
* - ``bettercap_config``
- ``dict[str, BettercapConfig]``
- Named Bettercap instances. Keys are referenced by ``webserv`` commands.
Expand Down Expand Up @@ -440,7 +440,7 @@ Running a Single Command
initialize_logger(debug=False, append_logs=False)

config = Config(
msf_config={"password": "your_password", "ssl": True, "port": 55553},
msf_config={"default": {"password": "your_password", "ssl": True, "port": 55553}},
cmd_config={"loop_sleep": 10},
)
varstore = {"HOST": "10.0.0.1"}
Expand Down
9 changes: 8 additions & 1 deletion docs/source/playbook/commands/msf-module.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,14 @@ Most exploit modules do not produce direct output but instead open a session

:type: str

The following example illustrates the use of sessions and payloads:
.. confval:: connection

Name of the MSF server connection to use, as defined in :ref:`msf_config`.
If omitted, the first configured connection is used.

:type: str

The following example illustrates the use of sessions and payloads:

.. code-block:: yaml

Expand Down
7 changes: 7 additions & 0 deletions docs/source/playbook/commands/msf-session.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,10 @@ Execute commands in an active Meterpreter session previously opened by an
String indicating the end of a read-operation.

:type: str

.. confval:: connection

Name of the MSF server connection to use, as defined in :ref:`msf_config`.
If omitted, the first configured connection is used.

:type: str
7 changes: 7 additions & 0 deletions docs/source/playbook/commands/payload.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,10 @@ Generate a Metasploit payload and save it to a file.

:type: int
:default: ``0``

.. confval:: connection

Name of the MSF server connection to use, as defined in :ref:`msf_config`.
If omitted, the first configured connection is used.

:type: str
9 changes: 9 additions & 0 deletions docs/source/playbook/commands/sliver-session.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Execute commands within an active Sliver implant session. All commands require a

.. note::

To configure the connection to the Sliver server, see :ref:`sliver_config`.

**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``
Expand All @@ -22,6 +24,13 @@ Execute commands within an active Sliver implant session. All commands require a
:type: str
:required: True

.. confval:: connection

Name of the Sliver server connection to use, as defined in :ref:`sliver_config`.
If omitted, the first configured connection is used.

:type: str

File System
-----------

Expand Down
9 changes: 9 additions & 0 deletions docs/source/playbook/commands/sliver.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,20 @@ Control the Sliver C2 server via its API. All commands use ``type: sliver``.

.. note::

To configure the connection to the Sliver server, see :ref:`sliver_config`.

**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:: connection

Name of the Sliver server connection to use, as defined in :ref:`sliver_config`.
If omitted, the first configured connection is used.

:type: str

start_https_listener
--------------------

Expand Down
8 changes: 4 additions & 4 deletions src/attackmate/attackmate.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import logging
from attackmate.result import Result
import attackmate.executors as executors
from attackmate.schemas.config import CommandConfig, Config, MsfConfig, SliverConfig
from attackmate.schemas.config import CommandConfig, Config
from attackmate.schemas.playbook import Playbook
from attackmate.schemas.command_types import Commands, Command
from attackmate.variablestore import VariableStore
Expand Down Expand Up @@ -87,8 +87,8 @@ def _default_playbook(self) -> Playbook:
def _default_config(self) -> Config:
return Config(
cmd_config=CommandConfig(),
msf_config=MsfConfig(),
sliver_config=SliverConfig(),
msf_config={},
sliver_config={},
bettercap_config={},
remote_config={}
)
Expand All @@ -109,7 +109,7 @@ def _get_executor_config(self) -> dict:
'pm': self.pm,
'varstore': self.varstore,
'cmdconfig': self.pyconfig.cmd_config,
'msfconfig': self.pyconfig.msf_config,
'msf_config': self.pyconfig.msf_config,
'bettercap_config': self.pyconfig.bettercap_config,
'remote_config': self.pyconfig.remote_config,
'msfsessionstore': self.msfsessionstore,
Expand Down
2 changes: 1 addition & 1 deletion src/attackmate/executors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from .browser.browserexecutor import BrowserExecutor

__all__ = [
'RemoteExecutor'
'RemoteExecutor',
'BrowserExecutor',
'ShellExecutor',
'SSHExecutor',
Expand Down
40 changes: 40 additions & 0 deletions src/attackmate/executors/metasploit/msfclientmixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import logging
from typing import Dict
from pymetasploit3.msfrpc import MsfRpcClient, MsfAuthError
from attackmate.schemas.base import BaseCommand
from attackmate.schemas.config import MsfConfig
from attackmate.execexception import ExecException


class MsfClientMixin:
msf_config: Dict[str, MsfConfig]
_msf_clients: Dict[str, MsfRpcClient]
logger: logging.Logger

def _resolve_connection(self, command: BaseCommand) -> str:
conn = getattr(command, 'connection', None)
if conn:
return conn
if self.msf_config:
conn_name = next(iter(self.msf_config))
self.logger.debug(f'No connection specified, using default: {conn_name}')
return conn_name
raise ExecException('No MSF connections configured')

def _get_client(self, conn_name: str) -> MsfRpcClient:
if conn_name not in self._msf_clients:
if conn_name not in self.msf_config:
raise ExecException(f"MSF connection '{conn_name}' not found in config")
config = self.msf_config[conn_name]
self.logger.debug(
f"Connecting to MSF server '{conn_name}' at {config.server}:{config.port} (ssl={config.ssl})"
)
try:
self._msf_clients[conn_name] = MsfRpcClient(**config.model_dump())
except IOError as e:
self.logger.error(e)
raise ExecException(f'MSF connection failed: {e}')
except MsfAuthError as e:
self.logger.error(e)
raise ExecException(f'MSF authentication failed: {e}')
return self._msf_clients[conn_name]
Loading
Loading