<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
<!-- NERF is a trademark of defconxt. -->
---
name: performing-endpoint-baseline-monitoring
description: >-
  Establish and monitor endpoint baselines for processes, services, network
  connections, scheduled tasks, and file integrity. Detect deviations that
  indicate compromise, persistence mechanisms, or unauthorized changes
  through continuous comparison against known-good state.
domain: cybersecurity
subdomain: endpoint-security
tags:
  - baseline
  - monitoring
  - file-integrity
  - process-monitoring
  - change-detection
  - drift
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1543", "T1053", "T1547"]
  tools: [python3, powershell, osquery, auditd]
---

# Performing Endpoint Baseline Monitoring

## Overview

Endpoint baselines capture the known-good state of processes, services,
network listeners, scheduled tasks, and critical files. Continuous monitoring
detects deviations — new services, unauthorized scheduled tasks, unexpected
network connections, or file modifications — that indicate compromise or
configuration drift. Baseline comparison is foundational for both detection
and compliance.

## Prerequisites

| Requirement | Purpose |
|---|---|
| Baseline collection tool | Capture initial state (osquery, PowerShell) |
| File integrity monitoring | Detect changes to critical system files |
| Scheduled collection | Periodic re-baseline and comparison |
| SIEM integration | Alert on baseline deviations |

## Workflow

### Step 1: Capture Process Baseline

```powershell
# Capture running processes with hashes
Get-Process | Select-Object Name, Id, Path, StartTime |
  ForEach-Object {
    $hash = if ($_.Path) { (Get-FileHash $_.Path -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash } else { "N/A" }
    [PSCustomObject]@{
      Name = $_.Name; PID = $_.Id; Path = $_.Path
      StartTime = $_.StartTime; SHA256 = $hash
    }
  } | Export-Csv -Path "baseline_processes.csv" -NoTypeInformation

# Capture listening ports
Get-NetTCPConnection -State Listen |
  Select-Object LocalAddress, LocalPort, OwningProcess,
  @{N='ProcessName';E={(Get-Process -Id $_.OwningProcess).Name}} |
  Export-Csv -Path "baseline_listeners.csv" -NoTypeInformation
```

### Step 2: Capture Service Baseline

```powershell
# All services with binary paths
Get-WmiObject Win32_Service |
  Select-Object Name, DisplayName, State, StartMode, PathName |
  Export-Csv -Path "baseline_services.csv" -NoTypeInformation

# Scheduled tasks
Get-ScheduledTask |
  Select-Object TaskName, TaskPath, State,
  @{N='Action';E={$_.Actions.Execute}} |
  Export-Csv -Path "baseline_tasks.csv" -NoTypeInformation
```

### Step 3: Compare Against Baseline

```python
import csv
from typing import Any

def compare_baselines(baseline_path: str, current_path: str,
                      key_field: str) -> dict[str, Any]:
    """Compare two CSV baselines and report differences."""
    def load_csv(path: str) -> dict[str, dict[str, str]]:
        with open(path, newline="") as f:
            reader = csv.DictReader(f)
            return {row[key_field]: row for row in reader}

    baseline = load_csv(baseline_path)
    current = load_csv(current_path)

    new_items = [k for k in current if k not in baseline]
    removed_items = [k for k in baseline if k not in current]
    changed_items = []
    for k in set(baseline) & set(current):
        if baseline[k] != current[k]:
            changed_items.append({"key": k, "baseline": baseline[k], "current": current[k]})

    return {
        "new": new_items,
        "removed": removed_items,
        "changed": changed_items[:50],
        "total_new": len(new_items),
        "total_removed": len(removed_items),
        "total_changed": len(changed_items),
    }
```

### Step 4: File Integrity Monitoring

```bash
# Linux — generate file integrity baseline
find /etc /usr/bin /usr/sbin -type f -exec sha256sum {} \; > baseline_files.sha256

# Compare against baseline
sha256sum -c baseline_files.sha256 2>/dev/null | grep -v ": OK$"

# osquery — query for FIM changes
osqueryi "SELECT * FROM file_events WHERE target_path LIKE '/etc/%' AND time > (SELECT CAST(strftime('%s','now','-1 day') AS INTEGER));"
```

## Detection Opportunities

| Signal | Source | Description |
|--------|--------|-------------|
| New service registered | Service baseline diff | Service not in baseline |
| New scheduled task | Task baseline diff | Task created outside change window |
| File integrity change | FIM | Critical file hash mismatch |

```yaml
title: New Service Installed Outside Change Window
id: a7b8c9d0-e123-4567-fghi-890123456789
status: experimental
description: Detects new Windows services not present in the endpoint baseline
logsource:
  category: system
  product: windows
detection:
  selection:
    EventID: 7045
  filter_time:
    TimeCreated|endswith: "T02:00"
  condition: selection and not filter_time
falsepositives:
  - Legitimate software installations during maintenance
level: medium
tags:
  - attack.t1543.003
  - attack.persistence
```

## Verification

- [ ] Process baseline captured with executable hashes
- [ ] Service baseline includes binary paths and start modes
- [ ] Scheduled task baseline covers all task actions
- [ ] Network listener baseline documents expected ports
- [ ] File integrity baseline covers critical system directories
- [ ] Automated comparison runs daily and alerts on deviations

## References

- [MITRE T1543 — Create or Modify System Process](https://attack.mitre.org/techniques/T1543/)
- [CIS Controls v8 — Control 1: Inventory of Enterprise Assets](https://www.cisecurity.org/controls/v8)
- [osquery Documentation](https://osquery.readthedocs.io/)

---
v1.0 | Validated: 2026-03-18
