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
- Event occurs on endpoint
- Agent sends log files to Wazuh
- Wazuh generates an alert
- Alert triggers Active Response
velo-installon endpoint via Wazuh Agent velo-installpulls Velociraptor MSI from webhost and installs it- 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.CreateMSIand 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:
- Compile with PyInstaller to create an
.exe - Place binary at:
C:\Program Files (x86)\ossec-agent\active-response\bin\install-velo.exe - 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
- Ensure binary is placed on the endpoint
- Adapt manager configuration as shown above
- Configure Windows Defender log collection in Wazuh
- Place an EICAR test file on the endpoint
- After a few minutes, the client should appear in Velociraptor
Thanks to Christoph Lünswilken and John Olatunde for proofreading.
Quellen
- [1] https://github.com/sn0b4ll/wazuh_active_responses/tree/main/install_velociraptor
- [2] https://documentation.wazuh.com/current/user-manual/capabilities/active-response/custom-active-response-scripts.html#python-active-response-script-sample
- [3] https://documentation.wazuh.com/current/user-manual/capabilities/active-response/custom-active-response-scripts.html#method-1-convert-the-python-script-to-an-executable-application
- [4] https://www.eicar.org/download-anti-malware-testfile/
- [5] https://documentation.wazuh.com/current/user-manual/capabilities/malware-detection/win-defender-logs-collection.html