2025-08-19 20:03:34 +02:00
import terminal , strformat , strutils , tables , times , system , parsetoml
2025-05-12 21:53:37 +02:00
2025-07-28 21:29:47 +02:00
import . / task
2025-07-15 23:26:54 +02:00
import .. / utils
import .. / db / database
2025-08-19 20:03:34 +02:00
import .. / .. / common / types
2025-05-12 21:53:37 +02:00
2025-07-16 14:45:45 +02:00
# Utility functions
proc addMultiple * ( cq : Conquest , agents : seq [ Agent ] ) =
for a in agents :
2025-07-21 22:07:25 +02:00
cq . agents [ a . agentId ] = a
2025-07-16 14:45:45 +02:00
proc delAgent * ( cq : Conquest , agentName : string ) =
cq . agents . del ( agentName )
proc getAgentsAsSeq * ( cq : Conquest ) : seq [ Agent ] =
var agents : seq [ Agent ] = @ [ ]
for agent in cq . agents . values :
agents . add ( agent )
return agents
#[
Agent management
] #
2025-05-12 21:53:37 +02:00
proc agentUsage * ( cq : Conquest ) =
cq . writeLine ( """ Manage, build and interact with agents.
Usage :
agent [ options ] COMMAND
Commands :
list List all agents .
2025-05-15 14:27:45 +02:00
info Display details for a specific agent .
2025-05-14 15:48:01 +02:00
kill Terminate the connection of an active listener and remove it from the interface .
2025-05-12 21:53:37 +02:00
interact Interact with an active agent .
2025-08-18 22:05:23 +02:00
build Generate a new agent to connect to an active listener .
2025-05-12 21:53:37 +02:00
Options :
- h , - - help""" )
2025-05-14 15:48:01 +02:00
# List agents
2025-05-15 14:27:45 +02:00
proc agentList * ( cq : Conquest , listener : string ) =
2025-05-15 15:24:46 +02:00
# If no argument is passed via -n, list all agents, otherwise only display agents connected to a specific listener
if listener = = " " :
cq . drawTable ( cq . dbGetAllAgents ( ) )
2025-05-29 14:19:55 +02:00
2025-05-15 15:24:46 +02:00
else :
# Check if listener exists
if not cq . dbListenerExists ( listener . toUpperAscii ) :
cq . writeLine ( fgRed , styleBright , fmt" [-] Listener {listener.toUpperAscii} does not exist. " )
return
2025-05-15 14:27:45 +02:00
2025-05-15 15:24:46 +02:00
cq . drawTable ( cq . dbGetAllAgentsByListener ( listener . toUpperAscii ) )
2025-05-15 14:27:45 +02:00
2025-05-29 14:19:55 +02:00
2025-05-15 14:27:45 +02:00
# Display agent properties and details
proc agentInfo * ( cq : Conquest , name : string ) =
# Check if agent supplied via -n parameter exists in database
if not cq . dbAgentExists ( name . toUpperAscii ) :
cq . writeLine ( fgRed , styleBright , fmt" [-] Agent {name.toUpperAscii} does not exist. " )
return
let agent = cq . agents [ name . toUpperAscii ]
2025-05-15 15:24:46 +02:00
# TODO: Improve formatting
2025-05-15 14:27:45 +02:00
cq . writeLine ( fmt"""
2025-07-21 22:07:25 +02:00
Agent name ( UUID ) : { agent . agentId }
Connected to listener : { agent . listenerId }
2025-05-15 14:27:45 +02:00
──────────────────────────────────────────
Username : { agent . username }
Hostname : { agent . hostname }
Domain : { agent . domain }
IP - Address : { agent . ip }
Operating system : { agent . os }
──────────────────────────────────────────
Process name : { agent . process }
Process ID : { $ agent . pid }
Process elevated : { $ agent . elevated }
2025-05-23 13:55:00 +02:00
First checkin : { agent . firstCheckin . format ( " dd-MM-yyyy HH:mm:ss " ) }
Latest checkin : { agent . latestCheckin . format ( " dd-MM-yyyy HH:mm:ss " ) }
""" )
2025-05-15 14:27:45 +02:00
2025-05-14 15:48:01 +02:00
# Terminate agent and remove it from the database
proc agentKill * ( cq : Conquest , name : string ) =
# Check if agent supplied via -n parameter exists in database
if not cq . dbAgentExists ( name . toUpperAscii ) :
cq . writeLine ( fgRed , styleBright , fmt" [-] Agent {name.toUpperAscii} does not exist. " )
return
# TODO: Stop the process of the agent on the target system
# TODO: Add flag to self-delete executable after killing agent
# Remove the agent from the database
if not cq . dbDeleteAgentByName ( name . toUpperAscii ) :
cq . writeLine ( fgRed , styleBright , " [-] Failed to terminate agent: " , getCurrentExceptionMsg ( ) )
return
cq . delAgent ( name )
cq . writeLine ( fgYellow , styleBright , " [+] " , resetStyle , " Terminated agent " , fgYellow , styleBright , name . toUpperAscii , resetStyle , " . " )
2025-05-12 21:53:37 +02:00
# Switch to interact mode
2025-05-18 12:51:26 +02:00
proc agentInteract * ( cq : Conquest , name : string ) =
2025-05-12 21:53:37 +02:00
2025-05-18 12:51:26 +02:00
# Verify that agent exists
if not cq . dbAgentExists ( name . toUpperAscii ) :
cq . writeLine ( fgRed , styleBright , fmt" [-] Agent {name.toUpperAscii} does not exist. " )
return
let agent = cq . agents [ name . toUpperAscii ]
var command : string = " "
# Change prompt indicator to show agent interaction
2025-07-21 22:07:25 +02:00
cq . setIndicator ( fmt" [{agent.agentId}]> " )
2025-05-18 12:51:26 +02:00
cq . setStatusBar ( @ [ ( " [mode] " , " interact " ) , ( " [username] " , fmt" {agent.username} " ) , ( " [hostname] " , fmt" {agent.hostname} " ) , ( " [ip] " , fmt" {agent.ip} " ) , ( " [domain] " , fmt" {agent.domain} " ) ] )
2025-07-21 22:07:25 +02:00
cq . writeLine ( fgYellow , styleBright , " [+] " , resetStyle , fmt" Started interacting with agent " , fgYellow , styleBright , agent . agentId , resetStyle , " . Type ' help ' to list available commands. \n " )
2025-05-18 12:51:26 +02:00
cq . interactAgent = agent
2025-05-22 20:03:22 +02:00
while command . replace ( " " , " " ) ! = " back " :
2025-05-18 12:51:26 +02:00
command = cq . readLine ( )
cq . withOutput ( handleAgentCommand , command )
2025-05-12 21:53:37 +02:00
2025-05-18 12:51:26 +02:00
cq . interactAgent = nil
2025-05-12 21:53:37 +02:00