A production-grade Endpoint Detection & Response (EDR) toolkit for Linux
Kernel-level telemetry, behavioural analysis, and automated mitigation.
Introduction • Features • Installation • Documentation • Support
- Introduction - Overview and purpose
- Features - Core capabilities
- Architecture - System design and components
- Installation - Setup instructions
- Quick Start - Getting started guide
- Documentation - Additional resources
- Configuration - Customization options
- Development - Contributing and building
- Contributing - Contribution guidelines
- Support - Getting help
- License - License information
Zenith-Sentry is an advanced, host-based intrusion detection and forensic response toolkit designed specifically for the Linux ecosystem. Unlike traditional antivirus solutions that rely on static file signatures, Zenith-Sentry leverages Kernel-level telemetry and Behavioral heuristics to identify malicious activity as it happens.
In a modern security environment, the question is no longer if you will be breached, but when. Zenith-Sentry is built with an "Assume Breach" philosophy, providing security engineers with the visibility required to hunt for lateral movement, persistence mechanisms, and exfiltration attempts that would otherwise remain silent.
The "Assume Breach" philosophy dictates that we treat every host as potentially compromised. Instead of focusing solely on keeping the attacker out, we focus on identifying the artifacts of their presence. Zenith-Sentry looks for the "unnatural" behavior of system components—the suspicious pipe to bash, the root process running from /tmp, or the sudden outbound connection to a high-numbered port.
Every finding generated by Zenith-Sentry is mapped directly to the MITRE ATT&CK® framework, allowing responders to immediately understand the tactic and technique being employed by the adversary.
┌─────────────────────────────────────────────────────────────────────┐
│ ZENITH LIFECYCLE │
└─────────────────────────────────────────────────────────────────────┘
MONITOR ──▶ COLLECT ──▶ ANALYSE ──▶ SCORE ──▶ RESPOND
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ MONITOR │──▶│ COLLECT │──▶│ ANALYSE │──▶│ RESPOND │
│ │ │ │ │ │ │ │
│ • eBPF trace │ │ • /proc │ │ • Heuristics │ │ • SIGKILL │
│ • Kprobes │ │ • Sockets │ │ • Risk score │ │ • iptables │
│ • Ring buffer│ │ • Filesystem │ │ • MITRE map │ │ • Report │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
▲ │
└─────────────── continuous feedback loop ────────────────┘
- Kernel-Level Monitoring: eBPF-based process and network monitoring for visibility integrity
- Behavioral Analysis: Detects malicious behavior patterns rather than relying on static signatures
- Automated Mitigation: Real-time response with process termination and IP blocking
- Plugin Architecture: Extensible detection system with hot-swap plugin support
- REST API: Full-featured API for integration with SIEM and security tools
- Web UI: Zero-dependency vanilla HTML/CSS/JS Command Center served over HTTPS
- Database Support: SQLite for development, PostgreSQL for production
- Monitoring: Prometheus metrics and health checks for operational visibility
- Alerting: Email alerts with configurable severity thresholds
- Backup/Restore: Automated database backup and restore functionality
- Input Validation: Comprehensive validation for file paths, IPs, and commands
- Command Injection Prevention: Parameterized commands and IP whitelisting
- Secure Signal Handling: Safe signal handlers with proper cleanup
- Encryption at Rest: AES-256 encryption for sensitive data
- Secure Logging: PII redaction and security event correlation
- Authentication: JWT tokens and API key authentication
- Authorization: Role-based access control (RBAC)
The v2.0 release ("Hardened") is a significant architectural overhaul focused on production reliability, performance parity, and proactive defense.
We have unified the process and network monitoring into a single, high-efficiency kernel engine. By hooking into sys_execve and tcp_v4_connect, Zenith-Sentry captures system events before they can be tampered with by userspace rootkits or LD_PRELOAD shims.
Detection is only half the battle. Zenith-Sentry now includes a mitigation layer capable of instantly neutralizing threats. This includes kernel-level process termination (SIGKILL) and automated destination IP blocking via iptables.
The tool now features a "Hot-Swap" plugin architecture. Detectors are no longer hardcoded into the engine; instead, they are dynamically discovered and instantiated at runtime based on the contents of the zenith/plugins/ directory.
To ensure stability when running as root (a requirement for eBPF), we've implemented a pre-flight dependency check in main.py. This prevents the tool from starting if critical libraries like PyYAML or psutil are missing, providing clear remediation steps.
Zenith-Sentry is designed with a decoupled, event-driven architecture that ensures high performance even under heavy system load.
The following diagram illustrates the data flow from the Linux Kernel up to the User Interface:
┌─────────────────────────────────────────────────────────────────┐
│ KERNEL SPACE (RING 0) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│Tracepoint: sys_enter_execve ───▶ Lock-Free Ring Buffer │
│Kprobe: tcp_v4_connect ───▶ Lock-Free Ring Buffer │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ USER SPACE (ZENITH-SENTRY) │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────── ─┐
│Lock-Free Ring Buffer ───▶ BCC Interface ───▶ Zenith Engine│
└──────────────────────────────────────────────────────────── ─┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Telemetry Collectors │
│ Process Collector (Native /proc) ───▶ Zenith Engine │
│ Network Collector (psutil.net_connections)───▶ Zenith Engine│
│ System Collector (fs recursive scan)───▶ Zenith Engine │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│Zenith Engine ───▶ Telemetry Injection ───▶ Plugin Registry│
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Detectors │
│Plugin Registry ───▶ ProcessDetector │
│Plugin Registry ───▶ EBPFDetector │
│Plugin Registry ───▶ Custom Detectors... │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│Scoring Engine ◀── Findings (from Detectors) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│JSON Report ───▶ user_data/scan_YYYYMMDD.json │
│Live Alert ───▶ gui.py │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Mitigation Manager │
│EBPFDetector ───▶ Trigger ───▶ Mitigation Manager │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────┴─────────────┐
│ │
▼ ▼
┌─────────────┐ ┌───────────── ┐
│ os.kill │ │ subprocess │
│(Target PID) │ │IPTables Rules│
└─────────────┘ └───────────── ┘
A comprehensive breakdown of the Zenith-Sentry repository structure and the purpose of each component:
Zenith-Sentry/
├── main.py # Multi-component CLI Controller
│ # - Handles command-line arguments
│ # - Orchestrates the ZenithEngine
│ # - Performs pre-flight dependency checks
│ # - Manages help text and versioning info
│ # - Implements the Dependency Shield mechanism
├── gui.py # Premium Interactive TUI (Curses)
│ # - Renders the menu-driven interface
│ # - Displays color-coded risk findings
│ # - Manages user input for quick-scans
│ # - Handles scrolling and key remapping
│ # - Provides real-time feedback during scans
├── process_execve_monitor.py # eBPF Kernel Monitor & Mitigation Subsystem
│ # - Loads C code into the kernel
│ # - Manages perf/ring buffers
│ # - Executes SIGKILL and iptables logic
│ # - Implements standalone monitor CLI
│ # - Handles signal propagation for cleanup
├── start.sh # Automated Setup & Launcher
│ # - Creates persistent virtual environment
│ # - Installs core dependencies
│ # - Verifies system privileges
│ # - Provides interactive setup for eBPF
│ # - Automates venv activation and script launch
├── install_ebpf_deps.sh # BCC Dependency Provisioner
│ # - Detects OS (Ubuntu/Fedora/RHEL)
│ # - Syncs kernel headers with BCC
│ # - Installs python3-bpfcc bindings
│ # - Verifies kernel config for BPF support
├── config.yaml # Global Security Policies
│ # - Defines port/binary watchlists
│ # - Configures mitigation safety modes
│ # - Sets scan directory parameters
│ # - Global tuning for detection thresholds
├── logo.svg # Brand Identity
├── zenith/ # Core Subsystem Package
│ ├── api/ # REST API Layer
│ │ ├── main.py # FastAPI application
│ │ ├── auth.py # Authentication (JWT, API keys)
│ │ ├── models.py # Pydantic models
│ │ └── routes/ # API endpoints
│ ├── cli/ # Command-line Interface
│ │ └── main.py # CLI commands
│ ├── config/ # Configuration Management
│ │ └── paths.py # Path management (FHS/XDG)
│ ├── db/ # Database Layer
│ │ ├── base.py # SQLAlchemy setup
│ │ ├── models.py # ORM models
│ │ ├── repository.py # Query interface
│ │ └── retention.py # Data retention
│ ├── monitoring/ # Monitoring & Metrics
│ │ ├── metrics.py # Prometheus metrics
│ │ ├── health.py # Health checks
│ │ └── alerts.py # Email alerting
│ ├── scripts/ # Utility Scripts
│ │ ├── backup.py # Database backup
│ │ ├── restore.py # Database restore
│ │ └── verify_install.py # Installation verification
│ ├── security/ # Security Utilities
│ │ ├── encryption.py # Encryption utilities
│ │ └── event_logger.py # Security event logging
│ ├── utils/ # Utility Functions
│ │ ├── validation.py # Input validation
│ │ ├── logging.py # Logging utilities
│ │ └── signals.py # Signal handling
│ ├── engine.py # Central Intelligence Engine
│ │ # - Orchestrated collectors and detectors
│ │ # - Calculates Host Risk Score (0-100)
│ │ # - Generates timestamped JSON reports
│ │ # - Manages background eBPF threads
│ │ # - Handles scan life-cycle and reporting
│ ├── collectors.py # Telemetry Extraction Layer
│ │ # - Process: ProcFS enumeration
│ │ # - Network: Active socket discovery
│ │ # - System: Persistence artifact scanning
│ │ # - Error-resistant telemetry polling
│ ├── core.py # Data Models & Interfaces
│ │ # - Defines Finding and IDetector classes
│ │ # - Enums for RiskLevel and Severity
│ │ # - Tactic strings for MITRE mapping
│ │ # - Core abstraction for all security items
│ ├── registry.py # Dynamic Plugin Discovery System
│ │ # - Introspective import of all plugins
│ │ # - Dependency injection into detectors
│ │ # - Error isolation during plugin loads
│ │ # - Maintains the global detector manifest
│ ├── utils.py # Shared Helper Utilities
│ │ # - Logging configuration
│ │ # - String formatting and data sanitization
│ │ # - Path resolution helpers
│ │ # - Standardized terminal output styles
│ ├── config.py # YAML Configuration Loader
│ │ # - Single-entry point for global settings
│ │ # - Recursive dictionary management
│ │ # - Safe-default injection for missing keys
│ ├── ebpf/ # Kernel-Space Source
│ │ ├── execve_monitor.c # BPF C Program (Kernel Hooks)
│ │ │ # - Low-level tracepoint management
│ │ │ # - Ring buffer event packaging
│ │ │ # - Kernel-side filtering for performance
│ │ │ # - Dynamic map management for IPs
│ │ └── EBPF_GUIDE.md # Subsystem Technical Reference
│ └── plugins/ # Extensible Detection Layer
│ ├── base.py # Plugin base classes
│ ├── detectors.py # Behavioral Process Analysis
│ │ # - Regex patterns for malicious bash pipes
│ │ # - Detection of base64 obfuscation
│ │ # - Command substitution detection
│ │ # - Pipeline injection hunter
│ └── ebpf_detector.py # eBPF Event Processor
│ # - Correlates kernel events to findings
│ # - Detects root executions and failed execve
│ # - Maps network events to C2 patterns
└── README.md # Comprehensive Documentation (Current File)
The following diagram illustrates the decoupled planes of the Zenith-Sentry toolkit:
┌──────────────────────────────────────────────────────────────────────┐
│ CONTROL PLANE · USER INTERACTION │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │
│ │ main.py CLI │ │ gui.py TUI │ │ REST API / │ │
│ │ (arguments) │◀─▶│ (interactive) │◀─▶│ Web UI (8000) │ │
│ └──────────────────┘ └──────────────────┘ └─────────────────┘ │
│ ▲ ▲ ▲ │
│ └──────────────────────┼──────────────────────┘ │
│ │ │
│ ┌──────────────────┐ │
│ │ config.yaml │ ← policy & thresholds │
│ └──────────────────┘ │
└───────────────────────────────────┬──────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────┐
│ DATA PLANE · ANALYSIS ENGINE │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ ZenithEngine │──────▶│ PluginRegistry │ │
│ │ (orchestrator) │ │ (hot-swap load) │ │
│ └──────────────────┘ └────────┬─────────┘ │
│ ▲ │ │
│ │ ▼ │
│ │ ┌──────────────────┐ │
│ │ │ Detectors / │ │
│ └─────────────────│ IDetector │ │
│ │ subclasses │ │
│ └────────┬─────────┘ │
│ │ Findings │
└───────────────────────────────────────┼──────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────────┐
│ ENFORCEMENT PLANE · KERNEL & OS │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ eBPF Monitor │──────▶│ Linux Kernel │ │
│ │ (tracepoints) │ │ (ring buffer) │ │
│ └──────────────────┘ └──────────────────┘ │
│ ▲ │
│ │ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Mitigation │──────▶│ iptables DROP │ │
│ │ Manager │ │ SIGKILL PID │ │
│ └──────────────────┘ └──────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────── ┐
│ KERNEL SPACE · Ring 0 │
├────────────────────────────────────────────────────────────────────── ┤
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌─ ─────────────── ──┐ │
│ │ Tracepoint │──▶ │ sys_execve │──▶│ │ │
│ │ sys_enter_... │ │ (process) │ │ │ │
│ └────────────────┘ └────────────────┘ │ BPF_RINGBUF │ │
│ │ (lock-free │ │
│ ┌────────────────┐ ┌────────────────┐ │ ring buffer) │ │
│ │ Kprobe │──▶ │ tcp_v4_connect │──▶│ │ │
│ │ (network) │ │ │ │ │ │
│ └────────────────┘ └────────────────┘ └─────────┬──────────┘ │
│ │ │
└────────────────────────────────────────────────────────┼──────────────┘
│ perf events
▼
┌──────────────────────────────────────────────────────────────────────┐
│ USER SPACE MONITOR · Ring 3 │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────┐ │
│ │ ProcessExecveMonitor│ ← Python BCC │
│ │ (poll ring buffer) │ │
│ └──────────┬───────────┘ │
│ │ │
│ ┌──────────┴───────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ JSON / Human │ │ Mitigation │ │
│ │ Log Stream │ │ Engine │ │
│ │ (stdout/stderr)│ │ (kill / block) │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────┘
One of the most critical aspects of modern EDR is Visibility Integrity. If an attacker has compromised userspace (e.g., via a library pre-load rootkit), they can easily hide their presence from standard tools like ps or netstat. Zenith-Sentry solves this by moving its "eyes" into the kernel.
Zenith-Sentry utilizes a hybrid approach to kernel monitoring:
- Tracepoints (
sys_enter_execve): These are static hooks established in the Linux kernel source. Unlike dynamic kprobes, tracepoints are stable across kernel versions and provide a predictable API. We use these for process execution tracking because they capture the exact arguments being passed to theexecvesyscall before the process even begins execution. This is critical for preventing "Time of Check/Time of Use" (TOCTOU) exploits where an attacker changes the binary on disk after the monitor has checked it. - Kprobes (
tcp_v4_connect): Networking events are more dynamic. We use kprobes to hook into the TCP stack's connection initiation logic. This allows us to see outbound connection attempts the moment they are triggered, providing a "wire-speed" view of Command & Control (C2) activity.
To ensure minimal impact on system performance, Zenith-Sentry uses Lock-Free Ring Buffers (specifically BPF_PERF_OUTPUT and BPF_RINGBUF_OUTPUT).
In high-concurrency environments, traditional mutex locks cause "context switch storms" that can degrade system performance. By using lock-free rings, the kernel can "fire and forget" security events into a shared memory space that the Zenith-Sentry userspace engine polls. This results in an overhead of less than 2 microseconds per event, making Zenith-Sentry suitable for high-transaction servers.
In zenith/ebpf/execve_monitor.c, we define precise C structs for event packaging. This ensures binary compatibility between the kernel and userspace:
struct execve_event_t {
u32 pid; // Process ID
u32 tgid; // Thread Group ID (User-perceived PID)
u32 uid; // User ID (Critical for root detection)
char comm[16]; // Executable Name
char filename[256]; // Full path of target binary
};This structure ensures that every piece of data required for a forensic audit is captured in a single atomic kernel operation.
┌──────────────────┐
│ ZenithEngine │ ── kicks off scan cycle
└────────┬─────────┘
│ registry.discover()
▼
┌──────────────────┐
│ PluginRegistry │
└────────┬─────────┘
│
▼
┌────────────────────────────┐
│ Walk `zenith/plugins/*.py`│
└────────────┬───────────────┘
│ importlib
▼
┌────────────────────────────┐
│ Loaded Modules │
└────────────┬───────────────┘
│ inspect.getmembers(module, isclass)
▼
┌────────────────────────────┐
│ Filter: issubclass of │
│ IDetector (not abstract) │
└────────────┬───────────────┘
│
▼
┌────────────────────────────┐
│ Candidate Classes │
└────────────┬───────────────┘
│ cls(**telemetry)
▼
┌────────────────────────────┐
│ Detector Instances │
└────────────┬───────────────┘
│ detector.analyze()
▼
┌────────────────────────────┐
│ Findings[] │
└────────────┬───────────────┘
│
▼
┌──────────────────┐
│ ZenithEngine │ ← aggregates & scores
└──────────────────┘
A core philosophy of Zenith-Sentry is Decoupled Intelligence. The engine itself should not need to know how to detect a threat; it should only know how to provide the telemetry to specialized plugins.
In zenith/registry.py, we employ Python's introspection capabilities (importlib and inspect) to build a dynamic plugin loader.
- The registry scans the
zenith/plugins/directory. - It dynamically imports every
.pyfile found within. - It searches the module for any class that inherits from the
IDetectorbase class (defined inzenith/core.py). - It constructs an instance of each found class, injecting the required telemetry data.
When the ZenithEngine (in zenith/engine.py) prepares to run a scan, it executes a "Harvest" phase. It gathers data from all collectors (Process, Network, System, eBPF) and then Injects this data into the plugins.
This dependency-injection model allows plugin developers to focus purely on the detection logic without worrying about how to extract data from the system.
To prevent a single buggy plugin from crashing the entire security suite, Zenith-Sentry implements strict error isolation:
- Each plugin is loaded within a
try-exceptblock. - If a plugin fails to initialize or analyze, the error is logged, but the scan continues with the remaining healthy plugins.
- Findings from failed plugins are marked with an "incomplete" flag in the internal logs.
┌────────────────────┐
│ Risk Detected │
└──────────┬─────────┘
│
▼
┌────────────────────┐
│ Risk Level ? │──── Low / Med ───▶ ┌────────────────┐
└──────────┬─────────┘ │ Log Finding │
│ High / Critical │ (report) │
▼ └────────┬───────┘
┌────────────────────┐ │
│ Enforce mode ? │──── No (monitor) ──▶ ┌────────────────┐
└──────────┬─────────┘ │ Log "would │
│ Yes (enforce) │ mitigate" │
▼ └────────┬───────┘
┌────────────────────┐ │
│ Mitigation type ? │ │
└──────────┬─────────┘ │
│ │
┌──────────┴──────────┐ │
│ │ │
Process Network │
│ │ │
▼ ▼ │
┌──────────────┐ ┌─────────────────────┐ │
│ SIGKILL PID │ │ iptables -I OUTPUT │ │
│ (kernel, │ │ 1 -d IP -j DROP │ │
│ uninterrupt.)│ │ │ │
└──────┬───────┘ └──────────┬──────────┘ │
│ │ │
└ ──────────┬───────── ┘ │
│ │
└───────────────┬─────────────────── ┘
|
▼
┌──────────────────────────────┐
│ Log Forensic Event │
│ (timestamp · action · │
│ pid · ip · detector) │
└──────────────────────────────┘
Zenith-Sentry v2.0 represents the evolution from "Detection" to "Response". The mitigation layer is designed to bridge the "Time to Response" gap.
When a CRITICAL risk is identified by the kernel monitor (such as an unauthorized binary execution from /tmp), the system can immediately trigger a containment event.
- Why SIGKILL?: Unlike
SIGTERM, which can be intercepted or ignored by a malicious binary,SIGKILL(signal 9) is handled directly by the kernel's scheduler. The process is terminated immediately, and its memory space is reclaimed. This is the most reliable way to stop an active malware payload in its tracks.
In addition to process termination, Zenith-Sentry can isolate the host from a specific C2 destination.
- Mechanism: The mitigation manager executes a system call to
iptables. - Logic: It appends a
DROPrule for the specific malicious IP detected:iptables -I OUTPUT 1 -d [MALICIOUS_IP] -j DROP - Immediate Effect: By inserting at position
1in theOUTPUTchain, we ensure that the block takes precedence over all other configured rules. This effectively "shuts the door" on any exfiltration attempt.
The mitigation engine is designed to be cautious. It verifies the existence of the process and the validity of the IP before acting. To prevent accidental system lockouts, it includes:
- Whitelisting: Critical system PIDs (like PID 1) and IPs (like DNS resolvers) are protected from automated mitigation.
- Circuit Breakers: If the mitigation engine triggers more than 10 times in a 60-second window, it automatically disables itself and alerts the administrator, as this likely indicates a false positive firestorm.
COLLECTORS SOURCES OUTPUT
┌──────────────────┐ ┌──────────────────┐
│ ProcessCollector │────▶│ procfs │─────┐
└──────────────────┘ └──────────────────┘ │
┌──────────────────┐ ┌──────────────────┐ │
│ NetworkCollector │────▶│ net_connections │─────┤
└──────────────────┘ └──────────────────┘ │
┌──────────────────┐ ┌──────────────────┐ │ ┌──────────────────────┐
│ SystemCollector │────▶│ filesystem walk │─────┼────▶│ Integrated Telemetry │
└──────────────────┘ └──────────────────┘ │ │ Context │
┌──────────────────┐ ┌──────────────────┐ │ └──────────┬───────────┘
│ eBPF Monitor │────▶│ kernel events │─────┘ │
└──────────────────┘ └──────────────────┘ │
▼
┌──────────────────────┐
│ Telemetry Injection │
│ (**kwargs to │
│ detectors) │
└──────────┬───────────┘
▼
┌──────────────────────┐
│ Plugin Detectors │
│ (IDetector.run) │
└──────────┬───────────┘
▼
┌──────────────────────┐
│ Behavioural Analysis │
│ (pattern matching) │
└──────────┬───────────┘
▼
┌──────────────────────┐
│ Findings[] │
└──────────────────────┘
Zenith-Sentry uses a multi-vector approach to system state collection to ensure no blind spots.
The ProcessCollector in zenith/collectors.py performs a deep-dive into the Linux /proc filesystem via the psutil library.
- Argument Enumeration: It extracts the full command line, not just the process name. This is critical for detecting obfuscated pipes (e.g.,
curl ... | bash). - Context Mapping: It correlates every process to its effective UID and GID, enabling its "Unauthorized Root Process" detector.
- Error Resilience: It is designed to handle "Racy" processes that may exit between enumeration and inspection, using robust exception handling to prevent scan failures.
The NetworkCollector monitors active connections by querying the system's network state.
- Capabilities: Detects established TCP connections, listening sockets, and UDP endpoints.
- Noise Reduction: Automatically filters out loopback (127.0.0.1) and internal IPC traffic to focus on outbound "reach-back" attempts.
- Attribution: Maps varje socket back to a process ID (PID), allowing the detection engine to see which application is making the connection.
Persistence is the holy grail for an attacker (MITRE T1037, T1543). The SystemCollector recursively scans system-critical directories:
/etc/systemd/system/: To find unauthorized services./etc/cron.d/: To find hidden scheduled tasks./etc/rc.local: To identify ancient but effective persistence tricks.
It collects file metadata (size, owner, modification time, permissions), which is then analyzed for anomalies (e.g., a root-owned script in a user directory).
Most traditional security tools rely on Signatures—hashes or byte patterns of known malware. While effective against legacy threats, signature analysis fails against:
- Polymorphic Malware: Payloads that change their hash on every execution.
- Living-off-the-Land (LotL) Attacks: Using legitimate system tools (
curl,bash,ssh) for malicious purposes. - Zero-Day Exploits: New attacks that have no existing signature.
Zenith-Sentry focuses on Behavioral Analysis. We don't care what the file "looks like" on disk; we care what it "does" when it runs. If a binary is trying to pipe a web download directly into a shell, that is inherently suspicious regardless of the binary's hash. This approach is significantly more robust against modern, state-sponsored attack chains.
The Interactive TUI (gui.py) is built using the Python curses library. To keep the interface responsive during heavy scans:
- Asynchronous Updates: We use non-blocking keyboard input and periodic screen refreshes.
- Color-Coding Latency: Risk levels are calculated and cached per-finding to avoid redundant computation during TUI scrolling.
- Buffer Management: The results window uses a pad virtual coordinate system, allowing it to display thousands of findings without memory or performance degradation.
● START
│
▼
┌──────────────────┐
│ Event Detected │◀──────────────────┐
│ (from eBPF / │ │
│ detector) │ │
└────────┬─────────┘ │
│ │
▼ │
╱──────────────────╲ │
╱ Already mitigated ╲──── Yes ──┐ │
╲ for this PID/IP? ╱ │ │
╲──────────┬───────╱ │ │
│ No ▼ │
▼ ┌──────────┐ │
╱──────────────────╲ │ Drop │ │
╱ PID / IP still ╲── No│ (dedupe)│ │
╲ present? ╱ └──────────┘ │
╲──────────┬───────╱ │
│ Yes │
▼ │
┌──────────────────┐ │
│ Execute Action │ │
│ ─ SIGKILL pid │ │
│ ─ iptables DROP │ │
└────────┬─────────┘ │
│ │
▼ │
┌──────────────────┐ │
│ Record Forensic │ │
│ Timestamp │ │
└────────┬─────────┘ │
│ │
▼ │
╱──────────────────╲ │
╱ Circuit breaker ╲── Yes ──┐ │
╲ tripped (>10/60s)╱ │ │
╲──────────┬───────╱ ▼ │
│ No ┌──────────────┐ │
│ │ Disable & │ │
│ │ alert admin │ │
│ └──────┬───────┘ │
│ │ │
└────────────┬────┘ │
▼ │
● END ───────────┘
(awaits next)
The mitigation manager is not just a collection of shell commands; it is a stateful event observer.
- Deduplication: It tracks which IPs have already been blocked to avoid flooding the
iptablesruleset with redundant entries. - Verification: Before killing a PID, it re-verifies that the PID is still active and matches the telemetry metadata (name, UID) to prevent "PID Wrap" accidents where a new, legitimate process has inherited the old PID.
- Logging: Every mitigation action is logged with high-precision timestamps for later forensic reconciliation.
When reporting evidence in JSON format, Zenith-Sentry applies a "Clean Slate" logic:
- Truncation: Command lines are truncated to 512 characters to prevent memory exhaustion in SIEM pipelines.
- Escaping: All evidence is properly JSON-escaped to prevent injection attacks into the logging platform.
- Identification: Every finding is assigned a unique UUIDv4, allowing security teams to track the lifecycle of a specific alert across multiple scans.
Centralized management is handled via config.yaml. This file allows administrators to define the "High-Water Mark" for security on their systems.
# Network Security Policy
network:
suspicious_ports: [4444, 1337, 5555, 6667, 8888, 9999]
ignore_loopback: true
# Kernel Monitor Configuration
ebpf:
critical_bins: ["nc", "ncat", "socat", "nmap", "ssh-keygen", "tcpdump"]
suspicious_paths: ["/tmp/", "/dev/shm/", "/var/tmp/", "/run/shm/"]
mitigation:
safe_mode: true # Critical safety override
max_mitigations: 10 # Rate limiting
# Persistence Scanning Configuration
persistence:
scan_dirs: ["/home", "/opt", "/usr/local/bin"]A major cause of tool failure in the field is a mismatched environment. main.py implements a Dependency Shield that runs before any security logic:
- Library Verification: Checks for
PyYAML,psutil, andbcc(optional) before initializing any logic. - Privilege Enforcement: Prevents the tool from starting if
--ebpfis requested without root privileges. - Remediation Mapping: Provides exact
piporaptcommands to fix the environment, tailored to the specific missing library.
| Component | Minimum | Recommended |
|---|---|---|
| OS | Any Linux Distro | Ubuntu 22.04+ |
| Kernel | 4.8+ | 5.8+ (for Ring Buffer) |
| Python | 3.8+ | 3.10+ |
| Privileges | Root (for eBPF) | Root (Full Visibility) |
| Memory | 4GB | 8GB |
| Disk | 20GB | 50GB |
# Clone the repository
git clone https://github.com/syed-sameer-ul-hassan/Zenith-Sentry.git
cd Zenith-Sentry
# Install dependencies
pip install -r requirements.txt
# Install eBPF dependencies (optional, for eBPF monitoring)
sudo bash install_ebpf_deps.sh
# Verify installation
python zenith/scripts/verify_install.pypip install zenith-sentry# Build Docker image
docker build -t zenith-sentry:latest .
# Run container
docker run -d \
--name zenith-sentry \
-v /var/log/zenith-sentry:/var/log/zenith-sentry \
-v /etc/zenith-sentry:/etc/zenith-sentry \
-p 8000:8000 \
zenith-sentry:latest# Run a basic scan
python3 main.py full-scan
# Enable eBPF monitoring (requires sudo)
sudo python3 main.py full-scan --ebpf
# JSON output for SIEM integration
python3 main.py full-scan --json
# Interactive TUI
python3 gui.py# Start the API server
uvicorn zenith.api.main:app --host 0.0.0.0 --port 8000
# Access the API documentation
# Open http://localhost:8000/docs in your browserThe web UI is a zero-dependency vanilla HTML/CSS/JS tactical command center served over HTTPS by a small Python server that reverse-proxies the FastAPI backend. Every button triggers a real API call — scans, findings, network panel, system info and lockdown.
# Starts FastAPI (:8000) + Command Center UI (:8080) together
./start-web.sh
# Then open:
# http://localhost:8080The launcher:
- Activates
.venv/if present. - Boots
uvicorn zenith.api.main:appon port 8000. - Boots the static web server on port 8080 in HTTP mode (no self-signed cert prompts during development).
- Stops both processes cleanly on
Ctrl+C.
# Terminal 1 — backend API
uvicorn zenith.api.main:app --host 0.0.0.0 --port 8000
# Terminal 2 — web server (HTTPS with auto self-signed cert)
python3 web/server.py --port 8443
# …or HTTP mode
python3 web/server.py --http --port 8080| Section | Endpoint(s) used |
|---|---|
| Dashboard | /api/v1/system/resources, /system/processes, /system/network, /scans/ |
| Findings | /api/v1/findings/ (with risk filtering) |
| Defense | /api/v1/scans/, /api/v1/system/config, /api/v1/defense/lockdown |
| System | /api/v1/system/info, /system/resources, /system/processes |
All telemetry is refreshed automatically every 30 seconds.
- Full System Scan: The most comprehensive assessment.
- Process Analysis: Rapid hunt for behavioral process anomalies.
- Network Analysis: Monitoring of active socket telemetry.
- Persistence Discovery: Scanning for filesystem-based persistence.
The TUI is built for speed.
- Arrows: Navigate the menu vertically.
- Enter: Trigger the selected scan.
- 'q': Exit the results dashboard.
- Colors: Red findings indicate critical risk, Yellow for medium, and Green for low/info.
When a scan is complete, the TUI provides a color-coded summary of the findings:
==================================================
ZENITH-SENTRY Scan Results
==================================================
Risk Score: 85/100
Findings (3):
[1] CRITICAL | Privilege Escalation
Module: EBPFDetector
Description: Unauthorized root process execution from /tmp detected via kernel tracepoint.
Evidence: {'pid': 4122, 'binary': '/tmp/zero_day_exploit', 'uid': 0}
[2] HIGH | Command & Control
Module: NetworkDetector
Description: Outbound connection to suspicious port 4444.
Evidence: {'pid': 4122, 'dest': '192.168.1.100:4444', 'status': 'ESTABLISHED'}
[3] MEDIUM | Persistence
Module: SystemCollector
Description: New unauthorized systemd service detected in /etc/systemd/system/.
Evidence: {'file': 'backdoor.service', 'owner': 'root'}
Press any key to return to the menu...
For SIEM integration, Zenith-Sentry generates structured JSON evidence:
{
"score": 85,
"timestamp": "20260419_202500",
"findings": [
{
"id": "f83a2b41-e912-4c5d-b710-4c9093eefce8",
"module": "EBPFDetector",
"risk": "CRITICAL",
"severity": "CRITICAL",
"tactic": "Privilege Escalation",
"description": "Unauthorized root process execution from /tmp detected.",
"evidence": {
"pid": 4122,
"binary": "/tmp/zero_day_exploit",
"uid": 0
}
}
]
}
---
## CLI Command Reference
### Basic Scan Operations
# Full scan with default settings
```bash
python3 main.py full-scan
# Enable eBPF (requires sudo)
sudo python3 main.py full-scan --ebpf
# JSON output for SIEM integration
python3 main.py full-scan --json
# Combined high-security scan
sudo python3 main.py full-scan --ebpf --json --verbose
| Flag | Description | Root Required | SIEM Impact |
|---|---|---|---|
--ebpf |
Enables Kernel-level process monitoring | YES | High (Deep Telemetry) |
--json |
Outputs results in structured JSON | NO | Critical (Integration) |
--verbose |
Debug logging for engine internals | NO | Medium (Debugging) |
--risk-threshold |
Filters results by severity score | NO | High (Noise Reduction) |
python3 main.py full-scan --risk-threshold 75
# Threshold mapping:
# 0 -> INFO (Everything)
# 25 -> LOW (Informational + Suspicious)
# 50 -> MEDIUM (Anomalous behavior)
# 75 -> HIGH (Likely malicious)
# 100 -> CRITICAL (Known attack patterns)The standalone process_execve_monitor.py is perfect for background monitoring.
# Standalone monitor with human-readable output
sudo python3 process_execve_monitor.py --source zenith/ebpf/execve_monitor.c --human
# Monitor with live mitigation (WARNING: Active containment)
sudo python3 process_execve_monitor.py --source zenith/ebpf/execve_monitor.c --enforce
# Debugging eBPF issues
sudo python3 process_execve_monitor.py --source zenith/ebpf/execve_monitor.c --debugAll project documentation lives in the docs/ directory, plus
subsystem-specific guides co-located with the code they describe.
| Document | Description |
|---|---|
docs/architecture.md |
System architecture, component boundaries, data flow, database schema, and deployment topologies. |
docs/deployment.md |
Installation (source / pip / Docker / Kubernetes), systemd units, environment configuration, Prometheus, health checks, backups. |
docs/security.md |
Threat model, hardening checklist, incident response playbooks, and compliance mappings (GDPR, SOC2, HIPAA). |
docs/troubleshooting.md |
Common issues + FAQ covering install, config, DB, eBPF, API, performance, and security. |
| Document | Description |
|---|---|
zenith/ebpf/EBPF_GUIDE.md |
Complete eBPF kernel engine reference — architecture, installation (BCC + headers), output formats, threat heuristics, performance, tuning, and SIEM integration. |
web/index.html + web/static/app.js |
Command Center web UI source (vanilla HTML/CSS/JS). See Web UI — Command Center above. |
Once the API server is running, interactive API docs are available at:
- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc - OpenAPI JSON:
http://localhost:8000/openapi.json
# Database configuration
export DATABASE_URL="postgresql://zenith:password@localhost:5432/zenith"
# Encryption key (required)
export ZENITH_ENCRYPTION_KEY="your-encryption-key-here"
# API configuration
export API_HOST="0.0.0.0"
export API_PORT="8000"
# Log level
export LOG_LEVEL="INFO"
# Enable eBPF monitoring
export EBPF_ENABLED="true"Create /etc/zenith-sentry/config.yaml:
version: "1.0"
# Collectors configuration
collectors:
processes:
enabled: true
interval: 60
network:
enabled: true
interval: 30
system:
enabled: true
interval: 300
# Detectors configuration
detectors:
process_detector:
enabled: true
suspicious_ports: [4444, 5555, 6666]
critical_binaries: ["/bin/sh", "/bin/bash", "/usr/bin/python3"]
network_detector:
enabled: true
blocked_ips: []
allowed_ips: ["192.168.1.0/24"]
# Database configuration
database:
url: "postgresql://zenith:password@localhost:5432/zenith"
pool_size: 10
max_overflow: 20
# Retention configuration
retention:
findings_days: 90
events_days: 30
scans_days: 365
# Alert configuration
alerts:
enabled: true
smtp_host: "smtp.example.com"
smtp_port: 587
smtp_username: "alerts@example.com"
smtp_password: "password"
recipients: ["security@example.com"]
severity_threshold: "high"# Run all tests
pytest
# Run with coverage
pytest --cov=zenith --cov-report=html
# Run specific test
pytest tests/test_engine.py# Format code
black zenith/
# Lint code
flake8 zenith/
# Type check
mypy zenith/
# Security scan
bandit -r zenith/# Build wheel
python -m build
# Build Docker image
docker build -t zenith-sentry:latest .We welcome contributions! Please see docs/architecture.md for development guidelines.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
MIT License - see LICENSE file for details
- Documentation:
docs/directory and the subsystem guides listed above. - Bug reports: Open an issue on the project's GitHub repository.
- Security disclosures: See
docs/security.mdfor the responsible disclosure policy.
- BCC — eBPF tooling
- FastAPI — REST API framework
- Prometheus — metrics
- psutil — system telemetry
Zenith-Sentry's JSON reports are designed to be queried.
cat scan_report.json | jq '.findings[].risk' | sort | uniq -ccat scan_report.json | jq '.findings[] | select(.risk=="CRITICAL") | .evidence.pid'cat scan_report.json | jq '.findings[] | .tactic' | sort | uniq -ccat scan_report.json | jq '.findings[].evidence.binary' | sort | uniqDeploy Zenith-Sentry as a systemd service to monitor ephemeral instances and alert via syslog to a centralized SIEM.
Run Zenith-Sentry with --enforce mode on jump boxes and bastion hosts to immediately terminate unauthorized remote shells.
Mount the target system's disk and use the Zenith collectors to perform a rapid persistence and artifact hunt on a live system.
Integrate Zenith-Sentry into build runners to detect unauthorized tools or exfiltration attempts during the build process.
- eBPF Network Filtering (XDP): Drop malicious packets before they even enter the network stack.
- YARA In-Memory Scanning: Trigger YARA scans on suspicious processes identified by the EDR.
- LSM (Linux Security Module) Integration: Provide mandatory access control based on scan results.
- Centralized Dashboard: A web-based "Command Center" for managing multiple Zenith-Sentry agents.
- Windows Support: Porting the telemetry collectors to Windows via ETW.
| Syscall / Symbol | Probe Type | Description |
|---|---|---|
sys_enter_execve |
Tracepoint | Captured at the start of process execution. |
sys_exit_execve |
Tracepoint | Captured at the end of process execution. |
tcp_v4_connect |
Kprobe | Captured when a socket connection is initiated. |
| Finding Pattern | Tactic | Technique |
|---|---|---|
| Piped Shell | Execution | T1059 — Command & Scripting Interpreter |
| Base64 Obfuscation | Defense Evasion | T1027 — Obfuscated Files or Information |
| Critical Port Connection | Command & Control | T1071 — Application Layer Protocol |
Root Exec from /tmp |
Privilege Escalation | T1068 — Exploitation for Privilege Escalation |
- CPU: 1 core minimum, 2+ recommended.
- RAM: 512 MB baseline; 2 GB recommended when eBPF buffering is active.
- Storage: 500 MB for logs, reports, and the Python environment.
Implemented Collectors:
- ProcessCollector:
- Uses
psutil.process_iter. - Captures
pid,name,cmdline. - Handles
AccessDeniedandNoSuchProcessexceptions. - Outputs a dictionary keyed by PID.
- Implements a safety timeout for long-running process lists.
- Uses
- NetworkCollector:
- Uses
psutil.net_connections. - Captures source/destination IPs, ports, and status.
- Maps connections back to the owning PID.
- Filters out local IPC and loopback connection telemetry.
- Supports both IPv4 and IPv6 connection enumeration.
- Uses
- SystemCollector:
- Recursive directory walker for
/etc/systemd,/etc/cron.d, etc. - Collects file stat info (size, mode, owner, modification time).
- Allows user-defined scan directories via
config.yaml. - Implements robust error handling for broken symlinks and unreadable mount points.
- Recursive directory walker for
Implemented Analysis Patterns:
curl ... | bash: High-risk shell pipe detection.wget ... | sh: High-risk shell pipe detection.base64 -d: Common obfuscation indicator for payload delivery.$(...): Command substitution detection (Potential Execution tactic).- Backtick substitution: Legacy execution tactic detection.
echo ... | base64: Detection of local data staging for exfiltration.- Pipeline termination check: Ensures rules apply to complete command chains.
eBPF Implementation Details:
- Tracepoints:
syscalls/sys_enter_execveandsyscalls/sys_exit_execve. - Kprobes:
tcp_v4_connectfor network observability. - Mitigation: Python-based orchestration of
os.killandsubprocess.run(["iptables", ...]). - Signal Handling: Comprehensive trap for SIGINT and SIGTERM to clean up kernel probes.
- Privilege Separation: Dedicated checks for
os.geteuid() == 0for kernel interaction. - Event Parsing: Uses
ctypesfor high-performance memory mapping of kernel structs.
The engine is the nervous system of Zenith-Sentry.
- Orchestration: Manages the sequential execution of collectors -> harvest -> plugins -> analysis.
- Risk Calculation: Aggregates finding weights to produce a single 0-100 risk score.
- Reporting: Thread-safe report generation to
user_data/. - Background Threads: Manages the lifecycle of the eBPF monitor thread.
The plugin discovery engine.
- Introspection: Uses
inspect.isclassto identify plugin candidates. - Filtering: Specifically looks for classes inheriting from
IDetector. - Instantiation: Handles variable argument injection into plugin constructors.
- Registry State: Maintains a persistent record of all successfully loaded modules.
Configuration is the brain's baseline.
- YAML Loading: Uses
PyYAMLwith safe loading protocols. - Path Resolution: Ensures the config file is found regardless of the execution context.
- Validation: Basic schema verification for critical sections like
ebpfandnetwork.
The user interface and guardrail center.
- Arguement Parsing: Comprehensive
argparseimplementation. - Dependency Shield: Prevents runtime crashes due to missing environment components.
- TUI/CLI Switching: Logic to bridge the interactive and automated modes.
Built for Linux defenders. Engineered for the future.
Assume Breach. Hunt Threats. Automate Defense.