I am not a seasoned analyst. I've been learning cybersecurity on my own for a few months. This was my first real DFIR lab and it was equal parts exciting and humbling. I'm writing this so future-me (and maybe you) can look back and understand how to approach a Windows malware investigation from zero.
I kept hearing people say "the best way to learn DFIR is to just do it." So I did. I grabbed a Windows 10 VM, infected it with a well-known malware sample from a controlled lab environment, then put on my analyst hat and tried to figure out what the malware actually did. No hints, no answer key — just me, the tools, and a lot of Stack Overflow tabs.
This write-up covers every single step in the order I did them. I'll tell you what worked, what confused me, and what I had to re-do because I made a mistake. Think of it as a field journal, not a textbook.
Setting Up a Safe Lab Environment
Before touching anything malware-related, I needed a safe, isolated environment. The golden rule here: never run malware on your host machine. I learned this by reading horror stories online. Malware can escape VMs in edge cases, but more importantly, it can make outbound connections and do real damage if it's on a real machine.
Here's what I used to build my lab:
FlareVM is a free Windows-based security distribution by Mandiant (now Google). You install it on top of a vanilla Windows VM and it automatically installs about 50+ tools used by malware analysts and DFIR folks. It saved me hours of manual tool installation.
1. Install VirtualBox → Create new Windows 10 VM → Allocate at least 4GB RAM and 60GB disk
2. Set the network adapter to Host-Only — this cuts off internet access so malware can't phone home
3. Install Windows 10, then run the FlareVM installer script in PowerShell
4. Once everything is set up, take a clean snapshot — this is your "before infection" baseline
5. Take a second snapshot after infection — this is your "crime scene"
The snapshot step is critical. Having a clean baseline means I could diff the before and after states, which is exactly how investigators find what changed. I named mine CLEAN_BASELINE and POST_INFECTION.
I also kept my host machine's network completely separate during this. VirtualBox's host-only adapter means the VM can only talk to itself and the host — it can't reach the real internet.
I used MalwareBazaar by Abuse.ch — a public repository of malware samples for researchers. Specifically, I grabbed a known Emotet sample. Everything was done inside the isolated VM only. Never extract malware samples outside a sandboxed environment.
Live Triage — What's Running Right Now?
After running the malware sample and giving it about 5 minutes to do its thing, I started my investigation. The first thing I wanted to know: what is running on this machine right now?
The principle here is called live triage. Before shutting anything down, you capture everything that's volatile — things that only exist in memory and disappear the moment you power off. I had read about the Order of Volatility and I wanted to actually apply it.
2.1 — Capturing Running Processes
I opened a PowerShell window (as Administrator) and started dumping process information. The goal was to see if anything looked suspicious — unusual names, unusual parent-child relationships, processes running from weird directories.
# List all running processes with paths
Get-Process | Select-Object Name, Id, Path | Format-Table -AutoSize
# Also check for processes without a verified path (suspicious)
Get-Process | Where-Object { $_.Path -eq $null } | Select-Object Name, Id
This gave me a long list. Most of it was normal Windows stuff — svchost.exe, explorer.exe, lsass.exe. But one entry immediately stood out:
A process called svchost.exe was running from C:\Users\User\AppData\Local\Temp\svchost.exe — not from C:\Windows\System32 where the real svchost lives. Legitimate Windows services never live in AppData. This is a classic malware trick: masquerade as a known Windows process name.
2.2 — Checking Network Connections
Next I wanted to see if the malware was making any network connections. Even though the VM was on a host-only network, I wanted to see what it was trying to connect to.
# Show all active TCP connections with process IDs
netstat -ano
# Cross-reference with process names
Get-NetTCPConnection | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, State, OwningProcess | Sort-Object State
I saw several connection attempts in a SYN_SENT state going to external IPs — the malware was trying to beacon out, but getting blocked by the network isolation. Those destination IPs became my first set of Indicators of Compromise (IoCs).
2.3 — Checking Persistence with Autoruns
Malware wants to survive reboots. So it almost always establishes some kind of persistence — a registry key, a scheduled task, a startup folder entry. Autoruns by Sysinternals is the best tool I've found for this. It shows you every single thing that auto-starts on Windows, categorized neatly.
I opened Autoruns and immediately saw something under the HKCU\Run registry key — a new entry pointing to that same fake svchost.exe in AppData. Confirmed: the malware had set up persistence.
Registry key: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
Value name: WindowsUpdate (deliberately deceptive name)
Value data: C:\Users\User\AppData\Local\Temp\svchost.exe
Memory Forensics with Volatility 3
This step genuinely broke my brain the first time. Memory forensics means analyzing a raw dump of the system's RAM to find things that aren't stored on disk — injected code, decrypted payloads, network connections, passwords in memory.
I had to read the Volatility 3 docs twice and watch a YouTube walkthrough before this clicked. The key insight: RAM is a snapshot of everything the computer was doing at that exact moment. Even malware that tries to hide on disk can't hide from a memory dump if it's running.
3.1 — Acquiring the Memory Dump
I used FTK Imager (free tool from Exterro) to capture the RAM dump. Inside the infected VM, I opened FTK Imager → File → Capture Memory. It saved a .mem file to my analysis folder. This whole process took about 3 minutes.
Before doing anything else, I generated an MD5 and SHA-256 hash of the memory dump. This proves the file hasn't been modified since collection — essential for maintaining evidence integrity, even in a personal lab.
# Generate SHA-256 hash of the memory dump
Get-FileHash -Algorithm SHA256 .\memdump.mem
# Output something like:
# Algorithm Hash Path
# SHA256 3A7F2B... memdump.mem
# Write it down / save it. This is your chain of custody entry.
3.2 — Running Volatility 3 Analysis
I moved the dump file to my analysis machine (host) and ran Volatility 3 from there. Volatility is a Python-based framework — you run plugins against the memory dump to extract specific information.
# 1. List all processes at time of capture
python3 vol.py -f memdump.mem windows.pslist.PsList
# 2. Show process tree (parent-child relationships)
python3 vol.py -f memdump.mem windows.pstree.PsTree
# 3. Look for injected code in process memory (DLL injection)
python3 vol.py -f memdump.mem windows.malfind.Malfind
# 4. Check network connections at time of capture
python3 vol.py -f memdump.mem windows.netstat.NetStat
# 5. List loaded DLLs per process
python3 vol.py -f memdump.mem windows.dlllist.DllList
The malfind plugin was the most revealing. It scans all process memory regions looking for patterns that suggest injected code — specifically, memory that has executable permissions but isn't backed by a file on disk. That's a major red flag.
Malfind flagged the fake svchost.exe process and also showed signs of process hollowing in a explorer.exe instance. Process hollowing is when malware starts a legitimate process (like explorer), empties its memory, and injects its own malicious code into it. It's a technique used to hide in plain sight.
Volatility's malfind plugin flagged explorer.exe (PID 3412) with executable memory pages that had no corresponding file on disk. The MZ header (magic bytes that mark a Windows executable) was present inside the hollowed region — strong indicator of process hollowing injection.
3.3 — Dumping the Injected Code
I could actually dump the injected code from memory for further analysis. This was the point where I felt like an actual analyst for the first time.
# Dump the memory of the suspicious process (PID 3412 = hollowed explorer)
python3 vol.py -f memdump.mem windows.memmap.MemMap --pid 3412 --dump
# This outputs a .dmp file you can examine further with a hex editor
# or submit to VirusTotal / analyze with PE tools
# Get strings from the dump to look for URLs, IPs, mutex names
strings pid.3412.dmp | grep -E "http|\.exe|\.dll|MUTEX"
Running strings on the dump revealed embedded C2 (Command and Control) server URLs and a mutex name — unique strings that malware uses to prevent running multiple copies of itself. These are high-confidence IoCs.
Disk Artifacts — What Did It Leave Behind?
Memory forensics tells you what was running. Disk forensics tells you what was written. Malware almost always leaves traces on disk — dropped files, modified registry keys, log entries, prefetch files that prove a program was executed.
4.1 — Windows Event Logs
Event logs are one of the most valuable sources of evidence on a Windows machine. I used Event Viewer and also PowerShell to query specific log channels.
# Security log: Account logon events (look for lateral movement)
Get-WinEvent -LogName Security | Where-Object { $_.Id -eq 4624 } | Select-Object TimeCreated, Message -First 20
# System log: Service installations (malware often installs as service)
Get-WinEvent -LogName System | Where-Object { $_.Id -eq 7045 } | Select-Object TimeCreated, Message
# PowerShell operational log: Script block logging (if enabled)
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" | Select-Object TimeCreated, Message -First 30
# Sysmon log (if Sysmon was installed before infection — I had it on my FlareVM)
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" | Where-Object { $_.Id -eq 1 } | Select-Object TimeCreated, Message -First 20
# Event ID 1 = Process Creation — shows every process that launched with full command line
The Sysmon log was incredibly useful here. Because I had installed Sysmon (a free Sysinternals tool that logs detailed system activity) before infecting the VM, I had a full record of every process that launched, every network connection that was attempted, and every file that was created.
Sysmon gives you visibility that Windows' built-in logs just don't have. Event ID 1 (Process Create) with full command-line arguments is a game changer. If you're setting up a future lab, install Sysmon with the SwiftOnSecurity config before you infect the machine.
4.2 — Prefetch Files
Prefetch files are a gold mine. Windows creates .pf files for every application that runs, storing the executable's name, last run time, and run count. Even if malware deletes itself after running, the prefetch file often survives.
# List prefetch files sorted by last modified time (most recent first)
Get-ChildItem C:\Windows\Prefetch -Filter "*.pf" | Sort-Object LastWriteTime -Descending | Select-Object Name, LastWriteTime -First 20
I found a prefetch file for SVCHOST.EXE-XXXXXXXX.pf that had a different hash suffix than the legitimate system svchost entries. This confirmed that the fake svchost in AppData had been executed. I used PECmd (Eric Zimmerman's prefetch parser) to extract the full details including which files it accessed on first run.
4.3 — Registry Investigation
Beyond the Run key I found with Autoruns, I dug deeper into the registry to find other malware artifacts. Malware often stores configuration data and additional payloads in obscure registry locations.
# Check all common Run/RunOnce keys for persistence
$runKeys = @(
"HKCU:\Software\Microsoft\Windows\CurrentVersion\Run",
"HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce",
"HKLM:\Software\Microsoft\Windows\CurrentVersion\Run",
"HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce"
)
foreach ($key in $runKeys) {
Write-Host "`n[+] $key" -ForegroundColor Cyan
Get-ItemProperty -Path $key -ErrorAction SilentlyContinue
}
# Look at recently modified registry keys (using last write timestamps)
# This requires Eric Zimmerman's Registry Explorer for deep analysis
4.4 — Static Analysis of the Malware File
I copied the suspicious svchost.exe from AppData to my analysis machine (with the sample renamed to .malz to prevent accidental execution) and ran static analysis on it.
# Hash the file — submit to VirusTotal to check AV detections
sha256sum suspicious_svchost.malz
# Extract readable strings from the binary
strings suspicious_svchost.malz | grep -E "http|cmd|powershell|reg|taskkill"
# Check file entropy (high entropy = likely packed/encrypted)
# I used "detect-it-easy" (die) from FlareVM for this
die suspicious_svchost.malz
# Output showed: Packer: UPX (common packing tool)
# High entropy section confirmed — code was compressed to evade AV
The entropy analysis confirmed the binary was packed with UPX — a common packer that compresses the executable to make it harder for antivirus to scan. This is why it may have slipped past basic AV detection.
Reconstructing the Attack Timeline
With all the evidence gathered, I could now put together a coherent timeline of what happened. This is arguably the most important part of any incident investigation — turning a pile of logs and artifacts into a story that a human can understand and act on.
I cross-referenced timestamps from Sysmon logs, Event Viewer, prefetch files, and registry key modification times to build this:
Malware Sample Dropped and Executed
The malicious file was placed in C:\Users\User\AppData\Local\Temp\ and executed manually (in a real attack, this would likely be via a phishing email attachment or drive-by download). Sysmon Event ID 1 captured the process creation with full command line.
Registry Run Key Created
Within 2 minutes, the malware wrote a new value to HKCU\...\Run under the alias WindowsUpdate. This would cause it to restart automatically after any reboot.
Process Hollowing into explorer.exe
The malware launched a new instance of explorer.exe, hollowed it out, and injected its second-stage payload. This was the evasion mechanism — running inside a trusted process.
Outbound Connection Attempts to C2 Servers
The hollowed explorer process began attempting connections to three external IP addresses on port 443 and 8080. All attempts were blocked by the host-only network. In a real network, these would have succeeded.
System Reconnaissance Commands Observed
Sysmon logs showed child processes spawned from the malware: systeminfo.exe, net user, ipconfig /all — classic living-off-the-land recon to gather info about the victim machine and network.
IoC Summary
Here are the Indicators of Compromise I collected across the investigation:
Fake svchost.exe
SHA-256: 3a7f2b...
Path: AppData\Local\Temp\svchost.exe
Persistence Run Key
HKCU\...\Run\WindowsUpdate pointing to malicious binary in Temp folder
C2 IP Addresses
3 external IPs on ports 443 and 8080 with repeated SYN_SENT connection attempts
Process Hollowing
explorer.exe (PID 3412) with injected PE header and executable memory not backed by disk file
Mutex Name
Unique mutex string extracted from memory dump — confirms specific malware family
UPX Packing
Binary packed with UPX to reduce file size and evade static AV detection
Lessons Learned — What I'd Do Differently
This investigation took me about 4 hours spread across two days. A lot of that time was getting confused, going down wrong paths, and having to re-read documentation. Here's what I'd tell myself if I was starting over:
Personal Takeaways
Install Sysmon before you infect. I almost forgot this and had to redo the whole setup. Without Sysmon, I would have missed the process creation and network connection events entirely. It's a 5-minute install that pays off enormously.
Take a memory dump early. I waited too long before capturing RAM. The order of volatility matters — memory data is gone the moment the machine restarts. Next time, memory dump is the first thing I do after triage.
Document every command you run. I forgot to save some of my early PowerShell output and had to re-run commands. Keep a running notes file open the whole time. I now use a simple investigation.md file where I paste everything.
Don't panic when Volatility looks scary. The output is verbose and confusing at first. Focus on pslist, pstree, and malfind first. Everything else can wait until you're more comfortable.
The timeline is the deliverable. Anyone can run tools. The skill is connecting the dots into a coherent story. Every piece of evidence should answer one of: what happened, when did it happen, how did it happen, and what was the impact.
Know your normal. Half of this investigation was comparing what I found against "normal" Windows behavior. Building a baseline of what clean Windows looks like is fundamental — it makes anomalies obvious.
My next lab is going to be a network PCAP analysis using Wireshark — looking at the traffic a malware sample generates when it does have internet access. I also want to go deeper into Volatility and practice extracting credentials from memory (mimikatz artifacts).
Tools Used in This Lab
VirtualBox + FlareVM
Free. FlareVM auto-installs 50+ analysis tools on Windows. Best starting point for a beginner lab.
FTK Imager
Free. GUI tool to capture RAM dumps. Simple, reliable, industry standard.
Volatility 3
Free, open-source. Python framework. Start with pslist, pstree, malfind, netstat plugins.
Autoruns (Sysinternals)
Free from Microsoft. Shows every auto-start entry on Windows. Invaluable for finding persistence.
Sysmon
Free from Microsoft Sysinternals. Use SwiftOnSecurity config. Must be installed before infection.
Eric Zimmerman Tools
Free suite. PECmd (prefetch), Registry Explorer, MFTECmd. Best Windows artifact parsers available.