Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
15bf5fd
Debian 13 support (#800)
OlehAhieienko Dec 12, 2025
1534952
Use Annotated fastapi deps (#1110)
vinnybod Dec 19, 2025
61dda36
Recategorize Modules (#1112)
Cx01N Dec 19, 2025
54e8fe3
add debian 13 tests
vinnybod Dec 19, 2025
a9aeded
Merge branch 'private-main' into cherry-pick-62f17b80f8a00ec11b8fbfe7…
vinnybod Dec 19, 2025
ae18407
add query param to disable modules (#1111)
vinnybod Dec 19, 2025
b0ecab6
fix mysql check for debian13
vinnybod Dec 19, 2025
f8a9874
Merge branch 'private-main' into cherry-pick-62f17b80f8a00ec11b8fbfe7…
vinnybod Dec 19, 2025
787a7b5
yamlfmt
vinnybod Dec 19, 2025
d7af560
Cherry-pick 62f17b80f8a00ec11b8fbfe7fe2608629e444f80 to private-main …
vinnybod Dec 20, 2025
95e6679
Merge pull request #1113 from BC-SECURITY/vinnybod/healthcheck
vinnybod Dec 29, 2025
07d05bc
Added OS install override (#1114)
Cx01N Dec 29, 2025
d840e4f
Added options to agent task and plugins (#1115)
Cx01N Dec 30, 2025
bb31e9a
Bump tj-actions/changed-files from 47.0.0 to 47.0.1 (#1109)
dependabot[bot] Dec 31, 2025
d010037
Fixes for C# taskings (#1118)
Cx01N Jan 17, 2026
fa7c3b2
feat: allow user to use local ticket auth (#803)
e1kfL0ck Jan 15, 2026
b5a9079
Add stop task option for jobs (#1119)
Cx01N Jan 18, 2026
b71f744
bump python version in release actions
vinnybod Jan 18, 2026
56ff8e1
add missing changelog entries
vinnybod Jan 18, 2026
8291e20
Prepare release 6.4.0 private
web-flow Jan 18, 2026
1330ed3
Merge pull request #1120 from BC-SECURITY/release/6.4.0-private
vinnybod Jan 18, 2026
7bca79c
Fixed Go agent failing to run powershell modules that are too long (#…
Cx01N Jan 24, 2026
3278515
feat: add server.socketio config option to disable Socket.IO (#1124)
vinnybod Feb 2, 2026
2eef94e
feat: add plugin auto-install support (#1123)
vinnybod Feb 2, 2026
e5a9902
Updated Docs and added OpenAPI (#806)
Cx01N Jan 27, 2026
4ee20e3
Merge pull request #1126 from BC-SECURITY/vinnybod/cherry-pick-803-806
vinnybod Feb 2, 2026
d670443
feat: add config.user.yaml layering support (#1127)
vinnybod Feb 4, 2026
b228c65
Copy config.user.yaml alongside config.yaml on bootstrap (#1128)
vinnybod Feb 4, 2026
b2ad4e8
fixed issue with computername being removed from options (#1129)
Cx01N Feb 4, 2026
7666fde
Update exe stagers (#1125)
Cx01N Feb 6, 2026
a5e7e38
Fixed missing CompatibleDotNetVersions for ShellcmdRunas and ShellRun…
Cx01N Feb 6, 2026
7583acc
Fixed missing C# modules Assembly and AssemblyReflect (#1131)
Cx01N Feb 7, 2026
4dbb5d6
Added C# spawn module with Powershell and C# executables (#1132)
Cx01N Feb 10, 2026
9f506e1
fixed multi_launcher being overwritten (#1133)
Cx01N Feb 11, 2026
9f5f41e
Prepare release 6.4.1 private
web-flow Feb 15, 2026
2321ca6
Merge pull request #1134 from BC-SECURITY/release/6.4.1-private
vinnybod Feb 15, 2026
da63d86
Update starkiller version to v3.3.0
web-flow Feb 15, 2026
8907f85
Merge remote-tracking branch 'public/main' into release/6.4.1
vinnybod Feb 15, 2026
6ae3636
Fix CI Docker builds failing on public repo
vinnybod Feb 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/install_tests/cst-config-debian.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ commandTests:
- name: "mysql version"
command: "mysql"
args: ["--version"]
expectedOutput: ["mysql Ver 15.*10.*-MariaDB"]
expectedOutput: ["mysql Ver 15.*10.*-MariaDB|mysql from 11.*-MariaDB, client
15.*"]
2 changes: 1 addition & 1 deletion .github/install_tests/cst-config-ubuntu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ commandTests:
- name: "mysql version"
command: "mysql"
args: ["--version"]
expectedOutput: ["mysql Ver 8.0.*"]
expectedOutput: ["mysql Ver 8\\.[04].*"]
7 changes: 7 additions & 0 deletions .github/install_tests/docker-compose-install-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ services:
BASE_IMAGE: debian:bookworm
image: bcsecurity/empire-test-debian12
<<: *common-platform
debian13:
build:
<<: *common-build
args:
BASE_IMAGE: debian:trixie
image: bcsecurity/empire-test-debian13
<<: *common-platform
kalirolling:
build:
<<: *common-build
Expand Down
2 changes: 1 addition & 1 deletion .github/install_tests/run-all-cst.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set -e
# or `./run-all-cst.sh debian12` to test a single image
# or `./run-all-cst.sh` to test all images

all_images=(debian12 debian11 ubuntu2204 ubuntu2404 kalirolling parrotrolling)
all_images=(debian13 debian12 debian11 ubuntu2204 ubuntu2404 kalirolling parrotrolling)

for image in "${@:-${all_images[@]}}"
do
Expand Down
10 changes: 4 additions & 6 deletions .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ jobs:
with:
submodules: 'recursive'
token: ${{ secrets.RELEASE_TOKEN }}
- name: Set up SSH (sponsors only)
if: ${{ endswith(github.repository, 'Empire-Sponsors') }}
- name: Set up SSH
run: |
eval "$(ssh-agent -s)"
echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK" >> $GITHUB_ENV
Expand Down Expand Up @@ -133,7 +132,7 @@ jobs:
matrix:
# Because the box runs out of disk space, we can't run all tests on a single docker compose build.
images:
- ['debian11', 'debian12']
- ['debian11', 'debian12', 'debian13']
- ['ubuntu2204', 'ubuntu2404']
- ['kalirolling'] # 'parrotrolling'
# Parrot disabled for now because the apt repo is having some slowness issues.
Expand All @@ -143,8 +142,7 @@ jobs:
with:
submodules: 'recursive'
depth: 0
- name: Set up SSH (sponsors only)
if: ${{ endswith(github.repository, 'Empire-Sponsors') }}
- name: Set up SSH
run: |
eval "$(ssh-agent -s)"
echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK" >> $GITHUB_ENV
Expand All @@ -159,7 +157,7 @@ jobs:
# To save CI time, only run these tests when the install script or deps changed
- name: Get changed files using defaults
id: changed-files
uses: tj-actions/[email protected].0
uses: tj-actions/[email protected].1
- name: Build images
if: ${{ contains(steps.changed-files.outputs.modified_files, 'setup/install.sh')
|| contains(steps.changed-files.outputs.modified_files, 'poetry.lock')
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-private-start.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: '3.9'
python-version: '3.12'
- name: Setup poetry
run: |
curl -sL https://install.python-poetry.org | python - -y
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-private-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: '3.9'
python-version: '3.12'
- name: Setup poetry
run: |
curl -sL https://install.python-poetry.org | python - -y
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,5 @@ addons/
__pycache__/
workspace.xml
starkiller-dist.tar.gz
.worktrees/
config.user.yaml
49 changes: 47 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,53 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [6.4.1] - 2026-02-15
- Updated Starkiller to v3.3.0

### Added

- Added `config.user.yaml` layering support — create a `config.user.yaml` next to `config.yaml` to override specific settings without modifying the base config
- Added `auto_install` option to `plugin_marketplace` config for automatic plugin installation during setup
- Added `server.socketio` config option to disable Socket.IO (default: `true`)
- Added C# spawn module with Powershell and C# executables

### Fixed

- Fixed Go agent failing to run powershell modules that are too long
- Removed StagerURI from http listeners
- Fixed HTTP hop listener not getting proper host address
- Fixed arguments for bof module netloggedon
- Fixed option ComputerName being removed from modules without custom_generate
- Fixed missing CompatibleDotNetVersions for ShellcmdRunas and ShellRunAs
- Fixed missing CompatibleDotNetVersions for Assembly and AssemblyReflect
- Fixed parameter error when running Sharpsploit.Assembly

## [6.4.0] - 2026-01-18


### Added

- Added Debian 13 support
- Added error message if running `ps-empire server` under root without `-f`
- Added Get-ClipboardHistory PowerShell module to enumerate Windows clipboard history (Windows 10/11) via WinRT APIs
- Added `hide_disabled` parameter to `GET /api/v2/modules/` endpoint
- Added a health check endpoint at `/healthz`
- Added `module_options` to `AgentTask` and `plugin_options` to `PluginTask` for better execution tracking
- Added `-c` (compile from source) and `-o` (override) options to `ps-empire`
- Added local ticket support to Invoke-PSRemoting module
- Added an endpoint to stop background jobs on agents
- Added foreground C# tasking support to IronPython agent
- Added Get-ClipboardHistory PowerShell module to enumerate Windows clipboard history (Windows 10/11) via WinRT APIs

### Changed

- Updated the module categeories to be more clear
- Updated FastAPI deps to use Annotated types
- Changed StratumMiner, Moriarty, and Sharpup to background tasks
- Updated empire-compiler to v0.4.3

### Fixed

- Fixed results not coming back properly for powershell agents on C# background tasks

## [6.3.0] - 2025-12-11
- Updated Starkiller to v3.2.0
Expand Down Expand Up @@ -1206,7 +1247,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated shellcoderdi to newest version (@Cx01N)
- Added a Nim launcher (@Hubbl3)

[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v6.3.0...HEAD
[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v6.4.1...HEAD

[6.4.1]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v6.4.0...v6.4.1

[6.4.0]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v6.3.0...v6.4.0

[6.3.0]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v6.2.1...v6.3.0

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Empire is a post-exploitation and adversary emulation framework that is used to
- JA3/S and JARM Evasion
- MITRE ATT&CK Integration
- Integrated Roslyn compiler (Thanks to [Covenant](https://github.com/cobbr/Covenant))
- Docker, Kali, ParrotOS, Ubuntu 22.04/24.04, and Debian 11/12 Install Support
- Docker, Kali, ParrotOS, Ubuntu 22.04/24.04, and Debian 11/12/13 Install Support

### Agents
- PowerShell
Expand Down
15 changes: 7 additions & 8 deletions docs/listeners/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,13 @@ Empire provides JA3 evasion to help prevent detection by TLS fingerprinting tool

Empire provides additional settings to customize listener behavior:

* CertPath – Path to an SSL certificate for HTTPS listeners.
* KillDate – The expiration date when the agent will automatically exit (MM/DD/YYYY).
* WorkingHours – Defines when the agent will operate (09:00-17:00).
* Cookie – Custom cookie name used for agent communication.
* StagerURI – The URI for the stager (must use /download/, e.g., /download/stager.php).
* UserAgent – Defines the user-agent string used for staging requests (default, none, or other).
* Proxy – Proxy settings for agent communication.
* ProxyCreds – Proxy credentials (domain\username:password).
- CertPath – Path to an SSL certificate for HTTPS listeners.
- KillDate – The expiration date when the agent will automatically exit (MM/DD/YYYY).
- WorkingHours – Defines when the agent will operate (09:00-17:00).
- Cookie – Custom cookie name used for agent communication.
- UserAgent – Defines the user-agent string used for staging requests (default, none, or other).
- Proxy – Proxy settings for agent communication.
- ProxyCreds – Proxy credentials (domain\username:password).

## Default Response Page

Expand Down
22 changes: 22 additions & 0 deletions docs/plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ This allows anyone to build or add community projects to extend Empire functiona

Plugin installation is available through the Starkiller __Plugin Marketplace__.

### Auto-Installing Plugins

Plugins can be automatically installed during `./ps-empire setup` by adding them to the
`auto_install` list in `config.yaml`. This is useful for Docker builds or automated deployments
where plugins need to be pre-installed without manual API calls.

```yaml
plugin_marketplace:
registries:
- name: BC-SECURITY
git_url: https://github.com/BC-SECURITY/Empire-Plugin-Registry.git
ref: main
file: registry.yaml
auto_install:
- name: Report Generation Plugin
version: '2.0.0'
registry: BC-SECURITY
```

Each entry requires `name`, `version`, and `registry` matching a plugin in the configured registries.
Plugins that are already installed will be skipped.

### Additional Dependencies

If a plugin requires additional Python dependencies, the plugin page will show a warning
Expand Down
3 changes: 2 additions & 1 deletion docs/plugins/development/execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
The execute function is called when the plugin is executed via the API. The execute function is passed the following arguments:

* command - A dict of the command arguments, already parsed and validated by the core Empire code
* kwargs - Additional arguments that may be passed in by the core Empire code. Right now there are only two.
* kwargs - Additional arguments that may be passed in by the core Empire code.
* user - The user database object for the user that is executing the plugin
* db - The database session object
* plugin_options - A dict of the original options passed to the plugin execution

### Error Handling

Expand Down
2 changes: 2 additions & 0 deletions docs/plugins/development/plugin-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ from empire.server.core.db import models
def execute(self, command, **kwargs):
user = kwargs.get('user', None)
db = kwargs.get('db', None)
plugin_options = kwargs.get('plugin_options', None)

input = 'Example plugin execution.'

Expand All @@ -21,6 +22,7 @@ def execute(self, command, **kwargs):
input_full=input,
user_id=user.id,
status=models.PluginTaskStatus.completed,
plugin_options=plugin_options,
)

db.add(plugin_task)
Expand Down
35 changes: 33 additions & 2 deletions docs/quickstart/installation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ We recommend using the installation script or the Docker images to run Empire. A
The following operating systems have been tested for Empire compatibility.

* 22.04 / 24.04
* Debian 11 / 12
* Debian 11 / 12 / 13
* Kali Linux
* ParrotOS

Expand All @@ -28,6 +28,8 @@ When running the ps-empire installation script, you can use the following option

* `-y`: Automatically answer 'Yes' to all prompts during installation. This is useful if you want to install all optional dependencies without being prompted for confirmation.
* `-f`: Force the installation as root. Normally, Empire does not recommend installing as the root user for security reasons. However, if you need to bypass this restriction, you can use this flag. **Note: Using this option is not recommended unless absolutely necessary.**
* `-c`: Compile Empire-Compiler from source.
* `-o`: Override OS check. This flag allows the installation script to proceed even if the detected operating system is not officially supported.
* `-h`: Displays the help text.

```
Expand Down Expand Up @@ -100,4 +102,33 @@ All image versions can be found at: [https://hub.docker.com/r/bcsecurity/empire/

## Community-Supported Operating Systems

At this time, we are choosing to only support Kali, ParrotOS, Debian 11/12, and Ubuntu 22.04/24.04 installations, however, we will accept pull requests that fix issues or provide installation scripts specific to other operating systems to this wiki.
At this time, we are choosing to only support Kali, ParrotOS, Debian 11/12/13, and Ubuntu 22.04/24.04 installations, however, we will accept pull requests that fix issues or provide installation scripts specific to other operating systems to this wiki.

## Common Issues


### Issue

```
Current Python version (3.12.2) is not allowed by the project (>=3.13,<3.14).
Please change python executable via the "env use" command.
```

#### Solution

```
sudo rm -rf .venv
poetry install
```


### Issue

```
[*] Updating goenv
fatal: not a git repository (or any of the parent directories): git
```

#### Solution

Open a new terminal, the install script should have set `$GOENV_ROOT` in your bashrc or zshrc file.
26 changes: 26 additions & 0 deletions docs/quickstart/server.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@ The Server configuration is managed via [empire/server/config.yaml](https://gith

Once launched, Empire checks for user write permissions on paths specified in `config.yaml`. If the current user does not have write permissions on these paths, `~/.empire` will be set as fallback parent directory and the configuration file will be updated as well. If `empire-priv.key` and `empire-chain.pem` are not found in \~/.local/share/empire directory, self-signed certs will be generated.


## User Config Overrides

To customize settings without modifying `config.yaml`, create a `config.user.yaml` file in the same directory as the base config (e.g. `~/.config/empire/config.user.yaml`). This file only needs to contain the settings you want to override — everything else falls through to the base config.

For example, to override the API port and database type:

```yaml
api:
port: 8443
database:
use: mysql
mysql:
password: my_secret_password
```

The config priority order (first wins):
1. Environment variables (`EMPIRE_*`, e.g. `EMPIRE_API__PORT=8443`)
2. `.env` file
3. `config.user.yaml` (user overrides)
4. `config.yaml` (base defaults)

Nested settings are deep-merged: overriding `database.mysql.password` in `config.user.yaml` does not affect sibling fields like `database.mysql.username`. Lists are replaced entirely rather than appended.

If using `--config /path/to/config.yaml`, Empire looks for `config.user.yaml` in the same directory as the specified config file.

* **suppress-self-cert-warning** - Suppress the http warnings when launching an Empire instance that uses a self-signed cert.
* **api** - Configure the RESTful API.

Expand Down
36 changes: 33 additions & 3 deletions empire.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,56 @@
#! /usr/bin/env python3

import logging
import sys

from empire import arguments
from empire.server.common import empire
from empire.server.core.config import config_manager
from empire.server.core.config.data_manager import (
sync_empire_compiler,
sync_plugin_registry,
sync_starkiller,
)
from empire.server.core.db import base
from empire.server.core.db.base import SessionLocal
from empire.server.core.exceptions import PluginValidationException
from empire.server.server import run

log = logging.getLogger(__name__)

if __name__ == "__main__":
args = arguments.args

if args.subparser_name == "server":
from empire.server import server

server.run(args)
run(args)
if args.subparser_name == "setup":
sync_starkiller(config_manager.empire_config.starkiller)
sync_empire_compiler(config_manager.empire_config.empire_compiler)
for registry in config_manager.empire_config.plugin_marketplace.registries:
sync_plugin_registry(registry)

auto_install = config_manager.empire_config.plugin_marketplace.auto_install
if auto_install:
base.startup_db()
main = empire.MainMenu(args=args)

with SessionLocal.begin() as db:
for entry in auto_install:
try:
main.pluginregistriesv2.install_plugin(
db, entry.name, entry.version, entry.registry
)
log.info(
f"Auto-install: plugin '{entry.name}' v{entry.version} installed"
)
except PluginValidationException as e:
log.info(f"Auto-install: skipping '{entry.name}': {e}")
except Exception:
log.error(
f"Auto-install: failed to install '{entry.name}'",
exc_info=True,
)

main.shutdown()

sys.exit(0)
Loading
Loading