use core::sync::atomic::{AtomicBool, Ordering};
use core::ptr;
use wdk::println;
use wdk_sys::NTSTATUS;
#[allow(non_camel_case_types)]
pub type PFLT_FILTER = PVOID;
#[allow(non_camel_case_types)]
pub type PFLT_INSTANCE = PVOID;
#[allow(non_camel_case_types)]
pub type PFLT_VOLUME = PVOID;
#[allow(non_camel_case_types)]
pub type PFLT_CALLBACK_DATA = PVOID;
#[allow(non_camel_case_types)]
pub type PCFLT_RELATED_OBJECTS = PVOID;
#[allow(non_camel_case_types)]
pub type FLT_PREOP_CALLBACK_STATUS = u32;
#[allow(non_camel_case_types)]
pub type FLT_POSTOP_CALLBACK_STATUS = u32;
pub const FLT_PREOP_SUCCESS_WITH_CALLBACK: FLT_PREOP_CALLBACK_STATUS = 0;
pub const FLT_PREOP_SUCCESS_NO_CALLBACK: FLT_PREOP_CALLBACK_STATUS = 1;
pub const FLT_PREOP_PENDING: FLT_PREOP_CALLBACK_STATUS = 2;
pub const FLT_PREOP_DISALLOW_FASTIO: FLT_PREOP_CALLBACK_STATUS = 3;
pub const FLT_PREOP_COMPLETE: FLT_PREOP_CALLBACK_STATUS = 4;
pub const FLT_PREOP_SYNCHRONIZE: FLT_PREOP_CALLBACK_STATUS = 5;
pub const FLT_POSTOP_FINISHED_PROCESSING: FLT_POSTOP_CALLBACK_STATUS = 0;
pub const FLT_POSTOP_MORE_PROCESSING_REQUIRED: FLT_POSTOP_CALLBACK_STATUS = 1;
pub const FLT_POSTOP_DISALLOW_FSFILTER_OP: FLT_POSTOP_CALLBACK_STATUS = 2;
pub const STATUS_FLT_DO_NOT_ATTACH: NTSTATUS = -1071962673i32;
use wdk_sys::PVOID;
#[repr(C)]
#[allow(non_snake_case)]
pub struct FLT_OPERATION_REGISTRATION {
pub MajorFunction: u8,
pub Flags: u32,
pub PreOperation: Option<unsafe extern "C" fn(
PFLT_CALLBACK_DATA, PCFLT_RELATED_OBJECTS, *mut PVOID
) -> FLT_PREOP_CALLBACK_STATUS>,
pub PostOperation: Option<unsafe extern "C" fn(
PFLT_CALLBACK_DATA, PCFLT_RELATED_OBJECTS, PVOID, u32
) -> FLT_POSTOP_CALLBACK_STATUS>,
pub Reserved1: PVOID,
}
#[repr(C)]
#[allow(non_snake_case)]
pub struct FLT_REGISTRATION {
pub Size: u16,
pub Version: u16,
pub Flags: u32,
pub ContextRegistration: PVOID,
pub OperationRegistration: *const FLT_OPERATION_REGISTRATION,
pub FilterUnloadCallback: Option<unsafe extern "C" fn(u32) -> NTSTATUS>,
pub InstanceSetupCallback: Option<unsafe extern "C" fn(
PCFLT_RELATED_OBJECTS, u32, u32, u32
) -> NTSTATUS>,
pub InstanceQueryTeardownCallback: Option<unsafe extern "C" fn(
PCFLT_RELATED_OBJECTS, u32
) -> NTSTATUS>,
pub InstanceTeardownStartCallback: Option<unsafe extern "C" fn(
PCFLT_RELATED_OBJECTS, u32
)>,
pub InstanceTeardownCompleteCallback: Option<unsafe extern "C" fn(
PCFLT_RELATED_OBJECTS, u32
)>,
pub GenerateFileNameCallback: PVOID,
pub NormalizeNameComponentCallback: PVOID,
pub NormalizeContextCleanupCallback: PVOID,
pub TransactionNotificationCallback: PVOID,
pub NormalizeNameComponentExCallback: PVOID,
pub SectionNotificationCallback: PVOID,
}
static REGISTERED: AtomicBool = AtomicBool::new(false);
static mut FILTER_HANDLE: PFLT_FILTER = ptr::null_mut();
pub const FILTER_ALTITUDE: &str = "370030";
const SCANNABLE_EXTENSIONS: &[&str] = &[
".exe", ".dll", ".sys", ".scr", ".bat", ".cmd", ".ps1",
".vbs", ".js", ".hta", ".msi", ".jar",
];
const PROTECTED_PATHS: &[&str] = &[
"\\Windows\\System32\\",
"\\Windows\\SysWOW64\\",
"\\Program Files\\",
"\\Program Files (x86)\\",
];
const RANSOMWARE_EXTENSIONS: &[&str] = &[
".encrypted", ".locked", ".crypto", ".locky", ".zepto",
".cerber", ".crypt", ".cry", ".wncry",
];
mod irp_mj {
pub const CREATE: u8 = 0x00;
pub const READ: u8 = 0x03;
pub const WRITE: u8 = 0x04;
pub const SET_INFORMATION: u8 = 0x06; pub const CLEANUP: u8 = 0x12;
pub const CLOSE: u8 = 0x02;
}
pub unsafe fn register(_driver_object: PVOID) -> Result<(), NTSTATUS> {
if REGISTERED.load(Ordering::SeqCst) {
return Ok(());
}
println!("[Leviathan] Minifilter registration skipped - not available in wdk-sys 0.5");
println!("[Leviathan] To enable: add minifilter feature flags to wdk-sys dependency");
REGISTERED.store(true, Ordering::SeqCst);
Ok(())
}
pub unsafe fn unregister() {
if !REGISTERED.load(Ordering::SeqCst) {
return;
}
REGISTERED.store(false, Ordering::SeqCst);
println!("[Leviathan] Minifilter unregistered");
}
unsafe extern "C" fn filter_unload(_flags: u32) -> NTSTATUS {
println!("[Leviathan] Minifilter unload requested");
unsafe { unregister() };
0 }
unsafe extern "C" fn instance_setup(
_flt_objects: PCFLT_RELATED_OBJECTS,
_flags: u32,
_volume_device_type: u32,
_volume_filesystem_type: u32,
) -> NTSTATUS {
println!("[Leviathan] Attaching to volume");
0 }
unsafe extern "C" fn pre_create(
_data: PFLT_CALLBACK_DATA,
_flt_objects: PCFLT_RELATED_OBJECTS,
_completion_context: *mut PVOID,
) -> FLT_PREOP_CALLBACK_STATUS {
FLT_PREOP_SUCCESS_WITH_CALLBACK
}
unsafe extern "C" fn post_create(
_data: PFLT_CALLBACK_DATA,
_flt_objects: PCFLT_RELATED_OBJECTS,
_completion_context: PVOID,
_flags: u32,
) -> FLT_POSTOP_CALLBACK_STATUS {
FLT_POSTOP_FINISHED_PROCESSING
}
unsafe extern "C" fn pre_read(
_data: PFLT_CALLBACK_DATA,
_flt_objects: PCFLT_RELATED_OBJECTS,
_completion_context: *mut PVOID,
) -> FLT_PREOP_CALLBACK_STATUS {
FLT_PREOP_SUCCESS_NO_CALLBACK
}
unsafe extern "C" fn pre_write(
_data: PFLT_CALLBACK_DATA,
_flt_objects: PCFLT_RELATED_OBJECTS,
_completion_context: *mut PVOID,
) -> FLT_PREOP_CALLBACK_STATUS {
FLT_PREOP_SUCCESS_NO_CALLBACK
}
unsafe extern "C" fn pre_set_information(
_data: PFLT_CALLBACK_DATA,
_flt_objects: PCFLT_RELATED_OBJECTS,
_completion_context: *mut PVOID,
) -> FLT_PREOP_CALLBACK_STATUS {
FLT_PREOP_SUCCESS_NO_CALLBACK
}
unsafe extern "C" fn post_cleanup(
_data: PFLT_CALLBACK_DATA,
_flt_objects: PCFLT_RELATED_OBJECTS,
_completion_context: PVOID,
_flags: u32,
) -> FLT_POSTOP_CALLBACK_STATUS {
FLT_POSTOP_FINISHED_PROCESSING
}
#[allow(dead_code)]
fn calculate_entropy(data: &[u8]) -> f32 {
if data.is_empty() {
return 0.0;
}
let mut freq = [0u32; 256];
for &byte in data {
freq[byte as usize] += 1;
}
let len = data.len() as f32;
let mut entropy = 0.0f32;
for &count in &freq {
if count > 0 {
let p = count as f32 / len;
entropy -= p * libm::log2f(p);
}
}
entropy
}
#[allow(dead_code)]
fn is_ransomware_behavior(
_process_id: usize,
_files_modified: usize,
_files_renamed: usize,
avg_entropy: f32,
) -> bool {
avg_entropy > 7.5
}