Installing Velociraptor using Wazuh Active Response on Windows endpoints

Dominik Sigl 19. September 2025 Wazuh 30 Minuten Lesezeit

Why use Velociraptor in addition to Wazuh

While Wazuh provides robust detection capabilities, its active response functionality is limited to default scripts or in-house custom developments. This limitation creates challenges during active security incidents. By integrating Velociraptor – a leading open-source DFIR tool – we can dramatically enhance incident response capabilities directly from a Wazuh alert.

Prerequisites

  • Working Wazuh environment
  • Working Velociraptor installation
  • Windows system for testing and binary compilation
  • Web-Share (Apache, NGINX, or similar) to host the installer

How does an Active Response work?

Active responses execute either on the Wazuh server or directly on monitored endpoints. This guide focuses on endpoint-level responses, which require the response script to be present on the client machine.

Action Flow

  1. Event occurs on endpoint
  2. Agent sends log files to Wazuh
  3. Wazuh generates an alert
  4. Alert triggers Active Response velo-install on endpoint via Wazuh Agent
  5. velo-install pulls Velociraptor MSI from webhost and installs it
  6. velo-agent calls back to Velociraptor server

Creating a Velociraptor installation MSI

Referenced documentation: https://docs.velociraptor.app/docs/deployment/clients/

Steps:

  • Open Velociraptor GUI/Web-Page
  • Navigate to server artifacts
  • Add new collection using cross icon
  • Search for Server.Utils.CreateMSI and launch
  • Download MSI from the “Uploaded Files” tab
  • Move MSI to your Web-Share
  • Document the download link

Source Code „velo-installer"

The Python 3 script below is based on Wazuh active response templates. Set VELO_MSI_URL to your Web-Share link, then compile with PyInstaller.

#!/usr/bin/python3
# Copyright (C) 2015-2022, Wazuh Inc.
# Modified by sn0b4ll
# Date: 2025-08-15

import sys
import json
import datetime
import urllib.request
import subprocess
from pathlib import PureWindowsPath, PurePosixPath

LOG_FILE = "C:\\Program Files (x86)\\ossec-agent\\active-response\\active-responses.log"

VELO_MSI_URL = "<replace with VELO-MSI>"

ADD_COMMAND = 0
OS_SUCCESS = 0
OS_INVALID = -1

class message:
    def __init__(self):
        self.alert = ""
        self.command = 0

def write_debug_file(ar_name, msg):
    with open(LOG_FILE, mode="a") as log_file:
        ar_name_posix = str(PurePosixPath(PureWindowsPath(ar_name[ar_name.find("active-response"):])))
        log_file.write(str(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')) + " " + ar_name_posix + ": " + msg + "\n")

def setup_and_check_message(argv):
    input_str = ""
    for line in sys.stdin:
        input_str = line
        break

    write_debug_file(argv[0], input_str)

    try:
        data = json.loads(input_str)
    except ValueError:
        write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format')
        message.command = OS_INVALID
        return message

    message.alert = data
    command = data.get("command")

    if command == "add":
        message.command = ADD_COMMAND
    else:
        message.command = OS_INVALID
        write_debug_file(argv[0], 'Not valid command: ' + command)

    return message

def main(argv):
    write_debug_file(argv[0], "Started")

    msg = setup_and_check_message(argv)

    if msg.command < 0:
        sys.exit(OS_INVALID)

    if msg.command == ADD_COMMAND:
        alert = msg.alert["parameters"]["alert"]
        keys = [alert["rule"]["id"]]

        msi_url = VELO_MSI_URL
        try:
            msi_filename = "velo_install.msi"
            urllib.request.urlretrieve(msi_url, msi_filename)
            subprocess.run(["msiexec", "/i", msi_filename, "/quiet"], check=True)
            write_debug_file(argv[0], f"Successfully downloaded and installed {msi_filename}")
        except Exception as e:
            write_debug_file(argv[0], f"Failed to download or install MSI: {str(e)}")
        finally:
            try:
                os.remove(msi_filename)
                write_debug_file(argv[0], f"Successfully removed installer file: {msi_filename}")
            except OSError as e:
                write_debug_file(argv[0], f"Error removing installer file {msi_filename}: {e}")

        with open("ar-test-result.txt", mode="a") as test_file:
            test_file.write("Active response triggered by rule ID: <" + str(keys) + ">\n")

    write_debug_file(argv[0], "Ended")
    sys.exit(OS_SUCCESS)

if __name__ == "__main__":
    main(sys.argv)

Deployment:

  1. Compile with PyInstaller to create an .exe
  2. Place binary at: C:\Program Files (x86)\ossec-agent\active-response\bin\install-velo.exe
  3. Restart agent: Restart-Service -Name wazuh (PowerShell)

Source: https://github.com/sn0b4ll/wazuh_active_responses/tree/main/install_velociraptor

Manager Configuration

Add the following to the Wazuh manager’s <ossec_conf>:

<command>
  <name>windows-install-velo</name>
  <executable>install-velo.exe</executable>
  <timeout_allowed>no</timeout_allowed>
</command>

<active-response>
  <disabled>no</disabled>
  <command>windows-install-velo</command>
  <location>local</location>
  <rules_id>62123</rules_id>
</active-response>

This configuration triggers the active response on alert ID 62123 (Windows Defender malware detection). Restart the manager after the change.

POC-Video

A demonstration video is available at: https://drive.google.com/file/d/1V6lWvtfFo_FhFXIE-Ghx9rbkSUnyd09g/view?usp=sharing

Testing

  1. Ensure binary is placed on the endpoint
  2. Adapt manager configuration as shown above
  3. Configure Windows Defender log collection in Wazuh
  4. Place an EICAR test file on the endpoint
  5. After a few minutes, the client should appear in Velociraptor

Thanks to Christoph Lünswilken and John Olatunde for proofreading.

Quellen

Machen Sie schon heute den ersten Schritt

Unser Managed Detection & Response Service schützt Ihr Unternehmen unkompliziert vor Bedrohungen.

✉ Anfragen