Implemented agent generation from teamserver

This commit is contained in:
Jakob Friedl
2025-05-24 16:15:41 +02:00
parent ac0bb3c915
commit c03592c7fd
3 changed files with 74 additions and 13 deletions

View File

@@ -1,5 +1,5 @@
# Agent configuration # Agent configuration
-d:ListenerUuid="HVVOGEOM" -d:ListenerUuid="KPDHWZNT"
-d:ListenerIp="localhost" -d:ListenerIp="localhost"
-d:ListenerPort=5555 -d:ListenerPort=7777
-d:SleepDelay=10 -d:SleepDelay=10

View File

@@ -1,4 +1,4 @@
import terminal, strformat, strutils, sequtils, tables, json, times, base64 import terminal, strformat, strutils, sequtils, tables, json, times, base64, system, osproc, streams
import ./interact import ./interact
import ../[types, globals, utils] import ../[types, globals, utils]
import ../db/database import ../db/database
@@ -108,6 +108,56 @@ proc agentInteract*(cq: Conquest, name: string) =
cq.interactAgent = nil cq.interactAgent = nil
# Agent generation
proc agentBuild*(cq: Conquest, listener, sleep, payload: string) =
# Verify that listener exists
if not cq.dbListenerExists(listener.toUpperAscii):
cq.writeLine(fgRed, styleBright, fmt"[-] Listener {listener.toUpperAscii} does not exist.")
return
let listener = cq.listeners[listener.toUpperAscii]
# Create/overwrite nim.cfg file to set agent configuration
let agentConfigFile = fmt"../agents/{payload}/nim.cfg"
# The following shows the format of the agent configuration file that defines compile-time variables
let config = fmt"""
# Agent configuration
-d:ListenerUuid="{listener.name}"
-d:ListenerIp="{listener.address}"
-d:ListenerPort={listener.port}
-d:SleepDelay={sleep}
""".replace(" ", "")
writeFile(agentConfigFile, config)
cq.writeLine(fgBlack, styleBright, "[*] ", resetStyle, "Configuration file created.")
# Build agent by executing the ./build.sh script on the system.
let agentBuildScript = fmt"../agents/{payload}/build.sh"
cq.writeLine(fgBlack, styleBright, "[*] ", resetStyle, "Building agent...")
try:
# Using the startProcess function from the 'osproc' module, it is possible to retrieve the output as it is received, line-by-line instead of all at once
let process = startProcess(agentBuildScript, options={poUsePath, poStdErrToStdOut})
let outputStream = process.outputStream
var line: string
while outputStream.readLine(line):
cq.writeLine(line)
let exitCode = process.waitForExit()
# Check if the build succeeded or not
if exitCode == 0:
cq.writeLine(fgGreen, "[+] ", resetStyle, "Agent payload generated successfully.")
else:
cq.writeLine(fgRed, styleBright, "[-] ", resetStyle, "Build script exited with code ", $exitCode)
except CatchableError as err:
cq.writeLine(fgRed, styleBright, "[-] ", resetStyle, "An error occurred: ", err.msg)
#[ #[
Agent API Agent API
Functions relevant for dealing with the agent API, such as registering new agents, querying tasks and posting results Functions relevant for dealing with the agent API, such as registering new agents, querying tasks and posting results

View File

@@ -9,6 +9,7 @@ import agent/agent, listener/listener, db/database
]# ]#
var parser = newParser: var parser = newParser:
help("Conquest Command & Control") help("Conquest Command & Control")
nohelpflag()
command("listener"): command("listener"):
help("Manage, start and stop listeners.") help("Manage, start and stop listeners.")
@@ -17,33 +18,41 @@ var parser = newParser:
help("List all active listeners.") help("List all active listeners.")
command("start"): command("start"):
help("Starts a new HTTP listener.") help("Starts a new HTTP listener.")
option("-h", "-host", default=some("0.0.0.0"), help="IPv4 address to listen on.", required=false) option("-i", "--ip", default=some("localhost"), help="IPv4 address to listen on.", required=false)
option("-p", "-port", help="Port to listen on.", required=true) option("-p", "--port", help="Port to listen on.", required=true)
# TODO: Future features: # TODO: Future features:
# flag("--dns", help="Use the DNS protocol for C2 communication.") # flag("--dns", help="Use the DNS protocol for C2 communication.")
# flag("--doh", help="Use DNS over HTTPS for C2 communication.) # flag("--doh", help="Use DNS over HTTPS for C2 communication.)
command("stop"): command("stop"):
help("Stop an active listener.") help("Stop an active listener.")
option("-n", "-name", help="Name of the listener.", required=true) option("-n", "--name", help="Name of the listener.", required=true)
command("agent"): command("agent"):
help("Manage, build and interact with agents.") help("Manage, build and interact with agents.")
command("list"): command("list"):
help("List all agents.") help("List all agents.")
option("-l", "-listener", help="Name of the listener.") option("-l", "--listener", help="Name of the listener.")
command("info"): command("info"):
help("Display details for a specific agent.") help("Display details for a specific agent.")
option("-n", "-name", help="Name of the agent.", required=true) option("-n", "--name", help="Name of the agent.", required=true)
command("kill"): command("kill"):
help("Terminate the connection of an active listener and remove it from the interface.") help("Terminate the connection of an active listener and remove it from the interface.")
option("-n", "-name", help="Name of the agent.", required=true) option("-n", "--name", help="Name of the agent.", required=true)
# flag("--self-delete", help="Remove agent executable from target system.")
command("interact"): command("interact"):
help("Interact with an active agent.") help("Interact with an active agent.")
option("-n", "-name", help="Name of the agent.", required=true) option("-n", "--name", help="Name of the agent.", required=true)
command("build"):
help("Generate a new agent to connect to an active listener.")
option("-l", "--listener", help="Name of the listener.", required=true)
option("-s", "--sleep", help="Sleep delay in seconds.", default=some("10") )
option("-p", "--payload", help="Agent type", choices = @["monarch"], default=some("monarch"))
command("help"): command("help"):
nohelpflag() nohelpflag()
@@ -76,7 +85,7 @@ proc handleConsoleCommand*(cq: Conquest, args: varargs[string]) =
of "list": of "list":
cq.listenerList() cq.listenerList()
of "start": of "start":
cq.listenerStart(opts.listener.get.start.get.host, opts.listener.get.start.get.port) cq.listenerStart(opts.listener.get.start.get.ip, opts.listener.get.start.get.port)
of "stop": of "stop":
cq.listenerStop(opts.listener.get.stop.get.name) cq.listenerStop(opts.listener.get.stop.get.name)
else: else:
@@ -92,6 +101,8 @@ proc handleConsoleCommand*(cq: Conquest, args: varargs[string]) =
cq.agentKill(opts.agent.get.kill.get.name) cq.agentKill(opts.agent.get.kill.get.name)
of "interact": of "interact":
cq.agentInteract(opts.agent.get.interact.get.name) cq.agentInteract(opts.agent.get.interact.get.name)
of "build":
cq.agentBuild(opts.agent.get.build.get.listener, opts.agent.get.build.get.sleep, opts.agent.get.build.get.payload)
else: else:
cq.agentUsage() cq.agentUsage()
@@ -101,7 +112,7 @@ proc handleConsoleCommand*(cq: Conquest, args: varargs[string]) =
cq.writeLine(err.help) cq.writeLine(err.help)
# Handle invalid arguments # Handle invalid arguments
except UsageError: except CatchableError:
cq.writeLine(fgRed, styleBright, "[-] ", getCurrentExceptionMsg()) cq.writeLine(fgRed, styleBright, "[-] ", getCurrentExceptionMsg())
cq.writeLine("") cq.writeLine("")