← All hunts high TLP:CLEAR

Linux Fileless and In-Memory Execution

An adversary is executing malicious code on Linux hosts by staging payloads in memory-backed file descriptors, using interpreter one-liners, or running unlinked binaries to avoid on-disk detection.

Based on research by Elastic Security Labs 2026-09-20 12 steps · 5 queries T1014 T1059.004 T1059.006 T1070.004 T1105 T1620

Brief

Why this hunt

Linux fileless execution is a standard method for modern rootkits and stealthy implants. Adversaries use these techniques to bypass signature-based controls and file-scanning tools. This hunt design builds on research from Elastic Security Labs in their article, Linux Detection Engineering — Fileless Execution. While a single detection rule for memfd_create might be noisy in development environments, a structured hunt allows an analyst to verify the full execution chain from staging to persistence.

How the Hunt Flows

The first phase scopes the environment to Linux assets and identifies early staging leads. The hunt queries DNS activity for resolutions to common repositories like GitHub or PyPI. These resolutions often precede the download of a loader or a malicious package used for fileless execution.

Next, the hunt looks for specific behavioral primitives in process telemetry. It searches command lines for memfd_create calls, the use of memory-backed file descriptors in /proc/self/fd, and interpreter one-liners. This identifies the mechanism the adversary uses to transition from a script or download to a running process without a backing file on disk.

In the third phase, the hunt identifies the aftermath of successful execution. One query groups rare processes running from unlinked files — where the original binary was deleted after execution — and baselines them by host count. Simultaneously, another query checks for kernel modules loaded from ephemeral paths like /dev/shm or /tmp, which suggests rootkit activity.

Finally, an automated agent correlates these findings. It looks for hosts where the initial staging leads align with confirmed evasive execution or anomalous module loads to produce a high-confidence verdict for the analyst.

What this hunt cannot see

This hunt has two primary blind spots. First, kernel module detection relies on telemetry that may require eBPF-based monitoring. On older kernels or systems without finit_module syscall tracking, rootkits loaded through non-standard interfaces might stay hidden. Second, the search for interpreter one-liners is vulnerable to obfuscation. If an adversary pipes base64-encoded or encrypted content directly into a shell or interpreter, the process command line will not reveal the malicious logic.

Steps

  1. Identify Linux host scope

    Query · scoping

    Scope the hunt to Linux hosts by identifying systems with Linux-specific package management activity.

    reads hb_software_inventorysql
    SELECT DISTINCT device_hostname FROM hb_software_inventory WHERE package_type IN ('deb', 'rpm', 'python') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0)

    What a hit looks like. A list of Linux hosts to be used as a filter in subsequent steps.

  2. DNS staging to repositories

    Query · enrichment

    Find hosts resolving common staging domains, which may precede a fileless download.

    reads hb_dns_activitysql
    SELECT device_hostname, query_hostname, process_name, time FROM hb_dns_activity WHERE instr(',' || '{{staging_domains}}' || ',', ',' || LOWER(query_hostname) || ',') > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. DNS resolutions from tools like curl, git, or python to public code repositories.

  3. Fileless execution behavioral patterns

    Query · detection candidate

    Detect command-line indicators and process name patterns of fileless execution, including memfd_create strings and interpreter one-liners.

    reads hb_process_activitysql
    SELECT device_hostname, process_name, process_cmd_line, user_name, time FROM hb_process_activity WHERE (LOWER(process_name) LIKE 'memfd:%' OR LOWER(process_cmd_line) LIKE '%memfd:%' OR LOWER(process_cmd_line) LIKE '%memfd_create%' OR LOWER(process_cmd_line) LIKE '%/proc/self/fd/%' OR LOWER(process_cmd_line) LIKE '%python -c%' OR LOWER(process_cmd_line) LIKE '%bash -c%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. Processes named with memfd prefixes or command lines containing memory-backed execution primitives.

  4. Evaluate early-stage staging

    Agent triage

    Assess whether the observed staging and primitives indicate the start of a fileless intrusion.

  5. Prevalence of unlinked binaries

    Query · baseline

    Identify rare processes running from unlinked files by grouping on process name when on_disk is false.

    reads hb_process_activitysql
    SELECT process_name, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_process_activity WHERE on_disk = 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY process_name HAVING host_count <= 3

    What a hit looks like. Rare processes that were deleted after execution, grouped by their original identifier.

  6. Anomalous kernel module loads

    Query · triage

    Detect kernel modules loaded from memory descriptors, suspicious temporary paths, or with missing paths.

    reads hb_module_activitysql
    SELECT device_hostname, module_name, module_path, process_name, time FROM hb_module_activity WHERE (module_path LIKE '/proc/%' OR module_path LIKE '/dev/shm/%' OR module_path LIKE '/tmp/%' OR module_path IS NULL) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. Kernel module loads that do not originate from standard library paths or have null paths, suggesting rootkit activity.

  7. Correlate full fileless chain

    Agent triage

    Combine the early-stage staging verdicts with the follow-on evidence of unlinked binaries and module loads.

  8. Route on fileless intrusion

    Decision

    Decide the response based on the correlation of staging and execution evidence.

  9. Isolate compromised host

    Response action

    Contain the threat and prevent further lateral movement or command-and-control communication.

  10. Forensic memory and procfs review

    Analyst task

    Recover the fileless payload from the isolated host's memory or proc filesystem.

  11. Hunt summary and close-out

    Analyst task

    Document the findings and recommend detection engineering improvements.

Coverage

Scenario coverage

StageCoveredHow, or why not
Remote Payload Staging
T1105 · T1204.002
Yes dns-staging-leads
memfd_create Fileless Execution
T1620
Yes memfd-behavioral-leads
Interpreter One-Liner Execution
T1059.004 · T1059.006
Yes memfd-behavioral-leads
Execution of Unlinked Binaries
T1070.004
Yes deleted-binary-baseline
In-Memory Kernel Module Loading
T1014 · T1547.006
Yes kernel-module-leads

Blind spots

  • Needs eBPF-based syscall monitoring on Kernel 5.10+. Rootkits loaded on older kernels or through non-standard interfaces may not trigger hb_module_activity. It would answer whether the provider can observe finit_module calls on older kernels.
  • Needs Deep script block inspection (hb_script_activity). A loader that pipes encrypted content directly into an interpreter bypasses the process_cmd_line search. It would answer what code ran if the command line was base64 encoded or read from stdin.

Parameters & data

Parameters

ParameterTypeDefaultWhat it is
lookback_daysnumber14Days of history to examine.
scope_hostslist[host]Limit the hunt to specific Linux hostnames; leave empty for the entire estate.
staging_domainslist[domain]github.com, pypi.org, files.pythonhosted.org, raw.githubusercontent.comDomains commonly used to stage loaders or download malicious PyPI packages.

Telemetry

SourceCategoryTelemetry
Endpoint telemetry (hb_ surfaces)endpointendpoint

Source

Download hunt.md Definition (JSON) An open hunt.md file; it runs anywhere that reads the format.
---
analysis: A single rule for memfd_create may trigger high noise in development environments.
  This hunt pivots across DNS (staging), prevalence (unlinked binaries), and module
  activity to identify a complete, high-confidence intrusion chain that a single rule
  cannot resolve.
blind_spots:
- id: limited-kernel-telemetry
  question: whether the provider can observe finit_module calls on older kernels
  requires: eBPF-based syscall monitoring on Kernel 5.10+
  risk: Rootkits loaded on older kernels or through non-standard interfaces may not
    trigger hb_module_activity.
  stage: in-memory-kernel-module-load
- id: obfuscated-one-liners
  question: what code ran if the command line was base64 encoded or read from stdin
  requires: Deep script block inspection (hb_script_activity)
  risk: A loader that pipes encrypted content directly into an interpreter bypasses
    the process_cmd_line search.
  stage: interpreter-one-liners
coverage:
- stage: remote-payload-staging
  status: covered
  steps:
  - dns-staging-leads
- stage: memfd-fileless-execution
  status: covered
  steps:
  - memfd-behavioral-leads
- stage: interpreter-one-liners
  status: covered
  steps:
  - memfd-behavioral-leads
- stage: deleted-binary-execution
  status: covered
  steps:
  - deleted-binary-baseline
- stage: in-memory-kernel-module-load
  status: covered
  steps:
  - kernel-module-leads
guardrails:
  claims: no_unsupported
  evidence: citation_required
  missing_data: not_benign
  telemetry: untrusted
hunt:
  applicability: campaign-specific
  handoff: promote-to-detection
  justification: Fileless execution is the standard method for modern Linux rootkits
    and stealthy implants to bypass signature-based and file-scanning controls; a
    negative result over the fleet is a significant assurance of asset integrity.
  methodology: model-assisted
  trigger: intel-report
hypothesis: An adversary is executing malicious code on Linux hosts by staging payloads
  in memory-backed file descriptors, using interpreter one-liners, or running unlinked
  binaries to avoid on-disk detection.
labels:
- hunt
- attack.t1620
- attack.t1059.004
- attack.t1059.006
- attack.t1070.004
- attack.t1014
- attack.t1105
name: Linux Fileless and In-Memory Execution
parameters:
  lookback_days:
    default: '14'
    description: Days of history to examine.
    from:
      kind: manual
      observed: '2024-09-01'
      ref: hunt-designer
    type: number
  scope_hosts:
    default: []
    description: Limit the hunt to specific Linux hostnames; leave empty for the entire
      estate.
    from:
      kind: manual
      observed: '2024-09-01'
      ref: analyst-defined
    type: list[host]
  staging_domains:
    default:
    - github.com
    - pypi.org
    - files.pythonhosted.org
    - raw.githubusercontent.com
    description: Domains commonly used to stage loaders or download malicious PyPI
      packages.
    from:
      kind: article
      observed: '2024-09-01'
      ref: elastic-security-labs
    type: list[domain]
provenance:
  authors:
  - name: Huntbase hunt generation
    org: huntbase.io
  generated:
    by: huntbase-hunt-generation
    from: https://www.elastic.co/security-labs/threat-command/memfd-create-linux-fileless-execution
    gates:
    - dry-run
    - lint
    model: hb_google/gemini-3-flash-preview
rationale: Start with public-facing Linux servers (DMZ) and development systems where
  tools like git and python are authorized. Focus the hunt on processes running with
  on_disk = 0 first, as these are the strongest indicators of evasion.
references:
- name: "Elastic Security Labs \u2014 Linux Detection Engineering \u2014 Fileless\
    \ Execution"
  url: https://www.elastic.co/security-labs/threat-command/memfd-create-linux-fileless-execution
related:
- hunt: linux-ebpf-rootkit-detection
  reason: This hunt focuses on the execution phase; rootkit detection focuses on the
    persistent hooks in the kernel.
  relation: alternative
scenario:
  stages:
  - name: Remote Payload Staging
    observables:
    - curl
    - wget
    - git clone https://github.com/elastic/FENIX.git
    - pip install sympy-dev
    - fenix.git
    - sympy-dev (PyPI)
    slug: remote-payload-staging
    tactic: initial-access
    techniques:
    - T1105
    - T1204.002
  - name: memfd_create Fileless Execution
    observables:
    - memfd_create
    - process.ext.memfd.name
    - /proc/self/fd/
    - MFD_CLOEXEC
    - MFD_ALLOW_SEALING
    - MFD_HUGETLB
    slug: memfd-fileless-execution
    tactic: execution
    techniques:
    - T1620
  - name: Interpreter One-Liner Execution
    observables:
    - python -c
    - bash -c
    - perl -e
    - base64 -d
    - openssl
    - gzip -d
    - curl ... | bash
    - sh one-liners
    slug: interpreter-one-liners
    tactic: execution
    techniques:
    - T1059.004
    - T1059.006
  - name: Execution of Unlinked Binaries
    observables:
    - /proc/<pid>/exe
    - (deleted)
    - on_disk = 0
    - unlinked payload in /tmp
    slug: deleted-binary-execution
    tactic: defense-evasion
    techniques:
    - T1070.004
  - name: In-Memory Kernel Module Loading
    observables:
    - init_module
    - finit_module
    - load_module event
    - memfd_create for module bytes
    slug: in-memory-kernel-module-load
    tactic: persistence
    techniques:
    - T1014
    - T1547.006
  summary: Adversaries utilize Linux fileless execution primitives such as memfd_create,
    interpreter one-liners, and unlinked binaries to execute malicious payloads while
    minimizing on-disk footprints. These techniques, often staged via remote downloads
    or malicious packages, enable in-memory execution of ELFs and kernel modules that
    complicate traditional file-based detection and inspection.
severity: high
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
---


# Linux Fileless and In-Memory Execution

This hunt follows a phased flow to detect the lifecycle of Linux fileless execution. It starts by scoping to Linux assets and identifying early staging leads such as DNS resolutions to public repositories and the use of memfd_create primitives. It then pivots to verify high-confidence indicators of successful execution, including processes running from deleted binaries (stack-counted for prevalence) and the loading of kernel modules directly from memory or ephemeral paths.

## linux-host-inventory
<!-- Identify Linux host scope -->
Scope the hunt to Linux hosts by identifying systems with Linux-specific package management activity.

```sqlite target=endpoint role=scoping params=(scope_hosts=scope_hosts)
~~~yaml
expected: A list of Linux hosts to be used as a filter in subsequent steps.
reads:
- device_hostname
- package_type
silence: not_evidence_of_absence
source: hb_software_inventory
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT DISTINCT device_hostname FROM hb_software_inventory WHERE package_type IN ('deb', 'rpm', 'python') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0)
```

## early-stage-leads
<!-- Early stage staging and primitives -->
parallel:
- → dns-staging-leads
- → memfd-behavioral-leads
join: → early-stage-agent

## dns-staging-leads
<!-- DNS staging to repositories -->
Find hosts resolving common staging domains, which may precede a fileless download.

```sqlite target=endpoint role=enrichment params=(staging_domains=staging_domains, scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: DNS resolutions from tools like curl, git, or python to public code repositories.
reads:
- device_hostname
- query_hostname
- process_name
- time
silence: not_evidence_of_absence
source: hb_dns_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, query_hostname, process_name, time FROM hb_dns_activity WHERE instr(',' || '{{staging_domains}}' || ',', ',' || LOWER(query_hostname) || ',') > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## memfd-behavioral-leads
<!-- Fileless execution behavioral patterns -->
Detect command-line indicators and process name patterns of fileless execution, including memfd_create strings and interpreter one-liners.

```sqlite target=endpoint role=detection-candidate params=(scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: Processes named with memfd prefixes or command lines containing memory-backed
  execution primitives.
reads:
- device_hostname
- process_name
- process_cmd_line
- user_name
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, process_name, process_cmd_line, user_name, time FROM hb_process_activity WHERE (LOWER(process_name) LIKE 'memfd:%' OR LOWER(process_cmd_line) LIKE '%memfd:%' OR LOWER(process_cmd_line) LIKE '%memfd_create%' OR LOWER(process_cmd_line) LIKE '%/proc/self/fd/%' OR LOWER(process_cmd_line) LIKE '%python -c%' OR LOWER(process_cmd_line) LIKE '%bash -c%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## early-stage-agent
<!-- Evaluate early-stage staging -->
```agent target=hunter
cite: required
context:
- dns-staging-leads
- memfd-behavioral-leads
max_iterations: 3
objective: Identify hosts where staging activity (DNS) aligns with fileless command-line
  primitives.
success_criteria: A per-host verdict citing the specific staging domains and command-line
  arguments found.
tools:
- endpoint
```

## follow-on-leads
<!-- Hunt for evasive persistence -->
parallel:
- → deleted-binary-baseline
- → kernel-module-leads
join: → follow-on-agent

## deleted-binary-baseline
<!-- Prevalence of unlinked binaries -->
Identify rare processes running from unlinked files by grouping on process name when on_disk is false.

```sqlite target=endpoint role=baseline params=(scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
baseline:
  compare: first_seen
  window: '{{lookback_days}}d'
expected: Rare processes that were deleted after execution, grouped by their original
  identifier.
prevalence:
  by: device_hostname
  key:
  - process_name
  rare_below: 3
reads:
- process_name
- device_hostname
- time
- on_disk
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT process_name, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_process_activity WHERE on_disk = 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY process_name HAVING host_count <= 3
```

## kernel-module-leads
<!-- Anomalous kernel module loads -->
Detect kernel modules loaded from memory descriptors, suspicious temporary paths, or with missing paths.

```sqlite target=endpoint role=triage params=(scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: Kernel module loads that do not originate from standard library paths or
  have null paths, suggesting rootkit activity.
reads:
- device_hostname
- module_name
- module_path
- process_name
- time
silence: not_evidence_of_absence
source: hb_module_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, module_name, module_path, process_name, time FROM hb_module_activity WHERE (module_path LIKE '/proc/%' OR module_path LIKE '/dev/shm/%' OR module_path LIKE '/tmp/%' OR module_path IS NULL) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## follow-on-agent
<!-- Correlate full fileless chain -->
```agent target=hunter
cite: required
context:
- early-stage-agent
- deleted-binary-baseline
- kernel-module-leads
max_iterations: 4
objective: Determine if hosts with early-stage leads successfully transitioned to
  evasive execution states.
success_criteria: A final verdict identifying the compromised hosts and the specific
  fileless tradecraft observed across all stages.
tools:
- endpoint
```

## intrusion-decision
<!-- Route on fileless intrusion -->
if~: "the follow-on-agent identifies at least one host with staging activity and confirmed evasive execution (on_disk=0 or in-memory module load)" (confidence: high, judge=hunter)
then: → isolate-host
indeterminate: → forensic-review
unavailable: → forensic-review (blind_spot: limited-kernel-telemetry)
else: → close-out

## isolate-host
<!-- Isolate compromised host -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the host and preserve the process state for memory analysis.
```
→ forensic-review

## forensic-review
<!-- Forensic memory and procfs review -->
```manual target=analyst
Examine /proc/<pid>/fd/ for memory-backed file descriptors and /proc/<pid>/exe if on_disk was 0 to recover the executed binary.
```
→ end

## close-out
<!-- Hunt summary and close-out -->
```manual target=analyst
Record the examined hosts and findings. If the behavioral leads were high-fidelity, promote the memfd-behavioral-leads query to a permanent rule.
```
→ 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.