From 5922a5b85017df09eac16eda99c4b497cfdd40cb Mon Sep 17 00:00:00 2001 From: Jakob Friedl <71284620+jakobfriedl@users.noreply.github.com> Date: Fri, 22 Aug 2025 10:48:00 +0200 Subject: [PATCH] Created nimble package and installation instructions. --- conquest.nimble | 29 +++++++++++++++++++++++++++++ data/profile.toml | 5 ++--- docs/COMMANDS.md | 4 ++-- docs/INSTALL.md | 29 +++++++++++++++++++++++++++++ src/agent/nim.cfg | 2 +- src/server/core/builder.nim | 12 ++++++++---- src/server/core/logger.nim | 8 ++++---- src/server/core/server.nim | 9 ++++++--- src/server/globals.nim | 4 +++- src/server/nim.cfg | 3 +-- 10 files changed, 85 insertions(+), 20 deletions(-) create mode 100644 conquest.nimble create mode 100644 docs/INSTALL.md diff --git a/conquest.nimble b/conquest.nimble new file mode 100644 index 0000000..3228480 --- /dev/null +++ b/conquest.nimble @@ -0,0 +1,29 @@ +# Package + +version = "0.1.0" +author = "Jakob Friedl" +description = "Command & control framework written in Nim" +license = "MIT" +srcDir = "src" + +# Build tasks + +import os, strformat +task server, "Build conquest server binary": + let cqRoot = getCurrentDir() + exec fmt"nim c -d:CONQUEST_ROOT={cqRoot} src/server/main.nim" + +task client, "Build conquest client binary": + discard + +# Dependencies + +requires "nim >= 2.2.4" + +requires "prompt >= 0.0.1" +requires "argparse >= 4.0.2" +requires "parsetoml >= 0.7.2" +requires "nimcrypto >= 0.6.4" +requires "tiny_sqlite >= 0.2.0" +requires "prologue >= 0.6.6" +requires "winim >= 3.9.4" diff --git a/data/profile.toml b/data/profile.toml index f74e447..454f516 100644 --- a/data/profile.toml +++ b/data/profile.toml @@ -3,9 +3,8 @@ name = "cq-default-profile" # Important file paths and locations -conquest_directory = "/mnt/c/Users/jakob/Documents/Projects/conquest" -private_key_file = "/mnt/c/Users/jakob/Documents/Projects/conquest/data/keys/conquest-server_x25519_private.key" -database_file = "/mnt/c/Users/jakob/Documents/Projects/conquest/data/conquest.db" +private-key-file = "data/keys/conquest-server_x25519_private.key" +database-file = "data/conquest.db" # General agent settings [agent] diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md index c2ad7db..c7b5340 100644 --- a/docs/COMMANDS.md +++ b/docs/COMMANDS.md @@ -14,8 +14,8 @@ Basic API-only Commands - [x] mv : Move a file - [x] cp : Copy a file - [ ] cat/type : Display contents of a file -- [ ] env : Display environment variables -- [ ] ps : List processes +- [x] env : Display environment variables +- [x] ps : List processes - [ ] whoami : Get UID and privileges, etc. - [ ] token : Token impersonation diff --git a/docs/INSTALL.md b/docs/INSTALL.md new file mode 100644 index 0000000..b75f54d --- /dev/null +++ b/docs/INSTALL.md @@ -0,0 +1,29 @@ +# Installation Guide + +1. Clone the Conquest repository +``` +git clone https://github.com/jakobfriedl/conquest +cd conquest +``` + +2. Install Nim + +```bash +curl https://nim-lang.org/choosenim/init.sh -sSf | sh +``` + +3. Install Nimble dependencies +``` +nimble install -d +``` + +4. Build conquest binaries +``` +nimble server +``` + +5. Start the Conquest server with a C2 Profile +``` +./bin/server -p ./data/profile.toml +``` + diff --git a/src/agent/nim.cfg b/src/agent/nim.cfg index d3fcb5f..1d27f3e 100644 --- a/src/agent/nim.cfg +++ b/src/agent/nim.cfg @@ -1,5 +1,5 @@ # Compiler flags -d:agent -d:release --d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER" +-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER" -o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe" \ No newline at end of file diff --git a/src/server/core/builder.nim b/src/server/core/builder.nim index 9d15cbb..7d2168f 100644 --- a/src/server/core/builder.nim +++ b/src/server/core/builder.nim @@ -1,5 +1,6 @@ import terminal, strformat, strutils, sequtils, tables, system, osproc, streams, parsetoml +import ../globals import ../core/logger import ../db/database import ../../common/[types, utils, profile, serialize, crypto] @@ -51,10 +52,13 @@ proc replaceAfterPrefix(content, prefix, value: string): string = proc compile(cq: Conquest, placeholderLength: int): string = let - cqDir = cq.profile.getString("conquest_directory") - configFile = fmt"{cqDir}/src/agent/nim.cfg" - exeFile = fmt"{cqDir}/bin/monarch.x64.exe" - agentBuildScript = fmt"{cqDir}/src/agent/build.sh" + configFile = fmt"{CONQUEST_ROOT}/src/agent/nim.cfg" + exeFile = fmt"{CONQUEST_ROOT}/bin/monarch.x64.exe" + agentBuildScript = fmt"{CONQUEST_ROOT}/src/agent/build.sh" + + # Update conquest root directory in agent build script + var buildScript = readFile(agentBuildScript).replaceAfterPrefix("CONQUEST_ROOT=", CONQUEST_ROOT) + writeFile(agentBuildScript, buildScript) # Update placeholder and configuration values let placeholder = PLACEHOLDER & "A".repeat(placeholderLength - (2 * len(PLACEHOLDER))) & PLACEHOLDER diff --git a/src/server/core/logger.nim b/src/server/core/logger.nim index 0fc562a..eacf52b 100644 --- a/src/server/core/logger.nim +++ b/src/server/core/logger.nim @@ -1,11 +1,12 @@ import times, strformat, strutils, prompt, terminal import std/[dirs, paths] + +import ../globals import ../../common/[types, profile] proc makeAgentLogDirectory*(cq: Conquest, agentId: string): bool = try: - let cqDir = cq.profile.getString("conquest_directory") - createDir(cast[Path](fmt"{cqDir}/data/logs/{agentId}")) + createDir(cast[Path](fmt"{CONQUEST_ROOT}/data/logs/{agentId}")) return true except OSError: return false @@ -13,8 +14,7 @@ proc makeAgentLogDirectory*(cq: Conquest, agentId: string): bool = proc log*(cq: Conquest, logEntry: string) = let date = now().format("dd-MM-yyyy") - cqDir = cq.profile.getString("conquest_directory") - agentLogPath = fmt"{cqDir}/data/logs/{cq.interactAgent.agentId}/{date}.session.log" + agentLogPath = fmt"{CONQUEST_ROOT}/data/logs/{cq.interactAgent.agentId}/{date}.session.log" # Write log entry to file let file = open(agentLogPath, fmAppend) diff --git a/src/server/core/server.nim b/src/server/core/server.nim index b98881a..d9e26ae 100644 --- a/src/server/core/server.nim +++ b/src/server/core/server.nim @@ -134,12 +134,16 @@ proc init*(T: type Conquest, profile: Profile): Conquest = cq.agents = initTable[string, Agent]() cq.interactAgent = nil cq.profile = profile - cq.keyPair = loadKeyPair(profile.getString("private_key_file")) - cq.dbPath = profile.getString("database_file") + cq.keyPair = loadKeyPair(CONQUEST_ROOT & "/" & profile.getString("private-key-file")) + cq.dbPath = CONQUEST_ROOT & "/" & profile.getString("database-file") return cq proc startServer*(profilePath: string) = + # Ensure that the conquest root directory was passed as a compile-time define + when not defined(CONQUEST_ROOT): + quit(0) + # Handle CTRL+C, proc exit() {.noconv.} = echo "Received CTRL+C. Type \"exit\" to close the application.\n" @@ -154,7 +158,6 @@ proc startServer*(profilePath: string) = cq = Conquest.init(profile) cq.info("Using profile \"", profile.getString("name"), "\" (", profilePath ,").") - cq.info("Using private key \"", profile.getString("private_key_file"), "\".") except CatchableError as err: echo err.msg diff --git a/src/server/globals.nim b/src/server/globals.nim index 274e63a..796dfeb 100644 --- a/src/server/globals.nim +++ b/src/server/globals.nim @@ -1,4 +1,6 @@ +import os import ../common/types -# Global variable for handling listeners, agents and console output +# Global server context +const CONQUEST_ROOT* {.strdefine.} = "" var cq*: Conquest \ No newline at end of file diff --git a/src/server/nim.cfg b/src/server/nim.cfg index 7cb3844..516aad0 100644 --- a/src/server/nim.cfg +++ b/src/server/nim.cfg @@ -2,5 +2,4 @@ -d:server --threads:on -d:httpxServerName="" ---outdir:"../bin" --o:"server" \ No newline at end of file +-o:"bin/server" \ No newline at end of file