Detection rules › Splunk

Windows Cabinet File Extraction Via Expand

Status
production
Severity
medium
Group by
IntegrityLevel, command_line, computer_name, original_file_name, parent_process_guid, parent_process_id, parent_process_name, process_guid, process_hash, process_id, process_name, user, user_id, vendor_product
Author
Michael Haag, Splunk
Source
github.com/splunk/security_content

Detects usage of expand.exe to extract Microsoft Cabinet (CAB) archives, with emphasis on extractions into C:\\ProgramData or similar staging locations. In recent APT37 activity, a CAB payload (e.g., wonder.cab) was expanded into ProgramData prior to persistence and execution. This behavior is a strong signal for ingress tool transfer and staging of payloads.

Known false positives

  • Legitimate software deployment or administrators may use expand.exe for local file extraction. Filter by approved deployment tools, signed parent processes, and sanctioned paths.

MITRE ATT&CK coverage

TacticTechniques
Command & Control

Telemetry coverage

Rule body

name: Windows Cabinet File Extraction Via Expand
id: 4e3e3b8c-6d3a-4b47-9f5a-9e3e0a0a6f2f
version: 5
creation_date: '2025-10-13'
modification_date: '2026-05-13'
author: Michael Haag, Splunk
status: production
type: TTP
description: |
    Detects usage of expand.exe to extract Microsoft Cabinet (CAB) archives, with
    emphasis on extractions into `C:\\ProgramData` or similar staging locations. In
    recent APT37 activity, a CAB payload (e.g., wonder.cab) was expanded into
    ProgramData prior to persistence and execution. This behavior is a strong signal
    for ingress tool transfer and staging of payloads.
data_source:
    - Sysmon EventID 1
    - Windows Event Log Security 4688
    - CrowdStrike ProcessRollup2
search: |
    | tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime
    from datamodel=Endpoint.Processes
    where Processes.process_name="expand.exe"
      (Processes.process="*-F:*" OR Processes.process="*/F:*")
      Processes.process="*\\ProgramData\\*"
    by Processes.dest Processes.user Processes.parent_process_name Processes.process_name Processes.process Processes.original_file_name Processes.parent_process_exec Processes.parent_process_guid Processes.parent_process_id Processes.parent_process_path Processes.process_exec Processes.process_guid Processes.process_hash Processes.process_id Processes.process_integrity_level Processes.process_path Processes.user_id Processes.vendor_product
    | `drop_dm_object_name(Processes)`
    | `security_content_ctime(firstTime)`
    | `security_content_ctime(lastTime)`
    | `windows_cabinet_file_extraction_via_expand_filter`
how_to_implement: |
    This analytic relies on process creation telemetry mapped to the Endpoint.Processes
    datamodel (e.g., Sysmon EID 1 or EDR). Ensure full command-line logging is enabled
    to capture expand.exe arguments, including `/F:*` or `-F:*` and destination paths.
known_false_positives: |
    Legitimate software deployment or administrators may use expand.exe for local
    file extraction. Filter by approved deployment tools, signed parent processes,
    and sanctioned paths.
references:
    - https://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader
finding:
    title: expand.exe extracted cabinet contents on $dest$ executed by $user$.
    entity:
        field: user
        type: user
        score: 50
intermediate_findings:
    entities:
        - field: dest
          type: system
          score: 50
          message: expand.exe extracted cabinet contents on $dest$ executed by $user$.
threat_objects:
    - field: process_name
      type: process_name
analytic_story:
    - APT37 Rustonotto and FadeStealer
    - NetSupport RMM Tool Abuse
asset_type: Endpoint
mitre_attack_id:
    - T1105
product:
    - Splunk Enterprise
    - Splunk Enterprise Security
    - Splunk Cloud
category: endpoint
security_domain: endpoint

Stages and Predicates

Stage 1: tstats

| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime
from datamodel=Endpoint.Processes
where Processes.process_name="expand.exe"
  (Processes.process="*-F:*" OR Processes.process="*/F:*")
  Processes.process="*\\ProgramData\\*"
by Processes.dest Processes.user Processes.parent_process_name Processes.process_name Processes.process Processes.original_file_name Processes.parent_process_exec Processes.parent_process_guid Processes.parent_process_id Processes.parent_process_path Processes.process_exec Processes.process_guid Processes.process_hash Processes.process_id Processes.process_integrity_level Processes.process_path Processes.user_id Processes.vendor_product

Stage 2: search

| `drop_dm_object_name(Processes)`

Stage 3: search

| `security_content_ctime(firstTime)`

Stage 4: search

| `security_content_ctime(lastTime)`

Stage 5: search

| `windows_cabinet_file_extraction_via_expand_filter`

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Processes.processeq
  • "*-F:*" corpus 2 (sigma 1, splunk 1)
  • "*/F:*"
  • "*\\ProgramData\\*"
field:"CommandLine" kind:eq
Processes.process_nameeq
  • "expand.exe" corpus 8 (elastic 7, splunk 1)
field:"process_name" kind:eq