nano SIEM
Agents & MCPInvestigator

Hunt

Proactive hunting with the hunt_entity and hunt_campaign prompts, search_sql, prevalence, and MITRE coverage

Hunt

Hunting is looking for attacker activity before a detection fires. nano-investigator provides two hunting prompts, two search tools, and a set of prevalence and MITRE tools to scope and confirm what you find. This page covers each, and how a hunt that finds a coverage gap becomes a detection.

The hunting prompts

Two prompts structure a hunt into phases so you assess before you go deeper.

hunt_entity takes entity and entity_type (required) and time_range (optional, default -24h). It runs in three phases:

  1. Context. get_entity_context, lookup_ip, get_prevalence, and a search run in parallel (IOC matches surface on the search results' ioc_* columns).
  2. Assessment. The findings are presented before the hunt continues, so you can redirect.
  3. Type-specific deep dive. A branch per entity type (ip, user, host, hash, domain) with nPL templates tuned to that type.

hunt_campaign takes description (required) and time_range (optional, default -7d). It plans a hunt from a hypothesis:

  1. Plan. get_mitre_technique plus get_source_types, then 3 to 5 candidate queries.
  2. Build and run. Execute the queries with refinement between passes.
  3. Enrich hits. get_prevalence, the ioc_* columns, and related alerts and cases on whatever the queries surfaced.
  4. Report. A hunt report. Rule creation is deferred to nanodac; the prompt does not write detections.
> hunt for lateral movement in the last 7 days

Running hunt_campaign (description="lateral movement",
  time_range="-7d")...

Plan phase:
  get_mitre_technique(T1021): Remote Services — RDP, SMB, WinRM,
    SSH sub-techniques.
  get_source_types: windows_security, windows_sysmon, zeek_conn
    available.
  Drafted 4 queries:
    1. Type-3 logons fanning out from one source host
    2. SMB writes to ADMIN$ / C$ across hosts
    3. WinRM (5985/5986) sessions between workstations
    4. New service installs (7045) on multiple hosts, same name

Run phase (search_sql, window -7d):
  Q1 returned 1 standout: WIN-FS01 → 14 distinct hosts via
     type-3 logon, all in 40 minutes, service account svc-backup.
  Q2–Q4: nothing notable.

Enrich phase:
  get_prevalence not applicable (host fan-out, not an artifact).
  Related alerts on WIN-FS01: the credential-dumping alert #1180.
  Related cases: C-204 (already open on WIN-FS01).

Report: Probable lateral movement from WIN-FS01 using svc-backup,
14 hosts in 40 min, correlates with open case C-204. No detection
currently covers "single source, many type-3 logons in a short
window" — candidate for a new rule. Want this added to C-204?

Searching: nPL and SQL

Two tools run queries. Both hit the search service.

search runs an nPL (piped, Splunk-style) query. It is good for quick | stats and | timechart work. Params: query and start_time (required); end_time, limit (default 100), source_type.

search_sql is the primary search tool. It runs a read-only ClickHouse SELECT. Params: sql (required); start_time, end_time, limit (optional, default window is the last 24h).

> sql: count distinct destination hosts per source host for
  type-3 logons in the last 7 days, top 10

Calling search_sql (sql="SELECT src_host,
  count(DISTINCT dest_host) AS hosts
  FROM events
  WHERE timestamp >= now() - INTERVAL 7 DAY
    AND event_type = 'logon' AND logon_type = 3
  GROUP BY src_host ORDER BY hosts DESC LIMIT 10")...

  src_host    hosts
  WIN-FS01    14
  WIN-DC01     6
  WIN-JUMP1    4
  ...

Before you write SQL or nPL, two reference tools help: get_schema returns the UDM column inventory (call it once per session before SQL work), and explain_query compiles an nPL query to SQL without running it. get_field_values returns the top values for a field in a query scope, which is how you find the right filter value quickly.

Prevalence and rarity

Rarity is the core hunting signal: artifacts seen on few hosts, or seen for the first time recently, are worth a look.

  • get_prevalence answers how common one artifact is. Params: type (hash or domain only; IP errors) and value. Returns host count, occurrences, first and last seen, and is_rare.
  • get_rare_artifacts lists artifacts seen on few hosts. Optional params: type (hash_md5/hash_sha256/domain/ip_address), window, limit (default 50), offset.
  • get_new_artifacts lists first-seen-recently artifacts. Optional params: type, since, limit (default 50), offset.
> show me rare SHA256 hashes seen this week

Calling get_rare_artifacts (type=hash_sha256, window=7d)...

  hash a3f1...   1 host    first seen 2d ago
  hash 9c20...   2 hosts   first seen 5d ago
  ...

> how common is a3f1... ?

Calling get_prevalence (type=hash, value=a3f1...)...
  host_count=1, occurrences=3, first_seen=2d ago, is_rare=true

MITRE coverage and sources

Two MITRE tools tie a hunt to ATT&CK, and one lists your log sources:

  • get_mitre_technique returns ATT&CK data, optionally filtered to one technique by id (for example T1071).
  • get_mitre_coverage returns the coverage and gaps of the detection library, which is how you find techniques with no detection behind them.
  • get_source_types lists the available log source types. Call it before using a source_type filter so you use a real value.

A get_mitre_coverage gap is a strong reason to hunt: if a technique has no detection, an attacker using it produces no alert, and the hunt is your only way to see it.

From hunt to detection

A hunt that consistently surfaces real activity, or one that fills a get_mitre_coverage gap, should become a scheduled detection. nano-investigator is read-only for detections: it does not write rules. Rule authoring lives in nanodac.

Confirm the pattern is real and repeatable. Use get_prevalence, related alerts, and related cases to make sure the hunt query is finding attacker behavior and not a noisy baseline.

Capture the query. Save it with save_search so the exact nPL or SQL is not lost, and link it from the relevant case or notebook.

Hand it to nanodac. Take the working query into the detection-as-code workflow to draft, validate, and ship it as a scheduled rule. See Authoring detections.

> the WIN-FS01 fan-out query is a real gap. save it and tell me
  how to turn it into a detection.

Calling save_search (name="lateral-movement-type3-fanout",
  query="SELECT src_host, count(DISTINCT dest_host) ...",
  query_mode="sql", visibility="group")...
  → saved

This is a detection gap (no rule covers single-source type-3
fan-out). nano-investigator does not author rules. Open the
saved query in nanodac and run the detection workflow:
draft → validate → test → PR → sync. See
/agents/detection-as-code/detections.

What's next

On this page

On this page