Skip to main content

ClickFix Threat Detection

This example shows how to build a threat detection query that identifies ClickFix phishing attacks. ClickFix is a social engineering technique where attackers convince users to execute malicious commands through the Windows Run dialog or browser, often disguised as a way to "fix" a supposed error.

Attack Overview

ClickFix attacks follow a predictable pattern:

  1. Social Engineering - Users are tricked into thinking they need to "fix" something
  2. Command Execution - Users paste malicious commands into Windows Run dialog (Windows + R)
  3. Payload Download - PowerShell downloads and executes malicious files
  4. Command & Control - Establishes connection to attacker infrastructure

You can detect these attacks by correlating these behaviors within tight time windows to catch the complete attack chain while minimizing false positives.

Detection strategy

This detection identifies three key events within a 5-second window:

  • Registry modifications to RunMRU (tracks Windows+R usage)
  • Suspicious process creation (PowerShell with specific parameters)
  • Network connections to external command & control servers

The tight time correlation and requirement for all three behaviors helps distinguish real attacks from normal administrative activity.

Complete detection query

Here's the full detection query that correlates registry events, process creation, and network connections to identify ClickFix attacks. The query uses DEF statements to define each event type, then applies time-based windowing and pattern matching to find the complete attack sequence:

// Detection Name: Detection - ClickFix Initial Access
//
// Description:
// This detection identifies potential ClickFix phishing activity,
// a technique where users are socially engineered to execute
// malicious commands either through the Windows Run dialog
// (Windows + R) or directly from their browser. The attack
// typically involves convincing users to paste commands that lead
// to execution of PowerShell or other scripting tools, often
// disguised as a way to "fix" a supposed error.
//
// Detection Logic
// The detection correlates three key events within a 5-second window:
// 1. Registry modifications to RunMRU (tracks Windows+R usage) or
// process creation from common browsers
// 2. Creation of suspicious processes (PowerShell, CMD, MSHTA) with
// suspicious command-line parameters
// 3. Network connections to external IPs or domains
//
// The tight 5-second window and requirement for all three behaviors
// help reduce false positives while catching the typical ClickFix
// attack chain.

// Identify Windows Run Dialog useage
DEF registry_events = FROM simba.sysmon_events
| WHERE event.code == "13"
| SET reg_key = coalesce(winlog.parsed_event_data.target_object AS string, '')
| SET reg_value = coalesce(winlog.parsed_event_data.details AS string, '')
| SET image = lower(coalesce(winlog.parsed_event_data.image AS string, ''))
| SET host = host.name
| WHERE regexp_like(lower(reg_key), '(?i).*\\currentversion\\explorer\\runmru.*')
AND regexp_like(image, '(?i).*explorer\.exe.*');

// Get suspicious process creations
DEF process_events = FROM simba.sysmon_events
| WHERE event.code == "1"
| SET cmd_line = coalesce(winlog.parsed_event_data.command_line AS string, '')
| SET image = coalesce(winlog.parsed_event_data.image AS string, '')
| SET parent_image = coalesce(winlog.parsed_event_data.parent_image AS string, '')
| SET host = host.name
| SET user_name = coalesce(winlog.user.name AS string, '')
| WHERE regexp_like(lower(cmd_line), '(?i).*(iwr|invoke-webrequest|wget).*\$env:temp.*\.exe.*')
AND regexp_like(lower(cmd_line), '(?i).*-w\s+hidden.*')
AND regexp_like(lower(parent_image), '(?i).*explorer\.exe.*');

// Get suspicious network connections
DEF network_events = FROM simba.sysmon_events
| WHERE event.code == "3"
| SET dest_ip = coalesce(winlog.parsed_event_data.destination_ip AS string, '')
| SET dest_port = coalesce(winlog.parsed_event_data.destination_port AS string, '')
| SET image = lower(coalesce(winlog.parsed_event_data.image AS string, ''))
| SET host = host.name
| WHERE
dest_ip == "172.31.7.63" AND
dest_port == "4444" AND
regexp_like(image, '(?i).*\\temp\\.*\.exe');

// Main Detection Logic:
//
// Above we detect three distinct events happening in a Clickfix scenario:
// - A suspicious process is launched
// - A registry event signaling a Windows Run Dialog usage
// - Outbound network connections to a known C2 server
//
// Then, we detect a process event and a registry event happening together.
// Technically, the process event precedes the registry event.
// But in Windows, the timeestamps for the events are not very precise
// Therefore, we need look for those two events happening NOT one
// after the other, but in a small time window!
DEF process_near_registry = FROM registry_event = registry_events,
process_event = process_events
| WINDOW process_event = last_value(process_event),
registry_event = last_value(registry_event)
BY host WITHIN 1s
| WHERE process_event IS NOT NULL AND registry_event IS NOT NULL;

// Finally, we are looking for a pattern where a combination of the above
// mentioned process & registry events are on the same host followed by
// outbound network connections to the C2 server.
MATCH process_near_registry network_event=network_events+
AGG
timestamp = min(timestamp),
event.start = min(timestamp),
event.end = max(timestamp),
process_event = first(matched.process_event),
registry_event = first(matched.registry_event),
network_events = filter_null(array_agg(network_event))
BY host
WITHIN 5s

// Now we know it's Clickfix, so let's create a nice Signal for analysts to
// follow up on.
//
// Create simple message and structured labels:
| SET message = "ClickFix C2 Activity Detection - Initial Access and Command & Control"
| SET labels = map(
"Severity": "CRITICAL",
"Host": host,
"User": coalesce(process_event.user_name, "unknown"),
"Run Dialog Activity": registry_event.reg_value,
"Registry Key": registry_event.reg_key,
"PowerShell Command": process_event.cmd_line,
"Process Path": process_event.image,
"Parent Process": process_event.parent_image,
"Destination IP": network_events.dest_ip[0],
"Destination Port": network_events.dest_port[0],
"Beacon Count": len(array_distinct(network_events.dest_ip)) AS string)

// Detection Output
| SELECT
timestamp,
event.start = event.start,
event.end = event.end,
process_event,
registry_event,
network_events,
host.name = host,
process.name = process_event.image,
process.command_line = process_event.cmd_line,
process.parent.name = process_event.parent_image,
registry.key = registry_event.reg_key,
registry.value = registry_event.reg_value,
destination.ip = network_events.dest_ip[0],
destination.port = network_events.dest_port[0],
user.name = process_event.user_name,
beacons = array_distinct(network_events.dest_ip),
event.risk_score = 100,
message,
labels,
rule = {
name: "Windows ClickFix Initial Access",
description: message,
mitre_tactics: [
"Command and Control",
"Execution",
"Persistence"
],
mitre_techniques: [
"T1571", // Non-Standard Port
"T1105", // Ingress Tool Transfer
"T1572", // Protocol Tunneling
"T1059.001" // PowerShell
],
severity: "critical"
}

Query breakdown

This detection demonstrates several advanced Hamelin techniques working together. Let's examine each component:

Event collection phase

The query starts by defining three separate event types using DEF statements. Each clause filters and transforms raw Sysmon events to extract the specific indicators needed for correlation:

Registry events track Windows Run dialog usage by monitoring registry modifications to the RunMRU key:

DEF registry_events = FROM simba.sysmon_events
| WHERE event.code == "13" // Registry modification events
| SET reg_key = coalesce(winlog.parsed_event_data.target_object AS string, '')
| WHERE regexp_like(lower(reg_key), '(?i).*\\currentversion\\explorer\\runmru.*')
AND regexp_like(image, '(?i).*explorer\.exe.*');

Process events identify suspicious PowerShell execution with specific command-line patterns that indicate ClickFix behavior:

DEF process_events = FROM simba.sysmon_events
| WHERE event.code == "1" // Process creation events
| WHERE regexp_like(lower(cmd_line), '(?i).*(iwr|invoke-webrequest|wget).*\$env:temp.*\.exe.*')
AND regexp_like(lower(cmd_line), '(?i).*-w\s+hidden.*');

Network events detect connections to known command & control infrastructure by filtering for specific IP addresses and ports:

DEF network_events = FROM simba.sysmon_events
| WHERE event.code == "3" // Network connection events
| WHERE dest_ip == "172.31.7.63" AND dest_port == "4444";

Time-based correlation

The detection uses windowing to correlate process and registry events that occur close in time. Windows event timestamps aren't perfectly precise, so you need to look for events happening within a small time window rather than in strict sequence:

DEF process_near_registry = FROM registry_event = registry_events,
process_event = process_events
| WINDOW process_event = last_value(process_event),
registry_event = last_value(registry_event)
BY host WITHIN 1s;

This creates pairs of process and registry events that happen within 1 second of each other on the same host.

Pattern matching

The MATCH command identifies the complete attack sequence by finding correlated events followed by network connections:

MATCH process_near_registry network_event=network_events+ BY host WITHIN 5s

This finds patterns where process and registry events occur together, followed by one or more network connections, with the entire pattern completing within 5 seconds, all happening on the same host.

Structured output

The final section creates analyst-friendly output that includes event metadata like start/end times and risk scores, process details such as command lines and parent processes, network indicators including destination IPs and ports, MITRE mapping for threat intelligence, and structured labels as key-value pairs for SIEM integration.

Advanced techniques demonstrated

This detection showcases several techniques that make Hamelin effective for threat detection:

Multi-source correlation combines registry, process, and network events from the same data source but different event types.

Time-based windowing uses WINDOW operations to group events that occur close in time, accounting for timestamp precision limitations.

Pattern matching employs MATCH to identify ordered sequences of events that follow the attack pattern.

Flexible field extraction uses coalesce() to handle varying field names and missing data gracefully.

Regular expressions apply regexp_like() for flexible pattern matching in command lines and file paths.

Structured output creates both human-readable messages and machine-readable labels for different consumers.

Detection tuning

You can adapt this detection for different environments:

Adjust time windows by modifying the 1-second and 5-second windows based on event timing characteristics in the environment.

Update IOCs by replacing the hardcoded IP address and port with threat intelligence feeds.

Refine regex patterns by customizing the command line patterns based on observed ClickFix variants.

Modify thresholds by adjusting beacon counts or adding minimum connection duration requirements.

The modular structure with DEF statements makes it easy to test and tune individual components without affecting the entire detection logic.