Module 7: Introduction to Threat Hunting & Hunting With Elastic

Module 7 cover: Tactics, Techniques, and Procedures

These notes cover the threat hunting fundamentals and threat intelligence theory from the module, then the full Stuxbot investigation lab in Elastic/Kibana - pivoting from one suspicious file across Sysmon, Zeek, and PowerShell logs to a confirmed lateral movement chain.

Back to Module 6: Module 6: Detecting Windows Attacks with Splunk

Module 7 Navigation

On this page

Threat Hunting Fundamentals

Threat hunting is an active, human-led, hypothesis-driven practice that systematically combs through network data to identify stealthy, advanced threats that evade existing security solutions. It’s a shift from a reactive posture to a proactive one, with the principal objective of substantially reducing dwell time - the weeks or months an attacker might spend hidden inside a network before detection. By applying cognitive empathy to understand the adversarial mindset, organizations can neutralize threats at the earliest stage of the cyber kill chain.

When to initiate a hunt: Threat hunting is a sustained, continuous operation, meaning the ideal time to hunt is always the present. That said, immediate hunting operations are required during specific events:

Building the threat hunting team: Constructing a threat hunting team requires a diverse range of skills and perspectives. Key roles include:

Integration with incident handling: Hunters provide value throughout the various phases of incident handling. During preparation, they help establish operational protocols and clear rules of engagement. During detection and analysis, a hunter’s acumen is indispensable for validating indicators and uncovering additional artifacts missed by automated systems. During post-incident activity, hunters offer expert recommendations to strengthen the overall security posture of the organization.

The critical role of risk assessment: Risk assessment is a key enabler for strategic threat hunting, letting teams prioritize their activities effectively. It systematically identifies the most critical assets of an organization - the “crown jewels.” By highlighting specific system vulnerabilities and the tactics of likely threat actors, risk assessments tell hunters exactly where to focus for maximum impact.

Risk assessment as an enabler for strategic threat hunting

The Threat Hunting Process

This is a proactive, cyclical approach to finding hidden threats within a network, broken into four phases:

1. Preparation and Hypothesis (Setting the Stage & Formulating Hypotheses) - the planning phase. Before hunting, prepare the environment and decide what you’re looking for.

2. Execution and Analysis (Designing the Hunt & Data Gathering) - the active phase where you test the hypothesis.

3. Evaluation and Response (Evaluating Findings & Mitigating Threats) - once you find something, understand it and act on it.

4. Improvement and Refinement (After the Hunt & Continuous Learning) - the hunt isn’t over once the threat is gone.

The four-phase threat hunting process cycle

Example walked through in the module - Emotet:


Threat Hunting Glossary

Describing attacker operations:

The evidence of an attack:

Analytical frameworks for threat intelligence:

Pyramid of Pain - indicator difficulty vs. attacker cost

Diamond Model of Intrusion Analysis

My take on this: I think the Pyramid of Pain is still relevant, but its real value now depends on context. Basic IOCs like hashes, IPs, and domains are useful, but attackers can change them quickly. Stronger detection comes from understanding tools, behaviors, and TTPs.

Modern SOC teams can’t just chase every alert. They need context from SIEM, SOAR, asset criticality, vulnerabilities, and business risk to understand what actually matters. For example, a malware hash on a test VM may be low priority, but the same hash on a production finance server should be treated as far more serious.

In simple terms, good detection isn’t just finding bad activity - it’s finding the bad activity that matters most, on the systems that matter most, fast enough to stop the attacker. The shift is from IOC-based alert chasing to context-aware adversary disruption.


Threat Intelligence

The core of Cyber Threat Intelligence (CTI): CTI aims to move an organization’s defense from a reactive posture to a proactive, anticipatory strategy. To be truly valuable and avoid “alert fatigue” or wasted resources, intelligence must strictly adhere to four principles: Relevant to your specific environment, Timely to allow swift mitigation, Actionable with clear defensive direction, and Accurate so resources aren’t wasted on false leads.

Threat Intelligence vs. Threat Hunting: Closely connected, but distinct functions that create a feedback loop.

The three tiers of intelligence:

Actioning a tactical threat report: When defenders receive a tactical report (e.g., an alert on an Emotet campaign), they follow a structured methodology to maximize its value:

  1. Comprehend & Classify: Understand the attacker’s broader narrative and classify the provided IOCs into categories (Network, Host, Email).
  2. Map the Lifecycle: Track the attacker’s TTPs against frameworks like MITRE ATT&CK to anticipate their next moves.
  3. Validate: Cross-reference IOCs with external databases to ensure accuracy and filter out outdated indicators or false positives.
  4. Integrate: Update security infrastructure (firewalls, EDR, IPS) with validated IOCs while ensuring business operations aren’t disrupted.
  5. Hunt & Monitor: Proactively hunt through network logs for both the specific IOCs and broader behavioral patterns (TTPs). Continually monitor, refine defenses, and share new findings back with the security community.

Actioning a tactical threat report - five-step workflow


Hunting Stuxbot: A Live Investigation

The lab scenario: hunt for an actor codenamed Stuxbot inside an Elastic/Kibana environment, starting from one suspicious file and pivoting outward through Sysmon, Zeek, and PowerShell logs until the full lateral movement chain is confirmed.

1. Confirming the initial download

Started from this query for the hunt:

event.code:15 AND file.name:*invoice.one

This gives the basic suspicion, but it isn’t confirmed yet, so the next step is identifying the time to look (Pivot 1): Mar 26, 2023 @ 16:05:47.791.

Extending to process.name and file.path shows the file was downloaded via msedge, with the file path in the Downloads folder of an employee named Bob.

Pivot 1: process.name and file.path show the msedge download into Bob's Downloads folder

2. Corroborating with Sysmon Event ID 11

Now checking Event ID 11 (file create) as a download indicator when no browser is involved:

event.code:11 AND file.name:invoice.one*

Event ID 11 logs any file creation. By finding the same file creation event in both log types, the analyst proves with much higher confidence that the download occurred. The Zone.Identifier tag found in the Event ID 11 log is extra proof, since Windows adds this to files downloaded from the internet.

Event ID 11 with the Zone.Identifier tag confirming an internet download

The source IP is visible in the same event:

Source IP visible in the Event ID 11 log

3. Closing the Sysmon visibility gap

The next step should be agent.hostname, then ideally a Sysmon Event ID 3 to confirm the network connection - but there’s a problem: host WS001 with IP 192.168.28.130.

  1. The core problem - a data gap: As the module notes, it’s common practice to configure Sysmon to ignore network connections from web browsers (Edge, Chrome, etc.) to reduce log noise, since browsers make thousands of connections that would otherwise flood the SIEM.
  2. Find the event: A Sysmon Event ID 11 log shows the file invoice.one was created.
  3. Identify the host: The host.hostname field in that log identifies the computer as WS001.
  4. Pivot to find the IP: Searching for a network event (Sysmon Event ID 3) from WS001 should reveal its source.ip, 192.168.28.130 - except Sysmon was told to ignore exactly this kind of browser traffic.

In short, Zeek matters here because it contained the critical network information that was intentionally filtered out of the Sysmon logs - it filled the visibility gap and let the investigation continue.

4. Pivoting to Zeek DNS logs

Pivot is the IP and the time range - the question is where the file actually came from:

source.ip:192.168.28.130 AND dns.question.name:*

Zeek DNS query results for the compromised host Zeek DNS query results, continued

This shows the user’s machine looked up the domain file.io, a file-hosting service, right before the download occurred - alongside Google Mail access and a Microsoft Defender SmartScreen file scan, which typically triggers when a file is downloaded via Edge.

5. Resolving the file.io hosting IP

Extending the fields to dns.answers.data gives the IP of where the file was actually hosted via file.io:

34.197.10.85, 3.213.216.16

dns.answers.data resolving the file.io hosting IPs

6. Confirming the download connection

Pivot here is the hosting IP - checking for any connections to it in the same time frame:

Connections to the file.io hosting IP in the same time window

This corroborates that the user, Bob, successfully downloaded the file invoice.one from the hosting provider file.io.

7. OneNote spawning a batch script

Going the IR route: if invoice.one was opened, OneNote must have opened too - so before drafting the next query, the hypothesis is that OneNote was involved shortly after the download:

event.code:1 AND process.command_line:*invoice.one*

This confirms OneNote was accessed roughly six seconds after the download (Mar 26, 2023 @ 16:05:53.601). Since OneNote is now in play, the next pivot is OneNote.exe itself, to see if anything was attached:

event.code:1 AND process.parent.name:"ONENOTE.EXE"

OneNote.exe spawning cmd.exe, which launches invoice.bat

This establishes a connection between OneNote.exe, the suspicious invoice.one, and the execution of cmd.exe, which initiates invoice.bat from a temporary location - highly likely because the batch file was attached inside the OneNote file itself. Relevant events sit between Mar 26, 2023 @ 16:05:00.000 and 16:10:00.000, events outside that window can be ignored.

8. invoice.bat staging C2

The question now: has this batch script triggered anything else? Pivot is invoice.bat:

event.code:1 AND process.parent.command_line:*invoice.bat*

invoice.bat spawning further activity

This looks similar to a threat intel report seen earlier - with process.name, process.args, and process.pid as columns, a closer look shows a PowerShell script pulled from Pastebin. Assuming process.pid is the pivot here, this is very rich information:

PowerShell process pivot showing Pastebin and downstream activity

Time Process Event ID Indicator / Action Notes
Mar 26, 2023 16:06:35.187 powershell.exe 11 C:\Users\bob\AppData\Local\Temp\501352xg.cmdline Initial staging file created
Mar 26, 2023 16:06:35.187 powershell.exe 11 C:\Users\bob\AppData\Local\Temp\501352xg.dll DLL dropped in Temp folder
Mar 26, 2023 16:06:35.317 powershell.exe 22 pastebin.com DNS lookup to Pastebin
Mar 26, 2023 16:06:35.345 powershell.exe 3 104.20.67.143 Connection to Pastebin IP
Mar 26, 2023 16:06:36.943 powershell.exe 22 7eac-2a09-5e40-1090-4e0-4f03-def-90a4-eb.eu.ngrok.io DNS lookup to ngrok domain
Mar 26, 2023 16:06:36.970 powershell.exe 3 18.158.249.75 Connection to ngrok IP
Mar 26, 2023 16:06:37.472 powershell.exe 3 18.158.249.75 Follow-up connection to ngrok IP
Mar 26, 2023 16:17:32.961 powershell.exe 11 C:\Users\bob\AppData\Local\Temp\default.exe EXE dropped on disk
Mar 26, 2023 16:17:33.845 powershell.exe 13 Registry modification Possible persistence
Mar 26, 2023 23:23:57.243 powershell.exe 11 C:\Users\Public\DomainPasswordSpray.ps1 Password spraying script dropped
Mar 26, 2023 23:33:53.899 powershell.exe 3 192.168.28.200 Internal network connection
Mar 26, 2023 23:33:53.904 powershell.exe 22 DC1.eagle.local DNS lookup involving domain controller

PowerShell first staged files in Bob’s Temp folder at 16:06, contacted Pastebin, then resolved and connected to an ngrok address that may represent C2. Around 16:17, PowerShell dropped default.exe and modified the registry, suggesting possible persistence. Later, at 23:23, it dropped DomainPasswordSpray.ps1, followed by internal activity toward 192.168.28.200 and DC1.eagle.local.

9. Confirming C2 persistence

18.158.249.75 as a potential C2 - checking where it goes. Interestingly, activity extended over a period of two days:

C2 IP activity extending over a two-day period

Checking for any ngrok traffic around the same timeline to confirm whether the connection continued:

ngrok traffic around the same timeline

The fact that the C2 IP address changed shows it’s a resilient setup that can’t be stopped by simple blocking rules - the connection likely continued until March 29th. Searching the new IP confirms activity continued after the C2 change:

Activity continuing after the C2 IP change

10. Pivoting on default.exe

Pivoting to Windows logs for the executable found earlier, to see what it does:

process.name:"default.exe"

This shows SharpHound was also executed:

default.exe execution leading to SharpHound

11. The hash pivot to PKI

Pulling the field process.hash.sha256:

process.hash.sha256 field on default.exe

Checking that hash elsewhere:

process.hash.sha256:018d37cbd3878258c29db3bc3f2988b6ae688843801b9abc28e6151141ab66d4

The same hash also appearing on PKI

The same malicious file hash was found on both WS001 and PKI, which suggests the attacker moved beyond the initial workstation and also compromised the PKI server. A backdoor file was found under the svc-sql1 user profile, indicating that this service account may also be compromised. On PKI, the first execution of default.exe was launched by PSEXESVC, tied to Sysinternals PSExec - strongly suggesting PSExec was used for remote execution and lateral movement within the Active Directory environment.

PSEXESVC tied to PSExec, confirming lateral movement onto PKI

12. Password spray attempts from WS001

Open question: how was svc-sql1 compromised in the first place? Possibly the earlier PowerShell activity included a brute-force/spray attempt. Since DomainPasswordSpray.ps1 was uploaded on WS001, the next check is any successful or failed password attempts from that machine, excluding Bob (the machine’s own user):

Password spray attempts from WS001, excluding Bob

There’s also an attempt made against the Administrator account.

13. The VBS file on PKI

Module knowledge check: in the part where default.exe is under investigation on PKI, a VBS file is mentioned.

process.name:"default.exe"

Filtering file.path under the relevant timestamp:

Time File path
Mar 27, 2023 @ 18:21:48.009 C:\Users\svc-sql1\AppData\Local\Temp\XceGuhkzaTrOy.vbs

14. Mimikatz DCSync

Module knowledge check: Stuxbot uploaded and executed Mimikatz - what were the process arguments?

process.name:"mimikatz.exe"

Reading process.args:

Time Process args
Mar 27, 2023 @ 19:14:29.615 .\mimikatz.exe, lsadump::dcsync /domain:eagle.local /all /csv, exit

15. PowerView share enumeration

Module knowledge check: some PowerShell code was loaded into memory that scans/targets network shares - identify the tool it derives from.

First query:

event.code:4104 AND (*share* OR *shares* OR *smb* OR *admin$* OR *c$*)

Then filtering on powershell.file.script_block_text:

Time Script block text
Mar 27, 2023 @ 17:31:08.902 Invoke-ShareFinder -ExcludeStandard -ExcludeIPC

Invoke-ShareFinder script block, identifying PowerView

Invoke-ShareFinder is a PowerView cmdlet - the answer is PowerView.


Skill Assessment

Three graded hunts, building each KQL query from scratch off the Stuxbot scenario above.

Hunt 1 - hunt for Lateral Tool Transfer to C:\Users\Public. Enter the user.name field for the transferred tool that starts with “r”.

event.code:11 AND file.path:*\\Users\\Public\\*

Hunt 1: file creation events staged under C:\Users\Public

This was the right starting query because Event ID 11 = Sysmon FileCreate, and C:\Users\Public is a classic suspicious staging location. It showed multiple tools staged there, including Rubeus.exe at C:\Users\Public\Rubeus.exe, with user.name = svc-sql1, host.name = PKI.eagle.local, process.name = svchost.exe. Since the question asked for the tool starting with “r,” the relevant file is Rubeus.exe.

From there, the pivot is confirming how this was lateral, not just local file creation:

Pivot 1 - confirm remote logon to PKI before the tool staging:

host.name:"PKI.eagle.local" AND event.code:4624 AND user.name:"svc-sql1"

This shows 192.168.28.130 logged into PKI.eagle.local as svc-sql1 with LogonType = 3 - so svc-sql1 was used remotely against PKI.

Pivot 2 - confirm remote execution context around that login:

host.name:"PKI.eagle.local" AND @timestamp >= "2023-03-27T18:37:30" AND @timestamp <= "2023-03-27T18:38:10"

This shows PSEXESVC.exe started on PKI as SYSTEM, with Event 4624 logons for svc-sql1, Event 4648 explicit-credential activity, and default.exe executed as svc-sql1.

So the realistic chain is: 192.168.28.130 authenticated to PKI as svc-sql1PSEXESVC.exe appeared on PKI, showing remote execution context → default.exe executed on PKI → Rubeus.exe was later created in C:\Users\Public on PKI.

Hunt 1 answer: svc-sql1

Hunt 2 - hunt for Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder. Enter the registry.value field for the first registry-based persistence action.

First pass:

event.code:13 AND registry.path:*\\CurrentVersion\\Run*

Reducing the noise:

event.code:13 AND registry.path:*\\CurrentVersion\\Run*
AND NOT registry.value:"MicrosoftEdgeAutoLaunch_4ED9772FE1E7553A8F858520D6E0108B"
AND NOT registry.value:"Application Restart #0"
AND NOT registry.value:"Application Restart #1"

The first remaining hit is the PowerShell-set registry run key:

Hunt 2: first registry-based persistence event after noise filtering

Hunt 3 - hunt for PowerShell Remoting for Lateral Movement. Enter the winlog.user.name field for the document related to PowerShell remoting-based lateral movement toward DC1.

Network telemetry showed PowerShell-related activity from PKI.eagle.local toward another internal host, suggesting possible WinRM/PowerShell Remoting - but that didn’t directly answer the question, since it specifically asked for winlog.user.name. The hint pointed to Event ID 4104 (powershell.file.script_block_text), since that event records the actual PowerShell code executed. Pivoting from network telemetry to PowerShell script block logs:

event.code:4104 AND powershell.file.script_block_text:*PSSession* AND powershell.file.script_block_text:*dc1*

This returns the key event:

Hunt 3: Enter-PSSession dc1 in the PowerShell script block log

Mar 27, 2023 @ 19:17:08.058 - host.name = PKI.eagle.local, winlog.user.name = svc-sql1, powershell.file.script_block_text = Enter-PSSession dc1.

Event 4104 shows the executed PowerShell code. Enter-PSSession dc1 confirms PowerShell Remoting toward DC1, and winlog.user.name on that document is svc-sql1.

Hunt 3 answer: svc-sql1

Key Takeaway

Most of this hunt was just pivoting from one log source to the next when the current one ran out of answers.

What stuck with me:

References

[HTB Academy] Certified Defensive Security Analyst (CDSA) - Module 7: Introduction to Threat Hunting & Hunting With Elastic. https://academy.hackthebox.com/