Thereat Hunting

2022-01-25

Threat Hunting Simulator -- Technical Documentation

1. Overview

The Threat Hunting Simulator is TryHackMe's interactive training platform for developing proactive threat hunting skills. Unlike the SOC Simulator (which focuses on reactive alert triage), Threat Hunting places users in a proactive investigator role: they receive a hypothesis and threat intelligence briefing, then must independently hunt through SIEM logs, reconstruct a full attack chain using the MITRE ATT&CK framework, write adversary step descriptions, and generate an AI-powered threat report.

The system provides VMs (SIEM + analyst workstation), evaluates the user's timeline against expected attack stages, uses GPT-4o to assess the quality of adversary descriptions, and generates an overall performance report.


2. High-Level Architecture


3. Directory Structure

Backend (API)

apps/api/app/api/v2/src/
├── routes/threat-hunting/
│   ├── index.ts                     # Main router
│   ├── runs.ts                      # Run lifecycle routes
│   ├── timeline.ts                  # Timeline stage CRUD routes
│   ├── content.ts                   # CMS content routes
│   ├── vms.ts                       # VM management routes
│   └── public/                      # Unauthenticated routes
├── controllers/threat-hunting/
│   ├── runs.ts                      # Run request handlers
│   ├── timeline.ts                  # Timeline stage handlers
│   ├── content.ts                   # Content handlers
│   ├── stats.ts                     # Stats handlers
│   ├── leaderboard.ts               # Leaderboard handlers
│   └── vms.ts                       # VM handlers
├── services/threat-hunting/
│   ├── manage-runs.ts               # Run init, scoring, pause/resume
│   ├── vms.ts                       # VM deployment (wraps soc-sim)
│   ├── runs.ts                      # Run CRUD operations
│   ├── report.ts                    # AI report generation (GPT-4o)
│   ├── content.ts                   # Scenario content retrieval
│   ├── run-access.ts                # Access control
│   ├── run-public-summary.ts        # Public sharing
│   ├── stats.ts                     # Statistics
│   └── leaderboard.ts               # Leaderboard logic
├── models/threat-hunting/
│   └── run.ts                       # ThreatHuntingRun Mongoose model
├── common/
│   ├── interfaces/threat-hunting/    # TypeScript interfaces
│   ├── enums/threat-hunting/         # Status enums
│   └── constants/mitre/              # MITRE ATT&CK tactics & techniques
└── services/openai/
    └── index.ts                     # Shared OpenAI service (GPT-4o)

Frontend

apps/frontend/src/features/threat-hunting/
├── threat-hunting.tsx                # Root component
├── threat-hunting.slice.ts           # Core RTK Query API slice
├── threat-hunting.types.ts           # TypeScript types
├── threat-intel/                     # Hypothesis & threat intelligence
├── timeline/                         # Attack chain timeline builder
├── threat-report/                    # AI-generated threat report
├── summary/                          # Run summary & scoring
├── scenario-onboarding/              # Onboarding flow
├── scenario-overview/                # Scenario preview
├── my-computer/                      # Analyst VM iframe
├── my-notes/                         # Draggable notes editor
├── documentation/                    # Scenario documentation
├── guide-pages/                      # Help guides
├── landing-sections/
│   ├── threat-hunting-home/          # Landing page
│   ├── threat-hunting-scenarios/     # Scenario listing
│   ├── threat-hunting-stats/         # User statistics
│   └── threat-hunting-leaderboard/   # Leaderboard
└── components/
    ├── navigation/                   # Top navigation bar
    ├── notes-editor/                 # Draggable note-taking
    ├── vms-frame/                    # VM iframe wrapper
    ├── timeline-card/                # Timeline stage cards
    ├── tactic-select/                # MITRE tactic picker
    ├── mitre-accuracy/               # MITRE accuracy visualization
    └── machine-expiring-notification/# VM expiry warnings

4. Data Model

ThreatHuntingRun (threat_hunting_runs)

FieldTypeDescription
scenarioStringSanity CMS scenario ID
titleStringScenario display name
userObjectId (User)Run owner
statusEnumstarting, ready, completed, terminated, abandoned, paused
startedAt / endedAtDateRun time boundaries
pausedAt / resumedAtDatePause/resume timestamps
actualRuntimeNumberTotal active time (seconds)
hasInvestigationStartedBooleanWhether user clicked "Start Investigation"
hypothesisStringUser's threat hypothesis
vms.siem{ url, instance }SIEM VM connection
vms.analyst{ url, instance }Analyst VM connection
siemToolEnumsplunk, elastic, sentinel
usersString[]Selectable user entities in scenario
assetsString[]Selectable asset entities in scenario
notesStringUser's investigation notes
timelineStagesArrayUser-created attack chain stages
meta.hypothesisOutcomeStringExpected hypothesis outcome (ground truth)
meta.hypothesisOutcomePointsNumberPoints for correct hypothesis classification
meta.cmsTimelineStagesArraySnapshot of expected stages from CMS
reportEmbeddedEvaluation results (see below)
overallRunEvaluationStringAI-generated overall feedback
pointsAwardedNumberTotal points earned
successBooleanPass/fail (>=80% threshold)
isErroredBooleanVM deployment failure

Timeline Stage (user-created, embedded in run)

FieldTypeDescription
titleStringStage name
descriptionStringAdversary step description (free-text)
timestampDateWhen the attack step occurred
tacticStringMITRE ATT&CK Tactic ID
techniqueStringMITRE ATT&CK Technique ID
userStringCompromised user entity
assetStringCompromised asset
iocStringIndicators of Compromise
siemUrlLinkStringSIEM query URL as evidence
orderNumberStage position in chain
evaluationStringAI-generated feedback (post-submission)
*PointsAwardedNumberPoints per category (7 fields)

CMS Timeline Stage (ground truth, snapshotted into meta)

FieldTypeDescription
timelineStartTime / timelineEndTimeDateExpected timestamp window
timelinePointsNumberPoints for correct timestamp
tactic / tacticPointsString/NumberExpected tactic + points
technique / techniquePointsString/NumberExpected technique + points
expectedUser / userPointsString/NumberExpected user + points
expectedAsset / assetPointsString/NumberExpected asset + points
iocsArray<{value, points, type}>Expected IOCs with individual points
adversaryStepDescriptionEvaluationCriteriaStringCriteria for AI evaluation
adversaryStepDescriptionPointsNumberMax points for description

Report (embedded in run)

FieldType
hypothesisOutcomeClassificationString
hypothesisOutcomePointsAwardedNumber
threatReportEvaluationString (markdown)
techniquesAndTactics{ percentageIdentified, tactic[], technique[] }
compromisedAssets{ percentageIdentified, assets[] }
iocs{ percentageIdentified, network[], host[] }

5. Run Lifecycle

Key Difference from SOC-Sim

Threat Hunting has an explicit investigation start step (hasInvestigationStarted). After VMs are ready, the user reviews the scenario overview and threat intelligence before clicking "Start Investigation." In SOC-Sim, investigation begins immediately when the run is ready.


6. VM Creation & Deployment

Shared Infrastructure with SOC-Sim

Threat Hunting reuses the SOC-Sim VM infrastructure directly:

threat-hunting/vms.ts imports from soc-sim/vms.ts:
  ├── deployVMsWithRetry()        # Core EC2 deployment + retry logic
  ├── insertSOCSimInstance        # (aliased as insertThreatHuntingInstance)
  ├── insertMockInstance          # Local dev mock
  ├── extendVmTime                # 1-hour extension logic
  └── validateSimulationStarted   # Prevent duplicate VMs
AspectSOC-SimThreat Hunting
Cost CenterCostCenter.SOC_SIMCostCenter.THREAT_HUNTER
Health Check Jobsoc-sim-health-checkthreat-hunting-health-check
Post-deployImport logs + alerts25s wait only (logs pre-loaded)
Log ingestionEventBridge scheduledNone -- logs are pre-loaded on the SIEM VM
Alert insertionFrom CMS into MongoDBNone -- no alert queue

The critical difference: Threat Hunting VMs come with pre-loaded logs on the SIEM. There is no EventBridge log scheduling or alert insertion. The user proactively hunts through existing data rather than reacting to incoming alerts.


7. The Timeline: Attack Chain Building

Timeline API Endpoints

MethodEndpointDescription
GET/threat-hunting/timelineGet all stages for active run
GET/threat-hunting/timeline/stageGet single stage
POST/threat-hunting/timeline/stageCreate new stage
PATCH/threat-hunting/timeline/stageUpdate existing stage
DELETE/threat-hunting/timeline/stageDelete stage
POST/threat-hunting/timeline/stage/reorderReorder stages

The frontend uses @dnd-kit for drag-and-drop reordering of timeline stages.


8. AI Integration (GPT-4o)

AI Function 1: Adversary Step Description Evaluation

When: Called for each timeline stage during submitFindings() Purpose: Evaluates the quality of the user's free-text adversary step description against CMS-defined criteria Model: GPT-4o via OpenAIService.chatGptCompletionAPI()

System prompt (summarized):

"You are a Senior Threat Hunter. Evaluate the adversary step description strictly based on the given 'Criteria'. Calculate a totalScore. Write feedback as a senior SOC analyst speaking to a Junior Threat Hunter. Do not reveal evaluation criteria. Limit to 1000 characters."

Input:

Output (Zod-validated):

{ summary: string, totalScore: number }

AI Function 2: Threat Report Generation

When: User explicitly triggers via "Generate Threat Report" button Purpose: Creates a markdown threat case report from the full attack chain

System prompt (summarized):

"You are a Senior Threat Hunter. Generate a precise threat case report in markdown from attack chain stages. Validate data completeness. Reject single-stage chains. Limit to 15 sentences."

Input: All timeline stages with title, description, timestamp, tactic/technique names, user, asset, IOC, SIEM URL

Output: Markdown-formatted threat report

AI Function 3: Overall Run Evaluation

When: After scoring completes (async) Purpose: Generates manager-style overall performance feedback

System prompt (summarized):

"You are a Senior Threat Hunter. Provide overall feedback on the user's performance based on individual stage evaluations. 2-3 sentences focusing on improvement areas. Address user as 'Junior Threat Hunter'."

Input: All stage evaluations (AI-generated summaries from Function 1)

Output: 2-3 sentence overall feedback

AI Configuration

const openAiOptions = {
  temperature: 0.7,
  top_p: 0.95,
  n: 1,
  stream: false,
  max_tokens: 1000,
  presence_penalty: 0,
  frequency_penalty: 0,
};

All three functions use structured output (Zod schema validation) via OpenAI's chatGptCompletionAPI, which includes:


9. Scoring & Evaluation

Scoring Categories (per stage)

CategoryEvaluation MethodPoints Source
TimestampIs stage.timestamp within [timelineStartTime, timelineEndTime]?cmsStage.timelinePoints
TacticExact match: stage.tactic === cmsStage.tacticcmsStage.tacticPoints
TechniqueExact match: stage.technique === cmsStage.techniquecmsStage.techniquePoints
UserExact match: stage.user === cmsStage.expectedUsercmsStage.userPoints
AssetExact match: stage.asset === cmsStage.expectedAssetcmsStage.assetPoints
IOCSubstring match (case-insensitive) per IOC entrycmsStage.iocs[].points
DescriptionAI-evaluated against CMS criteriaUp to cmsStage.adversaryStepDescriptionPoints

IOC Matching Detail

const calculateIocPoints = (stageIoc: string, cmsIocs: Array<{ value: string; points: number }>) =>
  cmsIocs.reduce((acc, ioc) => {
    const normalizedStageIoc = stageIoc.replace(/\\/g, '');
    const normalizedValue = ioc.value.replace(/\\/g, '');
    if (normalizedStageIoc.toLowerCase().includes(normalizedValue.toLowerCase()))
      acc.iocPointsAwarded += ioc.points;
    acc.totalIocPoints += ioc.points;
    return acc;
  }, { iocPointsAwarded: 0, totalIocPoints: 0 });

IOCs are matched via case-insensitive substring inclusion -- the user's IOC field must contain the expected IOC value somewhere in the text.

Final Score Calculation

totalScenarioPoints = sum(all CMS stage points) + sum(all IOC points) + hypothesisOutcomePoints
totalAwarded = sum(all awarded stage points) + hypothesisOutcomePointsAwarded
success = (totalAwarded / totalScenarioPoints) * 100 >= 80

Report Breakdown Generation

After scoring, the system generates detailed breakdowns stored in run.report:

BreakdownWhat it shows
techniquesAndTactics% of tactics/techniques correctly identified, per-stage detail
compromisedAssets% of assets identified, list with identified flag
iocs% of IOCs identified, split into network vs host categories

10. Frontend User Flow


11. API Endpoints Summary

Run Management

MethodEndpointDescription
POST/threat-hunting/runsCreate new run
GET/threat-hunting/runs/activeGet active run data
POST/threat-hunting/runs/startStart investigation (sets flag)
POST/threat-hunting/runs/pausePause active run
POST/threat-hunting/runs/resumeResume paused run
POST/threat-hunting/runs/terminateTerminate run
POST/threat-hunting/runs/hypothesis-outcomeSet hypothesis classification
POST/threat-hunting/runs/threat-reportGenerate AI threat report
POST/threat-hunting/runs/submit-findingsSubmit & evaluate (triggers scoring + AI)
GET/threat-hunting/runs/summaryGet run summary
GET/threat-hunting/runs/summary/overall-evaluationGet AI overall evaluation
GET/threat-hunting/runs/shared-linksGet public sharing links
PATCH/threat-hunting/runs/notesUpdate investigation notes

Timeline

MethodEndpointDescription
GET/threat-hunting/timelineGet all stages
GET/threat-hunting/timeline/stageGet single stage
POST/threat-hunting/timeline/stageCreate stage
PATCH/threat-hunting/timeline/stageUpdate stage
DELETE/threat-hunting/timeline/stageDelete stage
POST/threat-hunting/timeline/stage/reorderReorder stages

Content & Reference

MethodEndpointDescription
GET/threat-hunting/content/scenariosList scenarios
GET/threat-hunting/content/scenarioScenario details
GET/threat-hunting/content/tacticsMITRE ATT&CK tactics
GET/threat-hunting/content/techniquesMITRE ATT&CK techniques

VMs

MethodEndpointDescription
POST/threat-hunting/vms/extendExtend VM by 1 hour
POST/threat-hunting/vms/refresh-urlRefresh Guacamole URL

Company / Management Dashboard

MethodEndpointDescription
POST/companies/threat-hunting/assignmentCreate assignment
GET/companies/threat-hunting/statsCompany stats
GET/companies/threat-hunting/usersUsers with runs
GET/companies/threat-hunting/runsUser runs
GET/companies/threat-hunting/average-statsAverage stats
GET/companies/threat-hunting/success-rate-progressionSuccess rate over time
GET/companies/threat-hunting/tactic-and-technique-accuracy-rateMITRE accuracy

12. SOC-Sim vs Threat Hunting: Architecture Comparison

DimensionSOC SimulatorThreat Hunting
User RoleReactive SOC AnalystProactive Threat Hunter
Core TaskTriage incoming alertsReconstruct attack chain
LogsIngested over time via EventBridgePre-loaded on VM
AlertsSystem-generated, timed releaseNone -- user finds evidence
Data StructureFlat alert listOrdered timeline stages
MITRE ATT&CKAlert types onlyFull tactic + technique per stage
AI UsageWriteup evaluation, overall evalDescription eval, threat report, overall eval
AI ModelGPT-4oGPT-4o
Pass ThresholdAll TPs resolved correctly>=80% of total points
ScoringClassification + escalation + evaluation7 categories + hypothesis
MultiplayerSupportedNot supported
CertificationIntegratedNot integrated
Cost CenterSOC_SIMTHREAT_HUNTER
VM InfraOwn deployment codeReuses SOC-Sim deployment code
WebSocketReal-time alert eventsNot used

13. Feature Flags (GrowthBook)

FlagTypePurpose
soc-sim-vms-deployBooleanShared with SOC-Sim; enables real VM deployment
vms-on-new-browserBooleanOpen VMs in new browser tab vs iframe
threat-hunting-siem-tool-modalBooleanSIEM tool selection UI
guac-common-jsBooleanGuacamole client implementation toggle
guacamole-v2BooleanGuacamole V2 infrastructure
cell-feature-accessBooleanCell-based feature gating

14. Infrastructure Summary

Key characteristics: