VSS Abuse Precursors: Exploitation and Lateral Movement
An attacker is moving laterally from a compromised internet-facing asset to locate high-value targets for VSS-based credential theft or ransomware deployment.
Based on research by Huntress 2026-09-17 9 steps · 4 queries T1003.002 T1018 T1021.001 T1021.002 T1190
Brief
The Shift from Detection to Hunting
Adversaries frequently abuse the Volume Shadow Copy Service (VSS) to facilitate credential theft via NTDS.dit or to ensure ransomware impact by deleting backups. While many detections focus on the final manipulation of VSS, Huntress's research in "How Attackers Abuse VSS, and How Huntress Detects It" (https://www.huntress.com/blog/vss-abuse-explained) highlights that these actions are often the culmination of a longer intrusion. This hunt shifts the focus upstream, identifying the precursors of VSS abuse during the exploitation and lateral movement phases.
How the Hunt Flows
The first phase of the hunt focuses on scoping the estate for high-risk beachheads. We use vulnerability finding surfaces to identify hosts with critical, unpatched vulnerabilities. These assets are prioritized because they represent the most likely entry points for an external attacker and provide context for subsequent behavioral anomalies.
In the second phase, we examine process activity for hallmarks of remote execution. Specifically, we look for command shells spawned as children of the Service Control Manager (services.exe), which is a common signature of PsExec-style lateral movement. By filtering these results against our initial list of vulnerable hosts, we can distinguish suspicious activity from routine administrative tasks performed on known, patched systems.
Simultaneously, we analyze environment reconnaissance through both process and network surfaces. We stack-count the use of session enumeration tools like qwinsta and query.exe across the fleet to find rare occurrences. We also inspect DNS activity for lookups targeting Active Directory infrastructure, such as LDAP or Kerberos service records. These lookups are essential for attackers trying to locate domain controllers for future VSS-based attacks.
The final phase synthesizes these signals. A host that is both vulnerable and exhibiting service-spawned shells or rare DNS reconnaissance is treated as a high-confidence indicator of a breach. This correlation allows us to route the finding directly to isolation or deep analyst review.
Blind Spots and Limitations
This hunt relies heavily on the availability of endpoint process logs. If a host lacks active monitoring or if the agent configuration does not capture parent-child process relationships, shells spawned via services.exe may go unobserved. Additionally, reconnaissance via DNS is highly ephemeral. If the attacker used a local resolver cache or if DNS logs are not retained long enough to cover the initial discovery window, the reconnaissance phase may be invisible.
In this series
Steps
-
Identify High-Risk Vulnerable Assets
Query · scopingLocate hosts with critical vulnerabilities that could serve as initial beachheads for an intrusion.
reads hb_vulnerability_findingsqlSELECT device_uid, cve_uid, severity, affected_package_name, first_seen FROM hb_vulnerability_finding WHERE severity_id >= 4 AND status != 'suppressed' AND resource_type = 'device'What a hit looks like. A list of hosts with unpatched high/critical vulnerabilities. Use these in the scope_hosts parameter for subsequent steps.
-
Shells Spawned via Service Control Manager
Query · detection candidateDetect the most common signature of remote administrative execution (PsExec) by identifying shells running as children of services.exe.
reads hb_process_activitysqlSELECT device_hostname, process_name, process_cmd_line, parent_process_name, user_name, time FROM hb_process_activity WHERE (instr(',' || '{{psexec_indicators}}' || ',', ',' || LOWER(process_name) || ',') > 0 OR (LOWER(parent_process_name) LIKE '%\\services.exe' AND instr(',' || '{{shell_interpreters}}' || ',', ',' || LOWER(process_name) || ',') > 0)) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. A shell like cmd.exe running as a child of services.exe on a host with critical vulnerabilities. This is a high-confidence indicator of lateral movement.
-
Rare Session and Network Recon Tool Usage
Query · baselineStack-count administrative tools that are uncommon across the fleet, identifying manual environment exploration.
reads hb_process_activitysqlSELECT LOWER(process_name) AS tool, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_process_activity WHERE instr(',' || '{{recon_utilities}}' || ',', ',' || LOWER(process_name) || ',') > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY tool HAVING host_count <= 3 ORDER BY host_count ASCWhat a hit looks like. Utilities like 'qwinsta' (session query) appearing on only one or two hosts, especially if those hosts are within the vulnerable scope.
-
Internal Domain Reconnaissance via DNS
Query · enrichmentIdentify hosts querying for Active Directory infrastructure, indicating reconnaissance prior to credential theft.
reads hb_dns_activitysqlSELECT device_hostname, query_hostname, COUNT(*) AS lookup_count, MIN(time) AS first_seen FROM hb_dns_activity WHERE (LOWER(query_hostname) LIKE '%_ldap._tcp.%' OR LOWER(query_hostname) LIKE '%_kerberos._tcp.%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, query_hostnameWhat a hit looks like. Any host querying for service records to locate domain controllers, which is a required step for VSS-based NTDS.dit theft.
-
Synthesize Breach Evidence
Agent triageCorrelate vulnerability scope with the behavioral results from the parallel branches.
-
Route on Verdict
DecisionRoute the findings based on the agent's synthesized verdict.
-
Isolate Endpoint
Response actionHalt the intrusion before the adversary can manipulate VSS or extract secrets.
-
Analyst Breach Review
Analyst taskReview the synthesized findings and identify the 'patient zero' exploit path.
Coverage
Scenario coverage
| Stage | Covered | How, or why not |
|---|---|---|
| Exploitation of Public-Facing Application T1190 |
Yes | scoping-vulnerable-targets |
| Lateral Movement via SMB and PsExec T1021.002 |
Yes | psexec-shell-spawn |
| Session and Network Reconnaissance T1021.001 |
Yes | rare-discovery-tools, dns-enumeration-lookups |
| Credential Access via Shadow Copy T1490 |
Out of scope | Belongs to another part of the 'How Attackers Abuse VSS, and How Huntress Detects It' series. |
| Inhibit System Recovery via Shadow Deletion T1490 |
Out of scope | Belongs to another part of the 'How Attackers Abuse VSS, and How Huntress Detects It' series. |
| Data Encrypted for Impact T1486 |
Out of scope | Belongs to another part of the 'How Attackers Abuse VSS, and How Huntress Detects It' series. |
Blind spots
- Needs hb_process_activity from a full endpoint agent (osquery/sysmon). A host without active process monitoring allows service-spawned shells to run entirely unobserved. It would answer Was a shell spawned that we missed due to agent configuration?.
- Needs hb_dns_activity from a network tap or full local agent. If DNS logs are not retained or if the attacker used a local resolver cache that was flushed, the reconnaissance phase will be invisible. It would answer Did the attacker use DNS records to find DCs before the hunt window?.
Parameters & data
Parameters
| Parameter | Type | Default | What it is |
|---|---|---|---|
lookback_days | number | 14 | Days of history to examine. |
psexec_indicators | list[string] | psexesvc.exe, psexec.exe, psexec64.exe | Binary names associated with PsExec or similar remote execution tools. |
recon_utilities | list[string] | qwinsta.exe, rwinsta.exe, query.exe, nslookup.exe, dnscmd.exe | Administrative tools used for session enumeration and network discovery. |
scope_hosts | list[host] | — | Target specific hosts identified in the scoping step; leave empty for fleet-wide. |
shell_interpreters | list[string] | cmd.exe, powershell.exe, pwsh.exe | Common command shell interpreters. |
Telemetry
| Source | Category | Telemetry |
|---|---|---|
| Endpoint telemetry (hb_ surfaces) | endpoint | endpoint |
Source
---
analysis: A single detection rule for PsExec often relies on the presence of a specific
service name or file hash, both of which are trivial to change. This hunt looks
for the underlying behavior (shells from services.exe) and contextualizes it with
both vulnerability exposure and rarity (prevalence) across the fleet.
blind_spots:
- id: no-process-logs
question: Was a shell spawned that we missed due to agent configuration?
requires: hb_process_activity from a full endpoint agent (osquery/sysmon)
risk: A host without active process monitoring allows service-spawned shells to
run entirely unobserved.
stage: lateral-movement-psexec
- id: ephemeral-dns-recon
question: Did the attacker use DNS records to find DCs before the hunt window?
requires: hb_dns_activity from a network tap or full local agent
risk: If DNS logs are not retained or if the attacker used a local resolver cache
that was flushed, the reconnaissance phase will be invisible.
stage: internal-reconnaissance
coverage:
- stage: initial-exploitation
status: covered
steps:
- scoping-vulnerable-targets
- stage: lateral-movement-psexec
status: covered
steps:
- psexec-shell-spawn
- stage: internal-reconnaissance
status: covered
steps:
- rare-discovery-tools
- dns-enumeration-lookups
- reason: Belongs to another part of the 'How Attackers Abuse VSS, and How Huntress
Detects It' series.
stage: vss-credential-access
status: out_of_scope
- reason: Belongs to another part of the 'How Attackers Abuse VSS, and How Huntress
Detects It' series.
stage: vss-recovery-inhibition
status: out_of_scope
- reason: Belongs to another part of the 'How Attackers Abuse VSS, and How Huntress
Detects It' series.
stage: ransomware-encryption
status: out_of_scope
guardrails:
claims: no_unsupported
evidence: citation_required
missing_data: not_benign
telemetry: untrusted
hunt:
applicability: campaign-specific
handoff: keep-as-periodic-hunt
justification: Attacker tradecraft often relies on legitimate tools (VSS, PsExec,
qwinsta) that are used by administrators. A negative result confirms that these
tools are operating within baseline norms across your high-risk assets, which
is a critical signal for defensive posture.
methodology: model-assisted
trigger: intel-report
hypothesis: An attacker is moving laterally from a compromised internet-facing asset
to locate high-value targets for VSS-based credential theft or ransomware deployment.
labels:
- hunt
- attack.t1190
- attack.t1021.002
- attack.t1021.001
- attack.t1018
- attack.t1003.002
name: 'VSS Abuse Precursors: Exploitation and Lateral Movement'
parameters:
lookback_days:
default: '14'
description: Days of history to examine.
type: number
psexec_indicators:
default:
- psexesvc.exe
- psexec.exe
- psexec64.exe
description: Binary names associated with PsExec or similar remote execution tools.
from:
kind: manual
observed: '2024-05-22'
ref: sysinternals-indicators
type: list[string]
recon_utilities:
default:
- qwinsta.exe
- rwinsta.exe
- query.exe
- nslookup.exe
- dnscmd.exe
description: Administrative tools used for session enumeration and network discovery.
from:
kind: article
observed: '2026-09-14'
ref: huntress-vss-abuse
type: list[string]
scope_hosts:
default: []
description: Target specific hosts identified in the scoping step; leave empty
for fleet-wide.
type: list[host]
shell_interpreters:
default:
- cmd.exe
- powershell.exe
- pwsh.exe
description: Common command shell interpreters.
type: list[string]
provenance:
authors:
- name: Huntbase hunt generation
org: huntbase.io
generated:
by: huntbase-hunt-generation
from: https://www.huntress.com/blog/vss-abuse-explained
gates:
- dry-run
- lint
model: hb_google/gemini-3-flash-preview
rationale: Start by identifying hosts with critical vulnerabilities (severity_id >=
4) that haven't been remediated. These hosts are the most likely entry points and
should be prioritized in the scope_hosts parameter if the fleet-wide results are
too noisy.
references:
- name: How Attackers Abuse VSS, and How Huntress Detects It
url: https://www.huntress.com/blog/vss-abuse-explained
related:
- hunt: vss-manipulation-and-ntds-theft
reason: This hunt identifies the early movement; the follow-on hunt focuses specifically
on the VSS creation/deletion and the theft of the ntds.dit file.
relation: follows
scenario:
stages:
- name: Exploitation of Public-Facing Application
observables:
- Exploitation of internet-facing host
- Vulnerability exploitation in web servers or databases
slug: initial-exploitation
tactic: initial-access
techniques:
- T1190
- name: Lateral Movement via SMB and PsExec
observables:
- PsExec usage
- Spawning of SYSTEM-level command shell processes
- Activity on domain controllers
slug: lateral-movement-psexec
tactic: lateral-movement
techniques:
- T1021.002
- name: Session and Network Reconnaissance
observables:
- Enumeration of active Remote Desktop sessions
- DNS enumeration commands
- Reconnaissance against additional network hosts
slug: internal-reconnaissance
tactic: discovery
techniques:
- T1021.001
- name: Credential Access via Shadow Copy
observables:
- vssadmin create shadow
- Extraction of ntds.dit from volume shadow copy
slug: vss-credential-access
tactic: credential-access
techniques:
- T1490
- name: Inhibit System Recovery via Shadow Deletion
observables:
- vssadmin delete shadows /all /quiet
- Deletion of shadow copies following credential extraction
slug: vss-recovery-inhibition
tactic: impact
techniques:
- T1490
- name: Data Encrypted for Impact
observables:
- Mass file encryption
- Ransomware detonation
slug: ransomware-encryption
tactic: impact
techniques:
- T1486
summary: Attackers leverage Volume Shadow Copy (VSS) to facilitate credential theft
by creating shadows to extract the NTDS.dit database or to inhibit recovery by
deleting shadows prior to ransomware deployment. These techniques are often preceded
by lateral movement using tools like PsExec and internal reconnaissance against
domain controllers.
series:
index: 1
slug: how-attackers-abuse-vss-and-how-huntress-detects-it
title: How Attackers Abuse VSS, and How Huntress Detects It
total: 2
severity: medium
targets:
analyst:
name: Tier-2 analyst
role: analyst
endpoint:
category: endpoint
name: Endpoint telemetry (hb_ surfaces)
telemetry:
- endpoint
hunter:
agent: true
name: Hunt agent
tlp: clear
type: investigation
---
# VSS Abuse Precursors: Exploitation and Lateral Movement
This hunt focuses on the early precursors of Volume Shadow Copy Service (VSS) abuse as researched by Huntress. It targets the initial transition from a web-based exploit to internal movement. By identifying vulnerable hosts, looking for the specific signature of PsExec-style remote execution (shells spawned by the Service Control Manager), and stack-counting the use of session enumeration tools, we identify attackers before they reach the destructive phase of deleting shadows or dumping Active Directory secrets. The hunt correlates these behaviors to distinguish an active breach from routine administrative disk hygiene.
## scoping-vulnerable-targets
<!-- Identify High-Risk Vulnerable Assets -->
Locate hosts with critical vulnerabilities that could serve as initial beachheads for an intrusion.
```sqlite target=endpoint role=scoping
~~~yaml
expected: A list of hosts with unpatched high/critical vulnerabilities. Use these
in the scope_hosts parameter for subsequent steps.
reads:
- device_uid
- cve_uid
- severity
- affected_package_name
- first_seen
silence: not_evidence_of_absence
source: hb_vulnerability_finding
verified: dry-run
verified_at: '2026-09-17'
~~~
SELECT device_uid, cve_uid, severity, affected_package_name, first_seen FROM hb_vulnerability_finding WHERE severity_id >= 4 AND status != 'suppressed' AND resource_type = 'device'
```
## parallel-behavior-check
<!-- Gather Evidence of Lateral Movement and Recon -->
parallel:
- → psexec-shell-spawn
- → rare-discovery-tools
- → dns-enumeration-lookups
join: → triage-precursors
## psexec-shell-spawn
<!-- Shells Spawned via Service Control Manager -->
Detect the most common signature of remote administrative execution (PsExec) by identifying shells running as children of services.exe.
```sqlite target=endpoint role=detection-candidate params=(psexec_indicators=psexec_indicators, shell_interpreters=shell_interpreters, scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: A shell like cmd.exe running as a child of services.exe on a host with critical
vulnerabilities. This is a high-confidence indicator of lateral movement.
reads:
- device_hostname
- process_name
- process_cmd_line
- parent_process_name
- user_name
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-17'
~~~
SELECT device_hostname, process_name, process_cmd_line, parent_process_name, user_name, time FROM hb_process_activity WHERE (instr(',' || '{{psexec_indicators}}' || ',', ',' || LOWER(process_name) || ',') > 0 OR (LOWER(parent_process_name) LIKE '%\\services.exe' AND instr(',' || '{{shell_interpreters}}' || ',', ',' || LOWER(process_name) || ',') > 0)) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```
## rare-discovery-tools
<!-- Rare Session and Network Recon Tool Usage -->
Stack-count administrative tools that are uncommon across the fleet, identifying manual environment exploration.
```sqlite target=endpoint role=baseline params=(recon_utilities=recon_utilities, scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
baseline:
compare: first_seen
window: '{{lookback_days}}d'
expected: Utilities like 'qwinsta' (session query) appearing on only one or two hosts,
especially if those hosts are within the vulnerable scope.
prevalence:
by: device_hostname
key:
- tool
rare_below: 3
reads:
- process_name
- device_hostname
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-17'
~~~
SELECT LOWER(process_name) AS tool, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_process_activity WHERE instr(',' || '{{recon_utilities}}' || ',', ',' || LOWER(process_name) || ',') > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY tool HAVING host_count <= 3 ORDER BY host_count ASC
```
## dns-enumeration-lookups
<!-- Internal Domain Reconnaissance via DNS -->
Identify hosts querying for Active Directory infrastructure, indicating reconnaissance prior to credential theft.
```sqlite target=endpoint role=enrichment params=(scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: Any host querying for service records to locate domain controllers, which
is a required step for VSS-based NTDS.dit theft.
reads:
- device_hostname
- query_hostname
- time
silence: not_evidence_of_absence
source: hb_dns_activity
verified: dry-run
verified_at: '2026-09-17'
~~~
SELECT device_hostname, query_hostname, COUNT(*) AS lookup_count, MIN(time) AS first_seen FROM hb_dns_activity WHERE (LOWER(query_hostname) LIKE '%_ldap._tcp.%' OR LOWER(query_hostname) LIKE '%_kerberos._tcp.%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, query_hostname
```
## triage-precursors
<!-- Synthesize Breach Evidence -->
```agent target=hunter
cite: required
context:
- scoping-vulnerable-targets
- psexec-shell-spawn
- rare-discovery-tools
- dns-enumeration-lookups
max_iterations: 3
objective: Determine if any host identified as vulnerable is also exhibiting signs
of lateral movement via PsExec or manual environment reconnaissance.
success_criteria: A verdict of malicious | suspicious | benign citing the intersection
of vulnerability data and behavioral rows.
tools:
- endpoint
```
## route-on-verdict
<!-- Route on Verdict -->
if~: "the triage verdict is malicious for at least one host involving PsExec shell behavior" (confidence: high, judge=hunter)
then: → isolate-beachhead
indeterminate: → analyst-confirmation
unavailable: → analyst-confirmation (blind_spot: no-process-logs)
else: → analyst-confirmation
## isolate-beachhead
<!-- Isolate Endpoint -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the affected host(s) and capture the memory of any active service-spawned shells for forensic analysis.
```
→ analyst-confirmation
## analyst-confirmation
<!-- Analyst Breach Review -->
```manual target=analyst
Examine hb_http_activity for the affected hosts to identify the specific URL or request that triggered the initial compromise. Compare timestamps of the vulnerability being first seen with the appearance of the PsExec behavior.
```
→ end
Run it
Take this hunt into your environment.
Open it in Huntbase to run every step against your own connections, with Scout weighing the evidence and your analysts in command. Or take the open hunt.md file anywhere that reads the format.
Machine-drafted by huntbase-hunt-generation using hb_google/gemini-3-flash-preview, gated by dry-run, lint, then reviewed by a person.