Skip to main content
  1. Documentation/
  2. Plugins/

Tools Modules

Table of Contents
Tools modules execute directly from the teamserver against remote services without deploying an agent.

Interface
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from tantoc2.server.agentless_base import (
    AgentlessModuleBase,
    AgentlessMetadata,
    AgentlessTarget,
    AgentlessResult,
    OptionSchema,
)

class MyToolModule(AgentlessModuleBase):
    @classmethod
    def plugin_name(cls) -> str:
        return "my_service"

    @classmethod
    def plugin_type(cls) -> str:
        return "agentless_module"

    @classmethod
    def metadata(cls) -> AgentlessMetadata:
        return AgentlessMetadata(
            name="my_service",
            description="Interact with MyService",
            author="Your Name",
            protocol="my_protocol",
            operations=["exec", "enumerate"],
            connection_params={
                "host": OptionSchema(name="host", type="str",
                    description="Target host", required=True, default=None),
                "port": OptionSchema(name="port", type="int",
                    description="Target port", required=True, default=None),
            },
            options_schema={
                "command": OptionSchema(name="command", type="str",
                    description="Command to execute", required=True,
                    default=None),
            },
            mitre_attack=["T1021"],
        )

    def execute(
        self,
        operation: str,
        targets: list[AgentlessTarget],
        options: dict[str, Any],
        credentials: dict[str, dict[str, str]] | None = None,
        proxy: dict[str, Any] | None = None,
    ) -> list[AgentlessResult]:
        """Execute an operation against one or more targets.

        Args:
            operation: Operation name (must be in metadata().operations).
            targets: List of AgentlessTarget objects to execute against.
            options: Operation-specific options.
            credentials: Map of credential_id -> decrypted credential dict.
            proxy: Proxy configuration dict, or None for direct connection.

        Returns:
            A list of per-target AgentlessResult objects.
        """
        ...

AgentlessTarget
#

Each target is represented as an AgentlessTarget dataclass:

1
2
3
4
5
@dataclass
class AgentlessTarget:
    host: str
    port: int | None = None
    credential_id: str | None = None  # ref to credential store

The credential_id field references a credential in the credential store. When credentials are provided, they are resolved and passed to execute() via the credentials mapping.

AgentlessResult
#

Each target produces an AgentlessResult:

1
2
3
4
5
6
7
8
@dataclass
class AgentlessResult:
    target: AgentlessTarget
    success: bool
    data: dict[str, Any] = field(default_factory=dict)
    credentials: list[ExtractedCredential] = field(default_factory=list)
    error: str | None = None
    raw_output: str | None = None

Metadata Fields
#

FieldTypeDescription
namestrUnique module name
descriptionstrHuman-readable description
authorstrAuthor name
protocolstrNetwork protocol (e.g., “ssh”, “smb”)
connection_paramsdict[str, OptionSchema]Required target connection parameters
operationslist[str]Supported operations (e.g., “exec”, “enumerate”)
options_schemadict[str, OptionSchema]Per-operation options
mitre_attacklist[str]ATT&CK technique IDs
dependencieslist[str]pip packages required by the module

Key Concepts
#

Multi-Target Execution
#

The execute method receives a list of AgentlessTarget objects and returns a list of AgentlessResult objects. Modules handle their own parallelism internally when targeting multiple hosts.

Credential Consumption
#

When targets have a credential_id set, the manager resolves the credentials from the store and passes them to execute() via the credentials parameter – a dict mapping each credential_id to a decrypted credential dict containing keys like username, secret, domain, etc.

Credential Contribution
#

Return ExtractedCredential objects in the result’s credentials field to auto-populate the credential store with discovered credentials.

Proxy Support
#

When a proxy configuration is specified, the resolved proxy dict is passed to execute() via the proxy parameter. Your module can use this to route connections through SOCKS or SSH tunnels.

Deployment
#

Place the file in plugins/agentless/my_tool.py. Discover with:

1
tantoc2> tools refresh