> For the complete documentation index, see [llms.txt](https://adaptix-framework.gitbook.io/adaptix-framework/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://adaptix-framework.gitbook.io/adaptix-framework/development/extenders/agent-plugin-in-dev.md).

# Agent plugin

Agent Plugin is responsible for payload generation, data parsing, and command handling.

### Flow Diagram

<figure><img src="https://2104178602-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FS8p8XLFtLmf0NkofQvoa%2Fuploads%2FFgBfadznFBRM17LU5aC8%2F04.png?alt=media&amp;token=fd8b2a3f-bd83-4609-8f32-32b8af491e6f" alt=""><figcaption></figcaption></figure>

```
┌──────────────────────────────────────────────────────────────────────────────────┐
│                            AGENT PLUGIN FLOW                                     │
├──────────────────────────────────────────────────────────────────────────────────┤
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          AGENT GENERATION                                  ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  GUI ──> WS /channel (agent/generate)                                            │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ TEAMSERVER                                                                  │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  TsAgentGenerate(agentType, config)                                         │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ EXTENDER                                                              │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  PluginAgent.GenerateProfiles(BuildProfile)                           │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> Create profiles for each listener                        │  │ │
│  │  │              return [][]byte (agentProfiles)                          │  │ │
│  │  │                                                                       │  │ │
│  │  │  PluginAgent.BuildPayload(BuildProfile, agentProfiles)                │  │ │
│  │  │         │                                                             │  │ │
│  │  │         ├──> TsAgentBuildExecute() ←── Run build commands             │  │ │
│  │  │         ├──> TsAgentBuildLog()     ←── Build logging                  │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> return []byte (payload), filename                        │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          AGENT REGISTRATION                                ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  Agent ──> Request to Listener (first contact)                                   │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ EXTENDER (Listener Plugin)                                                  │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  processRequest(ctx) ──> Parse data                                         │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ TEAMSERVER                                                            │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  TsAgentCreate(agentCrc, agentId, data, listenerName, IP, async)      │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  ┌─────────────────────────────────────────────────────────────────┐  │  │ │
│  │  │  │ EXTENDER (Agent Plugin)                                         │  │  │ │
│  │  │  │         │                                                       │  │  │ │
│  │  │  │         V                                                       │  │  │ │
│  │  │  │  PluginAgent.CreateAgent(data)                                  │  │  │ │
│  │  │  │         │                                                       │  │  │ │
│  │  │  │         ├──> Decrypt data                                       │  │  │ │
│  │  │  │         ├──> Parse agent info (OS, user, computer, etc.)        │  │  │ │
│  │  │  │         │                                                       │  │  │ │
│  │  │  │         └──> return AgentData, AgentFunctions                   │  │  │ │
│  │  │  │                                                                 │  │  │ │
│  │  │  └─────────────────────────────────────────────────────────────────┘  │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> Save to DBMS, broadcast to clients                       │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          COMMAND EXECUTION                                 ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  GUI ──> POST /agent/command/execute                                             │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ TEAMSERVER                                                                  │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  TsTaskCreate(agentId, command, args)                                       │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ EXTENDER                                                              │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  AgentFunctions.CreateCommand(agentData, args)                        │  │ │
│  │  │         │                                                             │  │ │
│  │  │         ├──> Parse command and arguments                              │  │ │
│  │  │         ├──> Create TaskData with packed command                      │  │ │
│  │  │         │                                                             │  │ │
│  │  │         └──> return TaskData, ConsoleMessageData                      │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │         │                                                                   │ │
│  │         └──> Add to agent queue, broadcast to clients                       │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
│  ╔════════════════════════════════════════════════════════════════════════════╗  │
│  ║                          DATA PROCESSING (Agent → Server)                  ║  │
│  ╚════════════════════════════════════════════════════════════════════════════╝  │
│                                                                                  │
│  Agent ──> Request to Listener (with results)                                    │
│                   │                                                              │
│                   V                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │ EXTENDER (Listener Plugin)                                                  │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  processRequest(ctx) ──> Parse body data                                    │ │
│  │         │                                                                   │ │
│  │         V                                                                   │ │
│  │  ┌───────────────────────────────────────────────────────────────────────┐  │ │
│  │  │ TEAMSERVER                                                            │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  TsAgentProcessData(agentId, bodyData)                                │  │ │
│  │  │         │                                                             │  │ │
│  │  │         V                                                             │  │ │
│  │  │  ┌─────────────────────────────────────────────────────────────────┐  │  │ │
│  │  │  │ EXTENDER (Agent Plugin)                                         │  │  │ │
│  │  │  │         │                                                       │  │  │ │
│  │  │  │         V                                                       │  │  │ │
│  │  │  │  AgentFunctions.Decrypt() + ProcessData()                       │  │  │ │
│  │  │  │         │                                                       │  │  │ │
│  │  │  │         ├──> case COMMAND_OUTPUT: TsTaskUpdate                  │  │  │ │
│  │  │  │         ├──> case COMMAND_DOWNLOAD: TsDownloadAdd/Update/Close  │  │  │ │
│  │  │  │         ├──> case COMMAND_SCREENSHOT: TsScreenshotAdd           │  │  │ │
│  │  │  │         ├──> case COMMAND_LINK: TsPivotCreate                   │  │  │ │
│  │  │  │         ├──> case COMMAND_TUNNEL_*: TsTunnelConnection*         │  │  │ │
│  │  │  │         └──> ... other commands                                 │  │  │ │
│  │  │  │                                                                 │  │  │ │
│  │  │  └─────────────────────────────────────────────────────────────────┘  │  │ │
│  │  │                                                                       │  │ │
│  │  └───────────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                             │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
│                                                                                  │
└──────────────────────────────────────────────────────────────────────────────────┘
```

### Agent Config (config.yaml)

```yaml
extender_type: "agent"
extender_file: "agent.so"
ax_file: "ax_config.axs"

agent_name: "AGENT_NAME"
agent_watermark: "deadbeef"
listeners:
  - "LISTENER_NAME_1"
  - "LISTENER_NAME_2"
# - ....
multi_listeners: false
```

### PluginAgent Interface

`InitPlugin` for an agent is `func InitPlugin(ts any, moduleDir string, watermark string) adaptix.PluginAgent`.

```go
type PluginAgent interface {
    GenerateProfiles(profile BuildProfile) ([][]byte, error)
    BuildPayload(profile BuildProfile, agentProfiles [][]byte) ([]byte, string, error)
    CreateAgent(beat []byte) (AgentData, AgentFunctions, error)
    AgentRestore(agentData AgentData) AgentFunctions
    Call(operator string, agentId int64, function string, args string)
}

type AgentFunctions struct {
    CreateCommand func(AgentData, map[string]any) (TaskData, ConsoleMessageData, error)
    PackTasks     func(AgentData, []TaskData) ([]byte, error)
    ProcessData   func(AgentData, []byte) error
    Encrypt       func([]byte, []byte) ([]byte, error)
    Decrypt       func([]byte, []byte) ([]byte, error)
    PivotPackData func(string, []byte) (TaskData, error)
    Delivery      DeliveryFunc
    TunnelCB      TunnelCallbacks
    TerminalCB    TerminalCallbacks
}

type TunnelCallbacks struct {
    ConnectTCP func(channelId int64, tunnelType, addressType int, address string, port int) TaskData
    ConnectUDP func(channelId int64, tunnelType, addressType int, address string, port int) TaskData
    WriteTCP   func(channelId int64, data []byte) TaskData
    WriteUDP   func(channelId int64, data []byte) TaskData
    Pause      func(channelId int64) TaskData
    Resume     func(channelId int64) TaskData
    Close      func(channelId int64) TaskData
    Reverse    func(tunnelId int64, port int) TaskData
    BindTCP    func(channelId int64, addressType int, address string, port int) TaskData
}

type TerminalCallbacks struct {
    Start func(terminalId int64, program string, sizeH, sizeW, oemCP int) TaskData
    Write func(terminalId int64, oemCP int, data []byte) TaskData
    Close func(terminalId int64) TaskData
}
```

### AxScript for Agent (ax\_config.axs)

The `.axs` file defines agent commands, context menus, and UI for payload generation.

**Required functions:**

```javascript
// 1. Register agent commands (called when plugin loads)
function RegisterCommands(listenerType) {
    // listenerType: "BeaconHTTP", "BeaconDNS", "BeaconSMB", "BeaconTCP", etc.
    
    // Create command
    let cmd_ls = ax.create_command("ls", "List files", "ls /tmp", "Task: list files");
    cmd_ls.addArgString("path", false, ".");  // name, required, default
    
    let cmd_cd = ax.create_command("cd", "Change directory", "cd /tmp", "Task: change dir");
    cmd_cd.addArgString("path", true);
    
    // Command with subcommands
    let cmd_ps_list = ax.create_command("list", "Show processes", "ps list");
    let cmd_ps_kill = ax.create_command("kill", "Kill process", "ps kill 1234");
    cmd_ps_kill.addArgInt("pid", true);
    let cmd_ps = ax.create_command("ps", "Process manager");
    cmd_ps.addSubCommands([cmd_ps_list, cmd_ps_kill]);
    
    // Alias with pre-hook
    let cmd_shell = ax.create_command("shell", "Execute via cmd.exe", "shell whoami");
    cmd_shell.addArgString("cmd", true);
    cmd_shell.setPreHook(function(id, cmdline, parsed_json) {
        ax.execute_alias(id, cmdline, "ps run -o cmd.exe /c " + parsed_json["cmd"]);
    });
    
    // Commands group
    let commands = ax.create_commands_group("beacon", [cmd_ls, cmd_cd, cmd_ps, cmd_shell]);
    
    return { 
        commands_windows: commands,  // Commands for Windows
        // commands_linux: commands, // Commands for Linux (optional)
    }
}

// 2. UI for payload generation (called when generation dialog opens)
function GenerateUI(listeners_type) {
    // listeners_type: array of selected listener types
    
    let labelArch = form.create_label("Arch:");
    let comboArch = form.create_combo();
    comboArch.addItems(["x64", "x86"]);
    
    let labelFormat = form.create_label("Format:");
    let comboFormat = form.create_combo();
    comboFormat.addItems(["Exe", "DLL", "Shellcode"]);
    
    let layout = form.create_gridlayout();
    layout.addWidget(labelArch, 0, 0);
    layout.addWidget(comboArch, 0, 1);
    layout.addWidget(labelFormat, 1, 0);
    layout.addWidget(comboFormat, 1, 1);
    
    let container = form.create_container();
    container.put("arch", comboArch);
    container.put("format", comboFormat);
    
    let panel = form.create_panel();
    panel.setLayout(layout);
    
    return {
        ui_panel: panel,
        ui_container: container,
        ui_height: 300,
        ui_width: 400
    }
}
```

**Optional elements:**

```javascript
// Context menus for agent sessions
let exit_action = menu.create_action("Terminate", function(agents) {
    agents.forEach(a => ax.execute_command(a, "terminate process"));
});
menu.add_session_agent(exit_action, ["beacon"]);  // For agents of type "beacon"

// Context menus for File Browser
let download_action = menu.create_action("Download", function(files) {
    files.forEach(f => ax.execute_command(f.agent_id, "download " + f.path + f.name));
});
menu.add_filebrowser(download_action, ["beacon"]);

// Browser event handlers
event.on_filebrowser_disks(function(id) {
    ax.execute_browser(id, "disks");
}, ["beacon"]);

event.on_filebrowser_list(function(id, path) {
    ax.execute_browser(id, "ls " + path);
}, ["beacon"]);

event.on_processbrowser_list(function(id) {
    ax.execute_browser(id, "ps list");
}, ["beacon"]);
```
