diff --git a/README.md b/README.md index f8b4665..543c607 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ nimble client 3. Start the team server with a C2 profile. ``` -bin/server -p data/profile.toml +sudo bin/server -p data/profile.toml ``` 4. Start the operator client and connect it to a team server diff --git a/assets/cq-architecture.png b/assets/architecture-1.png similarity index 100% rename from assets/cq-architecture.png rename to assets/architecture-1.png diff --git a/assets/ui.png b/assets/architecture-2.png similarity index 100% rename from assets/ui.png rename to assets/architecture-2.png diff --git a/assets/loot.png b/assets/architecture-3.png similarity index 100% rename from assets/loot.png rename to assets/architecture-3.png diff --git a/assets/ts-start.png b/assets/install.png similarity index 100% rename from assets/ts-start.png rename to assets/install.png diff --git a/assets/listener.png b/assets/listener.png new file mode 100644 index 0000000..ed0046d Binary files /dev/null and b/assets/listener.png differ diff --git a/assets/get.png b/assets/profile-1.png similarity index 100% rename from assets/get.png rename to assets/profile-1.png diff --git a/assets/traffic.png b/assets/profile-2.png similarity index 100% rename from assets/traffic.png rename to assets/profile-2.png diff --git a/assets/post.png b/assets/profile-3.png similarity index 100% rename from assets/post.png rename to assets/profile-3.png diff --git a/docs/1-INSTALLATION.md b/docs/1-INSTALLATION.md index ef8cccb..8b6a49d 100644 --- a/docs/1-INSTALLATION.md +++ b/docs/1-INSTALLATION.md @@ -12,27 +12,48 @@ cd conquest curl https://nim-lang.org/choosenim/init.sh -sSf | sh ``` -3. The Conquest binaries for team server and client are designed to be compiled on a UNIX system using the `nimble` command. This command installs and updates all dependencies and third-party libraries automatically. +After it is installed, the Nim binaries need to be added to the PATH. + +``` +export PATH=/home/kali/.nimble/bin:$PATH +``` + +3. Install dependencies + +The operator client requires the following dependencies to be installed on Ubuntu/Debian systems. +``` +sudo apt update +sudo apt install gcc g++ make git curl xz-utils +sudo apt install libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev +``` + +4. The Conquest binaries for team server and client are designed to be compiled on a UNIX system using the `nimble` command. This command installs and updates all dependencies and third-party libraries automatically. ``` nimble server nimble client ``` +Optionally, the required dependencies can be installed manually using the following command. + +``` +nimble install -d +``` + 4. Start the Conquest team server with a C2 profile. The default profile is located in data/profile.toml and can be adapted by the operator. ``` -bin/server -p data/profile +sudo bin/server -p data/profile ``` On the first start, the Conquest team server creates the Conquest database in the data directory, as well as the team server's private key in data/keys, which is used for the key exchange between team server, client and agent. -![Team server start](../assets/ts-start.png) +![Team server start](../assets/install.png) 5. Start the Conquest operator client ``` bin/client ``` -By default, the Conquest client connects to localhost:37573 to connect to the team server. The address and port can be specified from the command-line using the `-i` and `-p` flags. The team server port is specified in the malleable C2 profile. +By default, the Conquest client connects to localhost:37573 to connect to the team server. The address and port can be specified from the command-line using the `-i` and `-p` flags, in order to connect to a remote team server. The team server port is specified in the malleable C2 profile. ``` bin/client -i -p diff --git a/docs/2-ARCHITECTURE.md b/docs/2-ARCHITECTURE.md index 1fc971f..5d8719a 100644 --- a/docs/2-ARCHITECTURE.md +++ b/docs/2-ARCHITECTURE.md @@ -20,7 +20,7 @@ The Conquest command & control framework consist of three major components that interact with each other in different ways. Together, they enable penetration tester and red teamers to remotely control systems, transfer files and more. The diagram below shows Conquests's overall architecture. -![Architecture](../assets/cq-architecture.png) +![Architecture](../assets/architecture-1.png) ### Team Server @@ -45,7 +45,7 @@ The Conquest client is used by the operator to conduct the engagement. It is use bin/client -i -p ``` -![Operator Client](../assets/ui.png) +![Operator Client](../assets/architecture-2.png) More information about the user interface can be found [here](./4-CLIENT.md) @@ -349,4 +349,4 @@ The `teamserver.log` records other events, that don't involve an interaction wit In Conquest, the term loot encompasses file downloads and screenshots retrieved from an agent. While metadata about these loot items is stored in the database, the actual files and images are also stored on disk on the team server in the data/loot directory. -![Loot](../assets/loot.png) \ No newline at end of file +![Loot](../assets/architecture-3.png) \ No newline at end of file diff --git a/docs/3-PROFILE.md b/docs/3-PROFILE.md index 1a36fbd..89668b6 100644 --- a/docs/3-PROFILE.md +++ b/docs/3-PROFILE.md @@ -79,7 +79,7 @@ prefix = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." suffix = ".######################################-####" ``` -![Heartbeat in Authorization Header](../assets/get.png) +![Heartbeat in Authorization Header](../assets/profile-1.png) Check the [default profile](../data/profile.toml) for more examples. @@ -107,7 +107,7 @@ Connection = "Keep-Alive" Cache-Control = "no-cache" ``` -![GET Traffic with C2 Profiles](../assets/traffic.png) +![GET Traffic with C2 Profiles](../assets/profile-2.png) ### Response options @@ -165,4 +165,4 @@ Server = "nginx" placement = { type = "body" } ``` -![POST request with task data](../assets/post.png) \ No newline at end of file +![POST request with task data](../assets/profile-3.png) \ No newline at end of file diff --git a/docs/5-LISTENER.md b/docs/5-LISTENER.md index e69de29..58637e1 100644 --- a/docs/5-LISTENER.md +++ b/docs/5-LISTENER.md @@ -0,0 +1,12 @@ +# Listeners + +Listeners can be started by pressing the **Start Listener** button in the **Listeners** view. This opens the following modal popup. + +![Listener Modal](../assets/listener.png) + +| Name | Description | +| --- | --- | +| Protocol | Listener type. Currently only `http` listeners are implemented | +| Host (Bind) | IP address or interface that the listener binds to on the team server | +| Port (Bind) | Port that the listeners bind to on the team server | +| Hosts (Callback) | Callback hosts, one per line. The hosts are defined, separated by new-lines, in the format `:`. If no port is specified, the bind port is used instead. If no callback hosts are defined at all, the bind host and bind port are used.
Callback hosts are the endpoints that the `Monarch` agent connects to. If multiple are defined, a random entry of the list of callback hosts is selected for each request. \ No newline at end of file diff --git a/docs/6-AGENT.md b/docs/6-AGENT.md index e69de29..bbac160 100644 --- a/docs/6-AGENT.md +++ b/docs/6-AGENT.md @@ -0,0 +1,34 @@ +# Agents + +## Contents + +- [The Monarch](#the-monarch) +- [Sleep settings](#sleep-settings) + - [Sleep Obfuscation](#sleep-obfuscation) + - [Working hours](#working-hours) +- [String obfuscation](#string-obfuscation) +- [Kill date](#kill-date) +- [Evasion](#evasion) + +## The Monarch + +The `Monarch` agent can be customized using the payload generation modal pop-up, which is opened by pressing the **Generate Payload** button in the **Listeners** view. + +![Agent Modal](image-1.png) + +## Sleep settings + +### Sleep Obfuscation + +### Working hours + +![Working Hours Modal](image-2.png) + +## String obfuscation + +## Kill date + +![Kill Date Modal](image.png) + +## Evasion + diff --git a/docs/7-MODULES.md b/docs/7-MODULES.md index e69de29..2f4f696 100644 --- a/docs/7-MODULES.md +++ b/docs/7-MODULES.md @@ -0,0 +1,69 @@ +# Modules + +## Contents + +- [Overview](#overview) +- [EXIT](#exit) +- [SLEEP](#sleep) +- [SHELL](#shell) +- [BOF](#bof) +- [DOTNET](#dotnet) +- [FILESYSTEM](#filesystem) +- [FILETRANSFER](#filetransfer) +- [SCREENSHOT](#screenshot) +- [SYSTEMINFO](#systeminfo) +- [TOKEN](#token) + +## Overview + +Currently, the following commands are available in the `Monarch` agent when all modules are activated. + +``` + * exit Exit the agent. + * self-destruct Exit the agent and delete the executable from disk. + * sleep Update sleep delay settings. + * sleepmask Update sleepmask settings. + * shell Execute a shell command and retrieve the output. + * bof Execute an object file in memory and retrieve the output. + * dotnet Execute a .NET assembly in memory and retrieve the output. + * pwd Retrieve current working directory. + * cd Change current working directory. + * ls List files and directories. + * rm Remove a file. + * rmdir Remove a directory. + * move Move a file or directory. + * copy Copy a file or directory. + * download Download a file. + * upload Upload a file. + * screenshot Take a screenshot of the target system. + * ps Display running processes. + * env Display environment variables. + * make-token Create an access token from username and password. + * steal-token Steal the primary access token of a remote process. + * rev2self Revert to original access token. + * token-info Retrieve information about the current access token. + * enable-privilege Enable a token privilege. + * disable-privilege Disable a token privilege. +``` + +## EXIT + + + +## SLEEP + +## SHELL + +## BOF + +## DOTNET + +## FILESYSTEM + +## FILETRANSFER + +## SCREENSHOT + +## SYSTEMINFO + +## TOKEN \ No newline at end of file diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md deleted file mode 100644 index cebba08..0000000 --- a/docs/COMMANDS.md +++ /dev/null @@ -1,45 +0,0 @@ -# "Monarch" Agent commands: - -House-keeping -------------- -- [x] sleep : Set sleep obfuscation duration to a different value and persist that value in the agent - -Basic API-only Commands ------------------------ -- [x] pwd : Get current working directory -- [x] cd : Change directory -- [x] ls/dir : List all files in directory (including hidden ones) -- [x] rm : Remove a file -- [x] rmdir : Remove a empty directory -- [x] mv : Move a file -- [x] cp : Copy a file -- [ ] cat/type : Display contents of a file -- [x] env : Display environment variables -- [x] ps : List processes -- [ ] whoami : Get UID and privileges, etc. - -- [ ] token : Token impersonation - - [ ] make : Create a token from a user's plaintext password (LogonUserA, ImpersonateLoggedOnUser) - - [ ] steal : Steal the access token from a process (OpenProcess, OpenProcessToken, DuplicateToken, ImpersonateLoggedOnUser) - - [ ] use : Impersonate a token from the token vault (ImpersonateLoggedOnUser) -> update username like in Cobalt Strike -- [ ] rev2self : Revert to original logon session (RevertToSelf) - -Execution Commands ------------------- -- [x] shell : Execute shell command (to be implemented using Windows APIs instead of execCmdEx) -- [x] bof : Execute Beacon Object File in memory and retrieve output (bof /local/path/file.o) - - Read from listener endpoint directly to memory - - Base for all kinds of BOFs (Situational Awareness, ...) -- [ ] pe : Execute PE file in memory and retrieve output (pe /local/path/mimikatz.exe) -- [x] dotnet : Execute .NET assembly inline in memory and retrieve output (dotnet /local/path/Rubeus.exe ) - -Post-Exploitation ------------------ -- [x] upload : Upload file from server to agent (upload /local/path/to/file C:\Windows\Tasks) - - File to be downloaded moved to specific endpoint on listener, e.g. GET ////file - - Read from webserver and written to disk -- [x] download : Download file from agent to teamserver - - Create loot directory for agent to store files in - - Read file into memory and send byte stream to specific endpoint, e.g. POST ///-task/file - - Encrypt file in-transit!!! -- [x] screenshot : Take a screenshot of the entire desktop and all monitors diff --git a/docs/INSTALL.md b/docs/INSTALL.md deleted file mode 100644 index e522746..0000000 --- a/docs/INSTALL.md +++ /dev/null @@ -1,31 +0,0 @@ -# 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 -nimble client -``` - -5. Start the Conquest server with a C2 Profile and connect to it with the client -```bash -./bin/server -p ./data/profile.toml -./bin/client -i localhost -p 35753 -``` - diff --git a/docs/image-1.png b/docs/image-1.png new file mode 100644 index 0000000..d38dfa8 Binary files /dev/null and b/docs/image-1.png differ diff --git a/docs/image-2.png b/docs/image-2.png new file mode 100644 index 0000000..ffb0969 Binary files /dev/null and b/docs/image-2.png differ diff --git a/docs/image.png b/docs/image.png new file mode 100644 index 0000000..618d4d8 Binary files /dev/null and b/docs/image.png differ diff --git a/src/client/config.nims b/src/client/config.nims index b49c8a6..ea74832 100644 --- a/src/client/config.nims +++ b/src/client/config.nims @@ -29,6 +29,18 @@ else: # for Linux when STATIC_LINK_GLFW: # GLFW static link switch "define","glfwStaticLib" + when defined(windows): + discard # Windows-specific handling if needed + else: # Linux + switch "passL","-lglfw" + switch "passL","-lX11" + switch "passL","-lXrandr" + switch "passL","-lXinerama" + switch "passL","-lXcursor" + switch "passL","-lXi" + switch "passL","-lpthread" + switch "passL","-ldl" + switch "passL","-lm" else: # shared/dll when defined(windows): if TC == "vcc": @@ -39,6 +51,8 @@ else: # shared/dll #switch "define","cimguiDLL" else: switch "passL","-lglfw" + # Add X11 libs for shared linking too + switch "passL","-lX11" when STATIC_LINK_CC: # gcc static link case TC @@ -75,4 +89,5 @@ case TC of "clang": switch "cc.exe","clang" switch "cc.linkerexe","clang" - switch "cc",TC \ No newline at end of file + switch "cc",TC + diff --git a/src/client/main.nim b/src/client/main.nim index 9f8e664..31a32f0 100644 --- a/src/client/main.nim +++ b/src/client/main.nim @@ -123,12 +123,12 @@ proc main(ip: string = "localhost", port: int = 37573) = of CLIENT_AGENT_PAYLOAD: let payload = decode(event.data["payload"].getStr()) try: - let outFilePath = fmt"{CONQUEST_ROOT}/bin/monarch.x64.exe" + let path = fmt"{CONQUEST_ROOT}/bin/monarch.x64.exe" # TODO: Using native file dialogs to have the client select the output file path (does not work in WSL) - # let outFilePath = callDialogFileSave("Save Payload") + # let path = callDialogFileSave("Save Payload") - writeFile(outFilePath, payload) + writeFile(path, payload) except IOError: discard diff --git a/src/client/utils/setupFonts.nim b/src/client/utils/setupFonts.nim index 3ac76c5..7cd6808 100644 --- a/src/client/utils/setupFonts.nim +++ b/src/client/utils/setupFonts.nim @@ -25,13 +25,13 @@ when defined(windows): ("segoeui.ttf", "Seoge UI", 14.4), ] ) -else: # For Debian/Ubuntu/Mint +else: # Linux const fontInfo = TFontInfo( osRootDir: "/", fontDir: "usr/share/fonts", fontTable: @[ - ("truetype/noto/NotoSansMono-Regular.ttf", "Noto Sans Mono", 20.0) + ("truetype/noto/NotoSansMono-Regular.ttf", "Noto Sans Mono", 14.4) ] ) diff --git a/src/client/views/loot/downloads.nim b/src/client/views/loot/downloads.nim index a05be48..17fe051 100644 --- a/src/client/views/loot/downloads.nim +++ b/src/client/views/loot/downloads.nim @@ -1,4 +1,4 @@ -import strformat, strutils, times, os, tables +import strformat, strutils, times, os, tables # native_dialogs import imguin/[cimgui, glfw_opengl, simple] import ../../utils/[appImGui, colors] import ../../../common/[types, utils] @@ -96,8 +96,11 @@ proc draw*(component: DownloadsComponent, showComponent: ptr bool, connection: W if igMenuItem("Download", nil, false, true): # Download file try: - # TODO: Use native dialogs to select the download location let path = item.path & ".download" + + # TODO: Use native dialogs to select the download location + # let path = callDialogFileSave("Save File") + let data = component.contents[item.lootId] writeFile(path, data) except IOError: diff --git a/src/client/views/loot/screenshots.nim b/src/client/views/loot/screenshots.nim index 1b72288..bc9c7a0 100644 --- a/src/client/views/loot/screenshots.nim +++ b/src/client/views/loot/screenshots.nim @@ -1,4 +1,4 @@ -import strformat, strutils, times, os, tables +import strformat, strutils, times, os, tables # native_dialogs import imguin/[cimgui, glfw_opengl, simple] import ../../utils/[appImGui, colors] import ../../../common/[types, utils] @@ -104,8 +104,11 @@ proc draw*(component: ScreenshotsComponent, showComponent: ptr bool, connection: if igMenuItem("Download", nil, false, true): # Download screenshot try: - # TODO: Use native dialogs to select the download location let path = item.path & "_download.jpeg" + + # TODO: Use native dialogs to select the download location + # let path = callDialogFileSave("Save File") + let data = component.textures[item.lootId].data writeFile(path, data) except IOError: diff --git a/src/client/views/modals/generatePayload.nim b/src/client/views/modals/generatePayload.nim index 5d1b4ab..b9a51be 100644 --- a/src/client/views/modals/generatePayload.nim +++ b/src/client/views/modals/generatePayload.nim @@ -169,7 +169,7 @@ proc draw*(component: AgentModalComponent, listeners: seq[UIListener]): AgentBui component.killDate = killDate # Working hours - igText("Working Hours: ") + igText("Working hours: ") igSameLine(0.0f, textSpacing) igCheckbox("##InputWorkingHours", addr component.workingHoursEnabled) igSameLine(0.0f, textSpacing)