Skip to content

Commit

Permalink
A few changes (#2)
Browse files Browse the repository at this point in the history
see CHANGELOG v0.5.0
  • Loading branch information
sn99 authored Nov 9, 2022
1 parent 02626bd commit 3aa5485
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 70 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# v0.5.0

- Replace `ZwClose` with `FltClose` in minifilter to solve potential memory leak
- Remove unused dependencies and add categories to `Cargo.toml`
- Vastly improve documentation
- Refactor code to be more readable and conscience

# v0.4.0

- Improve performance even further
Expand Down
13 changes: 4 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
[package]
name = "fsfilter-rs"
version = "0.4.0"
version = "0.5.0"
edition = "2021"
authors = ["sn99 <[email protected]>"]
description = "A rust library to monitor filesystem and more in windows"
repository = "https://github.com/sn99/fsfilter-rs"
repository = "https://github.com/SubconsciousCompute/fsfilter-rs"
homepage = "https://github.com/SubconsciousCompute/fsfilter-rs"
license = "MIT"
readme = "README.md"
keywords = ["filesystem", "driver", "windows", "minifilter", "syscalls"]
categories = ["development-tools", "os::windows-apis", "filesystem", "api-bindings"]
documentation = "https://docs.rs/fsfilter-rs"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
sysinfo = "0.26.4"
widestring = "1.0.1"
serde_json = "1.0.68"
serde = { version = "1.0.130", features = ["derive"] }
num = "0.4"
num-derive = "0.3"
num-traits = "0.2.14"
strum = "0.24.1"
strum_macros = "0.24.3"
wchar = "0.11.0"
kodama = "0.2.3"

[dependencies.windows]
version = "0.43.0"
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ You can also build using [EWDK](EWDKbuild.md) if you don't want to install Visua
### RUNNING EXAMPLE

Use `cargo run --bin minifilter --release` to run the example application or just [run the `.exe` provided in
releases](https://github.com/SubconsciousCompute/fsfilter-rs/releases/latest/download/minifilter.exe).
releases](https://github.com/SubconsciousCompute/fsfilter-rs/releases/latest/download/minifilter.exe) as administrator (
for some reason the new default terminal on 2H22 is very, very slow
).

The program starts to print the `IOMessage` which is defined like:

Expand Down
6 changes: 3 additions & 3 deletions minifilter/snFilter/snFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1186,7 +1186,7 @@ VOID AddRemProcessRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
if (!NT_SUCCESS(hr))
{
DbgPrint("!!! snFilter: Failed to open process: %#010x.\n", hr);
hr = ZwClose(procHandleParent);
hr = FltClose(procHandleParent);
if (!NT_SUCCESS(hr))
{
DbgPrint("!!! snFilter: Failed to close process: %#010x.\n", hr);
Expand All @@ -1212,13 +1212,13 @@ VOID AddRemProcessRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)

DbgPrint("!!! snFilter: New Process, parent: %wZ. Pid: %d\n", parentName, (ULONG)(ULONG_PTR)ParentId);

hr = ZwClose(procHandleParent);
hr = FltClose(procHandleParent);
if (!NT_SUCCESS(hr))
{
DbgPrint("!!! snFilter: Failed to close process: %#010x.\n", hr);
return;
}
hr = ZwClose(procHandleProcess);
hr = FltClose(procHandleProcess);
if (!NT_SUCCESS(hr))
{
DbgPrint("!!! snFilter: Failed to close process: %#010x.\n", hr);
Expand Down
2 changes: 1 addition & 1 deletion src/bin/minifilter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn main() {
loop {
if let Ok(mut io_message) = rx_iomsgs.recv() {
io_message.exepath();
write!(lock, "{:?}", io_message);
write!(lock, "{io_message:?}");
}
}
}
Expand Down
89 changes: 55 additions & 34 deletions src/driver_comm.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! Low-level communication with the minifilter.
use core::ffi::c_void;
use std::mem;
use std::os::raw::*;
use std::os::raw::{c_ulong, c_ulonglong};
use std::ptr;

use sysinfo::{get_current_pid, Pid, PidExt};
Expand All @@ -19,6 +18,7 @@ use crate::driver_comm::DriveType::{
DriveCDRom, DriveFixed, DriveNoRootDir, DriveRamDisk, DriveRemote, DriveRemovable, DriveUnknown,
};
use crate::driver_comm::IrpMajorOp::{IrpCreate, IrpNone, IrpRead, IrpSetInfo, IrpWrite};
use crate::shared_def;
use crate::shared_def::ReplyIrp;

type BufPath = [wchar_t; 520];
Expand Down Expand Up @@ -72,54 +72,70 @@ impl Driver {
}

/// The user-mode running app (this one) has to register itself to the driver.
///
/// # Panics
/// This fn panics if it is unable to get the current pid.
///
/// # Errors
/// This fn returns an error if it is unable to register itself to the minifilter.
#[inline]
pub fn driver_set_app_pid(&self) -> Result<(), windows::core::Error> {
let buf = Driver::string_to_commessage_buffer(r"\Device\harddiskVolume");
let buf = Self::string_to_commessage_buffer(r"\Device\harddiskVolume");

let mut get_irp_msg: DriverComMessage = DriverComMessage {
r#type: DriverComMessageType::SetPid as c_ulong,
pid: get_current_pid().unwrap().as_u32() as c_ulong,
gid: 140713315094899,
gid: 140_713_315_094_899,
path: buf, //wch!("\0"),
};
let mut tmp: u32 = 0;

unsafe {
FilterSendMessage(
self.handle,
ptr::addr_of_mut!(get_irp_msg) as *mut c_void,
ptr::addr_of_mut!(get_irp_msg).cast::<std::ffi::c_void>(),
mem::size_of::<DriverComMessage>() as c_ulong,
None,
0,
&mut tmp as *mut u32,
std::ptr::addr_of_mut!(tmp),
)
}
}

/// Try to open a com canal with the minifilter before this app is registered. This fn can fail
/// is the minifilter is unreachable:
/// Try to open a com canal with the minifilter before this app is registered.
///
/// # Panics
/// This function will panic if the minifilter port has any nul value (except the last one)
/// in it's name.
///
/// # Errors
/// This fn can fail is the minifilter is unreachable:
///
/// * if it is not started (try `sc start snFilter` first
/// * if a connection is already established: it can accepts only one at a time.
///
/// In that case the Error is raised by the OS (windows::Error) and is generally readable.
/// In that case the Error is raised by the OS (`windows::Error`) and is generally readable.
#[inline]
pub fn open_kernel_driver_com() -> Result<Driver, windows::core::Error> {
let _com_port_name = U16CString::from_str("\\snFilter").unwrap().into_raw();
let _handle;
pub fn open_kernel_driver_com() -> Result<Self, windows::core::Error> {
let com_port_name = U16CString::from_str("\\snFilter").unwrap().into_raw();
let handle;
unsafe {
_handle = FilterConnectCommunicationPort(PCWSTR(_com_port_name), 0, None, 0, None)?
handle = FilterConnectCommunicationPort(PCWSTR(com_port_name), 0, None, 0, None)?;
}
let res = Driver { handle: _handle };
let res = Self { handle };
Ok(res)
}

/// Ask the driver for a [ReplyIrp], if any. This is a low-level function and the returned object
/// Ask the driver for a [`ReplyIrp`], if any. This is a low-level function and the returned object
/// uses C pointers. Managing C pointers requires a special care, because of the Rust timelines.
/// [ReplyIrp] is optional since the minifilter returns null if there is no new activity.
/// [`ReplyIrp`] is optional since the minifilter returns null if there is no new activity.
///
/// # Panics
/// This fn panics if it is unable to get the current pid or cannot get driver message from the
/// minifilter.
#[inline]
pub fn get_irp(&self, vecnew: &mut Vec<u8>) -> Option<ReplyIrp> {
let mut get_irp_msg = Driver::build_irp_msg(
let mut get_irp_msg = Self::build_irp_msg(
DriverComMessageType::GetOps,
get_current_pid().unwrap(),
0,
Expand All @@ -130,27 +146,28 @@ impl Driver {
unsafe {
FilterSendMessage(
self.handle,
ptr::addr_of_mut!(get_irp_msg) as *mut c_void,
ptr::addr_of_mut!(get_irp_msg).cast::<std::ffi::c_void>(),
mem::size_of::<DriverComMessage>() as c_ulong,
Option::from(vecnew.as_ptr() as *mut c_void),
Option::from(vecnew.as_mut_ptr().cast::<std::ffi::c_void>()),
65536_u32,
ptr::addr_of_mut!(tmp) as *mut u32,
ptr::addr_of_mut!(tmp).cast::<u32>(),
)
.expect("Cannot get driver message from driver");
}

if tmp != 0 {
let reply_irp: ReplyIrp;
unsafe {
reply_irp = std::ptr::read_unaligned(vecnew.as_ptr() as *const ReplyIrp);
reply_irp =
std::ptr::read_unaligned(vecnew.as_ptr().cast::<shared_def::ReplyIrp>());
}
return Some(reply_irp);
}
None
}

/// Ask the minifilter to kill all pids related to the given *gid*. Pids are killed in driver-mode
/// by calls to NtClose.
/// by calls to `NtClose`.
#[inline]
pub fn try_kill(&self, gid: c_ulonglong) -> Result<HRESULT, windows::core::Error> {
let mut killmsg = DriverComMessage {
Expand All @@ -165,11 +182,11 @@ impl Driver {
unsafe {
FilterSendMessage(
self.handle,
ptr::addr_of_mut!(killmsg) as *mut c_void,
ptr::addr_of_mut!(killmsg).cast::<std::ffi::c_void>(),
mem::size_of::<DriverComMessage>() as c_ulong,
Option::from(ptr::addr_of_mut!(res) as *mut c_void),
Option::from(ptr::addr_of_mut!(res).cast::<std::ffi::c_void>()),
4_u32,
ptr::addr_of_mut!(res_size) as *mut u32,
ptr::addr_of_mut!(res_size).cast::<u32>(),
)?;
}

Expand All @@ -178,7 +195,7 @@ impl Driver {

#[inline]
fn string_to_commessage_buffer(bufstr: &str) -> BufPath {
let temp = U16CString::from_str(&bufstr).unwrap();
let temp = U16CString::from_str(bufstr).unwrap();
let mut buf: BufPath = [0; 520];
for (i, c) in temp.as_slice_with_nul().iter().enumerate() {
buf[i] = *c as wchar_t;
Expand All @@ -198,7 +215,7 @@ impl Driver {
r#type: commsgtype as c_ulong, // SetPid
pid: pid.as_u32() as c_ulong,
gid,
path: Driver::string_to_commessage_buffer(path),
path: Self::string_to_commessage_buffer(path),
}
}
}
Expand All @@ -223,14 +240,14 @@ pub enum IrpMajorOp {
}

impl IrpMajorOp {
pub fn from_byte(b: u8) -> IrpMajorOp {
#[inline]
pub fn from_byte(b: u8) -> Self {
match b {
0 => IrpNone,
// 0 => IrpNone,
1 => IrpRead,
2 => IrpWrite,
3 => IrpSetInfo,
4 => IrpCreate,
5 => IrpCreate,
4 | 5 => IrpCreate,
_ => IrpNone,
}
}
Expand All @@ -257,18 +274,22 @@ pub enum DriveType {
}

impl DriveType {
/// Determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive.
///
/// # Panics
/// Will panic if drive path is invalid.
#[inline]
pub fn from_filepath(filepath: String) -> DriveType {
pub fn from_filepath(filepath: &str) -> Self {
let mut drive_type = 1u32;
if !filepath.is_empty() {
let drive_path = &filepath[..(filepath.find('\\').unwrap() + 1)];
let drive_path = &filepath[..=filepath.find('\\').unwrap()];
unsafe {
drive_type = GetDriveTypeA(PCSTR(String::from(drive_path).as_ptr()));
}
}
match drive_type {
0 => DriveUnknown,
1 => DriveNoRootDir,
// 1 => DriveNoRootDir,
2 => DriveRemovable,
3 => DriveFixed,
4 => DriveRemote,
Expand Down
26 changes: 13 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! # minifilter-rs
//!
//! Checkout the [README](https://github.com/sn99/fsfilter-rs/blob/master/README.md) too at github.
//! Checkout the [README](https://github.com/SubconsciousCompute/fsfilter-rs/blob/master/README.md) too at github.
//!
//! **Use `cargo doc --no-deps --document-private-items --open` to read Documentation**
//!
Expand All @@ -9,14 +9,14 @@
//! <details>
//! <summary>Table of Contents</summary>
//!
//! - [Minifilter Driver](https://!github.com/sn99/fsfilter-rs#minifilter-driver)
//! - [Building Driver](https://!github.com/sn99/fsfilter-rs#building-driver)
//! - [Installing Driver](https://!github.com/sn99/fsfilter-rs#building-driver)
//! - [Loading/Removing Driver](https://!github.com/sn99/fsfilter-rs#loadingremoving-driver)
//! - [Rust Application](https://!github.com/sn99/fsfilter-rs#rust-application)
//! - [Building Rust App](https://!github.com/sn99/fsfilter-rs#building-rust-app)
//! - [Running Rust App](https://!github.com/sn99/fsfilter-rs#running-rust-app)
//! - [What and the How](https://!github.com/sn99/fsfilter-rs#what-and-the-how)
//! - [Minifilter Driver](https://!github.com/SubconsciousCompute/fsfilter-rs#minifilter-driver)
//! - [Building Driver](https://!github.com/SubconsciousCompute/fsfilter-rs#building-driver)
//! - [Installing Driver](https://!github.com/SubconsciousCompute/fsfilter-rs#building-driver)
//! - [Loading/Removing Driver](https://!github.com/SubconsciousCompute/fsfilter-rs#loadingremoving-driver)
//! - [Rust Application](https://!github.com/SubconsciousCompute/fsfilter-rs#rust-application)
//! - [Building Rust App](https://!github.com/SubconsciousCompute/fsfilter-rs#building-rust-app)
//! - [Running Rust App](https://!github.com/SubconsciousCompute/fsfilter-rs#running-rust-app)
//! - [What and the How](https://!github.com/SubconsciousCompute/fsfilter-rs#what-and-the-how)
//!
//! </details>
//!
Expand Down Expand Up @@ -74,7 +74,7 @@
//! Filter Name Num Instances Altitude Frame
//! ------------------------------ ------------- ------------ -----
//! bindflt 1 409800 0
//! snFilter 4 378781 0 //! our minifilter driver
//! snFilter 4 378781 0 //our minifilter driver
//! WdFilter 5 328010 0
//! storqosflt 0 244000 0
//! wcifs 0 189900 0
Expand Down Expand Up @@ -119,19 +119,19 @@
//! ```
//!
//! We end the process using `ctrl + c` in the example video:
//! ![video](https://!github.com/sn99/fsfilter-rs/readme_resources/example.gif)
//! ![video](https://!github.com/SubconsciousCompute/fsfilter-rs/readme_resources/example.gif)
//!
//! #### NOTE:
//!
//! - Might fail if not ran with administrative privileges
//! - You need to [load and start the driver]((https://!github.com/sn99/fsfilter-rs#loadingremoving-driver)) before running
//! - You need to [load and start the driver]((https://!github.com/SubconsciousCompute/fsfilter-rs#loadingremoving-driver)) before running
//! the program or else it will error out
//!
//! ## What and the How
//!
//! We basically share definition between the mini-filter and Rust using `#[repr(C)]`
//!
//! ![shared_def](https://!github.com/sn99/fsfilter-rs/readme_resources/shared_def.png)
//! ![`shared_def`](https://!github.com/SubconsciousCompute/fsfilter-rs/readme_resources/shared_def.png)
//!
//! We use [channels](https://!doc.rust-lang.org/std/sync/mpsc/fn.channel.html) to process
//! all [IRPs](https://!docs.microsoft.com/en-us/windows-hardware/drivers/ifs/irps-are-different-from-fast-i-o).
Expand Down
Loading

0 comments on commit 3aa5485

Please sign in to comment.