Cleanup types.nim to only contain type definitions.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,12 +39,28 @@ 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():
|
||||||
# Either the listener the agent tries to connect to does not exist in the database, or the insertion of the agent failed
|
# Either the listener the agent tries to connect to does not exist in the database, or the insertion of the agent failed
|
||||||
|
|||||||
@@ -5,10 +5,23 @@ import ../task/handler
|
|||||||
import ../db/database
|
import ../db/database
|
||||||
import ../../types
|
import ../../types
|
||||||
|
|
||||||
#[
|
# Utility functions
|
||||||
Agent management mode
|
proc addMultiple*(cq: Conquest, agents: seq[Agent]) =
|
||||||
These console commands allow dealing with agents from the Conquest framework's prompt interface
|
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) =
|
proc agentUsage*(cq: Conquest) =
|
||||||
cq.writeLine("""Manage, build and interact with agents.
|
cq.writeLine("""Manage, build and interact with agents.
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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.} =
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import system, terminal, tiny_sqlite, times
|
import system, terminal, tiny_sqlite, times
|
||||||
|
|
||||||
|
import ../utils
|
||||||
import ../../types
|
import ../../types
|
||||||
|
|
||||||
#[
|
#[
|
||||||
|
|||||||
@@ -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
|
||||||
]#
|
]#
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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] =
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
107
src/types.nim
107
src/types.nim
@@ -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,82 +100,11 @@ 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
|
||||||
dbPath*: string
|
dbPath*: string
|
||||||
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()
|
|
||||||
Reference in New Issue
Block a user