add eBPF kernel tracing for Linux process monitoring
This commit is contained in:
969
ghost-core/src/ebpf.rs
Normal file
969
ghost-core/src/ebpf.rs
Normal file
@@ -0,0 +1,969 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::time::{SystemTime, Duration};
|
||||||
|
use crate::{ProcessInfo, MemoryRegion, DetectionResult, ThreatLevel};
|
||||||
|
|
||||||
|
/// Linux eBPF-based Process Injection Detection
|
||||||
|
/// Provides kernel-level tracing and detection capabilities on Linux systems
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct EbpfDetector {
|
||||||
|
program_manager: EbpfProgramManager,
|
||||||
|
event_processor: EbpfEventProcessor,
|
||||||
|
filter_manager: EbpfFilterManager,
|
||||||
|
ring_buffer: Arc<Mutex<EbpfRingBuffer>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct EbpfProgramManager {
|
||||||
|
loaded_programs: HashMap<String, LoadedProgram>,
|
||||||
|
program_definitions: Vec<EbpfProgramDefinition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct LoadedProgram {
|
||||||
|
pub program_id: u32,
|
||||||
|
pub program_type: EbpfProgramType,
|
||||||
|
pub attach_point: String,
|
||||||
|
pub fd: i32,
|
||||||
|
pub loaded_at: SystemTime,
|
||||||
|
pub event_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum EbpfProgramType {
|
||||||
|
Kprobe,
|
||||||
|
Kretprobe,
|
||||||
|
Tracepoint,
|
||||||
|
Uprobe,
|
||||||
|
Uretprobe,
|
||||||
|
PerfEvent,
|
||||||
|
SocketFilter,
|
||||||
|
SchedCls,
|
||||||
|
SchedAct,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EbpfProgramDefinition {
|
||||||
|
pub name: String,
|
||||||
|
pub program_type: EbpfProgramType,
|
||||||
|
pub attach_points: Vec<String>,
|
||||||
|
pub bytecode: Vec<u8>,
|
||||||
|
pub description: String,
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct EbpfEventProcessor {
|
||||||
|
event_handlers: HashMap<EventType, Box<dyn EventHandler>>,
|
||||||
|
detection_rules: Vec<EbpfDetectionRule>,
|
||||||
|
process_tracker: ProcessTracker,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
|
pub enum EventType {
|
||||||
|
ProcessCreate,
|
||||||
|
ProcessExit,
|
||||||
|
MemoryMap,
|
||||||
|
MemoryUnmap,
|
||||||
|
MemoryProtect,
|
||||||
|
FileOpen,
|
||||||
|
FileClose,
|
||||||
|
NetworkConnect,
|
||||||
|
NetworkAccept,
|
||||||
|
SyscallEntry,
|
||||||
|
SyscallExit,
|
||||||
|
ThreadCreate,
|
||||||
|
ThreadExit,
|
||||||
|
ProcessInjection,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub trait EventHandler: Send + Sync {
|
||||||
|
fn handle_event(&mut self, event: &EbpfEvent) -> Option<DetectionEvent>;
|
||||||
|
fn get_event_type(&self) -> EventType;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EbpfEvent {
|
||||||
|
pub timestamp: u64,
|
||||||
|
pub pid: u32,
|
||||||
|
pub tid: u32,
|
||||||
|
pub event_type: EventType,
|
||||||
|
pub data: EbpfEventData,
|
||||||
|
pub cpu: u32,
|
||||||
|
pub comm: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum EbpfEventData {
|
||||||
|
ProcessCreate(ProcessCreateData),
|
||||||
|
ProcessExit(ProcessExitData),
|
||||||
|
MemoryMap(MemoryMapData),
|
||||||
|
MemoryProtect(MemoryProtectData),
|
||||||
|
FileAccess(FileAccessData),
|
||||||
|
NetworkActivity(NetworkActivityData),
|
||||||
|
Syscall(SyscallData),
|
||||||
|
ProcessInjection(ProcessInjectionData),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ProcessCreateData {
|
||||||
|
pub parent_pid: u32,
|
||||||
|
pub filename: String,
|
||||||
|
pub argv: Vec<String>,
|
||||||
|
pub envp: Vec<String>,
|
||||||
|
pub uid: u32,
|
||||||
|
pub gid: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ProcessExitData {
|
||||||
|
pub exit_code: i32,
|
||||||
|
pub exit_signal: i32,
|
||||||
|
pub runtime_ms: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct MemoryMapData {
|
||||||
|
pub address: u64,
|
||||||
|
pub length: u64,
|
||||||
|
pub protection: u32,
|
||||||
|
pub flags: u32,
|
||||||
|
pub fd: i32,
|
||||||
|
pub offset: u64,
|
||||||
|
pub filename: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct MemoryProtectData {
|
||||||
|
pub address: u64,
|
||||||
|
pub length: u64,
|
||||||
|
pub old_protection: u32,
|
||||||
|
pub new_protection: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FileAccessData {
|
||||||
|
pub filename: String,
|
||||||
|
pub flags: u32,
|
||||||
|
pub mode: u32,
|
||||||
|
pub fd: i32,
|
||||||
|
pub operation: FileOperation,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum FileOperation {
|
||||||
|
Open,
|
||||||
|
Close,
|
||||||
|
Read,
|
||||||
|
Write,
|
||||||
|
Seek,
|
||||||
|
Truncate,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct NetworkActivityData {
|
||||||
|
pub local_addr: String,
|
||||||
|
pub local_port: u16,
|
||||||
|
pub remote_addr: String,
|
||||||
|
pub remote_port: u16,
|
||||||
|
pub protocol: NetworkProtocol,
|
||||||
|
pub operation: NetworkOperation,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum NetworkProtocol {
|
||||||
|
TCP,
|
||||||
|
UDP,
|
||||||
|
ICMP,
|
||||||
|
RAW,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum NetworkOperation {
|
||||||
|
Connect,
|
||||||
|
Accept,
|
||||||
|
Send,
|
||||||
|
Receive,
|
||||||
|
Close,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SyscallData {
|
||||||
|
pub syscall_number: u64,
|
||||||
|
pub syscall_name: String,
|
||||||
|
pub args: Vec<u64>,
|
||||||
|
pub return_value: i64,
|
||||||
|
pub duration_ns: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ProcessInjectionData {
|
||||||
|
pub target_pid: u32,
|
||||||
|
pub injection_type: InjectionType,
|
||||||
|
pub memory_address: u64,
|
||||||
|
pub memory_size: u64,
|
||||||
|
pub source_process: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum InjectionType {
|
||||||
|
PtraceInject,
|
||||||
|
ProcMemInject,
|
||||||
|
SharedLibraryInject,
|
||||||
|
ElfInjection,
|
||||||
|
ShellcodeInject,
|
||||||
|
CodeCaveInject,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DetectionEvent {
|
||||||
|
pub timestamp: SystemTime,
|
||||||
|
pub event_id: String,
|
||||||
|
pub detection_type: DetectionType,
|
||||||
|
pub confidence: f32,
|
||||||
|
pub severity: EventSeverity,
|
||||||
|
pub process_info: ProcessInfo,
|
||||||
|
pub indicators: Vec<String>,
|
||||||
|
pub raw_events: Vec<EbpfEvent>,
|
||||||
|
pub context: DetectionContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum DetectionType {
|
||||||
|
ProcessHollowing,
|
||||||
|
DllInjection,
|
||||||
|
ShellcodeInjection,
|
||||||
|
PtraceInjection,
|
||||||
|
ProcessDoppelganging,
|
||||||
|
AtomBombing,
|
||||||
|
ProcessGhosting,
|
||||||
|
ManualDllLoading,
|
||||||
|
ReflectiveDllLoading,
|
||||||
|
ProcessOverwriting,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum EventSeverity {
|
||||||
|
Info,
|
||||||
|
Low,
|
||||||
|
Medium,
|
||||||
|
High,
|
||||||
|
Critical,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DetectionContext {
|
||||||
|
pub mitre_technique: String,
|
||||||
|
pub attack_chain: Vec<String>,
|
||||||
|
pub affected_processes: Vec<u32>,
|
||||||
|
pub network_connections: Vec<String>,
|
||||||
|
pub file_modifications: Vec<String>,
|
||||||
|
pub privilege_escalations: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct EbpfDetectionRule {
|
||||||
|
pub rule_id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub description: String,
|
||||||
|
pub conditions: Vec<DetectionCondition>,
|
||||||
|
pub confidence_weight: f32,
|
||||||
|
pub severity: EventSeverity,
|
||||||
|
pub mitre_technique: String,
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum DetectionCondition {
|
||||||
|
EventSequence {
|
||||||
|
events: Vec<EventType>,
|
||||||
|
time_window: Duration,
|
||||||
|
same_process: bool,
|
||||||
|
},
|
||||||
|
MemoryPattern {
|
||||||
|
pattern: MemoryPatternType,
|
||||||
|
threshold: f32,
|
||||||
|
},
|
||||||
|
ProcessBehavior {
|
||||||
|
behavior: ProcessBehaviorType,
|
||||||
|
threshold: u32,
|
||||||
|
},
|
||||||
|
FileSystemActivity {
|
||||||
|
pattern: FileSystemPattern,
|
||||||
|
suspicious_paths: Vec<String>,
|
||||||
|
},
|
||||||
|
NetworkActivity {
|
||||||
|
pattern: NetworkPattern,
|
||||||
|
suspicious_destinations: Vec<String>,
|
||||||
|
},
|
||||||
|
SyscallPattern {
|
||||||
|
syscalls: Vec<String>,
|
||||||
|
frequency_threshold: u32,
|
||||||
|
time_window: Duration,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum MemoryPatternType {
|
||||||
|
RWXAllocation,
|
||||||
|
ExecutableMapping,
|
||||||
|
SuspiciousProtectionChange,
|
||||||
|
LargeAllocation,
|
||||||
|
PatternMatching(Vec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum ProcessBehaviorType {
|
||||||
|
RapidProcessCreation,
|
||||||
|
UnusualParentChild,
|
||||||
|
PrivilegeEscalation,
|
||||||
|
ProcessMasquerading,
|
||||||
|
HollowedProcess,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum FileSystemPattern {
|
||||||
|
TemporaryFileCreation,
|
||||||
|
ExecutableModification,
|
||||||
|
SystemFileAccess,
|
||||||
|
HiddenFileCreation,
|
||||||
|
ConfigurationModification,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum NetworkPattern {
|
||||||
|
UnusualOutboundConnection,
|
||||||
|
CommandControlCommunication,
|
||||||
|
DataExfiltration,
|
||||||
|
LateralMovement,
|
||||||
|
TunneledTraffic,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct ProcessTracker {
|
||||||
|
processes: HashMap<u32, TrackedProcess>,
|
||||||
|
process_tree: HashMap<u32, Vec<u32>>,
|
||||||
|
injection_timeline: Vec<InjectionEvent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TrackedProcess {
|
||||||
|
pub pid: u32,
|
||||||
|
pub ppid: u32,
|
||||||
|
pub command: String,
|
||||||
|
pub start_time: SystemTime,
|
||||||
|
pub memory_maps: Vec<MemoryMapData>,
|
||||||
|
pub file_operations: Vec<FileAccessData>,
|
||||||
|
pub network_connections: Vec<NetworkActivityData>,
|
||||||
|
pub syscall_history: Vec<SyscallData>,
|
||||||
|
pub injection_indicators: Vec<InjectionIndicator>,
|
||||||
|
pub suspicious_score: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct InjectionEvent {
|
||||||
|
pub timestamp: SystemTime,
|
||||||
|
pub source_pid: u32,
|
||||||
|
pub target_pid: u32,
|
||||||
|
pub injection_type: InjectionType,
|
||||||
|
pub indicators: Vec<String>,
|
||||||
|
pub confidence: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct InjectionIndicator {
|
||||||
|
pub indicator_type: IndicatorType,
|
||||||
|
pub description: String,
|
||||||
|
pub confidence: f32,
|
||||||
|
pub timestamp: SystemTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum IndicatorType {
|
||||||
|
SuspiciousMemoryOperation,
|
||||||
|
UnusualSyscallSequence,
|
||||||
|
ProcessTreeAnomaly,
|
||||||
|
FileSystemModification,
|
||||||
|
NetworkCommunication,
|
||||||
|
PrivilegeOperation,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct EbpfFilterManager {
|
||||||
|
active_filters: HashMap<String, EbpfFilter>,
|
||||||
|
filter_statistics: HashMap<String, FilterStats>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EbpfFilter {
|
||||||
|
pub filter_id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub description: String,
|
||||||
|
pub event_types: Vec<EventType>,
|
||||||
|
pub conditions: Vec<FilterCondition>,
|
||||||
|
pub action: FilterAction,
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum FilterCondition {
|
||||||
|
ProcessName(String),
|
||||||
|
ProcessId(u32),
|
||||||
|
UserId(u32),
|
||||||
|
EventFrequency { max_events: u32, time_window: Duration },
|
||||||
|
MemoryThreshold(u64),
|
||||||
|
FilePattern(String),
|
||||||
|
NetworkDestination(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum FilterAction {
|
||||||
|
Allow,
|
||||||
|
Block,
|
||||||
|
Monitor,
|
||||||
|
Alert,
|
||||||
|
Quarantine,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FilterStats {
|
||||||
|
pub events_processed: u64,
|
||||||
|
pub events_filtered: u64,
|
||||||
|
pub last_update: SystemTime,
|
||||||
|
pub performance_impact: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct EbpfRingBuffer {
|
||||||
|
buffer: Vec<EbpfEvent>,
|
||||||
|
read_index: usize,
|
||||||
|
write_index: usize,
|
||||||
|
capacity: usize,
|
||||||
|
lost_events: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl EbpfDetector {
|
||||||
|
pub fn new() -> Result<Self, EbpfError> {
|
||||||
|
let program_manager = EbpfProgramManager::new()?;
|
||||||
|
let event_processor = EbpfEventProcessor::new();
|
||||||
|
let filter_manager = EbpfFilterManager::new();
|
||||||
|
let ring_buffer = Arc::new(Mutex::new(EbpfRingBuffer::new(1024 * 1024))); // 1MB buffer
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
program_manager,
|
||||||
|
event_processor,
|
||||||
|
filter_manager,
|
||||||
|
ring_buffer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize eBPF programs for process injection detection
|
||||||
|
pub fn initialize(&mut self) -> Result<(), EbpfError> {
|
||||||
|
// Load core detection programs
|
||||||
|
self.load_process_monitoring_programs()?;
|
||||||
|
self.load_memory_monitoring_programs()?;
|
||||||
|
self.load_injection_detection_programs()?;
|
||||||
|
self.load_syscall_monitoring_programs()?;
|
||||||
|
|
||||||
|
// Set up event processing
|
||||||
|
self.setup_event_handlers()?;
|
||||||
|
|
||||||
|
// Configure default filters
|
||||||
|
self.setup_default_filters()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load eBPF programs for process monitoring
|
||||||
|
fn load_process_monitoring_programs(&mut self) -> Result<(), EbpfError> {
|
||||||
|
// Process creation monitoring
|
||||||
|
let process_create_program = EbpfProgramDefinition {
|
||||||
|
name: "process_create_monitor".to_string(),
|
||||||
|
program_type: EbpfProgramType::Tracepoint,
|
||||||
|
attach_points: vec!["sched:sched_process_fork".to_string()],
|
||||||
|
bytecode: self.compile_process_create_program()?,
|
||||||
|
description: "Monitor process creation events".to_string(),
|
||||||
|
enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.program_manager.load_program(process_create_program)?;
|
||||||
|
|
||||||
|
// Process exit monitoring
|
||||||
|
let process_exit_program = EbpfProgramDefinition {
|
||||||
|
name: "process_exit_monitor".to_string(),
|
||||||
|
program_type: EbpfProgramType::Tracepoint,
|
||||||
|
attach_points: vec!["sched:sched_process_exit".to_string()],
|
||||||
|
bytecode: self.compile_process_exit_program()?,
|
||||||
|
description: "Monitor process exit events".to_string(),
|
||||||
|
enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.program_manager.load_program(process_exit_program)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load eBPF programs for memory monitoring
|
||||||
|
fn load_memory_monitoring_programs(&mut self) -> Result<(), EbpfError> {
|
||||||
|
// Memory mapping monitoring
|
||||||
|
let mmap_program = EbpfProgramDefinition {
|
||||||
|
name: "memory_map_monitor".to_string(),
|
||||||
|
program_type: EbpfProgramType::Kprobe,
|
||||||
|
attach_points: vec!["sys_mmap".to_string(), "sys_mmap2".to_string()],
|
||||||
|
bytecode: self.compile_mmap_program()?,
|
||||||
|
description: "Monitor memory mapping operations".to_string(),
|
||||||
|
enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.program_manager.load_program(mmap_program)?;
|
||||||
|
|
||||||
|
// Memory protection monitoring
|
||||||
|
let mprotect_program = EbpfProgramDefinition {
|
||||||
|
name: "memory_protect_monitor".to_string(),
|
||||||
|
program_type: EbpfProgramType::Kprobe,
|
||||||
|
attach_points: vec!["sys_mprotect".to_string()],
|
||||||
|
bytecode: self.compile_mprotect_program()?,
|
||||||
|
description: "Monitor memory protection changes".to_string(),
|
||||||
|
enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.program_manager.load_program(mprotect_program)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load eBPF programs for injection detection
|
||||||
|
fn load_injection_detection_programs(&mut self) -> Result<(), EbpfError> {
|
||||||
|
// Ptrace monitoring for injection detection
|
||||||
|
let ptrace_program = EbpfProgramDefinition {
|
||||||
|
name: "ptrace_injection_monitor".to_string(),
|
||||||
|
program_type: EbpfProgramType::Kprobe,
|
||||||
|
attach_points: vec!["sys_ptrace".to_string()],
|
||||||
|
bytecode: self.compile_ptrace_program()?,
|
||||||
|
description: "Monitor ptrace operations for injection".to_string(),
|
||||||
|
enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.program_manager.load_program(ptrace_program)?;
|
||||||
|
|
||||||
|
// Process memory access monitoring
|
||||||
|
let proc_mem_program = EbpfProgramDefinition {
|
||||||
|
name: "proc_mem_monitor".to_string(),
|
||||||
|
program_type: EbpfProgramType::Kprobe,
|
||||||
|
attach_points: vec!["vfs_read".to_string(), "vfs_write".to_string()],
|
||||||
|
bytecode: self.compile_proc_mem_program()?,
|
||||||
|
description: "Monitor /proc/[pid]/mem access".to_string(),
|
||||||
|
enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.program_manager.load_program(proc_mem_program)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load eBPF programs for syscall monitoring
|
||||||
|
fn load_syscall_monitoring_programs(&mut self) -> Result<(), EbpfError> {
|
||||||
|
// General syscall monitoring
|
||||||
|
let syscall_program = EbpfProgramDefinition {
|
||||||
|
name: "syscall_monitor".to_string(),
|
||||||
|
program_type: EbpfProgramType::Tracepoint,
|
||||||
|
attach_points: vec![
|
||||||
|
"raw_syscalls:sys_enter".to_string(),
|
||||||
|
"raw_syscalls:sys_exit".to_string(),
|
||||||
|
],
|
||||||
|
bytecode: self.compile_syscall_program()?,
|
||||||
|
description: "Monitor suspicious syscall patterns".to_string(),
|
||||||
|
enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.program_manager.load_program(syscall_program)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set up event handlers for different event types
|
||||||
|
fn setup_event_handlers(&mut self) -> Result<(), EbpfError> {
|
||||||
|
self.event_processor.register_handler(
|
||||||
|
EventType::ProcessCreate,
|
||||||
|
Box::new(ProcessCreateHandler::new()),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.event_processor.register_handler(
|
||||||
|
EventType::MemoryMap,
|
||||||
|
Box::new(MemoryMapHandler::new()),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.event_processor.register_handler(
|
||||||
|
EventType::MemoryProtect,
|
||||||
|
Box::new(MemoryProtectHandler::new()),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.event_processor.register_handler(
|
||||||
|
EventType::ProcessInjection,
|
||||||
|
Box::new(InjectionHandler::new()),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configure default filters to reduce noise
|
||||||
|
fn setup_default_filters(&mut self) -> Result<(), EbpfError> {
|
||||||
|
// Filter out common system processes
|
||||||
|
let system_filter = EbpfFilter {
|
||||||
|
filter_id: "system_processes".to_string(),
|
||||||
|
name: "System Process Filter".to_string(),
|
||||||
|
description: "Filter out common system processes".to_string(),
|
||||||
|
event_types: vec![EventType::ProcessCreate, EventType::MemoryMap],
|
||||||
|
conditions: vec![
|
||||||
|
FilterCondition::ProcessName("kthreadd".to_string()),
|
||||||
|
FilterCondition::ProcessName("ksoftirqd".to_string()),
|
||||||
|
FilterCondition::ProcessName("migration".to_string()),
|
||||||
|
],
|
||||||
|
action: FilterAction::Allow,
|
||||||
|
enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.filter_manager.add_filter(system_filter);
|
||||||
|
|
||||||
|
// High-frequency event throttling
|
||||||
|
let frequency_filter = EbpfFilter {
|
||||||
|
filter_id: "frequency_limit".to_string(),
|
||||||
|
name: "Event Frequency Limiter".to_string(),
|
||||||
|
description: "Limit high-frequency events".to_string(),
|
||||||
|
event_types: vec![EventType::SyscallEntry, EventType::SyscallExit],
|
||||||
|
conditions: vec![FilterCondition::EventFrequency {
|
||||||
|
max_events: 1000,
|
||||||
|
time_window: Duration::from_secs(1),
|
||||||
|
}],
|
||||||
|
action: FilterAction::Monitor,
|
||||||
|
enabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.filter_manager.add_filter(frequency_filter);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process events from the ring buffer
|
||||||
|
pub fn process_events(&mut self) -> Result<Vec<DetectionEvent>, EbpfError> {
|
||||||
|
let mut detection_events = Vec::new();
|
||||||
|
|
||||||
|
let events = {
|
||||||
|
let mut buffer = self.ring_buffer.lock().unwrap();
|
||||||
|
buffer.drain_events()
|
||||||
|
};
|
||||||
|
|
||||||
|
for event in events {
|
||||||
|
// Apply filters
|
||||||
|
if self.filter_manager.should_process(&event) {
|
||||||
|
// Process event through detection rules
|
||||||
|
if let Some(detection) = self.event_processor.process_event(event) {
|
||||||
|
detection_events.push(detection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(detection_events)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile eBPF bytecode for process creation monitoring
|
||||||
|
fn compile_process_create_program(&self) -> Result<Vec<u8>, EbpfError> {
|
||||||
|
// In a real implementation, this would compile eBPF C code
|
||||||
|
// For now, return placeholder bytecode
|
||||||
|
Ok(vec![0; 512]) // Placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile eBPF bytecode for process exit monitoring
|
||||||
|
fn compile_process_exit_program(&self) -> Result<Vec<u8>, EbpfError> {
|
||||||
|
Ok(vec![0; 512]) // Placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile eBPF bytecode for memory mapping monitoring
|
||||||
|
fn compile_mmap_program(&self) -> Result<Vec<u8>, EbpfError> {
|
||||||
|
Ok(vec![0; 1024]) // Placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile eBPF bytecode for memory protection monitoring
|
||||||
|
fn compile_mprotect_program(&self) -> Result<Vec<u8>, EbpfError> {
|
||||||
|
Ok(vec![0; 1024]) // Placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile eBPF bytecode for ptrace monitoring
|
||||||
|
fn compile_ptrace_program(&self) -> Result<Vec<u8>, EbpfError> {
|
||||||
|
Ok(vec![0; 1024]) // Placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile eBPF bytecode for /proc/mem monitoring
|
||||||
|
fn compile_proc_mem_program(&self) -> Result<Vec<u8>, EbpfError> {
|
||||||
|
Ok(vec![0; 1024]) // Placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile eBPF bytecode for syscall monitoring
|
||||||
|
fn compile_syscall_program(&self) -> Result<Vec<u8>, EbpfError> {
|
||||||
|
Ok(vec![0; 2048]) // Placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get detection statistics
|
||||||
|
pub fn get_statistics(&self) -> EbpfStatistics {
|
||||||
|
EbpfStatistics {
|
||||||
|
loaded_programs: self.program_manager.loaded_programs.len(),
|
||||||
|
total_events_processed: 0, // Would be tracked in real implementation
|
||||||
|
detections_generated: 0, // Would be tracked in real implementation
|
||||||
|
filter_efficiency: 0.0, // Would be calculated in real implementation
|
||||||
|
performance_impact: 0.0, // Would be measured in real implementation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EbpfStatistics {
|
||||||
|
pub loaded_programs: usize,
|
||||||
|
pub total_events_processed: u64,
|
||||||
|
pub detections_generated: u64,
|
||||||
|
pub filter_efficiency: f32,
|
||||||
|
pub performance_impact: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum EbpfError {
|
||||||
|
#[error("Failed to load eBPF program: {0}")]
|
||||||
|
ProgramLoadError(String),
|
||||||
|
#[error("Failed to attach eBPF program: {0}")]
|
||||||
|
AttachError(String),
|
||||||
|
#[error("Event processing error: {0}")]
|
||||||
|
EventProcessingError(String),
|
||||||
|
#[error("Compilation error: {0}")]
|
||||||
|
CompilationError(String),
|
||||||
|
#[error("Permission denied: {0}")]
|
||||||
|
PermissionError(String),
|
||||||
|
#[error("Kernel version not supported: {0}")]
|
||||||
|
KernelVersionError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Placeholder implementations for handlers
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct ProcessCreateHandler;
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl ProcessCreateHandler {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl EventHandler for ProcessCreateHandler {
|
||||||
|
fn handle_event(&mut self, event: &EbpfEvent) -> Option<DetectionEvent> {
|
||||||
|
// Process creation event handling logic
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_event_type(&self) -> EventType {
|
||||||
|
EventType::ProcessCreate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct MemoryMapHandler;
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl MemoryMapHandler {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl EventHandler for MemoryMapHandler {
|
||||||
|
fn handle_event(&mut self, event: &EbpfEvent) -> Option<DetectionEvent> {
|
||||||
|
// Memory mapping event handling logic
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_event_type(&self) -> EventType {
|
||||||
|
EventType::MemoryMap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct MemoryProtectHandler;
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl MemoryProtectHandler {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl EventHandler for MemoryProtectHandler {
|
||||||
|
fn handle_event(&mut self, event: &EbpfEvent) -> Option<DetectionEvent> {
|
||||||
|
// Memory protection change event handling logic
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_event_type(&self) -> EventType {
|
||||||
|
EventType::MemoryProtect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub struct InjectionHandler;
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl InjectionHandler {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl EventHandler for InjectionHandler {
|
||||||
|
fn handle_event(&mut self, event: &EbpfEvent) -> Option<DetectionEvent> {
|
||||||
|
// Process injection event handling logic
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_event_type(&self) -> EventType {
|
||||||
|
EventType::ProcessInjection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Placeholder implementations for managers
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl EbpfProgramManager {
|
||||||
|
pub fn new() -> Result<Self, EbpfError> {
|
||||||
|
Ok(Self {
|
||||||
|
loaded_programs: HashMap::new(),
|
||||||
|
program_definitions: Vec::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_program(&mut self, program: EbpfProgramDefinition) -> Result<(), EbpfError> {
|
||||||
|
// eBPF program loading logic
|
||||||
|
println!("Loading eBPF program: {}", program.name);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl EbpfEventProcessor {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
event_handlers: HashMap::new(),
|
||||||
|
detection_rules: Vec::new(),
|
||||||
|
process_tracker: ProcessTracker::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_handler(&mut self, event_type: EventType, handler: Box<dyn EventHandler>) {
|
||||||
|
self.event_handlers.insert(event_type, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_event(&mut self, event: EbpfEvent) -> Option<DetectionEvent> {
|
||||||
|
// Event processing logic
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl ProcessTracker {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
processes: HashMap::new(),
|
||||||
|
process_tree: HashMap::new(),
|
||||||
|
injection_timeline: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl EbpfFilterManager {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
active_filters: HashMap::new(),
|
||||||
|
filter_statistics: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_filter(&mut self, filter: EbpfFilter) {
|
||||||
|
self.active_filters.insert(filter.filter_id.clone(), filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn should_process(&self, event: &EbpfEvent) -> bool {
|
||||||
|
// Filter evaluation logic
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
impl EbpfRingBuffer {
|
||||||
|
pub fn new(capacity: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
buffer: Vec::with_capacity(capacity),
|
||||||
|
read_index: 0,
|
||||||
|
write_index: 0,
|
||||||
|
capacity,
|
||||||
|
lost_events: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drain_events(&mut self) -> Vec<EbpfEvent> {
|
||||||
|
// Drain events from ring buffer
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For non-Linux systems, provide a stub implementation
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
pub struct EbpfDetector;
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
impl EbpfDetector {
|
||||||
|
pub fn new() -> Result<Self, &'static str> {
|
||||||
|
Err("eBPF detection is only supported on Linux")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initialize(&mut self) -> Result<(), &'static str> {
|
||||||
|
Err("eBPF detection is only supported on Linux")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user