Files
conquest/src/server/db/dbAgent.nim
2025-08-21 15:08:52 +02:00

162 lines
6.2 KiB
Nim

import system, terminal, tiny_sqlite, times, sequtils
import ../utils
import ../../common/types
#[
Agent database functions - Updated with session key support (no jitter)
]#
proc dbStoreAgent*(cq: Conquest, agent: Agent): bool =
try:
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
# Convert session key to blob for storage
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)
conquestDb.close()
except:
cq.writeLine(fgRed, styleBright, "[ - ] ", getCurrentExceptionMsg())
return false
return true
proc dbGetAllAgents*(cq: Conquest): seq[Agent] =
var agents: 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]))
# 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.writeLine(fgYellow, styleBright, "[!] Invalid session key length for agent: ", agentId)
let a = Agent(
agentId: agentId,
listenerId: listenerId,
sleep: sleep,
pid: pid,
username: username,
hostname: hostname,
domain: domain,
ip: ip,
os: os,
elevated: elevated,
firstCheckin: parse(firstCheckin, "dd-MM-yyyy HH:mm:ss"),
latestCheckin: parse(latestCheckin, "dd-MM-yyyy HH:mm:ss"),
process: process,
sessionKey: sessionKey,
tasks: @[] # Initialize empty tasks
)
agents.add(a)
conquestDb.close()
except:
cq.writeLine(fgRed, styleBright, "[ - ] ", getCurrentExceptionMsg())
return agents
proc dbGetAllAgentsByListener*(cq: Conquest, listenerName: string): seq[Agent] =
var agents: 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]))
# Convert session key blob back to array
var sessionKey: Key
if sessionKeyBlob.len == 32:
copyMem(sessionKey[0].addr, sessionKeyBlob[0].unsafeAddr, 32)
else:
cq.writeLine(fgYellow, styleBright, "[!] Invalid session key length for agent: ", agentId)
let a = Agent(
agentId: agentId,
listenerId: listenerId,
sleep: sleep,
pid: pid,
username: username,
hostname: hostname,
domain: domain,
ip: ip,
os: os,
elevated: elevated,
firstCheckin: parse(firstCheckin, "dd-MM-yyyy HH:mm:ss"),
latestCheckin: parse(latestCheckin, "dd-MM-yyyy HH:mm:ss"),
process: process,
sessionKey: sessionKey,
tasks: @[]
)
agents.add(a)
conquestDb.close()
except:
cq.writeLine(fgRed, styleBright, "[ - ] ", getCurrentExceptionMsg())
return agents
proc dbDeleteAgentByName*(cq: Conquest, name: string): bool =
try:
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
conquestDb.exec("DELETE FROM agents WHERE name = ?", name)
conquestDb.close()
except:
cq.writeLine(fgRed, styleBright, "[ - ] ", getCurrentExceptionMsg())
return false
return true
proc dbAgentExists*(cq: Conquest, agentName: string): bool =
try:
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
let res = conquestDb.one("SELECT 1 FROM agents WHERE name = ? LIMIT 1", agentName)
conquestDb.close()
return res.isSome
except:
cq.writeLine(fgRed, styleBright, "[ - ] ", 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.writeLine(fgRed, styleBright, "[ - ] ", getCurrentExceptionMsg())
return false
proc dbUpdateSleep*(cq: Conquest, agentName: string, delay: int): bool =
try:
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
conquestDb.exec("UPDATE agents SET sleep = ? WHERE name = ?", delay, agentName)
conquestDb.close()
return true
except:
cq.writeLine(fgRed, styleBright, "[ - ] ", getCurrentExceptionMsg())
return false