Skip to content

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

OperatorDescription
=~Regex match
=Equality
!=Not equal
<, >, <=, >=Comparison
AND, OR, NOTLogical operators
INMembership 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

IssueSolution
Query returns no resultsCheck plugin arguments, verify accessor permissions, test with broader glob
Query timeoutAdd LIMIT clause, narrow glob patterns, reduce search scope
Client not connectingVerify client config, check network/firewall, review server frontend logs
Artifact compilation errorValidate YAML syntax, check VQL query indentation, test in notebook first
Permission denied on filesEnsure Velociraptor client runs as SYSTEM/root
High resource usage during huntSet CPU/IO limits in hunt configuration, throttle concurrent clients
Event log parsing errorsVerify .evtx file path, check for corrupted log files
YARA scan slowNarrow file globs, reduce rule complexity, set process scan limits