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 # Agent configuration
-d:ListenerUuid="JEBFQPEP" -d:ListenerUuid="CFD80565"
-d:Octet1="127" -d:Octet1="127"
-d:Octet2="0" -d:Octet2="0"
-d:Octet3="0" -d:Octet3="0"
-d:Octet4="1" -d:Octet4="1"
-d:ListenerPort=5555 -d:ListenerPort=9999
-d:SleepDelay=5 -d:SleepDelay=10

View File

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

View File

@@ -1,9 +1,13 @@
import terminal, strformat, strutils, sequtils, tables, json, times, base64, system import terminal, strformat, strutils, sequtils, tables, json, times, base64, system
import ../globals import ../[utils, globals]
import ../db/database import ../db/database
import ../../types import ../../types
# Utility functions
proc add*(cq: Conquest, agent: Agent) =
cq.agents[agent.name] = agent
#[ #[
Agent API Agent API
Functions relevant for dealing with the agent API, such as registering new agents, querying tasks and posting results 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 sequtils, strutils, times
import ./handlers import ./handlers
import ../utils
import ../../types import ../../types
proc error404*(ctx: Context) {.async.} = proc error404*(ctx: Context) {.async.} =
@@ -38,11 +39,27 @@ proc register*(ctx: Context) {.async.} =
let let
postData: JsonNode = parseJson(ctx.request.body) postData: JsonNode = parseJson(ctx.request.body)
agentRegistrationData: AgentRegistrationData = postData.to(AgentRegistrationData) agentRegistrationData: AgentRegistrationData = postData.to(AgentRegistrationData)
agentUuid: string = generate(alphabet=join(toSeq('A'..'Z'), ""), size=8) agentUuid: string = generateUUID()
listenerUuid: string = ctx.getPathParams("listener") listenerUuid: string = ctx.getPathParams("listener")
date: DateTime = now() 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 # Fully register agent and add it to database
if not agent.register(): if not agent.register():

View File

@@ -5,9 +5,22 @@ import ../task/handler
import ../db/database import ../db/database
import ../../types import ../../types
# 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 mode Agent management
These console commands allow dealing with agents from the Conquest framework's prompt interface
]# ]#
proc agentUsage*(cq: Conquest) = proc agentUsage*(cq: Conquest) =
cq.writeLine("""Manage, build and interact with agents. 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 prologue
import ../utils import ../utils
@@ -6,6 +6,25 @@ import ../api/routes
import ../db/database import ../db/database
import ../../types 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) = proc listenerUsage*(cq: Conquest) =
cq.writeLine("""Manage, start and stop listeners. cq.writeLine("""Manage, start and stop listeners.
@@ -36,7 +55,7 @@ proc listenerStart*(cq: Conquest, host: string, portStr: string) =
# Create new listener # Create new listener
let let
name: string = generate(alphabet=join(toSeq('A'..'Z'), ""), size=8) name: string = generateUUID()
listenerSettings = newSettings( listenerSettings = newSettings(
appName = name, appName = name,
debug = false, debug = false,

View File

@@ -2,8 +2,8 @@ import prompt, terminal, argparse
import strutils, strformat, times, system, tables import strutils, strformat, times, system, tables
import ./[agent, listener] import ./[agent, listener]
import ../[globals, utils]
import ../db/database import ../db/database
import ../globals
import ../../types import ../../types
#[ #[
@@ -127,6 +127,17 @@ proc header(cq: Conquest) =
cq.writeLine("".repeat(21)) cq.writeLine("".repeat(21))
cq.writeLine("") 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*() = proc startServer*() =
# Handle CTRL+C, # Handle CTRL+C,
proc exit() {.noconv.} = proc exit() {.noconv.} =

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
import times, strformat, terminal, tables, json, sequtils, strutils import times, strformat, terminal, tables, json, sequtils, strutils
import ./[parser, packer, dispatcher] import ./[parser, packer, dispatcher]
import ../utils
import ../../types import ../../types
proc initAgentCommands*(): Table[CommandType, Command] = 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 std/wordwrap
import ../types import ../types
# Utility functions
proc parseOctets*(ip: string): tuple[first, second, third, fourth: int] = proc parseOctets*(ip: string): tuple[first, second, third, fourth: int] =
# TODO: Verify that address is in correct, expected format # TODO: Verify that address is in correct, expected format
let octets = ip.split('.') let octets = ip.split('.')
@@ -15,8 +16,33 @@ proc validatePort*(portStr: string): bool =
except ValueError: except ValueError:
return false 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 type
Cell = object Cell = object
text: string text: string

View File

@@ -1,11 +1,8 @@
import prompt import prompt
import prologue
import tables import tables
import times import times
#[ # Task structure
Agent types & procs
]#
type type
CommandType* = enum CommandType* = enum
ExecuteShell = "shell" ExecuteShell = "shell"
@@ -62,6 +59,8 @@ type
args*: string # Json string containing all the positional arguments args*: string # Json string containing all the positional arguments
# Example: """{"command": "whoami", "arguments": "/all"}""" # Example: """{"command": "whoami", "arguments": "/all"}"""
# Agent structure
type
AgentRegistrationData* = object AgentRegistrationData* = object
username*: string username*: string
hostname*: string hostname*: string
@@ -90,30 +89,7 @@ type
firstCheckin*: DateTime firstCheckin*: DateTime
latestCheckin*: DateTime latestCheckin*: DateTime
# TODO: Take sleep value from agent registration data (set via nim.cfg file) # Listener structure
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
]#
type type
Protocol* = enum Protocol* = enum
HTTP = "http" HTTP = "http"
@@ -124,24 +100,7 @@ type
port*: int port*: int
protocol*: Protocol protocol*: Protocol
proc newListener*(name: string, address: string, port: int): Listener = # Server structure
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
]#
type type
Conquest* = ref object Conquest* = ref object
prompt*: Prompt prompt*: Prompt
@@ -149,57 +108,3 @@ type
listeners*: Table[string, Listener] listeners*: Table[string, Listener]
agents*: Table[string, Agent] agents*: Table[string, Agent]
interactAgent*: 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()