Removed unused code.
This commit is contained in:
@@ -3,6 +3,6 @@
|
||||
-d:release
|
||||
--opt:size
|
||||
--passL:"-s" # Strip symbols, such as sensitive function names
|
||||
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
||||
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
||||
-d:MODULES="255"
|
||||
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
||||
@@ -279,7 +279,6 @@ type
|
||||
listeners*: Table[string, Listener]
|
||||
threads*: Table[string, Thread[Listener]]
|
||||
agents*: Table[string, Agent]
|
||||
interactAgent*: Agent
|
||||
keyPair*: KeyPair
|
||||
profile*: Profile
|
||||
client*: UIClient
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import terminal, strformat, strutils, tables, times, system, parsetoml
|
||||
import terminal, strformat, strutils, tables, system, parsetoml
|
||||
|
||||
import ../utils
|
||||
import ../core/logger
|
||||
import ../db/database
|
||||
import ../../common/types
|
||||
import ../websocket
|
||||
|
||||
# Terminate agent and remove it from the database
|
||||
proc agentKill*(cq: Conquest, name: string) =
|
||||
@@ -17,7 +15,6 @@ proc agentKill*(cq: Conquest, name: string) =
|
||||
# TODO: Stop the process of the agent on the target system
|
||||
# TODO: Add flag to self-delete executable after killing agent
|
||||
|
||||
|
||||
# Remove the agent from the database
|
||||
if not cq.dbDeleteAgentByName(name.toUpperAscii):
|
||||
cq.error("Failed to terminate agent: ", getCurrentExceptionMsg())
|
||||
|
||||
@@ -3,7 +3,7 @@ import terminal, strformat, strutils, sequtils, tables, system, osproc, streams,
|
||||
import ../globals
|
||||
import ../core/logger
|
||||
import ../db/database
|
||||
import ../../common/[types, utils, profile, serialize, crypto]
|
||||
import ../../common/[types, utils, serialize, crypto]
|
||||
|
||||
const PLACEHOLDER = "PLACEHOLDER"
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ import strformat, strutils, terminal
|
||||
import mummy, mummy/routers
|
||||
import parsetoml
|
||||
|
||||
import ../globals
|
||||
import ../utils
|
||||
import ../api/routes
|
||||
import ../db/database
|
||||
import ../core/logger
|
||||
|
||||
@@ -11,14 +11,15 @@ proc makeAgentLogDirectory*(cq: Conquest, agentId: string): bool =
|
||||
except OSError:
|
||||
return false
|
||||
|
||||
proc log*(cq: Conquest, logEntry: string) =
|
||||
# TODO: Fix issue where log files are written to the wrong agent when the interact agent is changed in the middle of command execution
|
||||
# Though that problem would not occur when a proper GUI is used in the future
|
||||
let agentLogPath = fmt"{CONQUEST_ROOT}/data/logs/{cq.interactAgent.agentId}/session.log"
|
||||
|
||||
proc log*(cq: Conquest, agentId: string = "", logEntry: string) =
|
||||
# Write log entry to file
|
||||
let file = open(agentLogPath, fmAppend)
|
||||
file.writeLine(fmt"{logEntry}")
|
||||
var logFile: string
|
||||
if agentId.isEmptyOrWhitespace():
|
||||
logFile = fmt"{CONQUEST_ROOT}/data/logs/events.log"
|
||||
else:
|
||||
logFile = fmt"{CONQUEST_ROOT}/data/logs/{agentId}/session.log"
|
||||
let file = open(logFile, fmAppend)
|
||||
file.writeLine(logEntry)
|
||||
file.flushFile()
|
||||
|
||||
proc extractStrings*(args: string): string =
|
||||
@@ -38,8 +39,7 @@ proc getTimestamp*(): string =
|
||||
# Function templates and overwrites
|
||||
template writeLine*(cq: Conquest, args: varargs[untyped] = "") =
|
||||
stdout.styledWriteLine(args)
|
||||
if cq.interactAgent != nil:
|
||||
cq.log(extractStrings($(args)))
|
||||
# cq.log(extractStrings($(args)))
|
||||
|
||||
# Wrapper functions for logging/console output
|
||||
template info*(cq: Conquest, args: varargs[untyped] = "") =
|
||||
@@ -54,11 +54,5 @@ template success*(cq: Conquest, args: varargs[untyped] = "") =
|
||||
template warning*(cq: Conquest, args: varargs[untyped] = "") =
|
||||
cq.writeLine(fgBlack, styleBright, fmt"[{getTimestamp()}]", fgYellow, styleDim, $LOG_WARNING, resetStyle, args)
|
||||
|
||||
template input*(cq: Conquest, args: varargs[untyped] = "") =
|
||||
if cq.interactAgent != nil:
|
||||
cq.writeLine(fgBlue, styleBright, fmt"[{getTimestamp()}] ", fgYellow, fmt"[{cq.interactAgent.agentId}] ", resetStyle, args)
|
||||
else:
|
||||
cq.writeLine(fgBlue, styleBright, fmt"[{getTimestamp()}] ", resetStyle, args)
|
||||
|
||||
template output*(cq: Conquest, args: varargs[untyped] = "") =
|
||||
cq.writeLine(args)
|
||||
132
src/server/core/server.nim
Normal file
132
src/server/core/server.nim
Normal file
@@ -0,0 +1,132 @@
|
||||
import prompt, terminal, argparse, parsetoml, times, json, math
|
||||
import strutils, strformat, system, tables
|
||||
|
||||
import ./[agent, listener, builder]
|
||||
import ../globals
|
||||
import ../db/database
|
||||
import ../core/logger
|
||||
import ../../common/[types, crypto, utils, profile, event]
|
||||
import ../websocket
|
||||
import mummy, mummy/routers
|
||||
|
||||
proc header() =
|
||||
echo ""
|
||||
echo "┏┏┓┏┓┏┓┓┏┏┓┏╋"
|
||||
echo "┗┗┛┛┗┗┫┗┻┗ ┛┗ V0.1"
|
||||
echo " ┗ @jakobfriedl"
|
||||
echo "─".repeat(21)
|
||||
echo ""
|
||||
|
||||
proc init*(T: type Conquest, profile: Profile): Conquest =
|
||||
var cq = new Conquest
|
||||
cq.listeners = initTable[string, Listener]()
|
||||
cq.threads = initTable[string, Thread[Listener]]()
|
||||
cq.agents = initTable[string, Agent]()
|
||||
cq.interactAgent = nil
|
||||
cq.profile = profile
|
||||
cq.keyPair = loadKeyPair(CONQUEST_ROOT & "/" & profile.getString("private-key-file"))
|
||||
cq.dbPath = CONQUEST_ROOT & "/" & profile.getString("database-file")
|
||||
cq.client = nil
|
||||
return cq
|
||||
|
||||
#[
|
||||
WebSocket
|
||||
]#
|
||||
proc upgradeHandler(request: Request) =
|
||||
{.cast(gcsafe).}:
|
||||
let ws = request.upgradeToWebSocket()
|
||||
cq.client = UIClient(
|
||||
ws: ws
|
||||
)
|
||||
|
||||
proc websocketHandler(ws: WebSocket, event: WebSocketEvent, message: Message) {.gcsafe.} =
|
||||
{.cast(gcsafe).}:
|
||||
case event:
|
||||
of OpenEvent:
|
||||
# New client connected to team server
|
||||
# Send profile, sessions and listeners to the UI client
|
||||
cq.client.sendProfile(cq.profile)
|
||||
for id, listener in cq.listeners:
|
||||
cq.client.sendListener(listener)
|
||||
for id, agent in cq.agents:
|
||||
cq.client.sendAgent(agent)
|
||||
cq.client.sendEventlogItem(LOG_SUCCESS_SHORT, "CQ-V1")
|
||||
|
||||
of MessageEvent:
|
||||
# Continuously send heartbeat messages
|
||||
ws.sendHeartbeat()
|
||||
|
||||
let event = message.recvEvent()
|
||||
|
||||
case event.eventType:
|
||||
of CLIENT_AGENT_TASK:
|
||||
let agentId = event.data["agentId"].getStr()
|
||||
let task = event.data["task"].to(Task)
|
||||
cq.agents[agentId].tasks.add(task)
|
||||
|
||||
of CLIENT_LISTENER_START:
|
||||
let listener = event.data.to(UIListener)
|
||||
cq.listenerStart(listener.listenerId, listener.address, listener.port, listener.protocol)
|
||||
|
||||
of CLIENT_LISTENER_STOP:
|
||||
let listenerId = event.data["listenerId"].getStr()
|
||||
cq.listenerStop(listenerId)
|
||||
|
||||
of CLIENT_AGENT_BUILD:
|
||||
let
|
||||
listenerId = event.data["listenerId"].getStr()
|
||||
sleepDelay = event.data["sleepDelay"].getInt()
|
||||
sleepTechnique = cast[SleepObfuscationTechnique](event.data["sleepTechnique"].getInt())
|
||||
spoofStack = event.data["spoofStack"].getBool()
|
||||
modules = cast[uint32](event.data["modules"].getInt())
|
||||
|
||||
let payload = cq.agentBuild(listenerId, sleepDelay, sleepTechnique, spoofStack, modules)
|
||||
if payload.len() != 0:
|
||||
cq.client.sendAgentPayload(payload)
|
||||
|
||||
else: discard
|
||||
|
||||
of ErrorEvent:
|
||||
discard
|
||||
of CloseEvent:
|
||||
# Set the client instance to nil again to prevent debug error messages
|
||||
cq.client = nil
|
||||
|
||||
proc startServer*(profilePath: string) =
|
||||
|
||||
# Ensure that the conquest root directory was passed as a compile-time define
|
||||
when not defined(CONQUEST_ROOT):
|
||||
quit(0)
|
||||
|
||||
header()
|
||||
|
||||
try:
|
||||
# Initialize framework context
|
||||
# Load and parse profile
|
||||
let profile = parsetoml.parseFile(profilePath)
|
||||
cq = Conquest.init(profile)
|
||||
|
||||
cq.info("Using profile \"", profile.getString("name"), "\" (", profilePath ,").")
|
||||
|
||||
except CatchableError as err:
|
||||
echo err.msg
|
||||
quit(0)
|
||||
|
||||
# Initialize database
|
||||
cq.dbInit()
|
||||
for agent in cq.dbGetAllAgents():
|
||||
cq.agents[agent.agentId] = agent
|
||||
for listener in cq.dbGetAllListeners():
|
||||
cq.listeners[listener.listenerId] = listener
|
||||
|
||||
# Restart existing listeners
|
||||
for listenerId, listener in cq.listeners:
|
||||
cq.listenerStart(listenerId, listener.address, listener.port, listener.protocol)
|
||||
|
||||
# Start websocket server
|
||||
var router: Router
|
||||
router.get("/*", upgradeHandler)
|
||||
|
||||
# Increased websocket message length in order to support dotnet assembly execution
|
||||
let server = newServer(router, websocketHandler, maxMessageLen = 1024 * 1024 * 1024)
|
||||
server.serve(Port(cq.profile.getInt("team-server.port")), "0.0.0.0")
|
||||
@@ -1,11 +1,11 @@
|
||||
import terminal, parsetoml, times, json, math
|
||||
import terminal, parsetoml, json, math
|
||||
import strutils, strformat, system, tables
|
||||
|
||||
import ./core/[agent, listener, builder]
|
||||
import ./core/[listener, builder]
|
||||
import ./globals
|
||||
import ./db/database
|
||||
import ./core/logger
|
||||
import ../common/[types, crypto, utils, profile, event]
|
||||
import ../common/[types, crypto, profile, event]
|
||||
import ./websocket
|
||||
import mummy, mummy/routers
|
||||
|
||||
@@ -22,7 +22,6 @@ proc init*(T: type Conquest, profile: Profile): Conquest =
|
||||
cq.listeners = initTable[string, Listener]()
|
||||
cq.threads = initTable[string, Thread[Listener]]()
|
||||
cq.agents = initTable[string, Agent]()
|
||||
cq.interactAgent = nil
|
||||
cq.profile = profile
|
||||
cq.keyPair = loadKeyPair(CONQUEST_ROOT & "/" & profile.getString("private-key-file"))
|
||||
cq.dbPath = CONQUEST_ROOT & "/" & profile.getString("database-file")
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import times, json
|
||||
import ../common/types
|
||||
|
||||
proc `%`*(agent: Agent): JsonNode =
|
||||
result = newJObject()
|
||||
result["agentId"] = %agent.agentId
|
||||
result["listenerId"] = %agent.listenerId
|
||||
result["username"] = %agent.username
|
||||
result["hostname"] = %agent.hostname
|
||||
result["domain"] = %agent.domain
|
||||
result["ip"] = %agent.ip
|
||||
result["os"] = %agent.os
|
||||
result["process"] = %agent.process
|
||||
result["pid"] = %agent.pid
|
||||
result["elevated"] = %agent.elevated
|
||||
result["sleep"] = %agent.sleep
|
||||
result["firstCheckin"] = %agent.firstCheckin.toTime().toUnix()
|
||||
result["latestCheckin"] = %agent.latestCheckin.toTime().toUnix()
|
||||
|
||||
proc `%`*(listener: Listener): JsonNode =
|
||||
result = newJObject()
|
||||
result["listenerId"] = %listener.listenerId
|
||||
result["address"] = %listener.address
|
||||
result["port"] = %listener.port
|
||||
result["protocol"] = %listener.protocol
|
||||
@@ -1,9 +1,31 @@
|
||||
import mummy
|
||||
import times, tables, json, base64, parsetoml
|
||||
import ./utils
|
||||
import ../common/[types, utils, serialize, event]
|
||||
import times, json, base64, parsetoml
|
||||
import ../common/[types, event]
|
||||
|
||||
export sendHeartbeat, recvEvent
|
||||
|
||||
proc `%`*(agent: Agent): JsonNode =
|
||||
result = newJObject()
|
||||
result["agentId"] = %agent.agentId
|
||||
result["listenerId"] = %agent.listenerId
|
||||
result["username"] = %agent.username
|
||||
result["hostname"] = %agent.hostname
|
||||
result["domain"] = %agent.domain
|
||||
result["ip"] = %agent.ip
|
||||
result["os"] = %agent.os
|
||||
result["process"] = %agent.process
|
||||
result["pid"] = %agent.pid
|
||||
result["elevated"] = %agent.elevated
|
||||
result["sleep"] = %agent.sleep
|
||||
result["firstCheckin"] = %agent.firstCheckin.toTime().toUnix()
|
||||
result["latestCheckin"] = %agent.latestCheckin.toTime().toUnix()
|
||||
|
||||
proc `%`*(listener: Listener): JsonNode =
|
||||
result = newJObject()
|
||||
result["listenerId"] = %listener.listenerId
|
||||
result["address"] = %listener.address
|
||||
result["port"] = %listener.port
|
||||
result["protocol"] = %listener.protocol
|
||||
|
||||
#[
|
||||
Server -> Client
|
||||
]#
|
||||
|
||||
Reference in New Issue
Block a user