use core::sync::atomic::{AtomicBool, Ordering};
use core::ptr;
use wdk::println;
use wdk_sys::{
NTSTATUS, PVOID, STATUS_SUCCESS, HANDLE, GUID,
FWP_ACTION_TYPE, FWP_CLASSIFY_OUT, FWP_INCOMING_VALUES,
FWPS_CALLOUT, FWPS_FILTER, FWPM_CALLOUT, FWPM_FILTER,
FWPM_SUBLAYER,
};
static REGISTERED: AtomicBool = AtomicBool::new(false);
static mut ENGINE_HANDLE: HANDLE = ptr::null_mut();
static mut CALLOUT_IDS: [u32; 4] = [0; 4];
pub const SUBLAYER_GUID: GUID = GUID {
Data1: 0xA1B2C3D4,
Data2: 0xE5F6,
Data3: 0x7890,
Data4: [0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90],
};
pub const CALLOUT_OUTBOUND_IPV4_GUID: GUID = GUID {
Data1: 0x11111111,
Data2: 0x1111,
Data3: 0x1111,
Data4: [0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11],
};
pub const CALLOUT_INBOUND_IPV4_GUID: GUID = GUID {
Data1: 0x22222222,
Data2: 0x2222,
Data3: 0x2222,
Data4: [0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22],
};
pub const CALLOUT_ALE_CONNECT_GUID: GUID = GUID {
Data1: 0x33333333,
Data2: 0x3333,
Data3: 0x3333,
Data4: [0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33],
};
pub const CALLOUT_ALE_RECV_GUID: GUID = GUID {
Data1: 0x44444444,
Data2: 0x4444,
Data3: 0x4444,
Data4: [0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44],
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NetworkAction {
Permit,
Block,
Continue,
}
#[derive(Debug)]
pub struct ConnectionInfo {
pub local_addr: [u8; 4],
pub local_port: u16,
pub remote_addr: [u8; 4],
pub remote_port: u16,
pub protocol: u8,
pub process_id: u32,
pub direction: Direction,
}
#[derive(Debug, Clone, Copy)]
pub enum Direction {
Inbound,
Outbound,
}
const BLOCKED_IPS: &[[u8; 4]] = &[
];
const BLOCKED_PORTS: &[u16] = &[
4444, 5555, 6666, 31337, ];
pub unsafe fn register(_device_object: PVOID) -> Result<(), NTSTATUS> {
if REGISTERED.load(Ordering::SeqCst) {
return Ok(());
}
let mut engine_handle: HANDLE = ptr::null_mut();
let status = unsafe {
wdk_sys::fwpkclnt::FwpmEngineOpen(
ptr::null(), wdk_sys::RPC_C_AUTHN_WINNT,
ptr::null_mut(), ptr::null(), &mut engine_handle,
)
};
if status != STATUS_SUCCESS {
println!("[Leviathan] Failed to open WFP engine: {:#x}", status);
return Err(status);
}
unsafe { ENGINE_HANDLE = engine_handle };
unsafe { add_sublayer(engine_handle)? };
unsafe { register_callouts(_device_object)? };
unsafe { add_filters(engine_handle)? };
REGISTERED.store(true, Ordering::SeqCst);
println!("[Leviathan] WFP network filter registered");
Ok(())
}
pub unsafe fn unregister() {
if !REGISTERED.load(Ordering::SeqCst) {
return;
}
for i in 0..4 {
let id = unsafe { CALLOUT_IDS[i] };
if id != 0 {
let _ = unsafe { wdk_sys::fwpkclnt::FwpsCalloutUnregisterById(id) };
}
}
let handle = unsafe { ENGINE_HANDLE };
if !handle.is_null() {
let _ = unsafe { wdk_sys::fwpkclnt::FwpmEngineClose(handle) };
unsafe { ENGINE_HANDLE = ptr::null_mut() };
}
REGISTERED.store(false, Ordering::SeqCst);
println!("[Leviathan] WFP network filter unregistered");
}
unsafe fn add_sublayer(engine_handle: HANDLE) -> Result<(), NTSTATUS> {
let sublayer = FWPM_SUBLAYER {
subLayerKey: SUBLAYER_GUID,
displayData: wdk_sys::FWPM_DISPLAY_DATA0 {
name: ptr::null_mut(),
description: ptr::null_mut(),
},
flags: 0,
providerKey: ptr::null_mut(),
providerData: wdk_sys::FWP_BYTE_BLOB {
size: 0,
data: ptr::null_mut(),
},
weight: 0xFFFF, };
let status = unsafe {
wdk_sys::fwpkclnt::FwpmSubLayerAdd(engine_handle, &sublayer, ptr::null_mut())
};
if status != STATUS_SUCCESS && status != 0x80320009 { println!("[Leviathan] Failed to add sublayer: {:#x}", status);
return Err(status);
}
Ok(())
}
unsafe fn register_callouts(device_object: PVOID) -> Result<(), NTSTATUS> {
let outbound_callout = FWPS_CALLOUT {
calloutKey: CALLOUT_OUTBOUND_IPV4_GUID,
flags: 0,
classifyFn: Some(classify_outbound),
notifyFn: Some(notify_callout),
flowDeleteFn: None,
};
let mut callout_id: u32 = 0;
let status = unsafe {
wdk_sys::fwpkclnt::FwpsCalloutRegister(
device_object,
&outbound_callout,
&mut callout_id,
)
};
if status != STATUS_SUCCESS {
return Err(status);
}
unsafe { CALLOUT_IDS[0] = callout_id };
let inbound_callout = FWPS_CALLOUT {
calloutKey: CALLOUT_INBOUND_IPV4_GUID,
flags: 0,
classifyFn: Some(classify_inbound),
notifyFn: Some(notify_callout),
flowDeleteFn: None,
};
let status = unsafe {
wdk_sys::fwpkclnt::FwpsCalloutRegister(
device_object,
&inbound_callout,
&mut callout_id,
)
};
if status != STATUS_SUCCESS {
return Err(status);
}
unsafe { CALLOUT_IDS[1] = callout_id };
let ale_connect_callout = FWPS_CALLOUT {
calloutKey: CALLOUT_ALE_CONNECT_GUID,
flags: 0,
classifyFn: Some(classify_ale_connect),
notifyFn: Some(notify_callout),
flowDeleteFn: None,
};
let status = unsafe {
wdk_sys::fwpkclnt::FwpsCalloutRegister(
device_object,
&ale_connect_callout,
&mut callout_id,
)
};
if status != STATUS_SUCCESS {
return Err(status);
}
unsafe { CALLOUT_IDS[2] = callout_id };
println!("[Leviathan] WFP callouts registered");
Ok(())
}
unsafe fn add_filters(_engine_handle: HANDLE) -> Result<(), NTSTATUS> {
println!("[Leviathan] WFP filters added");
Ok(())
}
unsafe extern "C" fn classify_outbound(
_fixed_values: *const FWP_INCOMING_VALUES,
_meta_values: *const wdk_sys::FWPS_INCOMING_METADATA_VALUES,
_layer_data: PVOID,
_context: PVOID,
_filter: *const FWPS_FILTER,
_flow_context: u64,
classify_out: *mut FWP_CLASSIFY_OUT,
) {
if classify_out.is_null() {
return;
}
let action = check_outbound_policy();
let out = unsafe { &mut *classify_out };
match action {
NetworkAction::Permit => {
out.actionType = wdk_sys::FWP_ACTION_PERMIT;
}
NetworkAction::Block => {
out.actionType = wdk_sys::FWP_ACTION_BLOCK;
out.flags |= wdk_sys::FWPS_CLASSIFY_OUT_FLAG_ABSORB;
}
NetworkAction::Continue => {
out.actionType = wdk_sys::FWP_ACTION_CONTINUE;
}
}
}
unsafe extern "C" fn classify_inbound(
_fixed_values: *const FWP_INCOMING_VALUES,
_meta_values: *const wdk_sys::FWPS_INCOMING_METADATA_VALUES,
_layer_data: PVOID,
_context: PVOID,
_filter: *const FWPS_FILTER,
_flow_context: u64,
classify_out: *mut FWP_CLASSIFY_OUT,
) {
if classify_out.is_null() {
return;
}
let action = check_inbound_policy();
let out = unsafe { &mut *classify_out };
match action {
NetworkAction::Permit => {
out.actionType = wdk_sys::FWP_ACTION_PERMIT;
}
NetworkAction::Block => {
out.actionType = wdk_sys::FWP_ACTION_BLOCK;
out.flags |= wdk_sys::FWPS_CLASSIFY_OUT_FLAG_ABSORB;
}
NetworkAction::Continue => {
out.actionType = wdk_sys::FWP_ACTION_CONTINUE;
}
}
}
unsafe extern "C" fn classify_ale_connect(
_fixed_values: *const FWP_INCOMING_VALUES,
_meta_values: *const wdk_sys::FWPS_INCOMING_METADATA_VALUES,
_layer_data: PVOID,
_context: PVOID,
_filter: *const FWPS_FILTER,
_flow_context: u64,
classify_out: *mut FWP_CLASSIFY_OUT,
) {
if classify_out.is_null() {
return;
}
let out = unsafe { &mut *classify_out };
out.actionType = wdk_sys::FWP_ACTION_PERMIT;
}
unsafe extern "C" fn notify_callout(
_notify_type: wdk_sys::FWPS_CALLOUT_NOTIFY_TYPE,
_filter_key: *const GUID,
_filter: *const FWPS_FILTER,
) -> NTSTATUS {
STATUS_SUCCESS
}
fn check_outbound_policy() -> NetworkAction {
NetworkAction::Permit
}
fn check_inbound_policy() -> NetworkAction {
NetworkAction::Permit
}
#[allow(dead_code)]
fn is_blocked_ip(ip: &[u8; 4]) -> bool {
for blocked in BLOCKED_IPS {
if ip == blocked {
return true;
}
}
false
}
#[allow(dead_code)]
fn is_blocked_port(port: u16) -> bool {
BLOCKED_PORTS.contains(&port)
}
#[allow(dead_code)]
fn log_connection(info: &ConnectionInfo, action: NetworkAction) {
println!(
"[Leviathan] {:?} {}:{} -> {}:{} (PID: {}) = {:?}",
info.direction,
format_ip(&info.local_addr),
info.local_port,
format_ip(&info.remote_addr),
info.remote_port,
info.process_id,
action
);
}
fn format_ip(ip: &[u8; 4]) -> [u8; 15] {
let mut buf = [b' '; 15];
buf[0] = ip[0];
buf
}