Threat Hunting Exercise: Analyzing Linux Fileless Execution via memfd_create Dataset
This hunt uses a simulated Linux auditd dataset (linux_memfd_2022-08-23T140000.json) capturing T1620: Reflective Code Loading on Linux, where an attacker uses the memfd_create() syscall to create an anonymous, in-memory file descriptor, write an ELF binary into it, and execute it directly via fexecve() - leaving no file ever written to disk.
Step 1: Hypothesis Formation
Hypothesis: A process calls memfd_create() to obtain an anonymous memory file descriptor, writes ELF binary content into it, and then executes it via fexecve() or by referencing /proc/self/fd/<N> - resulting in a running process with no backing file on disk, which standard file-based antivirus/EDR scanning cannot inspect. Indicators:
- auditd syscall records show
memfd_createfollowed shortly bywriteto the returned file descriptor and thenexecvereferencing/proc/self/fd/<N>(memfd-backed). /proc/<pid>/exefor the resulting process resolves to/memfd:<name> (deleted)rather than a normal file path.- No corresponding file-creation event (Sysmon/auditd
PATH/CREATE) exists for any binary matching the process's behavior - it appeared without ever touching disk. - The parent process is a script interpreter (Python, Perl, or a downloader) that fetched the ELF content over the network immediately prior.
Null Hypothesis: A legitimate, container-runtime-adjacent tool (some language runtimes and JIT compilers legitimately use memfd for internal purposes) is responsible. Invalidate by checking the process's parent lineage and confirming it is not a known runtime (e.g., .NET's dotnet, certain sandboxing tools) with a documented memfd use case.
Rationale: Fileless execution via memfd_create is specifically designed to defeat disk-scanning antivirus and forensic file-carving, since the executed binary never has an on-disk representation; this hunt validates syscall-sequence monitoring (memfd_create → write → execve-via-fd) as the only reliable detection method, since file-hash or path-based tooling has nothing to inspect.
Step 2: Data Sources and Scope
- Sources: auditd syscall monitoring (
memfd_create,execve,execveat);/proc/<pid>/exeand/proc/<pid>/mapsinspection via EDR/osquery; network logs for the preceding ELF download. - Scope: ~2022-08-23T14:00:00-14:01:30 UTC; Host: lnx-app-node15 (10.280.3.19); Parent process:
python3(invoked via a compromised cron entry). - SIEM Queries (Splunk/ELK):
index=auditd type=SYSCALL syscall="memfd_create" | table _time host exe pid- Correlate:
... | transaction pid maxspan=5s startswith(syscall="memfd_create") endswith(syscall="execve" AND path="/proc/self/fd/") index=osquery table="process_open_files" OR query="SELECT * FROM processes WHERE on_disk=0"
Step 3: Key Findings
Parsed events (5 shown) confirm a Python process downloaded ELF content, wrote it to a memfd-backed descriptor, and executed it directly - with no file ever appearing on disk.
| Timestamp (UTC) | Host | Event | Detail | IOC/Why Suspicious? |
|---|---|---|---|---|
| 2022-08-23 14:00:05 | lnx-app-node15 | auditd EXECVE | python3 -c "import urllib.request,os,ctypes; ..." launched via a modified cron entry | Delivery IOC: an obfuscated inline Python one-liner run from cron, rather than a scheduled application script. |
| 2022-08-23 14:00:06 | lnx-app-node15 | Network | HTTP GET to hxxp://194.61.55.90/agent.elf, 1.8 MB response | Confirms the Python process fetched a binary payload over the network immediately before the memfd sequence. |
| 2022-08-23 14:00:07 | lnx-app-node15 | auditd SYSCALL | memfd_create("", MFD_CLOEXEC) returns fd=3, followed by write(3, ...) of 1.8 MB | Fileless IOC: binary content written into an anonymous, memory-only file descriptor rather than to any disk path. |
| 2022-08-23 14:00:08 | lnx-app-node15 | auditd SYSCALL | execve("/proc/self/fd/3", ...) - new process PID 22190 spawned | Execution-via-FD IOC: the ELF is executed by referencing its memory file descriptor directly, never touching the filesystem. |
| 2022-08-23 14:00:09 | lnx-app-node15 | (process check) | /proc/22190/exe resolves to memfd:agent (deleted); no matching file exists anywhere on disk | Confirmed Fileless: this is the definitive artifact of memfd-based execution - a running, fully-functional process with zero on-disk footprint for file-based AV/EDR to scan. |
Validation:
- Timeline: download, memfd write, and fd-based execution all within 4 seconds of a cron-triggered Python one-liner - a fully automated, deliberately fileless delivery chain.
- False Positives: the parent process (
python3via a tampered cron entry) is not a known runtime with a legitimate memfd use case; the downloaded content originates from a non-corporate IP with no software-distribution association. - Correlation: syscall sequence (memfd_create → write → execve-via-fd), the preceding network download, and the "(deleted)" memfd exe path together are conclusive, tool-agnostic evidence of fileless execution.
Step 4: Recommendations & Next Steps
- Immediate Response: Kill PID 22190 and any child processes; remove the malicious cron entry; capture the in-memory ELF content from the running process (via
/proc/<pid>/fd/3if still alive, or a memory image) for malware analysis since no on-disk copy exists; isolate lnx-app-node15; block 194.61.55.90. - Detection: Sigma-style rule:
title: Fileless Execution via memfd_create and execve-via-fd→selection: syscall="execve" AND path="/proc/self/fd/*"ORselection: process_exe_path contains "memfd:" AND contains "(deleted)". - Pro Tip: Because fileless memfd execution defeats disk-scanning AV entirely, prioritize syscall-level (auditd/eBPF-based) monitoring for the memfd_create→execve pattern on any Linux host handling untrusted input or scripts - this is one of the few detection strategies that works regardless of what the payload actually does once running.
Hypothesis confirmed - an attacker used a tampered cron entry to download an ELF payload and execute it entirely in memory via memfd_create, leaving no file on disk for traditional antivirus scanning to detect!