2025-11-07 18:05:07 +02:00
|
|
|
use anyhow::Result;
|
2025-11-08 11:48:20 +02:00
|
|
|
use clap::{Arg, Command};
|
2025-11-08 11:09:18 +02:00
|
|
|
use ghost_core::{memory, process, thread, DetectionEngine, ThreatLevel};
|
2025-11-08 11:48:20 +02:00
|
|
|
use std::time::Instant;
|
2025-11-07 18:05:07 +02:00
|
|
|
|
|
|
|
|
fn main() -> Result<()> {
|
|
|
|
|
env_logger::init();
|
|
|
|
|
|
2025-11-08 11:48:20 +02:00
|
|
|
let matches = Command::new("ghost")
|
|
|
|
|
.version("0.1.0")
|
|
|
|
|
.about("Cross-Platform Process Injection Detection Framework")
|
|
|
|
|
.arg(
|
|
|
|
|
Arg::new("format")
|
|
|
|
|
.short('f')
|
|
|
|
|
.long("format")
|
|
|
|
|
.value_name("FORMAT")
|
|
|
|
|
.help("Output format: table, json")
|
|
|
|
|
.default_value("table")
|
2025-11-08 12:21:27 +02:00
|
|
|
.value_parser(["table", "json", "csv"])
|
2025-11-08 11:48:20 +02:00
|
|
|
)
|
|
|
|
|
.arg(
|
|
|
|
|
Arg::new("verbose")
|
|
|
|
|
.short('v')
|
|
|
|
|
.long("verbose")
|
|
|
|
|
.help("Enable verbose output")
|
|
|
|
|
.action(clap::ArgAction::SetTrue)
|
|
|
|
|
)
|
2025-11-08 12:20:02 +02:00
|
|
|
.arg(
|
|
|
|
|
Arg::new("pid")
|
|
|
|
|
.short('p')
|
|
|
|
|
.long("pid")
|
|
|
|
|
.value_name("PID")
|
|
|
|
|
.help("Target specific process ID")
|
|
|
|
|
)
|
2025-11-08 11:48:20 +02:00
|
|
|
.get_matches();
|
|
|
|
|
|
|
|
|
|
let format = matches.get_one::<String>("format").unwrap();
|
|
|
|
|
let verbose = matches.get_flag("verbose");
|
2025-11-08 12:20:02 +02:00
|
|
|
let target_pid = matches.get_one::<String>("pid");
|
2025-11-08 11:48:20 +02:00
|
|
|
|
2025-11-07 18:08:21 +02:00
|
|
|
println!("Ghost v0.1.0 - Process Injection Detection\n");
|
2025-11-07 18:05:07 +02:00
|
|
|
|
2025-11-08 11:48:20 +02:00
|
|
|
let scan_start = Instant::now();
|
2025-11-07 18:08:21 +02:00
|
|
|
let mut engine = DetectionEngine::new();
|
2025-11-08 12:20:02 +02:00
|
|
|
|
|
|
|
|
let processes = if let Some(pid_str) = target_pid {
|
2025-11-08 12:21:52 +02:00
|
|
|
let pid: u32 = pid_str.parse().map_err(|_| anyhow::anyhow!("Invalid PID format: {}", pid_str))?;
|
|
|
|
|
let all_processes = process::enumerate_processes()?;
|
|
|
|
|
let filtered: Vec<_> = all_processes
|
2025-11-08 12:20:02 +02:00
|
|
|
.into_iter()
|
|
|
|
|
.filter(|p| p.pid == pid)
|
2025-11-08 12:21:52 +02:00
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
if filtered.is_empty() {
|
|
|
|
|
println!("Warning: No process found with PID {}", pid);
|
|
|
|
|
}
|
|
|
|
|
filtered
|
2025-11-08 12:20:02 +02:00
|
|
|
} else {
|
|
|
|
|
process::enumerate_processes()?
|
|
|
|
|
};
|
2025-11-07 18:05:07 +02:00
|
|
|
|
2025-11-07 18:08:21 +02:00
|
|
|
println!("Scanning {} processes...\n", processes.len());
|
2025-11-07 18:05:07 +02:00
|
|
|
|
2025-11-07 18:08:21 +02:00
|
|
|
let mut detections = Vec::new();
|
|
|
|
|
|
|
|
|
|
for proc in &processes {
|
2025-11-08 11:10:43 +02:00
|
|
|
// Skip known safe system processes for performance
|
|
|
|
|
if proc.name == "csrss.exe" || proc.name == "wininit.exe" || proc.name == "winlogon.exe" {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-07 18:05:07 +02:00
|
|
|
if let Ok(regions) = memory::enumerate_memory_regions(proc.pid) {
|
2025-11-08 11:09:18 +02:00
|
|
|
// Get thread information if available
|
|
|
|
|
let threads = thread::enumerate_threads(proc.pid).ok();
|
|
|
|
|
let result = engine.analyze_process(proc, ®ions, threads.as_deref());
|
2025-11-07 18:08:21 +02:00
|
|
|
|
|
|
|
|
if result.threat_level != ThreatLevel::Clean {
|
|
|
|
|
detections.push(result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if detections.is_empty() {
|
|
|
|
|
println!("No suspicious activity detected.");
|
|
|
|
|
} else {
|
|
|
|
|
println!("Found {} suspicious processes:\n", detections.len());
|
|
|
|
|
|
|
|
|
|
for detection in detections {
|
|
|
|
|
let level_str = match detection.threat_level {
|
|
|
|
|
ThreatLevel::Suspicious => "SUSPICIOUS",
|
|
|
|
|
ThreatLevel::Malicious => "MALICIOUS",
|
|
|
|
|
_ => "CLEAN",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
println!(
|
|
|
|
|
"[{}] {} (PID: {}) - Confidence: {:.1}%",
|
|
|
|
|
level_str,
|
|
|
|
|
detection.process.name,
|
|
|
|
|
detection.process.pid,
|
|
|
|
|
detection.confidence * 100.0
|
|
|
|
|
);
|
2025-11-07 18:05:07 +02:00
|
|
|
|
2025-11-07 18:08:21 +02:00
|
|
|
for indicator in &detection.indicators {
|
|
|
|
|
println!(" - {}", indicator);
|
2025-11-07 18:05:07 +02:00
|
|
|
}
|
2025-11-07 18:08:21 +02:00
|
|
|
println!();
|
2025-11-07 18:05:07 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|