Velociraptor VQL Cheat Sheet
Overview
Velociraptor Query Language (VQL) is the core query language powering Velociraptor, an open-source endpoint visibility and digital forensics platform. VQL allows security analysts to write powerful queries that collect forensic artifacts, hunt for indicators of compromise, monitor endpoint behavior, and automate incident response across thousands of endpoints simultaneously. VQL combines SQL-like syntax with a rich plugin ecosystem that provides direct access to OS internals — filesystem, registry, event logs, process memory, network connections, and more.
VQL queries can be executed interactively through the Velociraptor web UI, scheduled as monitoring artifacts for continuous detection, or deployed as hunts across the entire endpoint fleet. The language supports parameterized artifacts (reusable query templates), chaining through LET expressions, conditional logic, regular expressions, and output to multiple formats. Velociraptor ships with hundreds of pre-built artifacts covering Windows, Linux, and macOS forensics, MITRE ATT&CK technique detection, and common incident response workflows. Custom VQL artifacts can be developed and shared through the Velociraptor Artifact Exchange.
Installation
Velociraptor Server
# Download latest release
wget https://github.com/Velocidex/velociraptor/releases/latest/download/velociraptor-v0.73-linux-amd64
chmod +x velociraptor-v0.73-linux-amd64
sudo mv velociraptor-v0.73-linux-amd64 /usr/local/bin/velociraptor
# Generate server configuration
velociraptor config generate -i
# Start server
velociraptor --config server.config.yaml frontend -v
# Or install as a service
velociraptor --config server.config.yaml service install
sudo systemctl start velociraptor
Velociraptor Client
# Deploy client with embedded config
velociraptor --config client.config.yaml client -v
# Install as service (Windows)
velociraptor.exe --config client.config.yaml service install
# Repack client with embedded config
velociraptor config repack --exe velociraptor-v0.73-linux-amd64 client.config.yaml velociraptor-client
VQL Syntax Basics
Query Structure
-- Basic SELECT query
SELECT Column1, Column2
FROM plugin(arg1=value1, arg2=value2)
WHERE condition
-- LET expressions for variables
LET my_var = "value"
-- LET for subqueries
LET processes = SELECT Pid, Name, CommandLine
FROM pslist()
-- Chaining queries
SELECT * FROM foreach(
row={SELECT * FROM processes},
query={SELECT * FROM proc_yara(pid=Pid)}
)
Common Operators
| Operator | Description |
|---|---|
=~ | Regex match |
= | Equality |
!= | Not equal |
<, >, <=, >= | Comparison |
AND, OR, NOT | Logical operators |
IN | Membership test |
+ | String concatenation or addition |
format() | String formatting |
timestamp() | Parse timestamp |
if() | Conditional expression |
Core VQL Queries
Process Investigation
-- List all running processes
SELECT Pid, Ppid, Name, Username, CommandLine, Exe, CreateTime
FROM pslist()
-- Find suspicious processes
SELECT Pid, Name, CommandLine, Exe
FROM pslist()
WHERE Name =~ "powershell|cmd|wscript|cscript|mshta|rundll32"
AND CommandLine =~ "(?i)(encoded|hidden|bypass|invoke|download)"
-- Process tree reconstruction
SELECT Pid, Ppid, Name, CommandLine, TokenIsElevated
FROM pslist()
WHERE Ppid = 1234
-- Detect process injection (unsigned DLLs in signed processes)
SELECT Pid, Name as ProcessName, ModuleName, ExePath
FROM modules(pid=Pid)
WHERE NOT authenticode(filename=ExePath).Trusted
File System Analysis
-- Search for files by name pattern
SELECT FullPath, Size, Mtime, Atime, Ctime
FROM glob(globs="C:/Users/*/Downloads/*.exe")
-- Find recently modified executables
SELECT FullPath, Size, Mtime
FROM glob(globs="C:/Windows/System32/*.exe")
WHERE Mtime > timestamp(epoch=now() - 86400)
-- Hash files
SELECT FullPath, Size, hash(path=FullPath) AS Hash
FROM glob(globs="C:/Windows/Temp/*.exe")
-- Find files by hash
LET target_hash = "a1b2c3d4e5f6..."
SELECT FullPath, Size, Mtime
FROM glob(globs="C:/**/*.exe")
WHERE hash(path=FullPath).SHA256 = target_hash
-- Alternate data streams
SELECT FullPath, Size, Mtime
FROM glob(globs="C:/Users/**/*:*")
WHERE NOT FullPath =~ ":Zone.Identifier$"
Registry Analysis (Windows)
-- Read registry key
SELECT Name, Type, Data
FROM read_reg_key(globs="HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Run/*")
-- Find persistence mechanisms
SELECT * FROM Artifact.Windows.Persistence.Registry()
-- Search registry for value
SELECT Key, Name, Data
FROM glob(globs="HKEY_LOCAL_MACHINE/SOFTWARE/**",
accessor="registry")
WHERE Data =~ "suspicious_string"
-- Compare registry snapshots
LET baseline = SELECT * FROM read_reg_key(
globs="HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Run/*")
LET current = SELECT * FROM read_reg_key(
globs="HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Run/*")
SELECT * FROM diff(old=baseline, new=current)
Network Analysis
-- List network connections
SELECT Pid, Name, FamilyString as Protocol,
SrcAddr, SrcPort, DestAddr, DestPort, StatusString as State
FROM netstat()
-- Find connections to external IPs
SELECT Pid, Name, DestAddr, DestPort
FROM netstat()
WHERE NOT DestAddr =~ "^(10\\.|172\\.(1[6-9]|2|3[01])\\.|192\\.168\\.|127\\.)"
AND DestAddr != ""
-- DNS cache analysis
SELECT * FROM Artifact.Windows.System.DnsCache()
-- ARP table
SELECT * FROM arp()
Event Log Analysis (Windows)
-- Parse Windows Event Logs
SELECT EventTime, EventID, Computer, Message
FROM parse_evtx(filename="C:/Windows/System32/winevt/Logs/Security.evtx")
WHERE EventID IN (4624, 4625, 4648, 4672)
ORDER BY EventTime DESC
LIMIT 100
-- Failed logon attempts
SELECT EventTime, EventData.TargetUserName as User,
EventData.IpAddress as SourceIP,
EventData.LogonType as LogonType
FROM parse_evtx(filename="C:/Windows/System32/winevt/Logs/Security.evtx")
WHERE EventID = 4625
ORDER BY EventTime DESC
-- PowerShell Script Block Logging
SELECT EventTime, EventData.ScriptBlockText as Script
FROM parse_evtx(
filename="C:/Windows/System32/winevt/Logs/Microsoft-Windows-PowerShell%4Operational.evtx")
WHERE EventID = 4104
AND EventData.ScriptBlockText =~ "(?i)(invoke-|download|encoded|bypass)"
Custom Artifacts
Artifact Structure
name: Custom.Windows.Detection.SuspiciousService
description: |
Detect Windows services with suspicious characteristics
such as running from temp directories or user profile paths.
parameters:
- name: SuspiciousPathRegex
default: "(?i)(temp|tmp|appdata|users.*desktop|downloads)"
sources:
- query: |
SELECT Name, DisplayName, PathName, StartMode, State, StartName
FROM wmi(
query="SELECT * FROM Win32_Service",
namespace="root/cimv2")
WHERE PathName =~ SuspiciousPathRegex
Parameterized Artifact
name: Custom.Hunt.FileByHash
description: Hunt for files matching specific hashes across endpoints.
parameters:
- name: TargetHash
description: SHA256 hash to search for
- name: SearchPaths
default: "C:/Windows/Temp/**,C:/Users/*/Downloads/**"
sources:
- query: |
LET search_paths = split(string=SearchPaths, sep=",")
SELECT FullPath, Size, Mtime,
hash(path=FullPath).SHA256 as SHA256
FROM foreach(
row=search_paths,
query={
SELECT FullPath, Size, Mtime
FROM glob(globs=_value)
WHERE NOT IsDir
})
WHERE hash(path=FullPath).SHA256 = TargetHash
Advanced Usage
YARA Scanning
-- Scan processes with YARA rules
SELECT * FROM foreach(
row={SELECT Pid, Name FROM pslist()},
query={
SELECT Pid, Name, Rule, Strings
FROM proc_yara(
pid=Pid,
rules='rule suspicious {
strings:
$a = "mimikatz" nocase
$b = "sekurlsa" nocase
condition:
any of them
}')
})
-- Scan files with YARA
SELECT FullPath, Rule, Strings
FROM yara(
rules='rule webshell {
strings: $php = "<?php eval(" nocase
condition: $php
}',
files="C:/inetpub/wwwroot/**/*.php")
Automated Collection
-- Collect and upload evidence
SELECT upload(file=FullPath) as Upload,
FullPath, Size, Mtime
FROM glob(globs="C:/Windows/Prefetch/*.pf")
-- Collect memory dump of process
SELECT upload(file=FullPath) as Upload
FROM proc_dump(pid=1234)
Stacking and Anomaly Detection
-- Stack analysis: find rare executables across fleet
SELECT Name, CommandLine, count() as Count
FROM pslist()
GROUP BY Name
ORDER BY Count ASC
LIMIT 20
-- Find rare scheduled tasks
SELECT Name, Command, count() as HostCount
FROM Artifact.Windows.System.TaskScheduler()
GROUP BY Name, Command
HAVING HostCount < 3
Troubleshooting
| Issue | Solution |
|---|---|
| Query returns no results | Check plugin arguments, verify accessor permissions, test with broader glob |
| Query timeout | Add LIMIT clause, narrow glob patterns, reduce search scope |
| Client not connecting | Verify client config, check network/firewall, review server frontend logs |
| Artifact compilation error | Validate YAML syntax, check VQL query indentation, test in notebook first |
| Permission denied on files | Ensure Velociraptor client runs as SYSTEM/root |
| High resource usage during hunt | Set CPU/IO limits in hunt configuration, throttle concurrent clients |
| Event log parsing errors | Verify .evtx file path, check for corrupted log files |
| YARA scan slow | Narrow file globs, reduce rule complexity, set process scan limits |