Updated database to store session key (still unencrypted)

This commit is contained in:
Jakob Friedl
2025-07-23 15:25:19 +02:00
parent cb16a9c571
commit cf4e4a7017
7 changed files with 71 additions and 51 deletions

2
.gitignore vendored
View File

@@ -1,6 +1,8 @@
# Ignore agents # Ignore agents
# agents/ # agents/
*.db *.db
data/*
!data/.gitkeep
# Ignore binaries # Ignore binaries
bin/* bin/*
!bin/.gitkeep !bin/.gitkeep

View File

@@ -1,8 +1,8 @@
# Agent configuration # Agent configuration
-d:ListenerUuid="A5466110" -d:ListenerUuid="D3AC0FF3"
-d:Octet1="172" -d:Octet1="127"
-d:Octet2="29" -d:Octet2="0"
-d:Octet3="177" -d:Octet3="0"
-d:Octet4="43" -d:Octet4="1"
-d:ListenerPort=8888 -d:ListenerPort=9999
-d:SleepDelay=5 -d:SleepDelay=5

View File

@@ -45,4 +45,5 @@ proc decrypt*(key: Key, iv: Iv, encData: seq[byte], sequenceNumber: uint64): (se
ctx.getTag(tag) ctx.getTag(tag)
ctx.clear() ctx.clear()
return (data, tag) return (data, tag)

View File

@@ -150,7 +150,6 @@ type
pid*: int pid*: int
elevated*: bool elevated*: bool
sleep*: int sleep*: int
jitter*: float
tasks*: seq[Task] tasks*: seq[Task]
firstCheckin*: DateTime firstCheckin*: DateTime
latestCheckin*: DateTime latestCheckin*: DateTime

View File

@@ -33,9 +33,9 @@ proc dbInit*(cq: Conquest) =
os TEXT NOT NULL, os TEXT NOT NULL,
elevated BOOLEAN NOT NULL, elevated BOOLEAN NOT NULL,
sleep INTEGER DEFAULT 10, sleep INTEGER DEFAULT 10,
jitter REAL DEFAULT 0.1,
firstCheckin DATETIME NOT NULL, firstCheckin DATETIME NOT NULL,
latestCheckin DATETIME NOT NULL, latestCheckin DATETIME NOT NULL,
sessionKey BLOB NOT NULL,
FOREIGN KEY (listener) REFERENCES listeners(name) FOREIGN KEY (listener) REFERENCES listeners(name)
); );

View File

@@ -1,20 +1,23 @@
import system, terminal, tiny_sqlite, times import system, terminal, tiny_sqlite, times, sequtils
import ../utils import ../utils
import ../../common/[types, utils] import ../../common/[types, utils]
#[ #[
Agent database functions Agent database functions - Updated with session key support (no jitter)
]# ]#
proc dbStoreAgent*(cq: Conquest, agent: Agent): bool = proc dbStoreAgent*(cq: Conquest, agent: Agent): bool =
try: try:
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite) let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
# Convert session key to blob for storage
let sessionKeyBlob = agent.sessionKey.toSeq()
conquestDb.exec(""" conquestDb.exec("""
INSERT INTO agents (name, listener, process, pid, username, hostname, domain, ip, os, elevated, sleep, jitter, firstCheckin, latestCheckin) INSERT INTO agents (name, listener, process, pid, username, hostname, domain, ip, os, elevated, sleep, firstCheckin, latestCheckin, sessionKey)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""", agent.agentId, agent.listenerId, agent.process, agent.pid, agent.username, agent.hostname, agent.domain, agent.ip, agent.os, agent.elevated, agent.sleep, agent.jitter, agent.firstCheckin.format("dd-MM-yyyy HH:mm:ss"), agent.latestCheckin.format("dd-MM-yyyy HH:mm:ss")) """, 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() conquestDb.close()
except: except:
@@ -24,31 +27,39 @@ proc dbStoreAgent*(cq: Conquest, agent: Agent): bool =
return true return true
proc dbGetAllAgents*(cq: Conquest): seq[Agent] = proc dbGetAllAgents*(cq: Conquest): seq[Agent] =
var agents: seq[Agent] = @[] var agents: seq[Agent] = @[]
try: try:
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite) let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
for row in conquestDb.iterate("SELECT name, listener, sleep, jitter, process, pid, username, hostname, domain, ip, os, elevated, firstCheckin, latestCheckin FROM agents;"): 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, jitter, process, pid, username, hostname, domain, ip, os, elevated, firstCheckin, latestCheckin) = row.unpack((string, string, int, float, string, int, string, string, string, string, string, bool, string, string)) 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( let a = Agent(
agentId: agentId, agentId: agentId,
listenerId: listenerId, listenerId: listenerId,
sleep: sleep, sleep: sleep,
pid: pid, pid: pid,
username: username, username: username,
hostname: hostname, hostname: hostname,
domain: domain, domain: domain,
ip: ip, ip: ip,
os: os, os: os,
elevated: elevated, elevated: elevated,
firstCheckin: parse(firstCheckin, "dd-MM-yyyy HH:mm:ss"), firstCheckin: parse(firstCheckin, "dd-MM-yyyy HH:mm:ss"),
latestCheckin: parse(latestCheckin, "dd-MM-yyyy HH:mm:ss"), latestCheckin: parse(latestCheckin, "dd-MM-yyyy HH:mm:ss"),
jitter: jitter, process: process,
process: process sessionKey: sessionKey,
) tasks: @[] # Initialize empty tasks
)
agents.add(a) agents.add(a)
@@ -59,31 +70,38 @@ proc dbGetAllAgents*(cq: Conquest): seq[Agent] =
return agents return agents
proc dbGetAllAgentsByListener*(cq: Conquest, listenerName: string): seq[Agent] = proc dbGetAllAgentsByListener*(cq: Conquest, listenerName: string): seq[Agent] =
var agents: seq[Agent] = @[] var agents: seq[Agent] = @[]
try: try:
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite) let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
for row in conquestDb.iterate("SELECT name, listener, sleep, jitter, process, pid, username, hostname, domain, ip, os, elevated, firstCheckin, latestCheckin FROM agents WHERE listener = ?;", listenerName): 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, jitter, process, pid, username, hostname, domain, ip, os, elevated, firstCheckin, latestCheckin) = row.unpack((string, string, int, float, string, int, string, string, string, string, string, bool, string, string)) 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( let a = Agent(
agentId: agentId, agentId: agentId,
listenerId: listenerId, listenerId: listenerId,
sleep: sleep, sleep: sleep,
pid: pid, pid: pid,
username: username, username: username,
hostname: hostname, hostname: hostname,
domain: domain, domain: domain,
ip: ip, ip: ip,
os: os, os: os,
elevated: elevated, elevated: elevated,
firstCheckin: parse(firstCheckin, "dd-MM-yyyy HH:mm:ss"), firstCheckin: parse(firstCheckin, "dd-MM-yyyy HH:mm:ss"),
latestCheckin: parse(latestCheckin, "dd-MM-yyyy HH:mm:ss"), latestCheckin: parse(latestCheckin, "dd-MM-yyyy HH:mm:ss"),
jitter: jitter, process: process,
process: process, sessionKey: sessionKey,
) tasks: @[]
)
agents.add(a) agents.add(a)
@@ -101,6 +119,7 @@ proc dbDeleteAgentByName*(cq: Conquest, name: string): bool =
conquestDb.close() conquestDb.close()
except: except:
cq.writeLine(fgRed, styleBright, "[-] ", getCurrentExceptionMsg())
return false return false
return true return true

View File

@@ -132,7 +132,6 @@ proc deserializeNewAgent*(cq: Conquest, data: seq[byte]): Agent =
pid: int(pid), pid: int(pid),
elevated: isElevated != 0, elevated: isElevated != 0,
sleep: int(sleep), sleep: int(sleep),
jitter: 0.0, # TODO: Remove jitter
tasks: @[], tasks: @[],
firstCheckin: now(), firstCheckin: now(),
latestCheckin: now(), latestCheckin: now(),