Threat Hunting

What Is Threat Hunting? A Practical Guide for Modern SOCs

HuntRule Team · · 10 min read

A single fresh boot track pressed into wet ground, fog closing in behind it
On this page

C:\Users\jhale\AppData\Local\Temp\Rar$EXa0.372\GUP.exe is the shape a side-loading host leaves behind. One host, one execution, a real vendor name in the file metadata, sitting inside a WinRAR extraction directory. Every rule in the stack reads that row and shrugs, because nothing in it is individually wrong. Finding it anyway is threat hunting.

That path is a constructed example, not telemetry from a victim environment. This post is about method.

Threat hunting is the practice of searching telemetry for activity your detections would not have caught. The definition is deliberately negative. Hunting is defined by the gap, not by the tooling.

What hunting is not

Three things get called hunting and are not.

Alert triage works a queue that a detection already generated. The input is a rule that fired. Hunting has no queue, and the expected result of most hunts is zero interesting rows.

Vulnerability scanning answers what could be exploited. Hunting answers what did execute. A scanner telling you a host is three patches behind says nothing about whether w3wp.exe spawned cmd.exe last Tuesday.

Running a tool is not hunting either. Browsing an EDR's rare-process dashboard for an hour produces a feeling of coverage and no artifact. If the session ends without a written hypothesis, a query you can paste, and a result count, nothing was hunted. That is the most common failure mode in this discipline and it deserves a blunt name. Hunting without a hypothesis is dashboard tourism.

Three ways a hunt starts

Intel-driven. A report names artifacts: a service name, a mutex, a scheduled task path, a certificate thumbprint. You check whether those exist across the retention window you actually have. Cheapest hunt to run, and the lowest ceiling, because you can only find what somebody else already wrote up.

Hypothesis-driven. You start from a technique and reason about what it must leave behind. "If an operator used DLL side-loading (T1574.001) here, a vendor-signed executable is sitting in a user-writable directory next to a DLL that vendor never shipped." You go looking for the observable, not for the actor.

Anomaly and baseline-driven. You build a picture of normal for one narrow slice, then read the tail. Stack every parent-child process pair across the fleet for thirty days, sort ascending by host count, read the bottom fifty rows. winword.exe spawning cmd.exe lives in that tail. So does one legitimate macro that two people in finance run every month.

None of the three outranks the others. Anomaly-driven hunts find the things nobody has published a report about yet.

You cannot hunt in telemetry you do not collect

Check what you have before you write a hypothesis you cannot test.

  • Process creation with command line. Sysmon Event ID 1, or Windows Security 4688 with Include command line in process creation events enabled under Administrative Templates\System\Audit Process Creation. Without that policy the 4688 command line field is empty.

  • Parent process. Sysmon Event ID 1 carries ParentImage and ParentCommandLine. Event 4688 carries ParentProcessName (shown as Creator Process Name in Event Viewer) and no parent command line.

  • File metadata. Sysmon Event ID 1 carries OriginalFileName, Company, Product and Hashes. Event 4688 carries none of them, so half the hunt below is impossible on 4688 alone.

  • Retention. Thirty days of process creation is the floor for rarity analysis. Rarity over seven days is mostly a measure of who was on holiday.

One detail trips people up constantly. Sysmon Event ID 1 has no signature fields. There is no Signed, no Signature, no SignatureStatus on process creation. Those live on Event ID 7 (image loaded) and Event ID 6 (driver loaded). Any hunt guide telling you to filter Event ID 1 on Signed: true is wrong about the schema. Signature has to come from your EDR's own process telemetry or from verifying the hash out of band during triage.

The hunt

Hypothesis

Written down before a single query runs.

An operator staging a side-loading payload will drop a legitimately signed vendor executable into a user-writable directory and run it there. That executable will be rare across the fleet, its Company field will name a real vendor, and its parent will be an archive utility or explorer.exe rather than msiexec.exe.

A hypothesis names the observable, the field it lives in, and the expected shape of the false positives. If it does not name all three, it is a mood.

Data and fields

Process creation, thirty days, whole fleet. Fields: Image, OriginalFileName, Company, the SHA256 out of Hashes, ParentImage, User, timestamp and hostname. Signature is not in this data, which is why it does not appear in the query.

The query

SELECT p.sha256,
       min(p.image)           AS sample_path,
       p.original_file_name,
       p.company,
       count(DISTINCT p.host) AS hosts,
       count(*)               AS executions,
       min(p.event_time)      AS first_seen
FROM   process_creation p
WHERE  p.event_time >= now() - interval '30 days'
  AND (p.image ILIKE 'C:\Users\%'
   OR  p.image ILIKE 'C:\ProgramData\%'
   OR  p.image ILIKE 'C:\Windows\Temp\%')
  AND  p.company IS NOT NULL
  AND  p.company <> ''
GROUP  BY p.sha256, p.original_file_name, p.company
HAVING count(DISTINCT p.host) <= 3
   AND count(*) <= 10
ORDER  BY hosts, executions, first_seen;

Backslash handling differs by backend. PostgreSQL treats the backslash as the LIKE escape character, so you need doubled backslashes or an explicit ESCAPE clause. Fix that before you conclude the environment is clean.

Reading the result set

How many rows this returns depends on your fleet size and software mix, and most of them are boring in four predictable ways.

  • Per-user installer frameworks. Squirrel and ClickOnce packages stage vendor binaries under %LOCALAPPDATA%\Programs by design.

  • Update stubs. GoogleUpdate.exe, MicrosoftEdgeUpdate.exe and their temp-directory setup copies.

  • Developer toolchains. node.exe and python.exe shims under %LOCALAPPDATA% on the engineering laptops.

  • One-off extractions. Somebody unzipped a vendor diagnostic tool and ran it once, exactly as support told them to.

Three things separate the interesting rows from the boring ones, and none of them is the path.

  1. Metadata that disagrees with the file. OriginalFileName reads GUP.exe while the on-disk name is SecurityHealth.exe. Renaming a binary does not rewrite its PE version resource. That mismatch is T1036.005 in one field comparison.

  2. A parent no installer would have. 7zFM.exe, WinRAR.exe, outlook.exe, or explorer.exe right after an ISO mount. Legitimate per-user installers descend from msiexec.exe or a signed setup bootstrapper.

  3. Host count of one, execution count of one, and silence on either side. A tool a person actually uses gets used more than once.

Triage is where the signature check finally happens. Pull the SHA256, verify the signer, then list what that process loaded out of its own directory. A validly signed vendor executable in a temp folder next to a DLL that vendor never shipped is the entire finding. A genuine signature is the point rather than a contradiction, because abusing trusted signed code is T1553.002 working as intended.

Closing the loop

A hunt that produces no durable detection was entertainment.

Sqrrl's Threat Hunting Loop puts this in its fourth stage, "Inform and Enrich Analytics". David Bianco's Hunting Maturity Model, published in 2015, makes it the whole difference between HMM3 (Innovative) and HMM4 (Leading). At HMM4 every successful hunting process gets operationalized into automated detection, so no analyst ever runs it by hand a second time.

A plaster cast being lifted out of a footprint pressed into wet clay

Here is the rule the hunt produces. It is deliberately narrower than the query above.

title: Signed Vendor Binary Executed From User-Writable Path By Archive Tool
id: d993fad4-be07-4782-a821-8077d5c4ea43
status: experimental
description: |
  Detects an executable carrying vendor file metadata running from a
  user-writable directory with an archive utility or explorer.exe as its
  parent. This is the execution half of a DLL side-loading chain delivered
  inside an archive or a mounted image.
references:
  - https://attack.mitre.org/techniques/T1574/001/
  - https://attack.mitre.org/techniques/T1036/005/
author: HuntRule
date: 2026-07-31
tags:
  - attack.defense-evasion
  - attack.persistence
  - attack.privilege-escalation
  - attack.t1574.001
  - attack.t1036.005
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:
      - '\7zFM.exe'
      - '\7zG.exe'
      - '\WinRAR.exe'
      - '\Winzip64.exe'
      - '\explorer.exe'
  selection_path:
    Image|startswith:
      - 'C:\Users\'
      - 'C:\ProgramData\'
      - 'C:\Windows\Temp\'
  selection_metadata:
    Company|contains:
      - 'Microsoft'
      - 'Google'
      - 'VMware'
      - 'Cisco'
      - 'Notepad++'
  filter_peruser_installers:
    Image|contains:
      - '\AppData\Local\Programs\'
      - '\AppData\Local\Google\Update\'
      - '\AppData\Local\Microsoft\OneDrive\'
  condition: all of selection_* and not 1 of filter_*
falsepositives:
  - Portable vendor tools extracted from an archive and run in place
  - Squirrel and ClickOnce installers staging vendor binaries under %LOCALAPPDATA%
  - Per-user updaters that unpack into a temp directory before relaunching
level: medium

The hunt query asked what is rare here. The rule asks whether one specific shape occurred. A rule cannot compute fleet-wide rarity at detection time, so rarity moves out of the logic and into the path, parent and metadata constraints. That trade is why a hunt and a rule are two different objects rather than one artifact copied twice. If the format is new to you, the structure is covered in what Sigma rules are.

What the rule catches and what it misses

It catches a vendor-branded executable launched out of a user-writable directory by an archive tool or by explorer.exe, which is the moment the side-loading host runs. It misses more than that.

  • Payloads with an empty Company field, or one spoofing a vendor outside the list. That list is the weakest part of the rule and has to be fitted to your own software mix.

  • Anything on a 4688-only pipeline. Company does not exist in that event, so the rule compiles and silently matches nothing. Check your backend field mapping before you trust a zero.

  • Side-loading staged into C:\Windows\System32 by an already-privileged operator. Excluded by the path prefixes on purpose, because that region is too noisy for this shape.

  • The DLL half of the chain. Catch the payload with a companion rule on Sysmon Event ID 7 for an unsigned or untrusted module loading from the same directory as its parent executable, using Signed, Signature and SignatureStatus.

We have not run this rule against a production fleet, so treat the medium level and the filter block as starting points.

Technique mapping

ID

Title

Where it appears

T1574.001

Hijack Execution Flow: DLL

The hypothesis and the Sigma rule

T1036.005

Masquerading: Match Legitimate Resource Name or Location

The OriginalFileName mismatch during triage

T1553.002

Subvert Trust Controls: Code Signing

Why a valid signature is not exculpatory

T1218

System Binary Proxy Execution

The adjacent hunt when the host binary is a Windows LOLBin

T1574.002 (DLL Side-Loading) was revoked in ATT&CK v17 and merged into T1574.001. Older rule sets still tag the retired ID, which is worth a grep across your own catalog.

Summary

Hunting is the search for what your detections would have missed, defined by that gap rather than by any tool. Hunts start from intel, from a hypothesis about a technique, or from a baseline of normal, and all three need the same thing written down first: an observable, the field it lives in, and the false positives you expect. The hunt above grouped thirty days of process creation on hash to surface rare vendor-branded binaries in user-writable paths, then split boring from interesting on metadata mismatch, parent process and frequency. It ended in a Sigma rule, which is the only part of the exercise that keeps working after you stop paying attention to it. Rules of this family live under the Windows domain at /rules?domain=windows, and the side-loading shape at /rules?q=side-loading.

Collect before you hunt this:

  Sysmon Event ID 1    Process creation
                       Image, OriginalFileName, Company, Product,
                       Hashes, ParentImage, ParentCommandLine, User
                       No signature fields exist on this event.

  Sysmon Event ID 7    Image loaded
                       ImageLoaded, Signed, Signature, SignatureStatus
                       Disabled by default. Filter hard or it floods.

  Sysmon Event ID 11   File create
                       Catches the EXE and its sibling DLL landing on disk.

  Security 4688        Fallback only. Needs the command line audit GPO.
                       No Company, no OriginalFileName, no parent cmdline.

  Retention            30 days minimum for fleet rarity analysis.

Related articles