Added build log to client UI.
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="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
||||||
-d:MODULES="66"
|
-d:MODULES="12"
|
||||||
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
||||||
@@ -2,6 +2,7 @@ import whisky
|
|||||||
import tables, strutils, strformat, json, parsetoml, base64, os # native_dialogs
|
import tables, strutils, strformat, json, parsetoml, base64, os # native_dialogs
|
||||||
import ./utils/[appImGui, globals]
|
import ./utils/[appImGui, globals]
|
||||||
import ./views/[dockspace, sessions, listeners, eventlog, console]
|
import ./views/[dockspace, sessions, listeners, eventlog, console]
|
||||||
|
import ./views/modals/generatePayload
|
||||||
import ../common/[types, utils, crypto]
|
import ../common/[types, utils, crypto]
|
||||||
import ./websocket
|
import ./websocket
|
||||||
|
|
||||||
@@ -118,6 +119,10 @@ proc main(ip: string = "localhost", port: int = 37573) =
|
|||||||
except IOError:
|
except IOError:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
# Close and reset the payload generation modal window when the payload was received
|
||||||
|
listenersTable.generatePayloadModal.resetModalValues()
|
||||||
|
igClosePopupToLevel(0, false)
|
||||||
|
|
||||||
of CLIENT_CONSOLE_ITEM:
|
of CLIENT_CONSOLE_ITEM:
|
||||||
let agentId = event.data["agentId"].getStr()
|
let agentId = event.data["agentId"].getStr()
|
||||||
consoles[agentId].addItem(
|
consoles[agentId].addItem(
|
||||||
@@ -133,6 +138,13 @@ proc main(ip: string = "localhost", port: int = 37573) =
|
|||||||
event.timestamp
|
event.timestamp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
of CLIENT_BUILDLOG_ITEM:
|
||||||
|
listenersTable.generatePayloadModal.addBuildlogItem(
|
||||||
|
cast[LogType](event.data["logType"].getInt()),
|
||||||
|
event.data["message"].getStr(),
|
||||||
|
event.timestamp
|
||||||
|
)
|
||||||
|
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
# Draw/update UI components/views
|
# Draw/update UI components/views
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ proc draw*(component: ConsoleComponent, connection: WsConnection) =
|
|||||||
var labelSize: ImVec2
|
var labelSize: ImVec2
|
||||||
igCalcTextSize(addr labelSize, ICON_FA_MAGNIFYING_GLASS, nil, false, 0.0f)
|
igCalcTextSize(addr labelSize, ICON_FA_MAGNIFYING_GLASS, nil, false, 0.0f)
|
||||||
|
|
||||||
let searchBoxWidth: float32 = 200.0f
|
let searchBoxWidth: float32 = 400.0f
|
||||||
igSameLine(0.0f, availableSize.x - (labelSize.x + textSpacing) - searchBoxWidth)
|
igSameLine(0.0f, availableSize.x - (labelSize.x + textSpacing) - searchBoxWidth)
|
||||||
|
|
||||||
# Show tooltip when hovering the search icon
|
# Show tooltip when hovering the search icon
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import strutils, sequtils
|
import strutils, sequtils, times
|
||||||
import imguin/[cimgui, glfw_opengl, simple]
|
import imguin/[cimgui, glfw_opengl, simple]
|
||||||
import ../../utils/[appImGui, colors]
|
import ../../utils/[appImGui, colors]
|
||||||
import ../../../common/[types, profile, utils]
|
import ../../../common/[types, profile, utils]
|
||||||
@@ -13,6 +13,8 @@ type
|
|||||||
spoofStack: bool
|
spoofStack: bool
|
||||||
sleepMaskTechniques: seq[string]
|
sleepMaskTechniques: seq[string]
|
||||||
moduleSelection: DualListSelectionComponent[Module]
|
moduleSelection: DualListSelectionComponent[Module]
|
||||||
|
buildLog: ConsoleItems
|
||||||
|
|
||||||
|
|
||||||
proc AgentModal*(): AgentModalComponent =
|
proc AgentModal*(): AgentModalComponent =
|
||||||
result = new AgentModalComponent
|
result = new AgentModalComponent
|
||||||
@@ -36,12 +38,42 @@ proc AgentModal*(): AgentModalComponent =
|
|||||||
|
|
||||||
result.moduleSelection = DualListSelection(modules, moduleName, compareModules, moduleDesc)
|
result.moduleSelection = DualListSelection(modules, moduleName, compareModules, moduleDesc)
|
||||||
|
|
||||||
proc resetModalValues(component: AgentModalComponent) =
|
result.buildlog = new ConsoleItems
|
||||||
|
result.buildLog.items = @[]
|
||||||
|
|
||||||
|
proc resetModalValues*(component: AgentModalComponent) =
|
||||||
component.listener = 0
|
component.listener = 0
|
||||||
component.sleepDelay = 5
|
component.sleepDelay = 5
|
||||||
component.sleepMask = 0
|
component.sleepMask = 0
|
||||||
component.spoofStack = false
|
component.spoofStack = false
|
||||||
component.moduleSelection.reset()
|
component.moduleSelection.reset()
|
||||||
|
component.buildLog.items = @[]
|
||||||
|
|
||||||
|
proc addBuildlogItem*(component: AgentModalComponent, itemType: LogType, data: string, timestamp: int64 = now().toTime().toUnix()) =
|
||||||
|
for line in data.split("\n"):
|
||||||
|
component.buildLog.items.add(ConsoleItem(
|
||||||
|
timestamp: timestamp,
|
||||||
|
itemType: itemType,
|
||||||
|
text: line
|
||||||
|
))
|
||||||
|
|
||||||
|
proc print(component: AgentModalComponent, item: ConsoleItem) =
|
||||||
|
case item.itemType:
|
||||||
|
of LOG_INFO, LOG_INFO_SHORT:
|
||||||
|
igTextColored(CONSOLE_INFO, $item.itemType)
|
||||||
|
of LOG_ERROR, LOG_ERROR_SHORT:
|
||||||
|
igTextColored(CONSOLE_ERROR, $item.itemType)
|
||||||
|
of LOG_SUCCESS, LOG_SUCCESS_SHORT:
|
||||||
|
igTextColored(CONSOLE_SUCCESS, $item.itemType)
|
||||||
|
of LOG_WARNING, LOG_WARNING_SHORT:
|
||||||
|
igTextColored(CONSOLE_WARNING, $item.itemType)
|
||||||
|
of LOG_COMMAND:
|
||||||
|
igTextColored(CONSOLE_COMMAND, $item.itemType)
|
||||||
|
of LOG_OUTPUT:
|
||||||
|
igTextColored(vec4(0.0f, 0.0f, 0.0f, 0.0f), $item.itemType)
|
||||||
|
|
||||||
|
igSameLine(0.0f, 0.0f)
|
||||||
|
igTextUnformatted(item.text.cstring, nil)
|
||||||
|
|
||||||
proc draw*(component: AgentModalComponent, listeners: seq[UIListener]): AgentBuildInformation =
|
proc draw*(component: AgentModalComponent, listeners: seq[UIListener]): AgentBuildInformation =
|
||||||
|
|
||||||
@@ -109,6 +141,38 @@ proc draw*(component: AgentModalComponent, listeners: seq[UIListener]): AgentBui
|
|||||||
igSeparator()
|
igSeparator()
|
||||||
igDummy(vec2(0.0f, 10.0f))
|
igDummy(vec2(0.0f, 10.0f))
|
||||||
|
|
||||||
|
igText("Build log: ")
|
||||||
|
try:
|
||||||
|
# Set styles of the eventlog window
|
||||||
|
igPushStyleColor_Vec4(ImGui_Col_FrameBg.int32, vec4(0.1f, 0.1f, 0.1f, 1.0f))
|
||||||
|
igPushStyleColor_Vec4(ImGui_Col_ScrollbarBg.int32, vec4(0.1f, 0.1f, 0.1f, 1.0f))
|
||||||
|
igPushStyleColor_Vec4(ImGui_Col_Border.int32, vec4(0.2f, 0.2f, 0.2f, 1.0f))
|
||||||
|
igPushStyleVar_Float(ImGui_StyleVar_FrameBorderSize .int32, 1.0f)
|
||||||
|
|
||||||
|
let buildLogHeight = 250.0f
|
||||||
|
let childWindowFlags = ImGuiChildFlags_NavFlattened.int32 or ImGui_ChildFlags_Borders.int32 or ImGui_ChildFlags_AlwaysUseWindowPadding.int32 or ImGuiChildFlags_FrameStyle.int32
|
||||||
|
if igBeginChild_Str("##Log", vec2(-1.0f, buildLogHeight), childWindowFlags, ImGuiWindowFlags_HorizontalScrollbar.int32):
|
||||||
|
# Display eventlog items
|
||||||
|
for item in component.buildLog.items:
|
||||||
|
component.print(item)
|
||||||
|
|
||||||
|
# Auto-scroll to bottom
|
||||||
|
if igGetScrollY() >= igGetScrollMaxY():
|
||||||
|
igSetScrollHereY(1.0f)
|
||||||
|
|
||||||
|
except IndexDefect:
|
||||||
|
# CTRL+A crashes when no items are in the eventlog
|
||||||
|
discard
|
||||||
|
|
||||||
|
finally:
|
||||||
|
igPopStyleColor(3)
|
||||||
|
igPopStyleVar(1)
|
||||||
|
igEndChild()
|
||||||
|
|
||||||
|
igDummy(vec2(0.0f, 10.0f))
|
||||||
|
igSeparator()
|
||||||
|
igDummy(vec2(0.0f, 10.0f))
|
||||||
|
|
||||||
# Enable "Build" button if at least one module has been selected
|
# Enable "Build" button if at least one module has been selected
|
||||||
igBeginDisabled(component.moduleSelection.items[1].len() == 0)
|
igBeginDisabled(component.moduleSelection.items[1].len() == 0)
|
||||||
|
|
||||||
@@ -127,9 +191,6 @@ proc draw*(component: AgentModalComponent, listeners: seq[UIListener]): AgentBui
|
|||||||
modules: modules
|
modules: modules
|
||||||
)
|
)
|
||||||
|
|
||||||
component.resetModalValues()
|
|
||||||
igCloseCurrentPopup()
|
|
||||||
|
|
||||||
igEndDisabled()
|
igEndDisabled()
|
||||||
igSameLine(0.0f, textSpacing)
|
igSameLine(0.0f, textSpacing)
|
||||||
|
|
||||||
|
|||||||
@@ -264,7 +264,8 @@ type
|
|||||||
CLIENT_AGENT_PAYLOAD = 104'u8 # Return agent payload binary
|
CLIENT_AGENT_PAYLOAD = 104'u8 # Return agent payload binary
|
||||||
CLIENT_CONSOLE_ITEM = 105'u8 # Add entry to a agent's console
|
CLIENT_CONSOLE_ITEM = 105'u8 # Add entry to a agent's console
|
||||||
CLIENT_EVENTLOG_ITEM = 106'u8 # Add entry to the eventlog
|
CLIENT_EVENTLOG_ITEM = 106'u8 # Add entry to the eventlog
|
||||||
CLIENT_LOOT = 107'u8 # Download file or screenshot to the operator desktop
|
CLIENT_BUILDLOG_ITEM = 107'u8 # Add entry to the build log
|
||||||
|
CLIENT_LOOT = 108'u8 # Download file or screenshot to the operator desktop
|
||||||
|
|
||||||
Event* = object
|
Event* = object
|
||||||
eventType*: EventType
|
eventType*: EventType
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import ../globals
|
|||||||
import ../core/logger
|
import ../core/logger
|
||||||
import ../db/database
|
import ../db/database
|
||||||
import ../../common/[types, utils, serialize, crypto]
|
import ../../common/[types, utils, serialize, crypto]
|
||||||
|
import ../websocket
|
||||||
|
|
||||||
const PLACEHOLDER = "PLACEHOLDER"
|
const PLACEHOLDER = "PLACEHOLDER"
|
||||||
|
|
||||||
@@ -49,6 +50,8 @@ proc serializeConfiguration(cq: Conquest, listener: Listener, sleep: int, sleepT
|
|||||||
wipeKey(aesKey)
|
wipeKey(aesKey)
|
||||||
|
|
||||||
cq.info("Profile configuration serialized.")
|
cq.info("Profile configuration serialized.")
|
||||||
|
cq.client.sendBuildlogItem(LOG_INFO_SHORT, "Profile configuration serialized.")
|
||||||
|
|
||||||
return encMaterial & encData
|
return encMaterial & encData
|
||||||
|
|
||||||
proc replaceAfterPrefix(content, prefix, value: string): string =
|
proc replaceAfterPrefix(content, prefix, value: string): string =
|
||||||
@@ -79,9 +82,11 @@ proc compile(cq: Conquest, placeholderLength: int, modules: uint32): string =
|
|||||||
writeFile(configFile, config)
|
writeFile(configFile, config)
|
||||||
|
|
||||||
cq.info(fmt"Placeholder created ({placeholder.len()} bytes).")
|
cq.info(fmt"Placeholder created ({placeholder.len()} bytes).")
|
||||||
|
cq.client.sendBuildlogItem(LOG_INFO_SHORT, fmt"Placeholder created ({placeholder.len()} bytes).")
|
||||||
|
|
||||||
# Build agent by executing the ./build.sh script on the system.
|
# Build agent by executing the ./build.sh script on the system.
|
||||||
cq.info("Compiling agent.")
|
cq.info("Compiling agent.")
|
||||||
|
cq.client.sendBuildlogItem(LOG_INFO_SHORT, "Compiling agent...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Using the startProcess function from the 'osproc' module, it is possible to retrieve the output as it is received, line-by-line instead of all at once
|
# Using the startProcess function from the 'osproc' module, it is possible to retrieve the output as it is received, line-by-line instead of all at once
|
||||||
@@ -97,9 +102,13 @@ proc compile(cq: Conquest, placeholderLength: int, modules: uint32): string =
|
|||||||
# Check if the build succeeded or not
|
# Check if the build succeeded or not
|
||||||
if exitCode == 0:
|
if exitCode == 0:
|
||||||
cq.info("Agent payload generated successfully.")
|
cq.info("Agent payload generated successfully.")
|
||||||
|
cq.client.sendBuildlogItem(LOG_INFO_SHORT, "Agent payload generated successfully.")
|
||||||
|
|
||||||
return exeFile
|
return exeFile
|
||||||
else:
|
else:
|
||||||
cq.error("Build script exited with code ", $exitCode)
|
cq.error("Build script exited with code ", $exitCode)
|
||||||
|
cq.client.sendBuildlogItem(LOG_ERROR_SHORT, "Build script exited with code " & $exitCode)
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
@@ -109,6 +118,7 @@ proc compile(cq: Conquest, placeholderLength: int, modules: uint32): string =
|
|||||||
proc patch(cq: Conquest, unpatchedExePath: string, configuration: seq[byte]): seq[byte] =
|
proc patch(cq: Conquest, unpatchedExePath: string, configuration: seq[byte]): seq[byte] =
|
||||||
|
|
||||||
cq.info("Patching profile configuration into agent.")
|
cq.info("Patching profile configuration into agent.")
|
||||||
|
cq.client.sendBuildlogItem(LOG_INFO_SHORT, "Patching profile configuration into agent.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
var exeBytes = readFile(unpatchedExePath)
|
var exeBytes = readFile(unpatchedExePath)
|
||||||
@@ -119,6 +129,7 @@ proc patch(cq: Conquest, unpatchedExePath: string, configuration: seq[byte]): se
|
|||||||
raise newException(CatchableError, "Placeholder not found.")
|
raise newException(CatchableError, "Placeholder not found.")
|
||||||
|
|
||||||
cq.info(fmt"Placeholder found at offset 0x{placeholderPos:08X}.")
|
cq.info(fmt"Placeholder found at offset 0x{placeholderPos:08X}.")
|
||||||
|
cq.client.sendBuildlogItem(LOG_INFO_SHORT, fmt"Placeholder found at offset 0x{placeholderPos:08X}.")
|
||||||
|
|
||||||
# Patch placeholder bytes
|
# Patch placeholder bytes
|
||||||
for i, c in Bytes.toString(configuration):
|
for i, c in Bytes.toString(configuration):
|
||||||
@@ -127,10 +138,12 @@ proc patch(cq: Conquest, unpatchedExePath: string, configuration: seq[byte]): se
|
|||||||
writeFile(unpatchedExePath, exeBytes)
|
writeFile(unpatchedExePath, exeBytes)
|
||||||
|
|
||||||
cq.success(fmt"Agent payload patched successfully: {unpatchedExePath}.")
|
cq.success(fmt"Agent payload patched successfully: {unpatchedExePath}.")
|
||||||
|
cq.client.sendBuildlogItem(LOG_SUCCESS_SHORT, fmt"Agent payload patched successfully: {unpatchedExePath}.")
|
||||||
return string.toBytes(exeBytes)
|
return string.toBytes(exeBytes)
|
||||||
|
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
cq.error("An error occurred: ", err.msg)
|
cq.error("An error occurred: ", err.msg)
|
||||||
|
cq.client.sendBuildlogItem(LOG_ERROR_SHORT, "An error occurred: " & err.msg)
|
||||||
|
|
||||||
return @[]
|
return @[]
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import terminal, parsetoml, json, math, base64
|
import terminal, parsetoml, json, math, base64, times
|
||||||
import strutils, strformat, system, tables
|
import strutils, strformat, system, tables
|
||||||
|
|
||||||
import ./core/[listener, builder]
|
import ./core/[listener, builder]
|
||||||
@@ -101,11 +101,27 @@ proc websocketHandler(ws: WebSocket, event: WebSocketEvent, message: Message) {.
|
|||||||
# Set the client instance to nil again to prevent debug error messages
|
# Set the client instance to nil again to prevent debug error messages
|
||||||
cq.client = nil
|
cq.client = nil
|
||||||
|
|
||||||
|
var lastCtrlCTime = fromUnix(0)
|
||||||
|
var ctrlC = 0
|
||||||
|
|
||||||
|
proc handleCtrlC() {.noconv.} =
|
||||||
|
let now = getTime()
|
||||||
|
if now - lastCtrlCTime > initDuration(seconds = 2):
|
||||||
|
ctrlC = 0
|
||||||
|
|
||||||
|
inc ctrlC
|
||||||
|
lastCtrlCTime = now
|
||||||
|
|
||||||
|
if ctrlC == 1:
|
||||||
|
echo "\nPress Ctrl+C again to exit."
|
||||||
|
else:
|
||||||
|
echo "\nExiting."
|
||||||
|
quit(0)
|
||||||
|
|
||||||
proc startServer*(profilePath: string) =
|
proc startServer*(profilePath: string) =
|
||||||
|
|
||||||
# Ensure that the conquest root directory was passed as a compile-time define
|
# Handle team server exit
|
||||||
when not defined(CONQUEST_ROOT):
|
setControlCHook(handleCtrlC)
|
||||||
quit(0)
|
|
||||||
|
|
||||||
header()
|
header()
|
||||||
|
|
||||||
|
|||||||
@@ -116,3 +116,15 @@ proc sendConsoleItem*(client: WsConnection, agentId: string, logType: LogType, m
|
|||||||
)
|
)
|
||||||
if client != nil:
|
if client != nil:
|
||||||
client.ws.sendEvent(event, client.sessionKey)
|
client.ws.sendEvent(event, client.sessionKey)
|
||||||
|
|
||||||
|
proc sendBuildlogItem*(client: WsConnection, logType: LogType, message: string) =
|
||||||
|
let event = Event(
|
||||||
|
eventType: CLIENT_BUILDLOG_ITEM,
|
||||||
|
timestamp: now().toTime().toUnix(),
|
||||||
|
data: %*{
|
||||||
|
"logType": cast[uint8](logType),
|
||||||
|
"message": message
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if client != nil:
|
||||||
|
client.ws.sendEvent(event, client.sessionKey)
|
||||||
|
|||||||
Reference in New Issue
Block a user