Reworked installation instructions.

This commit is contained in:
Jakob Friedl
2025-10-31 10:14:35 +01:00
parent 394c98939e
commit d581e0d2b6
26 changed files with 179 additions and 98 deletions

View File

@@ -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

View File

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

BIN
assets/listener.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View File

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -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 <team-server-address> -p <team-server-port>

View File

@@ -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 <team-server-ip> -p <team-server-port>
```
![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)
![Loot](../assets/architecture-3.png)

View File

@@ -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)
![POST request with task data](../assets/profile-3.png)

View File

@@ -0,0 +1,12 @@
# Listeners <!-- omit from toc -->
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 `<ip/domain>:<port>`. 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.<br>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.

View File

@@ -0,0 +1,34 @@
# Agents <!-- omit from toc -->
## Contents <!-- omit from toc -->
- [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

View File

@@ -0,0 +1,69 @@
# Modules <!-- omit from toc -->
## Contents <!-- omit from toc -->
- [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

View File

@@ -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 /<listener>/<agent>/<upload-task>/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 /<listener>/<agent>/<download>-task/file
- Encrypt file in-transit!!!
- [x] screenshot : Take a screenshot of the entire desktop and all monitors

View File

@@ -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
```

BIN
docs/image-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
docs/image-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -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
@@ -76,3 +90,4 @@ case TC
switch "cc.exe","clang"
switch "cc.linkerexe","clang"
switch "cc",TC

View File

@@ -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

View File

@@ -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)
]
)

View File

@@ -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:

View File

@@ -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:

View File

@@ -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)