Skip to content

12. Adaptix

BaddKharma edited this page Jul 19, 2026 · 2 revisions

📡 Adaptix

Open-source, extensible C2 framework: a headless Go teamserver and a Qt GUI client, built by the Adaptix-Framework project. redStack replaces Havoc (archived read-only upstream, February 2026) with AdaptixC2 pinned to v1.2. The teamserver builds from source automatically during cloud-init and starts itself; the operator client runs on the Windows workstation.

Note

About Adaptix: a teamserver-and-client architecture similar to Cobalt Strike. Beacons (Adaptix's implants) are configured through listener "extenders" the teamserver loads at runtime. The GUI client is a prebuilt Qt application that runs on the Windows operator workstation, not on the Adaptix host, so the Adaptix box itself is lean and headless (no VNC or desktop).

At a glance
Hostname adaptix (private VPC only)
Client access Windows workstation > C:\Tools\AdaptixClient\AdaptixClient.exe (desktop shortcut), reached via Guacamole > Windows (RDP)
Teamserver port 4321 (operator client, TLS, endpoint /adaptix)
Beacon listener port 443 (BeaconHTTP, internal; redirector re-encrypts to it)
Operator login any nickname / lab password (teamserver runs in password-only mode)
Connect URL https://adaptix:4321/adaptix (the endpoint must be in the URL)
URI prefix /edge/cache/assets/ (full path preserved on forward, not stripped)
Version pinned to v1.2 (var.adaptix_version)
First-deploy build time ~12 minutes (Go teamserver + beacon extenders, automatic in cloud-init)
Full docs github.com/Adaptix-Framework/AdaptixC2

Tip

Adaptix is the slowest backend to come up because it compiles from source in the background. Stand up Sliver and Mythic first, then confirm Adaptix last. cloud-init status --wait on the Adaptix host tells you when the build has finished and the teamserver is live on 4321.

Note

v1.1 vs v1.2: the v1.1 and v1.2 upstream tags point at the same commit (a4b80bf), so git describe on the checkout may report v1.1. It is v1.2. The lab pins the tag via var.adaptix_version (default v1.2).


Considerations

When Adaptix is the right pick

  • Extensible, modern C2: Adaptix is actively developed and built around a plugin/extender model. Listener and agent behavior come from loadable modules, so the framework is easy to extend without recompiling the core.
  • Cobalt-Strike-like idiom: If you have used Cobalt Strike, Adaptix's client mirrors the Listener / Agent / Sessions / Tasking layout. It is a natural drop-in where a Cobalt-Strike-style GUI workflow is wanted.
  • BOF and .NET tradecraft: The Adaptix beacon runs Beacon Object Files in-session and executes .NET assemblies, which covers most post-exploitation tooling (token-impersonation BOFs, potato-family assemblies, and so on).
  • Lean infrastructure: The teamserver is a single Go binary with no desktop dependencies. The operator client lives on the Windows workstation, so the Adaptix host stays small (a t3.small is enough after build).

When to skip Adaptix

  • You need the most-exercised path: Sliver is the primary driver in redStack's examples; Adaptix and Mythic stand up as additional callback paths.
  • Non-Windows operator client: The redStack client is a prebuilt Windows Qt build hosted as a release asset. There is no Linux/macOS client shipped in this lab (the upstream Linux client needs Qt > 6.8, newer than Debian 12 provides).
  • You cannot wait for the source build: The teamserver compiles during cloud-init (~12 min). If you need a C2 up in seconds, use Mythic or Sliver first and return to Adaptix once it finishes.

Sizing tradeoffs

Default t3.small (2 vCPU, 2 GB RAM, 25 GB disk) plus a 2 GB swapfile:

  • The swapfile matters: the Go build and Windows beacon cross-compile spike RAM and can OOM a 2 GB box without it (the setup script adds it automatically).
  • After build, runtime is light: a single Go teamserver binary, no desktop.

Disk: 25 GB holds the source tree (/opt/AdaptixC2), the Go cache, and generated beacons. Periodic cleanup of old beacon builds keeps it healthy.

Build lifecycle

The Adaptix teamserver builds once per deployment cycle, automatically, during cloud-init:

  1. Clone AdaptixC2, git checkout v1.2 (pinned so the lab is reproducible).
  2. make server-ext builds the teamserver plus the beacon extenders.
  3. A self-signed cert is generated, profile.yaml is patched (password, endpoint, port, cert), and the BeaconHTTP listener defaults are preset for redStack.
  4. The adaptix.service systemd unit is enabled and started.

The build is non-fatal: a failure does not strand the box. If it did not finish, run the retry script once:

~/build_adaptix_server.sh

Stopping and starting the instance preserves the compiled binary; the build does not re-run.

What ships pre-installed

Component Where
Adaptix source /opt/AdaptixC2/ (cloned + built by cloud-init)
Teamserver binary /opt/AdaptixC2/dist/adaptixserver
Beacon extenders /opt/AdaptixC2/dist/extenders/ (built by make server-ext)
Teamserver profile /opt/AdaptixC2/dist/profile.yaml (password, endpoint /adaptix, port 4321, cert)
Self-signed cert/key /opt/AdaptixC2/dist/server.rsa.crt / server.rsa.key
Listener preset script /opt/AdaptixC2/dist/extenders/beacon_listener_http/ax_config.axs (AxScript; presets the BeaconHTTP form)
systemd unit /etc/systemd/system/adaptix.service (User=admin, CAP_NET_BIND_SERVICE so it can bind 443)
Build retry script /home/admin/build_adaptix_server.sh
Quickstart /home/admin/adaptix_quickstart.txt
Windows operator client C:\Tools\AdaptixClient\ on the Windows workstation (downloaded at Windows provisioning)

Operations model

The teamserver runs headless as admin under systemd. The operator connects the Windows client to https://adaptix:4321/adaptix, in password-only mode (any nickname, lab password). Generated beacons land in the client's project directory on the Windows box (C:\Users\Administrator\AdaptixProjects\<project>\).

A terraform destroy wipes the teamserver state. A systemctl restart adaptix preserves it.

URI prefix preservation

Adaptix's /edge/cache/assets/ prefix is preserved (not stripped) by the redirector on forward. The BeaconHTTP listener URIs are configured with the full prefix, so the path the beacon calls must match the listener's URI list. This is why the redStack build presets the listener URIs as /edge/cache/assets/... rather than bare paths.

Compare:

  • Mythic: redirector strips /cdn/media/stream/, forwards /update.
  • Sliver: redirector strips /cloud/storage/objects/, forwards /....
  • Adaptix: redirector preserves /edge/cache/assets/, forwards the full path.

Configured in terraform/setup_scripts/redirector_setup.sh via per-backend RewriteRule patterns.


Configuration

What runs where

adaptix (Debian 12) [t3.small, EBS gp3 25 GB, 2 GB swap]
├── /opt/AdaptixC2/                                  Adaptix source / install root (pinned v1.2)
│   └── dist/
│       ├── adaptixserver                            Compiled teamserver binary
│       ├── profile.yaml                             Teamserver profile (password, endpoint, port, cert)
│       ├── server.rsa.crt / server.rsa.key          Self-signed TLS cert/key
│       └── extenders/
│           └── beacon_listener_http/
│               ├── listener_beacon_http.so          BeaconHTTP listener plugin
│               └── ax_config.axs                    AxScript presetting the listener form for redStack
├── /home/admin/build_adaptix_server.sh              Build/retry + start script
├── /home/admin/adaptix_quickstart.txt               Operator quickstart notes
└── /etc/systemd/system/adaptix.service              Teamserver systemd unit

The operator GUI client is on the Windows workstation, not on this host:

windows
└── C:\Tools\AdaptixClient\AdaptixClient.exe         Prebuilt Qt client (desktop shortcut)

Teamserver profile

profile.yaml is patched at build time (lab password injected, endpoint /adaptix, port 4321, interface 0.0.0.0, self-signed cert). The teamserver runs in password-only mode, so any nickname connects with the lab password. Restart after any change:

sudo systemctl restart adaptix

Listener presets

The BeaconHTTP listener form is preset for this lab by patching ax_config.axs after the build. Presets:

Field Preset
Bind / Port 0.0.0.0 / 443, SSL on
Callback address <REDIR_PUBLIC_IP>:443 (redirector public EIP)
URIs three paths under /edge/cache/assets/
Request header X-Request-ID: <token> (on the HTTP Headers tab)
Trust X-Forwarded-For on

Note

The client caches extenders per project. If the listener form shows stock placeholders instead of the redStack presets, disconnect and reconnect on a fresh project name and the presets repopulate.

Warning

Defender is disabled on the lab Windows workstation by default so beacons run. If you re-enabled it, re-disable with Set-MpPreference -DisableRealtimeMonitoring $true or the beacon is quarantined on execution.

Test Beacon

The walkthrough to confirm Adaptix is wired correctly. Assumes Verify is complete and the Redirector cert step is done (Direct Access). Because the teamserver builds from source, confirm it last, after Sliver and Mythic.

Step 1: Confirm the teamserver is up

From the Adaptix host (Guacamole > Adaptix (SSH), or the MobaXterm bookmark on the Windows operator):

cloud-init status --wait
sudo systemctl status adaptix --no-pager
sudo ss -tlnp | grep 4321

Expected: active (running) and port 4321 listening. If the service is missing or the build did not finish, run ~/build_adaptix_server.sh once to rebuild and start it, then re-check. journalctl -u adaptix shows startup errors.

✅ Checkpoint: teamserver active (running) on port 4321.

Step 2: Connect the operator client

The AdaptixClient is pre-installed on the Windows operator at C:\Tools\AdaptixClient\AdaptixClient.exe (desktop shortcut). From the Windows operator (Guacamole > Windows (RDP)), launch it and click Connect. The dialog fields, in order:

Field Value
User any nickname (e.g. operator)
Password <lab-password> from deployment_info.txt
URL https://adaptix:4321/adaptix
Name any project name (e.g. redStack)
Directory leave default

The endpoint (/adaptix) is part of the URL and must be included, or the client returns a login failure. The teamserver is password-only, so any username works with the lab password.

Click Connect; the client opens on an empty sessions view.

AdaptixClient Connect dialog with User, Password, URL, and Project Name
[Figure 12.2.1: AdaptixClient Connect dialog pointed at https://adaptix:4321/adaptix]

✅ Checkpoint: client connected to the teamserver.

Step 3: Create the BeaconHTTP listener

Open Listeners (the headphone icon). Right-click the empty panel at the bottom of the client and choose Create. In the Create Listener dialog:

  • Name: https (the Profile field auto-fills to https)
  • Config: change it from the default BeaconDNS to BeaconHTTP

The redStack build has already preset the listener. On the Main settings tab, confirm:

Field (Main settings) Preset value
Host & port (Bind) 0.0.0.0 / 443
Callback addresses <REDIR_PUBLIC_IP>:443 (redirector public EIP)
Method POST
URIs three paths under /edge/cache/assets/
Use SSL (HTTPS) on

The X-Request-ID: <token> validation header the redirector requires is preset on the HTTP Headers tab.

Do not confuse these with the redirector token: the Heartbeat Header (X-Beacon-Id) and Encryption key on the Main settings tab are Adaptix's own beacon fields, not the redirector's X-Request-ID token. Leave both at their preset/generated values, and do not paste the X-Request-ID token into either.

Confirm the callback shows your redirector public EIP and the header shows your real token (both baked from deployment_info at deploy), then click Create.

AdaptixClient Create Listener dialog set to BeaconHTTP with redStack presets
[Figure 12.2.2: BeaconHTTP listener with the redStack callback, URIs, and header presets]

✅ Checkpoint: the BeaconHTTP listener shows running, bound on 443.

Step 4: Generate the beacon

With the listener selected, open the agent generator (right-click the listener > Generate agent, or the client's Generate action):

Field Value
Listener https (the BeaconHTTP listener)
Agent beacon
Profile beacon_1 (leave default)
Arch x64
Format Exe

There is no operating-system field: the OS is fixed by the Agent you pick, and the stock beacon agent is Windows only, so Format (Exe, DLL, shellcode) produces a Windows PE.

Generate and save. The client writes the beacon to C:\Users\Administrator\AdaptixProjects\<project>\ by default; move it to the Desktop before executing:

Move-Item "C:\Users\Administrator\AdaptixProjects\redStack\axUpdate.exe" C:\Users\Administrator\Desktop\axUpdate.exe

AdaptixClient Generate Agent dialog with beacon, x64, Exe
[Figure 12.2.3: Generate Agent dialog configured for a Windows x64 exe beacon]

✅ Checkpoint: the beacon exe is on the Windows Desktop.

Step 5: Execute on Windows

From PowerShell on the Windows workstation:

Start-Process -FilePath "C:\Users\Administrator\Desktop\axUpdate.exe" -WindowStyle Hidden

A new session appears in the Adaptix client's sessions view within ~10 seconds.

AdaptixClient sessions view showing the Windows beacon
[Figure 12.2.4: First Adaptix beacon registered in the sessions view]

✅ Checkpoint: first Adaptix beacon registered.

Step 6: Confirm the full path

Right-click the session > Interact (open its console) and run a quick check:

whoami
ps

Expected: whoami returns the operator host's Administrator context; ps returns the process list.

In Guacamole, open the Redirector (SSH) connection (or the MobaXterm Apache Redirector (SSH) bookmark) and run:

sudo tail -f /var/log/apache2/redirector-ssl-access.log

Look for GET/POST requests to /edge/cache/assets/.... The path is preserved (not stripped) for Adaptix, unlike Mythic / Sliver.

✅ Checkpoint: Lab is fully operational for Adaptix. With all three C2s live, re-run the redirector test:

sudo /home/admin/test_redirector.sh

All three entries under Testing direct backend connectivity should show OK.

test_redirector.sh output showing Mythic, Sliver, and Adaptix all OK
[Figure 12.2.5: All three C2 backends reachable from the redirector. Lab fully operational]


Troubleshooting

Teamserver not running / no service

The build is non-fatal, so a build failure leaves no adaptix.service. Check and retry:

cloud-init status
sudo systemctl status adaptix --no-pager
~/build_adaptix_server.sh

build_adaptix_server.sh exports a proper HOME/GOPATH/GOCACHE, rebuilds make server-ext, re-patches the profile and listener presets, and starts the service. journalctl -u adaptix shows runtime errors.

Client returns "login failure"

Almost always one of two things:

  1. URL is missing the endpoint. It must be https://adaptix:4321/adaptix, not https://adaptix:4321.
  2. Teamserver has not finished building. Confirm Step 1 first. From the Windows box, Test-NetConnection adaptix -Port 4321 should succeed.

Username does not matter (password-only mode); the password is the lab password from deployment_info.txt.

Listener form shows stock placeholders, not the redStack presets

The client caches extenders per project. Disconnect, reconnect on a fresh project name, and the preset AxScript repopulates the form.

Beacon doesn't call back

In order:

  1. Listener is running: Listeners view, status shows running, bound on 443.
  2. URIs start with /edge/cache/assets/: the prefix is preserved on forward, so the beacon's URIs must match the listener's list.
  3. Header includes X-Request-ID: <token>: from deployment_info.txt, on the HTTP Headers tab. Mismatch = decoy page from the redirector.
  4. Callback address is the redirector public EIP, not the tun0 IP (Tunneled Access): HSL does not route VPN client IPs back to the target.
  5. Defender / AV: re-disable if you re-enabled it (Set-MpPreference -DisableRealtimeMonitoring $true).

See Troubleshooting > Agent Won't Callback for the universal checklist.

Build fails on make server-ext

grep -Ei 'error|fail' /var/log/user-data.log | tail -20

Most common: an OOM during the Go build on a small box (the 2 GB swapfile normally prevents this; confirm swapon --show), or a transient module download failure. Re-run ~/build_adaptix_server.sh; it is incremental.

Teamserver port 4321 reachable from outside the VPC

It shouldn't be. The Adaptix SG allows 4321 only from the Windows workstation SG (so the operator client can connect) and the instructor IP. Audit:

aws ec2 describe-security-groups --filters "Name=tag:Hostname,Values=adaptix" --query 'SecurityGroups[*].IpPermissions'

Previous: Sliver | Next: Windows


"Water shapes its course according to the nature of the ground over which it flows; the soldier works out his victory in relation to the foe whom he is facing."

Sun Tzu, The Art of War (~5th century BC)

Clone this wiki locally