leukquant 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. leukquant-0.1.0/PKG-INFO +99 -0
  2. leukquant-0.1.0/README.md +72 -0
  3. leukquant-0.1.0/leukquant.egg-info/PKG-INFO +99 -0
  4. leukquant-0.1.0/leukquant.egg-info/SOURCES.txt +34 -0
  5. leukquant-0.1.0/leukquant.egg-info/dependency_links.txt +1 -0
  6. leukquant-0.1.0/leukquant.egg-info/entry_points.txt +2 -0
  7. leukquant-0.1.0/leukquant.egg-info/requires.txt +24 -0
  8. leukquant-0.1.0/leukquant.egg-info/top_level.txt +1 -0
  9. leukquant-0.1.0/pyproject.toml +39 -0
  10. leukquant-0.1.0/setup.cfg +4 -0
  11. leukquant-0.1.0/src/__init__.py +0 -0
  12. leukquant-0.1.0/src/behavior/__init__.py +0 -0
  13. leukquant-0.1.0/src/behavior/monitors.py +100 -0
  14. leukquant-0.1.0/src/behavior/profiler.py +99 -0
  15. leukquant-0.1.0/src/cli/__init__.py +0 -0
  16. leukquant-0.1.0/src/cli/main.py +616 -0
  17. leukquant-0.1.0/src/config.py +91 -0
  18. leukquant-0.1.0/src/crypto/__init__.py +0 -0
  19. leukquant-0.1.0/src/crypto/key_manager.py +130 -0
  20. leukquant-0.1.0/src/crypto/pq_encrypt.py +171 -0
  21. leukquant-0.1.0/src/db/__init__.py +0 -0
  22. leukquant-0.1.0/src/db/database.py +248 -0
  23. leukquant-0.1.0/src/offline/__init__.py +0 -0
  24. leukquant-0.1.0/src/offline/sync.py +165 -0
  25. leukquant-0.1.0/src/paths.py +70 -0
  26. leukquant-0.1.0/src/quarantine/__init__.py +0 -0
  27. leukquant-0.1.0/src/quarantine/manager.py +111 -0
  28. leukquant-0.1.0/src/scanner/__init__.py +0 -0
  29. leukquant-0.1.0/src/scanner/dataset_loaders.py +414 -0
  30. leukquant-0.1.0/src/scanner/extract.py +180 -0
  31. leukquant-0.1.0/src/scanner/scan.py +182 -0
  32. leukquant-0.1.0/src/scanner/train.py +340 -0
  33. leukquant-0.1.0/tests/test_behavior.py +112 -0
  34. leukquant-0.1.0/tests/test_crypto.py +148 -0
  35. leukquant-0.1.0/tests/test_quarantine.py +158 -0
  36. leukquant-0.1.0/tests/test_scanner.py +97 -0
@@ -0,0 +1,99 @@
1
+ Metadata-Version: 2.4
2
+ Name: leukquant
3
+ Version: 0.1.0
4
+ Summary: Fully Local, Decentralized Threat Defense
5
+ Requires-Python: >=3.9
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: onnxruntime>=1.16.0
8
+ Requires-Dist: numpy>=1.24.0
9
+ Requires-Dist: psutil>=5.9.0
10
+ Requires-Dist: cryptography>=41.0.0
11
+ Requires-Dist: pyyaml>=6.0.1
12
+ Requires-Dist: click>=8.1.7
13
+ Requires-Dist: rich>=13.7.0
14
+ Requires-Dist: watchdog>=3.0.0
15
+ Requires-Dist: scikit-learn>=1.3.2
16
+ Requires-Dist: skl2onnx>=1.16.0
17
+ Provides-Extra: pqc
18
+ Requires-Dist: liboqs-python>=0.8.0; extra == "pqc"
19
+ Provides-Extra: ember
20
+ Requires-Dist: ember; extra == "ember"
21
+ Requires-Dist: lief; extra == "ember"
22
+ Provides-Extra: kaggle
23
+ Requires-Dist: kaggle; extra == "kaggle"
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
26
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
27
+
28
+ # Leukquant — Fully Local, Decentralized Threat Defense
29
+
30
+ > **Zero cloud. Zero trust in corporations. Zero single point of failure.**
31
+
32
+ ## Overview
33
+
34
+ Leukquant is a fully local, decentralized threat defense system. It uses on-device AI for malware classification, a behavior profiler for anomaly detection, and post-quantum cryptography for file encryption.
35
+
36
+ *Note: The blockchain threat ledger is currently disabled in this version. We use datasets like EMBER, VirusShare, and Kaggle Malware datasets for local AI scanning.*
37
+
38
+ ## Features
39
+
40
+ 1. **Local AI Scanning**: On-device malware classification using ONNX models. No telemetry. No cloud calls.
41
+ 2. **Behavior Profiler**: Learns normal patterns over a 14-day baseline and flags deviations.
42
+ 3. **Post-Quantum Crypto Vault**: Encrypts files with NIST PQC standards (ML-KEM, ML-DSA, SLH-DSA).
43
+ 4. **Offline Mode**: Built for machines that never touch the internet.
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install -r requirements.txt
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ ### 1. Local AI Scanning
54
+
55
+ Scan a file using the local AI model:
56
+
57
+ ```bash
58
+ python src/cli/main.py scan --file /path/to/file
59
+ ```
60
+
61
+ ### 2. Behavior Profiler
62
+
63
+ Start monitoring system behavior:
64
+
65
+ ```bash
66
+ python src/cli/main.py monitor
67
+ ```
68
+
69
+ ### 3. Post-Quantum File Encryption
70
+
71
+ Encrypt a file:
72
+
73
+ ```bash
74
+ python src/cli/main.py encrypt --file secret.pdf --algo ml-kem-1024 --sign ml-dsa-87
75
+ ```
76
+
77
+ Decrypt a file:
78
+
79
+ ```bash
80
+ python src/cli/main.py decrypt --file secret.pdf.sqe --key ~/.Leukquant/private.key
81
+ ```
82
+
83
+ ## File Structure
84
+
85
+ - `models/`: Contains the ONNX/GGML models for malware detection.
86
+ - `db/`: Local SQLite databases for threat signatures and behavior baselines.
87
+ - `keys/`: Post-quantum cryptographic keys.
88
+ - `config/`: Configuration files (e.g., `Leukquant.yml`).
89
+ - `src/`: Source code for the scanner, behavior profiler, crypto vault, and CLI.
90
+ - `logs/`: Local logs for anomalies.
91
+
92
+ ## Datasets for Training
93
+
94
+ To train the local AI model, you can use the following datasets:
95
+ - **EMBER**: Open PE malware dataset.
96
+ - **VirusShare**: Repository of malware samples.
97
+ - **Kaggle Malware Datasets**: Various datasets available on Kaggle.
98
+
99
+ *Note: The pre-trained model should be placed in `models/malware_detector.onnx`.*
@@ -0,0 +1,72 @@
1
+ # Leukquant — Fully Local, Decentralized Threat Defense
2
+
3
+ > **Zero cloud. Zero trust in corporations. Zero single point of failure.**
4
+
5
+ ## Overview
6
+
7
+ Leukquant is a fully local, decentralized threat defense system. It uses on-device AI for malware classification, a behavior profiler for anomaly detection, and post-quantum cryptography for file encryption.
8
+
9
+ *Note: The blockchain threat ledger is currently disabled in this version. We use datasets like EMBER, VirusShare, and Kaggle Malware datasets for local AI scanning.*
10
+
11
+ ## Features
12
+
13
+ 1. **Local AI Scanning**: On-device malware classification using ONNX models. No telemetry. No cloud calls.
14
+ 2. **Behavior Profiler**: Learns normal patterns over a 14-day baseline and flags deviations.
15
+ 3. **Post-Quantum Crypto Vault**: Encrypts files with NIST PQC standards (ML-KEM, ML-DSA, SLH-DSA).
16
+ 4. **Offline Mode**: Built for machines that never touch the internet.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install -r requirements.txt
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### 1. Local AI Scanning
27
+
28
+ Scan a file using the local AI model:
29
+
30
+ ```bash
31
+ python src/cli/main.py scan --file /path/to/file
32
+ ```
33
+
34
+ ### 2. Behavior Profiler
35
+
36
+ Start monitoring system behavior:
37
+
38
+ ```bash
39
+ python src/cli/main.py monitor
40
+ ```
41
+
42
+ ### 3. Post-Quantum File Encryption
43
+
44
+ Encrypt a file:
45
+
46
+ ```bash
47
+ python src/cli/main.py encrypt --file secret.pdf --algo ml-kem-1024 --sign ml-dsa-87
48
+ ```
49
+
50
+ Decrypt a file:
51
+
52
+ ```bash
53
+ python src/cli/main.py decrypt --file secret.pdf.sqe --key ~/.Leukquant/private.key
54
+ ```
55
+
56
+ ## File Structure
57
+
58
+ - `models/`: Contains the ONNX/GGML models for malware detection.
59
+ - `db/`: Local SQLite databases for threat signatures and behavior baselines.
60
+ - `keys/`: Post-quantum cryptographic keys.
61
+ - `config/`: Configuration files (e.g., `Leukquant.yml`).
62
+ - `src/`: Source code for the scanner, behavior profiler, crypto vault, and CLI.
63
+ - `logs/`: Local logs for anomalies.
64
+
65
+ ## Datasets for Training
66
+
67
+ To train the local AI model, you can use the following datasets:
68
+ - **EMBER**: Open PE malware dataset.
69
+ - **VirusShare**: Repository of malware samples.
70
+ - **Kaggle Malware Datasets**: Various datasets available on Kaggle.
71
+
72
+ *Note: The pre-trained model should be placed in `models/malware_detector.onnx`.*
@@ -0,0 +1,99 @@
1
+ Metadata-Version: 2.4
2
+ Name: leukquant
3
+ Version: 0.1.0
4
+ Summary: Fully Local, Decentralized Threat Defense
5
+ Requires-Python: >=3.9
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: onnxruntime>=1.16.0
8
+ Requires-Dist: numpy>=1.24.0
9
+ Requires-Dist: psutil>=5.9.0
10
+ Requires-Dist: cryptography>=41.0.0
11
+ Requires-Dist: pyyaml>=6.0.1
12
+ Requires-Dist: click>=8.1.7
13
+ Requires-Dist: rich>=13.7.0
14
+ Requires-Dist: watchdog>=3.0.0
15
+ Requires-Dist: scikit-learn>=1.3.2
16
+ Requires-Dist: skl2onnx>=1.16.0
17
+ Provides-Extra: pqc
18
+ Requires-Dist: liboqs-python>=0.8.0; extra == "pqc"
19
+ Provides-Extra: ember
20
+ Requires-Dist: ember; extra == "ember"
21
+ Requires-Dist: lief; extra == "ember"
22
+ Provides-Extra: kaggle
23
+ Requires-Dist: kaggle; extra == "kaggle"
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
26
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
27
+
28
+ # Leukquant — Fully Local, Decentralized Threat Defense
29
+
30
+ > **Zero cloud. Zero trust in corporations. Zero single point of failure.**
31
+
32
+ ## Overview
33
+
34
+ Leukquant is a fully local, decentralized threat defense system. It uses on-device AI for malware classification, a behavior profiler for anomaly detection, and post-quantum cryptography for file encryption.
35
+
36
+ *Note: The blockchain threat ledger is currently disabled in this version. We use datasets like EMBER, VirusShare, and Kaggle Malware datasets for local AI scanning.*
37
+
38
+ ## Features
39
+
40
+ 1. **Local AI Scanning**: On-device malware classification using ONNX models. No telemetry. No cloud calls.
41
+ 2. **Behavior Profiler**: Learns normal patterns over a 14-day baseline and flags deviations.
42
+ 3. **Post-Quantum Crypto Vault**: Encrypts files with NIST PQC standards (ML-KEM, ML-DSA, SLH-DSA).
43
+ 4. **Offline Mode**: Built for machines that never touch the internet.
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install -r requirements.txt
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ ### 1. Local AI Scanning
54
+
55
+ Scan a file using the local AI model:
56
+
57
+ ```bash
58
+ python src/cli/main.py scan --file /path/to/file
59
+ ```
60
+
61
+ ### 2. Behavior Profiler
62
+
63
+ Start monitoring system behavior:
64
+
65
+ ```bash
66
+ python src/cli/main.py monitor
67
+ ```
68
+
69
+ ### 3. Post-Quantum File Encryption
70
+
71
+ Encrypt a file:
72
+
73
+ ```bash
74
+ python src/cli/main.py encrypt --file secret.pdf --algo ml-kem-1024 --sign ml-dsa-87
75
+ ```
76
+
77
+ Decrypt a file:
78
+
79
+ ```bash
80
+ python src/cli/main.py decrypt --file secret.pdf.sqe --key ~/.Leukquant/private.key
81
+ ```
82
+
83
+ ## File Structure
84
+
85
+ - `models/`: Contains the ONNX/GGML models for malware detection.
86
+ - `db/`: Local SQLite databases for threat signatures and behavior baselines.
87
+ - `keys/`: Post-quantum cryptographic keys.
88
+ - `config/`: Configuration files (e.g., `Leukquant.yml`).
89
+ - `src/`: Source code for the scanner, behavior profiler, crypto vault, and CLI.
90
+ - `logs/`: Local logs for anomalies.
91
+
92
+ ## Datasets for Training
93
+
94
+ To train the local AI model, you can use the following datasets:
95
+ - **EMBER**: Open PE malware dataset.
96
+ - **VirusShare**: Repository of malware samples.
97
+ - **Kaggle Malware Datasets**: Various datasets available on Kaggle.
98
+
99
+ *Note: The pre-trained model should be placed in `models/malware_detector.onnx`.*
@@ -0,0 +1,34 @@
1
+ README.md
2
+ pyproject.toml
3
+ leukquant.egg-info/PKG-INFO
4
+ leukquant.egg-info/SOURCES.txt
5
+ leukquant.egg-info/dependency_links.txt
6
+ leukquant.egg-info/entry_points.txt
7
+ leukquant.egg-info/requires.txt
8
+ leukquant.egg-info/top_level.txt
9
+ src/__init__.py
10
+ src/config.py
11
+ src/paths.py
12
+ src/behavior/__init__.py
13
+ src/behavior/monitors.py
14
+ src/behavior/profiler.py
15
+ src/cli/__init__.py
16
+ src/cli/main.py
17
+ src/crypto/__init__.py
18
+ src/crypto/key_manager.py
19
+ src/crypto/pq_encrypt.py
20
+ src/db/__init__.py
21
+ src/db/database.py
22
+ src/offline/__init__.py
23
+ src/offline/sync.py
24
+ src/quarantine/__init__.py
25
+ src/quarantine/manager.py
26
+ src/scanner/__init__.py
27
+ src/scanner/dataset_loaders.py
28
+ src/scanner/extract.py
29
+ src/scanner/scan.py
30
+ src/scanner/train.py
31
+ tests/test_behavior.py
32
+ tests/test_crypto.py
33
+ tests/test_quarantine.py
34
+ tests/test_scanner.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ leukquant = src.cli.main:cli
@@ -0,0 +1,24 @@
1
+ onnxruntime>=1.16.0
2
+ numpy>=1.24.0
3
+ psutil>=5.9.0
4
+ cryptography>=41.0.0
5
+ pyyaml>=6.0.1
6
+ click>=8.1.7
7
+ rich>=13.7.0
8
+ watchdog>=3.0.0
9
+ scikit-learn>=1.3.2
10
+ skl2onnx>=1.16.0
11
+
12
+ [dev]
13
+ pytest>=7.4.0
14
+ pytest-cov>=4.1.0
15
+
16
+ [ember]
17
+ ember
18
+ lief
19
+
20
+ [kaggle]
21
+ kaggle
22
+
23
+ [pqc]
24
+ liboqs-python>=0.8.0
@@ -0,0 +1 @@
1
+ src
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools>=65", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "leukquant"
7
+ version = "0.1.0"
8
+ description = "Fully Local, Decentralized Threat Defense"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ dependencies = [
12
+ "onnxruntime>=1.16.0",
13
+ "numpy>=1.24.0",
14
+ "psutil>=5.9.0",
15
+ "cryptography>=41.0.0",
16
+ "pyyaml>=6.0.1",
17
+ "click>=8.1.7",
18
+ "rich>=13.7.0",
19
+ "watchdog>=3.0.0",
20
+ "scikit-learn>=1.3.2",
21
+ "skl2onnx>=1.16.0",
22
+ ]
23
+
24
+ [project.optional-dependencies]
25
+ pqc = ["liboqs-python>=0.8.0"]
26
+ ember = ["ember", "lief"]
27
+ kaggle = ["kaggle"]
28
+ dev = ["pytest>=7.4.0", "pytest-cov>=4.1.0"]
29
+
30
+ [project.scripts]
31
+ leukquant = "src.cli.main:cli"
32
+
33
+ [tool.setuptools.packages.find]
34
+ where = ["."]
35
+ include = ["src*"]
36
+
37
+ [tool.pytest.ini_options]
38
+ testpaths = ["tests"]
39
+ python_files = ["test_*.py"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
File without changes
@@ -0,0 +1,100 @@
1
+ import threading
2
+ import time
3
+ import logging
4
+ from collections import deque
5
+ from watchdog.observers import Observer
6
+ from watchdog.events import FileSystemEventHandler
7
+ import psutil
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class FileEventTracker(FileSystemEventHandler):
13
+ """Tracks file system create/modify events using a rolling time window."""
14
+
15
+ def __init__(self, window_seconds: int = 60):
16
+ super().__init__()
17
+ self.window_seconds = window_seconds
18
+ self._events: deque = deque()
19
+ self._lock = threading.Lock()
20
+
21
+ def on_created(self, event):
22
+ if not event.is_directory:
23
+ self._record("created", event.src_path)
24
+
25
+ def on_modified(self, event):
26
+ if not event.is_directory:
27
+ self._record("modified", event.src_path)
28
+
29
+ def on_deleted(self, event):
30
+ if not event.is_directory:
31
+ self._record("deleted", event.src_path)
32
+
33
+ def _record(self, kind: str, path: str):
34
+ now = time.monotonic()
35
+ with self._lock:
36
+ self._events.append((now, kind, path))
37
+ cutoff = now - self.window_seconds
38
+ while self._events and self._events[0][0] < cutoff:
39
+ self._events.popleft()
40
+
41
+ def get_rate(self) -> float:
42
+ """Return events-per-minute in the current window."""
43
+ now = time.monotonic()
44
+ cutoff = now - self.window_seconds
45
+ with self._lock:
46
+ recent = sum(1 for ts, _, _ in self._events if ts >= cutoff)
47
+ # Normalize to events/minute
48
+ return (recent / self.window_seconds) * 60
49
+
50
+
51
+ class SystemMonitor:
52
+ """
53
+ Aggregates real-time system metrics:
54
+ - File system event rate (watchdog)
55
+ - Active process count (psutil)
56
+ - Network connection count (psutil)
57
+ - Memory utilization % (psutil)
58
+ """
59
+
60
+ def __init__(self, watch_path: str = "/tmp", window_seconds: int = 60):
61
+ self.watch_path = watch_path
62
+ self.file_tracker = FileEventTracker(window_seconds)
63
+ self._observer = Observer()
64
+ self._observer.schedule(self.file_tracker, watch_path, recursive=True)
65
+ self._running = False
66
+
67
+ def start(self):
68
+ if not self._running:
69
+ try:
70
+ self._observer.start()
71
+ self._running = True
72
+ logger.info(f"SystemMonitor started. Watching: {self.watch_path}")
73
+ except Exception as e:
74
+ logger.warning(f"Could not start file watcher: {e}")
75
+
76
+ def stop(self):
77
+ if self._running:
78
+ self._observer.stop()
79
+ self._observer.join()
80
+ self._running = False
81
+ logger.info("SystemMonitor stopped.")
82
+
83
+ def get_snapshot(self) -> dict:
84
+ try:
85
+ mem = psutil.virtual_memory()
86
+ net = psutil.net_connections(kind="inet")
87
+ return {
88
+ "process_spawn_rate": len(psutil.pids()),
89
+ "file_write_rate": self.file_tracker.get_rate(),
90
+ "network_socket_count": len(net),
91
+ "memory_alloc_spikes": mem.percent,
92
+ }
93
+ except Exception as e:
94
+ logger.warning(f"SystemMonitor snapshot error: {e}")
95
+ return {
96
+ "process_spawn_rate": 0,
97
+ "file_write_rate": 0.0,
98
+ "network_socket_count": 0,
99
+ "memory_alloc_spikes": 0.0,
100
+ }
@@ -0,0 +1,99 @@
1
+ import time
2
+ import numpy as np
3
+ import logging
4
+ import os
5
+ from datetime import datetime
6
+ from src.db.database import DatabaseManager
7
+ from src.behavior.monitors import SystemMonitor
8
+ from src.config import Config
9
+ from src.paths import app_path
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ MIN_BASELINE_SAMPLES = 10
14
+
15
+
16
+ class BehaviorProfiler:
17
+ """
18
+ Collects system metrics every `poll_interval` seconds, stores them in SQLite,
19
+ and computes a Z-score anomaly metric against the rolling `baseline_days`-day window.
20
+
21
+ A(t) = (1/N) * Σ |x_i(t) − μ_i| / σ_i
22
+
23
+ Scores above `alert_threshold` are logged; scores above `quarantine_threshold`
24
+ are also written as anomaly events for downstream quarantine decisions.
25
+ """
26
+
27
+ PID_FILE = app_path("logs", "monitor.pid")
28
+
29
+ def __init__(self, poll_interval: int = 60):
30
+ cfg = Config.get()
31
+ self.baseline_days: int = cfg.get_value("behavior", "baseline_period_days", default=14)
32
+ self.alert_threshold: float = cfg.get_value("behavior", "alert_threshold", default=3.5)
33
+ self.quarantine_threshold: float = cfg.get_value("behavior", "quarantine_threshold", default=5.0)
34
+ self.poll_interval = poll_interval
35
+ self.db = DatabaseManager()
36
+ self.monitor = SystemMonitor()
37
+
38
+ # ─── metric helpers ───────────────────────────────────────────────────────
39
+
40
+ def _collect(self) -> dict:
41
+ snap = self.monitor.get_snapshot()
42
+ snap["timestamp"] = datetime.now()
43
+ return snap
44
+
45
+ def calculate_anomaly_score(self, metrics: dict) -> float:
46
+ rows = self.db.get_baseline_metrics(days=self.baseline_days)
47
+ if len(rows) < MIN_BASELINE_SAMPLES:
48
+ logger.debug(f"Only {len(rows)} samples in baseline — skipping anomaly scoring.")
49
+ return 0.0
50
+
51
+ baseline = np.array(rows, dtype=float)
52
+ means = np.mean(baseline, axis=0)
53
+ stds = np.std(baseline, axis=0)
54
+ stds[stds == 0] = 1e-6
55
+
56
+ current = np.array([
57
+ metrics["process_spawn_rate"],
58
+ metrics["file_write_rate"],
59
+ metrics["network_socket_count"],
60
+ metrics["memory_alloc_spikes"],
61
+ ], dtype=float)
62
+
63
+ z_scores = np.abs(current - means) / stds
64
+ return float(np.mean(z_scores))
65
+
66
+ # ─── main loop ────────────────────────────────────────────────────────────
67
+
68
+ def monitor_loop(self):
69
+ os.makedirs(app_path("logs"), exist_ok=True)
70
+ with open(self.PID_FILE, "w") as f:
71
+ f.write(str(os.getpid()))
72
+
73
+ self.monitor.start()
74
+ logger.info(f"Behavior monitor started (PID {os.getpid()}, interval {self.poll_interval}s).")
75
+
76
+ try:
77
+ while True:
78
+ metrics = self._collect()
79
+ self.db.insert_metrics(metrics)
80
+ score = self.calculate_anomaly_score(metrics)
81
+
82
+ if score > self.alert_threshold:
83
+ details = (
84
+ f"score={score:.3f} | "
85
+ f"procs={metrics['process_spawn_rate']} | "
86
+ f"files/min={metrics['file_write_rate']:.1f} | "
87
+ f"sockets={metrics['network_socket_count']} | "
88
+ f"mem%={metrics['memory_alloc_spikes']:.1f}"
89
+ )
90
+ level = "CRITICAL" if score > self.quarantine_threshold else "WARNING"
91
+ logger.warning(f"[{level}] Anomaly score {score:.3f} — {details}")
92
+ self.db.log_anomaly(score, details)
93
+
94
+ time.sleep(self.poll_interval)
95
+ finally:
96
+ self.monitor.stop()
97
+ if os.path.exists(self.PID_FILE):
98
+ os.remove(self.PID_FILE)
99
+ logger.info("Behavior monitor stopped.")
File without changes