CtrlK
BlogDocsLog inGet started
Tessl Logo
SkillPublic

reverser-fileless-malware

In-memory and fileless malware detection — AMSI bypass analysis, reflective DLL injection, CLR-hosted payloads, process hollowing, PowerShell cradle chains, WMI/COM persistence, and registry-resident payloads. Covers detection, memory forensics, and payload extraction.

Quality

82%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

Medium

Suggest reviewing before use

SKILL.md
Quality
Evals
Security

Fileless Malware Analysis

Detect, extract, and analyze malware that lives entirely in memory — no files on disk. Covers AMSI bypass techniques, reflective loading, process injection variants, and LOLBin abuse chains.

Quick Reference

# Scan for injected code in running processes
pe-sieve.exe /pid <PID> /dir ./dump/ /shellc /iat 3

# Scan ALL processes at once
hollows_hunter.exe /dir ./hunt_results/

# Dump suspicious process memory
procdump.exe -ma <PID> process.dmp

# Search memory dump for PE headers
python3 -c "
d=open('process.dmp','rb').read()
import re
for m in re.finditer(b'MZ',d):
    off=m.start()
    if d[off+0x3c:off+0x40] != b'\x00'*4:
        print(f'PE header at offset 0x{off:x}')
"

# Extract PowerShell from event logs
wevtutil qe Microsoft-Windows-PowerShell/Operational /f:text /c:50

MITRE ATT&CK Mapping

TechniqueIDHow It Appears
PowerShellT1059.001Encoded cradles, AMSI bypass, download-execute chains
Reflective Code LoadingT1620Assembly.Load(byte[]), ReflectiveLoader in shellcode, Donut payloads
Process InjectionT1055Classic injection, process hollowing (T1055.012), thread hijacking
Impair Defenses: AMSIT1562.001Patching AmsiScanBuffer, CLR hooking, registry disable
WMI Event SubscriptionT1546.003Fileless persistence via WMI consumers
Signed Binary ProxyT1218mshta, rundll32, regsvr32, msbuild LOLBin execution

1. Detect In-Memory Artifacts

Identify processes with injected or hollowed code regions.

# pe-sieve — scan single process for implants
pe-sieve.exe /pid <PID> /shellc /threads /iat 3 /dir ./pe_sieve_out/
# Output: report.json with findings per memory region

# hollows_hunter — system-wide sweep
hollows_hunter.exe /dir ./hh_out/ /shellc /loop
# Scans every process; reports: hollowed, implanted, unreachable

# Process Hacker — manual inspection (GUI)
# 1. Open Process Hacker → Properties on suspect process
# 2. Memory tab → look for:
#    - RWX regions (should be rare in legit processes)
#    - Private regions with PE headers (MZ signature)
#    - Mapped regions not backed by a file
# 3. Threads tab → look for:
#    - Threads with start address in unbacked memory
#    - Threads in ntdll!RtlUserThreadStart pointing to RWX region

# Volatility 3 — analyze memory image
vol3 -f memory.raw windows.malfind
vol3 -f memory.raw windows.vadinfo --pid <PID>
vol3 -f memory.raw windows.hollowfind

2. AMSI Bypass Analysis

Understand and detect AMSI patching techniques.

# Common AMSI bypass: patching AmsiScanBuffer in amsi.dll
# The bypass writes 0xC3 (RET) or specific bytes to the function prolog
# Detection: compare amsi.dll in-memory vs on-disk

# Check if AMSI is patched in a process
python3 << 'EOF'
import ctypes, ctypes.wintypes
# Load amsi.dll and get AmsiScanBuffer address
amsi = ctypes.windll.LoadLibrary("amsi.dll")
addr = ctypes.windll.kernel32.GetProcAddress(amsi._handle, b"AmsiScanBuffer")
# Read first bytes — should NOT be 0xC3 (ret) or 0x80 (cmp byte patched)
buf = (ctypes.c_byte * 8)()
ctypes.memmove(buf, addr, 8)
first_bytes = bytes(buf)
print(f"AmsiScanBuffer prolog: {first_bytes.hex()}")
if first_bytes[0] == 0xC3 or first_bytes[:3] == bytes([0x48, 0x31, 0xC0]):
    print("[!] AMSI IS PATCHED — bypass active")
else:
    print("[+] AMSI appears intact")
EOF

# ETW-based AMSI logging analysis
# Check for disabled ETW providers (another bypass vector)
logman query providers | findstr /i "amsi\|antimalware"

# Scan PowerShell scriptblock logs for bypass patterns
# Event Log: Microsoft-Windows-PowerShell/Operational, Event ID 4104
wevtutil qe "Microsoft-Windows-PowerShell/Operational" /q:"*[System[EventID=4104]]" /f:text /c:100 > scriptblocks.txt
grep -iE "AmsiScanBuffer|amsiInitFailed|AmsiUtils|Reflection\.Assembly|VirtualProtect|Marshal\.Copy" scriptblocks.txt

# Known AMSI bypass signatures to hunt
# 1. Matt Graeber's reflection: [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
# 2. Direct patch: VirtualProtect + Marshal.Copy on AmsiScanBuffer
# 3. amsiInitFailed field set to $true
# 4. CLR hooking via profiler DLL
# 5. Registry disable: HKCU\Software\Microsoft\Windows Script\Settings\AmsiEnable=0

3. Reflective DLL Injection Analysis

Detect and extract reflectively loaded DLLs.

# Reflective loaders don't use LoadLibrary — they parse PE headers manually
# Key indicators:
# - RWX memory region with PE header
# - No corresponding file on disk
# - Thread start address in unbacked memory

# pe-sieve dump of reflective DLL
pe-sieve.exe /pid <PID> /dir ./dump/ /imp 3 /shellc
# Reconstructs import table from the dump

# Manual extraction from process memory
python3 << 'EOF'
import ctypes
from ctypes import wintypes

PROCESS_VM_READ = 0x0010
PROCESS_QUERY_INFORMATION = 0x0400
pid = <PID>

kernel32 = ctypes.windll.kernel32
handle = kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, False, pid)

# Walk memory regions looking for MZ headers in RWX pages
addr = 0
while addr < 0x7FFFFFFFFFFF:
    mbi = ctypes.create_string_buffer(48)
    if kernel32.VirtualQueryEx(handle, addr, mbi, 48) == 0:
        break
    # Parse MEMORY_BASIC_INFORMATION
    base = int.from_bytes(mbi[0:8], 'little')
    size = int.from_bytes(mbi[24:32], 'little')
    protect = int.from_bytes(mbi[32:36], 'little')
    state = int.from_bytes(mbi[16:20], 'little')

    # PAGE_EXECUTE_READWRITE = 0x40, MEM_COMMIT = 0x1000
    if state == 0x1000 and protect == 0x40 and size > 0x1000:
        buf = (ctypes.c_char * min(size, 0x200))()
        read = ctypes.c_size_t()
        kernel32.ReadProcessMemory(handle, base, buf, len(buf), ctypes.byref(read))
        if buf.raw[:2] == b'MZ':
            print(f"[!] PE in RWX at 0x{base:x} size=0x{size:x}")
    addr = base + size
kernel32.CloseHandle(handle)
EOF

# Volatility malfind — finds injected code regions
vol3 -f memory.raw windows.malfind --pid <PID> --dump --dump-dir ./malfind_dumps/

4. Process Hollowing Detection

# Detect hollowed processes: legitimate image path but injected code
# Key sign: PEB ImageBaseAddress differs from on-disk PE base

# Volatility hollow process detection
vol3 -f memory.raw windows.hollowfind

# Manual check with pe-sieve
pe-sieve.exe /pid <PID> /hooks /iat 3 /dir ./hollow_check/
# Look for "replaced" status in report.json

# Sysmon-based detection (Event ID 25 — process tampering)
wevtutil qe "Microsoft-Windows-Sysmon/Operational" /q:"*[System[EventID=25]]" /f:text /c:20

# Common hollowing targets (watch these processes):
# svchost.exe, explorer.exe, notepad.exe, dllhost.exe, RuntimeBroker.exe
# If their in-memory image doesn't match disk → hollowed

5. PowerShell Cradle Chain Reconstruction

# Extract full PowerShell execution chain from logs
# ScriptBlock Logging (Event ID 4104) captures decoded content

# Export all scriptblock events
powershell -c "Get-WinEvent -LogName 'Microsoft-Windows-PowerShell/Operational' | Where-Object {$_.Id -eq 4104} | Select-Object -Property TimeCreated,Message | Export-Csv scriptblocks.csv"

# Common fileless chain pattern:
# Stage 0: mshta/wscript/shortcut → powershell -enc <base64>
# Stage 1: IEX(New-Object Net.WebClient).DownloadString('http://...')
# Stage 2: Reflective load .NET assembly or shellcode via [System.Reflection.Assembly]::Load()
# Stage 3: In-memory C2 beacon (Cobalt Strike, Sliver, etc.)

# Decode base64 PowerShell
python3 << 'EOF'
import base64
encoded = "<BASE64_FROM_CMDLINE>"
decoded = base64.b64decode(encoded).decode('utf-16-le')
print(decoded)
# Extract URLs
import re
urls = re.findall(r'https?://[^\s\'"]+', decoded)
for u in urls:
    print(f"  URL: {u}")
EOF

# Reconstruct WMI persistence (fileless persistence mechanism)
wmic /namespace:\\root\subscription path __EventFilter list full
wmic /namespace:\\root\subscription path CommandLineEventConsumer list full
wmic /namespace:\\root\subscription path __FilterToConsumerBinding list full

6. CLR-Hosted Payload Extraction

# .NET assemblies loaded via Assembly.Load(byte[]) leave CLR artifacts
# Detect: ETW CLR events or inspect AppDomain loaded assemblies

# List loaded assemblies in a process using ClrMD
python3 << 'EOF'
# Use clrmd via pythonnet or dump with SOS
# Alternative: use procdump + dotnet-dump
import subprocess
subprocess.run(["procdump", "-ma", str(<PID>), "clr_dump.dmp"])
# Then analyze with dotnet-dump
subprocess.run(["dotnet-dump", "analyze", "clr_dump.dmp"],
               input=b"clrmodules\ndumpheap -stat -type System.Reflection.Assembly\nexit\n")
EOF

# WinDbg + SOS approach for CLR inspection
# .loadby sos clr
# !DumpDomain           — lists all AppDomains and loaded assemblies
# !DumpAssembly <addr>  — details of a specific assembly
# !SaveModule <addr> recovered.dll  — save module to disk

# ETW provider for CLR loading events
logman create trace clr_trace -p {E13C0D23-CCBC-4E12-931B-D9CC2EEE27E4} 0x8 -o clr_events.etl
# Keywords 0x8 = LoaderKeyword — captures Assembly.Load events

Tools & Resources

ToolPurposeInstall
pe-sieveDetect implants/hollowing in running processesgithub.com/hasherezade/pe-sieve
hollows_hunterSystem-wide pe-sieve scangithub.com/hasherezade/hollows_hunter
Process HackerAdvanced process inspector (GUI)processhacker.sourceforge.io
Volatility 3Memory image forensicsgithub.com/volatilityfoundation/volatility3
MonetaDetect in-memory malware artifactsgithub.com/forrest-orr/moneta
SysmonWindows system activity loggingdocs.microsoft.com/sysinternals/sysmon
procdumpProcess memory dumperdocs.microsoft.com/sysinternals/procdump
dotnet-dump.NET managed dump analyzerdotnet tool install -g dotnet-dump
ETWExplorerETW provider browsergithub.com/zodiacon/EtwExplorer

Detection Signatures

IndicatorDescriptionDetection
RWX memory region with MZ headerReflectively loaded PEpe-sieve /shellc; Volatility malfind
AmsiScanBuffer patched prologAMSI bypass activeCompare in-memory vs on-disk amsi.dll
PowerShell -enc with long base64Encoded PowerShell payloadSysmon Event ID 1, CommandLine regex
WMI event subscriptionFileless persistenceWMI query __EventFilter / CommandLineEventConsumer
Thread start in unbacked memoryInjected threadProcess Hacker threads tab; Moneta scan
csc.exe / msbuild.exe with no projectLOLBin code compilationSysmon: parent process analysis
High scriptblock Event ID 4104 volumePowerShell cradle chainSIEM correlation on 4104 burst

Error Handling & Edge Cases

IssueResolution
pe-sieve misses injected .NETUse /dotnet flag; .NET assemblies need CLR-aware scanning
Process terminates before dumpUse Sysmon + scriptblock logging for post-mortem; configure proactive ETW tracing
AMSI patched before logging startsUse kernel-mode ETW or driver-based monitoring (e.g., Microsoft Defender ATP kernel sensor)
PowerShell constrained language modeAttacker may bypass via Add-Type with inline C# or CMSTP/MSBuild LOLBins
Memory image too large for VolatilityUse --pid to scope analysis; increase system swap
Anti-forensics: timestomped/cleared logsCross-reference with NTFS $MFT, Sysmon, and network logs
Kernel-mode injection (driver-level)Out of scope for user-mode tools — see reverser/rootkit-analysis

Decision Gate

IF suspicious process has RWX regions or pe-sieve/hollows_hunter hits:
  → Dump process memory (procdump -ma)
  → Extract implants with pe-sieve /imp 3
  → Identify payload type (.NET → dnSpy; native → Ghidra)
  → Trace injection chain (parent process, command line, scriptblocks)
ELSE IF PowerShell scriptblock logs show encoded/obfuscated content:
  → Decode all stages
  → Identify download URLs and in-memory payloads
  → Check for AMSI bypass indicators
ELSE IF WMI persistence found:
  → Extract consumer script/command
  → Trace event filter trigger conditions
  → Remove binding + consumer + filter
ELSE:
  → Enable Sysmon + scriptblock logging + ETW
  → Re-run detection after activity window
Repository

PurpleAILAB/Decepticon

Path

packages/decepticon/decepticon/skills/standard/reverser/fileless-malware/SKILL.md

Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.