Agent plugin
Last updated
Last updated
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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, ExtenderAgent β β β β
β β β β β β β β
β β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β
β β β β β β β
β β β βββ> Save to DBMS, broadcast to clients β β β
β β β β β β
β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β COMMAND EXECUTION β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β GUI ββ> POST /agent/command/execute β
β β β
β V β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β TEAMSERVER β β
β β β β β
β β V β β
β β TsTaskCreate(agentId, command, args) β β
β β β β β
β β V β β
β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β EXTENDER β β β
β β β β β β β
β β β V β β β
β β β ExtenderAgent.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 β β β β
β β β β ExtenderAgent.Decrypt() + ProcessTasksResult() β β β β
β β β β β β β β β
β β β β βββ> case COMMAND_OUTPUT: TsTaskUpdate β β β β
β β β β βββ> case COMMAND_DOWNLOAD: TsDownloadAdd/Update/Close β β β β
β β β β βββ> case COMMAND_SCREENSHOT: TsScreenshotAdd β β β β
β β β β βββ> case COMMAND_LINK: TsPivotCreate β β β β
β β β β βββ> case COMMAND_TUNNEL_*: TsTunnelConnection* β β β β
β β β β βββ> ... other commands β β β β
β β β β β β β β
β β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β
β β β β β β
β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ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: falsetype PluginAgent interface {
// Get ExtenderAgent
GetExtender() ExtenderAgent
// Generate profiles for listeners
GenerateProfiles(profile BuildProfile) ([][]byte, error)
// Build agent payload
BuildPayload(profile BuildProfile, agentProfiles [][]byte) ([]byte, string, error)
// Create agent from beat data
CreateAgent(beat []byte) (AgentData, ExtenderAgent, error)
}
// ExtenderAgent - interface for working with agent
type ExtenderAgent interface {
// Encrypt data
Encrypt(data []byte, key []byte) ([]byte, error)
// Decrypt data
Decrypt(data []byte, key []byte) ([]byte, error)
// Pack tasks for sending to agent
PackTasks(agentData AgentData, tasks []TaskData) ([]byte, error)
// Pack data for pivot agent
PivotPackData(pivotId string, data []byte) (TaskData, error)
// Create task from command
CreateCommand(agentData AgentData, args map[string]any) (TaskData, ConsoleMessageData, error)
// Callbacks for tunnels
TunnelCallbacks() TunnelCallbacks
// Callbacks for terminal
TerminalCallbacks() TerminalCallbacks
}
// TunnelCallbacks - functions for tunnel management
type TunnelCallbacks struct {
ConnectTCP func(channelId, tunnelType, addressType int, address string, port int) TaskData
ConnectUDP func(channelId, tunnelType, addressType int, address string, port int) TaskData
WriteTCP func(channelId int, data []byte) TaskData
WriteUDP func(channelId int, data []byte) TaskData
Close func(channelId int) TaskData
Reverse func(tunnelId, port int) TaskData
}
// TerminalCallbacks - functions for terminal management
type TerminalCallbacks struct {
Start func(terminalId int, program string, sizeH, sizeW int, oemCP int) TaskData
Write func(terminalId int, oemCP int, data []byte) TaskData
Close func(terminalId int) TaskData
}// 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
}
}// 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"]);