Alerts to Answers
Lab 5 — Sysmon Investigation: Reconstructing an Attack from Endpoint Telemetry
Introduction
Objective
Reconstruct a complete attack chain on WIN11 using only Sysmon telemetry — then codify what you learned into a custom Wazuh detection rule that would catch the same behavior automatically.
This lab marks a deliberate shift. In Labs 1–4 you responded to alerts the system handed you. Here, no alert tells you what happened. You are given a compromised endpoint and a time window, and you must reconstruct the story yourself from raw process, network, and DNS events — the way a real analyst works a host after an EDR flags it. The investigation ends where mature SOC work always ends: you turn a manual finding into a durable detection so the next occurrence is caught without a human.
Overview
Standard Windows logging tells you that PowerShell ran. Sysmon tells you who launched it, with what command line, what it resolved in DNS, where it connected, what it wrote to disk, and in what order (Russinovich & Garnier, n.d.). That difference — from an event to a narrative — is what makes Sysmon the single richest host-based data source available to defenders.
You will investigate a scripted but realistic intrusion that mirrors a common initial-access pattern:
A user opens a document → a script interpreter spawns → an encoded command executes → a domain is resolved → a payload is downloaded → Defender quarantines it.
Your job is to arrive at that narrative having started with nothing but a hostname and a rough timestamp. Every activity follows the course pattern:
Generate → Observe Locally → Observe in Wazuh → Explain Why → Detect Automatically
Prerequisites
Lab 0 completed — your SOC is validated and Sysmon telemetry reaches Wazuh (Event IDs 1, 3, 22 confirmed).
Sysmon installed on WIN11 with the SwiftOnSecurity configuration (Appendix A, Section A.10).
The Wazuh Agent on WIN11 is collecting Microsoft-Windows-Sysmon/Operational (Appendix A, Section A.11).
You can log in to the Dashboard at https://192.168.1.30 and reach Explore → Discover.
If any prerequisite is unmet, run the Operational Readiness Validation (Appendix C) before continuing.
Lab Environment Recap
| System | Hostname | Agent Name | IP Address | Role in This Lab |
|---|---|---|---|---|
| Windows 11 Pro | WIN11 | win11 | 192.168.1.40 | Investigation target — Sysmon source |
| Wazuh Server 4.14.5 | WAZUH-SRV | — | 192.168.1.30 | SIEM — where you hunt and where the rule lives |
Remember the hostname/agent-name split: you query agent.name:"win11" (lowercase enrollment name), not the uppercase hostname WIN11.
Learning Outcomes
By the end of this lab, you will be able to:
Generate a controlled, repeatable attack chain on a Windows endpoint.
Locate the highest-value Sysmon events (IDs 1, 3, 11, 22) in the Wazuh Dashboard using precise field paths.
Reconstruct a process tree from parent-child relationships (ParentImage → Image).
Extract intent from command-line arguments, including decoding an encoded PowerShell command.
Build an endpoint timeline that establishes causality rather than coincidence.
Pivot across process, DNS, network, and file-creation events to follow a single actor.
Author, deploy, and test a custom Wazuh rule that detects the attack behavior automatically.
The Sysmon Events You Will Hunt
| Event ID | Event Type | What It Answers | ATT&CK Relevance |
|---|---|---|---|
| 1 | Process Creation | Who ran what, with which command line, from which parent? | T1059 Command/Scripting Interpreter |
| 22 | DNS Query | Which domain did a process resolve, and which process asked? | T1071 Application Layer Protocol |
| 3 | Network Connection | Which process connected outbound, to which IP and port? | T1071 / C2 indicators |
| 11 | File Creation | Which process wrote which file, where, and when? | T1105 Ingress Tool Transfer |
Key Terms
| Key Term | Description |
|---|---|
| Process Tree | The parent-child chain of processes, showing which program launched which. |
| Parent-Child Relationship | The link between a spawning process (parent) and the process it created (child); anomalous pairings are strong behavioral indicators. |
| Command-Line Argument | Parameters passed to a program at launch; often the richest single source of attacker intent. |
| Encoded Command | A Base64-encoded PowerShell payload (-EncodedCommand) used to obscure the actual instructions. |
| Process GUID | A globally unique identifier Sysmon assigns to each process, enabling reliable pivoting even when PIDs are reused. |
| Pivot | Moving from one piece of evidence to a related one (e.g., from a process to the DNS query it made) to follow a single actor. |
| Endpoint Timeline | A time-ordered reconstruction of host events that reveals causality. |
| LOLBin | A "living-off-the-land binary" — a legitimate signed Windows tool (powershell.exe, certutil.exe) abused by attackers to avoid dropping custom malware. |
| Custom Rule | A Wazuh detection rule authored by the analyst, stored in local_rules.xml, that fires on defined field conditions. |
Part 1 — Generate the Attack Chain
Task 1.1 — Snapshot First
Before generating any attack activity, take a VMware snapshot of WIN11 named Lab5-Clean. When the investigation is complete, you can revert to a known-good state.
Why this matters: Professionals never run adversary-emulation activity — even benign, scripted activity — without a rollback point. This is the same discipline that governs live-response work: preserve the ability to undo.
Task 1.2 — Deploy the Scenario Generator
The attack chain is produced by Invoke-Lab5Scenario_v18.ps1, provided with this lab (full source and a line-by-line explanation are in the Manual Appendix). It emulates a realistic initial-access sequence using only safe, standard Windows tooling and the harmless EICAR test file (EICAR, n.d.) — nothing in it is actually malicious.
Copy the script to WIN11 (for example, C:\Lab5\). Then open PowerShell as Administrator and allow the script to run for this session only:
::: {custom-style="CodeLabel"} WIN11 · PowerShell (Administrator) :::
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
If Windows flags the file as downloaded from another computer, unblock it:::: {custom-style="CodeLabel"} WIN11 · PowerShell (Administrator) :::
Unblock-File -Path C:\Lab5\Invoke-Lab5Scenario_v18.ps1Why this matters: Setting the execution policy at Process scope changes nothing permanently -- the relaxed policy dies with this PowerShell window. That is exactly the least-privilege habit you want: grant only the access the task needs, only for as long as it needs it.
Task 1.3 — Record the Start Time and Run
Note the exact wall-clock time before you run — this becomes the anchor for your investigation window. Then execute:
::: {custom-style="CodeLabel"} WIN11 · PowerShell :::
cd C:\Lab5
.\Invoke-Lab5Scenario_v18.ps1The script simulates the following sequence and prints each step as it goes:
Spawns a mock "document handler" parent process (a renamed PowerShell instance standing in for WINWORD.EXE) to create a realistic parent-child anomaly.
Launches powershell.exe with an -EncodedCommand payload.
The decoded payload performs a DNS lookup of a benign test domain.
It then downloads the EICAR test file over HTTP to disk.
Windows Defender quarantines the file, generating a detection.
Why this matters: Recording the start time is not bureaucratic -- it is how you scope a hunt. In a real incident you rarely know the full window, but you always establish an anchor and expand outward from it. Everything you search in this lab will be bounded by "the 15 minutes after this timestamp."
Task 1.4 — Confirm the Chain Executed
You do not investigate from the script's output — that would be cheating the exercise. But you do confirm the telemetry exists before hunting. In Event Viewer on WIN11, open Applications and Services Logs → Microsoft → Windows → Sysmon → Operational and confirm recent Event ID 1 entries are present.
CONCLUSION: You generated a controlled, repeatable attack chain and established your investigation anchor. From this point forward, treat the script's internals as unknown — you are the analyst who arrived after the activity, with only Sysmon to tell you what occurred.
Part 2 — The Investigation
You are now the analyst. An EDR sensor flagged WIN11 for a suspicious PowerShell execution around your recorded timestamp. You have no other context. Reconstruct what happened.
Task 2.1 — Establish the Hunting Window
In the Dashboard, go to Explore → Discover, select the wazuh-alerts-* index pattern, and set the time range to the 15 minutes following your recorded start time.
Start with the broadest possible view of the host:
::: {custom-style="CodeLabel"} Wazuh Dashboard · Discover query :::
agent.name:"win11"
Note the event volume. This is your haystack.
Why this matters: Every hunt begins by bounding time and scope, then narrowing. Starting broad and refining — rather than guessing a specific query first — is the disciplined approach; it ensures you never narrow past the evidence before you have seen its shape.
Task 2.2 — Find the Anchor Event (Process Creation)
Narrow to process-creation events and look for the anomaly:
::: {custom-style="CodeLabel"} Wazuh Dashboard · Discover query :::
agent.name:"win11" and data.win.system.eventID:"1"
Scan the data.win.eventdata.image and data.win.eventdata.parentImage fields. You are looking for a PowerShell process whose parent is not a normal interactive shell.
Locate the event where PowerShell was spawned by the mock document handler. Open it and record these fields:
| Field | Value to Record |
|---|---|
| data.win.eventdata.image | The executed process (powershell.exe) |
| data.win.eventdata.parentImage | The parent — your first anomaly |
| data.win.eventdata.commandLine | The full command line, including the encoded blob |
| data.win.eventdata.user | The account that ran it |
| data.win.eventdata.processGuid | The unique ID you will pivot on |
| data.win.eventdata.utcTime | The precise event time |
Why this matters: The parent-child relationship is the single strongest behavioral tell on an endpoint. A user double-clicking PowerShell produces explorer.exe → powershell.exe — unremarkable. A document handler spawning PowerShell (WINWORD.EXE → powershell.exe) is the classic signature of a malicious-macro initial access. The process name is identical in both cases; only the parent distinguishes benign from malicious. This is why experienced hunters read parents before anything else.
Task 2.3 — Decode the Command Line
The commandLine field contains an -EncodedCommand followed by a Base64 blob. Copy the Base64 string and decode it. In PowerShell:
::: {custom-style="CodeLabel"} WIN11 · PowerShell :::
[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("PASTE_BLOB_HERE"))Record the decoded command. It reveals the DNS lookup and download logic the attacker tried to hide.
Why this matters: Encoding is obfuscation, not encryption — it stops casual eyes, not analysts. -EncodedCommand is one of the most common evasion techniques in the wild precisely because it defeats naive keyword rules that only match "powershell.exe." Learning to decode it by reflex turns an opaque blob into a full confession. Note also why PowerShell uses Unicode (UTF-16LE) here — decoding with the wrong charset yields garbage, a detail that trips up beginners.
Task 2.4 — Follow the DNS Query (Pivot #1)
You now know the process. Pivot to what it resolved. Using the processGuid you recorded, find the DNS event from the same process:
::: {custom-style="CodeLabel"} Wazuh Dashboard · Discover query :::
agent.name:"win11" and data.win.system.eventID:"22"
Confirm the query originated from your PowerShell process (match data.win.eventdata.image and processGuid), and record data.win.eventdata.queryName.
Why this matters: DNS almost always precedes the network connection — the attacker's code must resolve a name before it can reach a host. Event ID 22 answers "which domain, requested by which process?" in one record. Pivoting on processGuid rather than process name is deliberate: GUIDs are unique, so you follow this exact process instance and never accidentally pick up an unrelated PowerShell window.
Task 2.5 — Follow the Network Connection (Pivot #2)
Next, find where that process connected:
::: {custom-style="CodeLabel"} Wazuh Dashboard · Discover query :::
agent.name:"win11" and data.win.system.eventID:"3"
Match on processGuid again and record data.win.eventdata.destinationIp, data.win.eventdata.destinationPort, and data.win.eventdata.destinationHostname if present.
Why this matters: Event ID 3 confirms the resolved domain became an actual outbound connection — intent turned into action. In a real hunt this is where you would check the destination against threat intelligence (the subject of Lab 7). For now, notice the causal chain forming: same process resolved a name, then connected to it.
Task 2.6 — Follow the File Creation (Pivot #3)
Find the payload written to disk:
::: {custom-style="CodeLabel"} Wazuh Dashboard · Discover query :::
agent.name:"win11" and data.win.system.eventID:"11"
Record data.win.eventdata.targetFilename and confirm the creating process matches your PowerShell processGuid.
Why this matters: A download immediately followed by the file's appearance on disk — written by the same process that just connected out — is a textbook ingress-tool-transfer pattern (T1105). Event ID 11 closes the loop between "connected somewhere" and "brought something back."
Task 2.7 — Confirm the Detection
Finally, find Defender's response:
::: {custom-style="CodeLabel"} Wazuh Dashboard · Discover query :::
agent.name:"win11" and rule.groups:"windows_defender"
(Or free-text search EICAR within the window.) Record what Defender detected and the file path it acted on -- it should match the targetFilename from Task 2.6.
Why this matters: The detection is the end of this story but the beginning of the analyst's real question: Defender caught the payload this time -- but would it catch a variant? That question is exactly why you will write your own behavioral detection in Part 4. Signature AV catches known files; behavioral rules catch the technique.
Part 3 — Build the Timeline
Individual events are data points. A timeline is evidence. Assemble everything you recorded into a single causal narrative.
Task 3.1 — Assemble the Sequence
Using the utcTime values from each event, complete this timeline in your SOC Engineering Notebook:
| Time (UTC) | Sysmon ID | Event | Key Evidence |
|---|---|---|---|
| (fill in) | 1 | Document handler spawns PowerShell | parentImage anomaly |
| (fill in) | 1 | Encoded command executes | decoded payload |
| (fill in) | 22 | DNS query | queryName |
| (fill in) | 3 | Outbound connection | destinationIp:port |
| (fill in) | 11 | Payload written to disk | targetFilename |
| (fill in) | — | Defender quarantine | detection + path |
Task 3.2 — State the Narrative
In two or three sentences, write what happened — as you would in the summary line of an incident ticket. A strong answer names the initial-access vector, the technique used to obscure execution, the attacker's network objective, and the outcome.
Why this matters: A timeline that a colleague can read in ten seconds is the deliverable of an investigation. The events did not change — but ordering them by time transformed six disconnected records into a story with cause and effect. This is the difference between searching logs and conducting an investigation.
Task 3.3 — Map to MITRE ATT&CK
Label each stage with its technique:
| Stage | Technique | ID |
|---|---|---|
| Document handler → PowerShell | Command and Scripting Interpreter: PowerShell | T1059.001 |
| Encoded command | Obfuscated Files or Information | T1027 |
| DNS + outbound connection | Application Layer Protocol: Web Protocols | T1071.001 |
| EICAR download to disk | Ingress Tool Transfer | T1105 |
Why this matters: Mapping to ATT&CK converts a one-off finding into shared vocabulary. When you tell another analyst "T1059.001 spawned by an Office parent," you have communicated the entire initial-access pattern in a phrase — and you have named exactly what your detection rule (next) must catch.
CONCLUSION: You reconstructed a full attack chain from raw endpoint telemetry, ordered it into a causal timeline, and mapped it to a recognized adversary framework. You did this with no alert guiding you — only Sysmon and method.
Part 4 — From Investigation to Detection
Manual reconstruction is powerful but does not scale — you cannot hand-investigate every host every day. The mature move is to codify what you found into a rule so the behavior is caught automatically next time. This is the bridge from analyst to detection engineer.
Task 4.1 — Define the Detection Logic
The strongest, lowest-noise signal you found was the parent-child anomaly: a document-handler process spawning PowerShell. Rather than alerting on "powershell.exe ran" (thousands of benign hits daily), you will alert on the behavior — PowerShell whose parent is a document application.
State the logic plainly:
IF Sysmon Event ID 1 AND image ends in powershell.exe AND parentImage is a document handler THEN generate a high-severity alert.
Why this matters: This is the core discipline of detection engineering — alert on the technique, not the tool. "PowerShell executed" is noise; "PowerShell spawned by a document" is signal. Encoding the relationship you discovered, rather than a single indicator, is what makes a detection both durable and low-noise.
Task 4.2 — Locate the Rules File
Wazuh custom rules live on WAZUH-SRV in:
::: {custom-style="CodeLabel"} WAZUH-SRV · Terminal :::
/var/ossec/etc/rules/local_rules.xml
Back it up before editing -- the professional reflex from Chapter 3:::: {custom-style="CodeLabel"} WAZUH-SRV · Terminal :::
sudo cp /var/ossec/etc/rules/local_rules.xml /var/ossec/etc/rules/local_rules.xml.bakWhy this matters: local_rules.xml is where your detections live, separate from the vendor ruleset in /var/ossec/ruleset/ (which upgrades overwrite). Custom detections belong in local_rules.xml for exactly the same reason custom Suricata signatures belong in local.rules -- never edit vendor-supplied content directly.
Task 4.4 — Validate the Rule Syntax
Before restarting the Manager, verify the configuration is well-formed:
::: {custom-style="CodeLabel"} WAZUH-SRV · Terminal :::
sudo /var/ossec/bin/wazuh-logtestPaste a sample Sysmon Event ID 1 log line when prompted, or simply confirm wazuh-logtest starts without XML parse errors. Then restart the Manager:
::: {custom-style="CodeLabel"} WAZUH-SRV · Terminal :::
sudo systemctl restart wazuh-manager
Confirm it came back healthy:::: {custom-style="CodeLabel"} WAZUH-SRV · Terminal :::
sudo /var/ossec/bin/wazuh-control statusWhy this matters: A malformed rule can stop wazuh-analysisd from loading -- which silently blinds your entire SIEM. Testing before restarting is the same "validate, then apply" habit you used with suricata -T. Never restart a detection engine on faith.
Task 4.5 — Test Your Detection
Revert WIN11 to the Lab5-Clean snapshot (or simply re-run the generator), and execute Invoke-Lab5Scenario_v18.ps1 again. Then, in the Dashboard:
::: {custom-style="CodeLabel"} Wazuh Dashboard · Discover query :::
agent.name:"win11" and rule.id:"100510"
Expected result: your custom alert fires, at level 12, tagged with T1059.001 -- with no manual investigation required. The behavior you spent Part 2 reconstructing by hand is now caught the instant it occurs.
Why this matters: This is the payoff of the entire lab. You closed the loop: an unalerted intrusion → a manual reconstruction → a durable automated detection. Every mature SOC runs on this cycle. An analyst who can only respond to existing alerts is a consumer of detections; an analyst who can create them is a force multiplier for the whole team.
Task 4.6 — Consider the Limits (Analyst Judgment)
Your rule is good, but no rule is perfect. In your notebook, answer:
What legitimate activity might trigger this rule (a false positive)? How would you scope an exclusion without creating a blind spot (recall Chapter 5's "responsible exclusions")?
The attacker used an encoded command. Could you write a second rule targeting -EncodedCommand in the command line? What would make that rule noisier than this one?
Defender caught the EICAR file by signature. Explain why your behavioral rule would still add value against a payload Defender has never seen.
Why this matters: Writing the rule is half the craft; understanding its failure modes is the other half. A detection engineer who cannot articulate their rule's false positives will eventually drown their SOC in noise or, worse, be lulled into false confidence. Judgment about when a rule fails is what separates a rule-writer from an engineer.
CONCLUSION: You transformed a manual finding into a tested, deployed, ATT&CK-mapped detection — and reasoned about its limits. This is the complete detection-engineering loop in miniature.
Lab Validation Checklist
| Item | Pass |
|---|---|
| Lab5-Clean snapshot created | ☐ |
| Scenario generator executed; start time recorded | ☐ |
| Anchor Event ID 1 located with parentImage anomaly | ☐ |
| Encoded command successfully decoded | ☐ |
| DNS query (ID 22) tied to the process via processGuid | ☐ |
| Network connection (ID 3) tied to the same processGuid | ☐ |
| File creation (ID 11) tied to the same processGuid | ☐ |
| Defender detection located and correlated to the file | ☐ |
| Complete timeline assembled | ☐ |
| Attack chain mapped to MITRE ATT&CK | ☐ |
| Custom rule 100510 authored in local_rules.xml | ☐ |
| Manager restarted healthy after rule addition | ☐ |
| Custom alert fired on re-run | ☐ |
| False-positive analysis completed | ☐ |
Lessons Learned
Read parents before processes. The process name rarely distinguishes benign from malicious; the parent almost always does. Parent-child anomalies are the highest-value, lowest-noise endpoint signal.
Encoding is not encryption. -EncodedCommand hides intent from casual review, not from an analyst — decoding it by reflex turns obfuscation into evidence.
Pivot on GUIDs, not names. processGuid follows one exact process instance; process names collide. Reliable pivoting is what lets you follow a single actor across DNS, network, and file events.
Timelines create causality. The same events, ordered by time, become a story. Ordering is analysis.
Codify findings into detections. Manual investigation does not scale; a good rule does. Alert on the technique (parent-child behavior), not the tool (powershell.exe).
Validate before you restart. A malformed rule can blind analysisd. "Test, then apply" is the same discipline everywhere in the SOC.
Know your rule's limits. A detection you cannot critique is a detection you cannot trust.
Knowledge Check
1. Two events both show data.win.eventdata.image ending in powershell.exe. Which single field best distinguishes a likely-malicious execution from a benign one?
A. data.win.eventdata.user B. data.win.eventdata.parentImage C. data.win.system.eventID D. data.win.eventdata.utcTime
2. Why pivot on processGuid rather than the process image name when following an actor across DNS, network, and file events?
A. GUIDs are shorter and easier to type B. Process names are case-sensitive C. A GUID uniquely identifies one process instance; names can match many unrelated processes D. Sysmon does not record image names for Event IDs 3 and 22
3. An -EncodedCommand payload is Base64. Decoding it with the wrong text encoding yields garbage. Which encoding does PowerShell use for -EncodedCommand?
A. ASCII B. UTF-8 C. Unicode (UTF-16LE) D. Windows-1252
4. Which Sysmon Event ID would confirm that a payload was written to disk, and by which process?
A. 1 B. 3 C. 11 D. 22
5. In the custom rule, what does 61603 accomplish?
A. It sets the alert severity to 61603 B. It evaluates the rule only after Wazuh's built-in Sysmon process-creation rule has matched C. It maps the alert to MITRE technique 61603 D. It suppresses the rule for agent 61603
6. Why should the custom rule be placed in local_rules.xml rather than a file under /var/ossec/ruleset/?
A. local_rules.xml loads faster B. Vendor ruleset files are overwritten on upgrade; local_rules.xml is preserved C. Rules in the ruleset directory are ignored by analysisd D. local_rules.xml supports MITRE tags and ruleset files do not
7. Which step correctly precedes restarting the Wazuh Manager after editing a rule?
A. Deleting the vendor ruleset B. Validating the rule/config (e.g., wazuh-logtest) to catch XML errors C. Disabling the Windows agent D. Rebooting WAZUH-SRV
8. Your behavioral rule fires on "document handler spawns PowerShell." Why does it still add value even though Defender already quarantined the EICAR file by signature?
A. It does not add value; signature detection is sufficient B. Signature AV detects known files; the behavioral rule detects the technique, catching novel payloads Defender has never seen C. It replaces the need for Defender entirely D. It runs faster than Defender
Answer Key
| Q | Answer | Why |
|---|---|---|
| 1 | B | The parent process distinguishes benign (explorer→PowerShell) from malicious (document→PowerShell); the image name is identical in both. |
| 2 | C | processGuid uniquely identifies one process instance; image names collide across unrelated processes. |
| 3 | C | PowerShell's -EncodedCommand expects a Base64-encoded UTF-16LE (Unicode) string. |
| 4 | C | Event ID 11 (File Creation) records the file written and the creating process. |
| 5 | B | chains the rule to a parent rule (61603), so it evaluates only after that rule matches. |
| 6 | B | Upgrades overwrite vendor ruleset files; custom detections in local_rules.xml survive. |
| 7 | B | Validate first (wazuh-logtest) — a malformed rule can stop analysisd from loading. |
| 8 | B | Behavioral detection catches the technique regardless of the specific payload, covering unknown files. |
Discussion Questions
This lab reconstructed an attack with no initiating alert. In a production SOC, what data source or process would typically point an analyst at a specific host and time window to begin such a hunt?
You alerted on the parent-child relationship rather than the encoded command. Argue for and against choosing the encoded-command indicator instead. Which produces fewer false positives, and why?
The scenario used a renamed PowerShell process to stand in for WINWORD.EXE. How might a real attacker make the parent-child relationship look legitimate, and what would that mean for your rule?
Defender caught the payload by signature; your rule catches the behavior. Describe a scenario where each would fire without the other, and explain why running both is stronger than either alone.
The generator sets execution policy at Process scope only. Explain why that choice is safer than setting it machine-wide, and connect it to the least-privilege principle.
What Comes Next
You reconstructed an attack from endpoint telemetry and built a detection for it — but you stayed entirely on the host. Lab 6 (Emerging Threats Investigation) returns to the network layer, hunting the same class of activity through Suricata and the Emerging Threats Open ruleset. Lab 7 (MISP Threat Intelligence) then teaches you to take an indicator like the destination IP you found in Task 2.5 and enrich it against threat intelligence — turning "an unknown connection" into "a known adversary." Keep your Lab 5 timeline and custom rule; later labs build directly on both.
Manual Appendix — The Scenario Generator Explained
This appendix contains the full source of Invoke-Lab5Scenario_v18.ps1 and explains each stage. Two audiences use it: students who want to understand exactly what they investigated, and instructors adapting the scenario. Nothing in the script is malicious — it uses only standard Windows tooling and the industry-standard EICAR test file (EICAR, n.d.), which every antivirus engine detects harmlessly by agreement.
Why a Script and a Manual Version
Running a script gets every student to the same telemetry quickly and identically — essential for a class working in parallel. But a script students cannot read is a black box, and black boxes teach nothing. This appendix opens the box: after investigating the effects in Parts 2–4, read here to connect each Sysmon event you found back to the exact line that produced it.
Full Script Source
The complete, verbatim source of Invoke-Lab5Scenario_v18.ps1. Type or copy it exactly as shown; everything between the rules below is the script.
::: {custom-style="CodeLabel"} WIN11 · PowerShell (Administrator) :::
<#
================================================================================
Invoke-Lab5Scenario_v18.ps1
Lab 5 — Sysmon Investigation
Runs on: WIN11 (192.168.1.40) | Run as: Administrator
================================================================================
PURPOSE
Generates a benign, repeatable "attack chain" for Sysmon investigation:
1. A mock document-handler process (renamed powershell.exe) spawns
PowerShell -> forges a realistic parent-child anomaly.
2. PowerShell runs an -EncodedCommand payload.
3. The payload resolves a benign test domain (DNS).
4. It downloads the harmless EICAR test file over HTTP.
5. Microsoft Defender quarantines the file (a real detection).
SAFE BY DESIGN
Uses only standard Windows tooling and the industry-standard EICAR test
file. Nothing malicious executes. Run in an isolated lab VM only.
BEFORE YOU RUN
1. Take a VMware snapshot named "Lab5-Clean".
2. Open PowerShell as Administrator.
3. Allow this session to run the script:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
4. If Windows flags the file as downloaded:
Unblock-File -Path .\Invoke-Lab5Scenario_v18.ps1
5. RECORD THE START TIME printed below — it anchors your investigation.
INVESTIGATE
In the Wazuh Dashboard (Explore -> Discover), hunt:
agent.name:"win11" and data.win.system.eventID:"1"
then pivot through Event IDs 22 (DNS), 3 (network), 11 (file creation).
================================================================================
#>
Write-Host "[*] Lab 5 scenario starting. RECORD THIS TIME:" (Get-Date -Format o) -ForegroundColor Cyan
# --- Stage 1: Create a mock 'document handler' parent -----------------------
# Copy powershell.exe under a document-application name to forge a realistic
# parent-child anomaly (document app -> PowerShell), the classic macro pattern.
$mockDir = "C:\Lab5\mock"
New-Item -ItemType Directory -Force -Path $mockDir | Out-Null
$mockExe = Join-Path $mockDir "winword.exe"
Copy-Item "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" $mockExe -Force
# --- Stage 2: Build the encoded payload -------------------------------------
# The payload resolves a benign domain, then downloads the EICAR test file.
# It is Base64(UTF-16LE) encoded to emulate a real -EncodedCommand payload.
$payload = @'
Resolve-DnsName -Name testmyids.com -ErrorAction SilentlyContinue | Out-Null
try {
Invoke-WebRequest -Uri "http://secure.eicar.org/eicar.com.txt" `
-OutFile "C:\Lab5\payload.txt" -UseBasicParsing
} catch { }
'@
$bytes = [System.Text.Encoding]::Unicode.GetBytes($payload)
$encoded = [System.Convert]::ToBase64String($bytes)
# --- Stage 3: Execute via the mock parent -----------------------------------
# The mock 'winword.exe' launches real powershell.exe with the encoded command.
# Sysmon records: parentImage = winword.exe, image = powershell.exe.
& $mockExe -NoProfile -EncodedCommand $encoded
Write-Host "[*] Scenario complete. Defender should quarantine the EICAR file." -ForegroundColor Green
Write-Host "[*] Investigate agent.name:win11 from the recorded time forward." -ForegroundColor Green
<#
CLEANUP (optional — reverting to the Lab5-Clean snapshot is preferred)
Remove-Item -Recurse -Force C:\Lab5\mock -ErrorAction SilentlyContinue
Remove-Item -Force C:\Lab5\payload.txt -ErrorAction SilentlyContinue
#>Stage-by-Stage Explanation
Stage 1 — The forged parent. The script copies the real powershell.exe to a file named winword.exe. When that copy runs, Windows and Sysmon report the file name as the parent — winword.exe — even though it is functionally PowerShell. This reproduces, safely, the exact telemetry a malicious Office macro produces: a document application appearing to spawn a script interpreter. This is the anomaly you detect in Task 2.2 and alert on in Part 4.
Stage 2 — The encoded payload. The actual instructions — resolve testmyids.com, download EICAR — are placed in a here-string, converted to UTF-16LE bytes, and Base64-encoded. This is precisely how real -EncodedCommand payloads are constructed, which is why decoding in Task 2.3 requires the Unicode charset. The payload wraps the download in a try/catch so the script completes cleanly even after Defender intervenes.
Stage 3 — Execution. The mock parent launches real PowerShell with -EncodedCommand. This single line produces the chain you investigate: Event ID 1 (the spawn), Event ID 22 (the DNS resolve), Event ID 3 (the HTTP connection), Event ID 11 (payload.txt written), and finally the Defender quarantine.
Telemetry-to-Line Mapping
| Sysmon Event You Found | Produced By |
|---|---|
| ID 1 — winword.exe → powershell.exe | Stage 3 execution via the mock parent |
| ID 1 — encoded command line | The -EncodedCommand $encoded argument |
| ID 22 — DNS query for testmyids.com | Resolve-DnsName inside the payload |
| ID 3 — outbound HTTP connection | Invoke-WebRequest inside the payload |
ID 11 — C:\Lab5\payload.txt created |
-OutFile in the download |
| Defender quarantine | EICAR content triggering real-time protection |
Cleanup
To reset between runs without reverting the snapshot:
::: {custom-style="CodeLabel"} WIN11 · PowerShell :::
Remove-Item -Recurse -Force C:\Lab5\mock -ErrorAction SilentlyContinue
Remove-Item -Force C:\Lab5\payload.txt -ErrorAction SilentlyContinueReverting to the Lab5-Clean snapshot is the cleanest reset and is preferred before a graded attempt.
Instructor Notes
Determinism: The domain (testmyids.com) and payload path are fixed so every student's telemetry matches the answer key. Change them per-section if you want unique investigations.
Defender dependency: The final detection assumes Defender real-time protection is enabled (verified in Lab 0). If disabled, the EICAR file persists on disk and Event ID 11 still provides the file-creation evidence.
Extending the chain: Adding a persistence stage (e.g., a Run-key registry write producing Sysmon Event ID 13) is a natural extension for an advanced section and sets up the DFIR lab.