diff --git a/Cargo.lock b/Cargo.lock index c0cec03c..266d1422 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,7 +157,7 @@ dependencies = [ "sha2", "tempfile", "tlsh2", - "windows", + "windows-sys", "yara", ] @@ -786,59 +786,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.56.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" -dependencies = [ - "windows-core", - "windows-targets", -] - -[[package]] -name = "windows-core" -version = "0.56.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", - "windows-targets", -] - -[[package]] -name = "windows-implement" -version = "0.56.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.56.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-result" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.52.0" diff --git a/boreal/Cargo.toml b/boreal/Cargo.toml index c1c377e6..fc9bd6b1 100644 --- a/boreal/Cargo.toml +++ b/boreal/Cargo.toml @@ -32,7 +32,7 @@ authenticode = ["dep:authenticode-parser", "dep:hex"] memmap = ["dep:memmap2"] # Adds APIs to scan process memories. -process = ["dep:libc", "dep:windows", "dep:mach2"] +process = ["dep:libc", "dep:windows-sys", "dep:mach2"] # Enables computation of statistics during scanning. profiling = [] @@ -76,7 +76,7 @@ libc = { version = "0.2", optional = true } mach2 = { version = "0.4", optional = true } [target.'cfg(windows)'.dependencies] -windows = { version = "0.56", optional = true, features = [ +windows-sys = { version = "0.52", optional = true, features = [ "Win32_Foundation", # LookupPrivilegeValue, AdjustTokenPrivileges "Win32_Security", diff --git a/boreal/src/scanner/process/sys/windows.rs b/boreal/src/scanner/process/sys/windows.rs index 5cfb30b6..bd0e42a6 100644 --- a/boreal/src/scanner/process/sys/windows.rs +++ b/boreal/src/scanner/process/sys/windows.rs @@ -2,16 +2,16 @@ use std::ffi::c_void; use std::mem::MaybeUninit; use std::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, OwnedHandle}; -use windows::Win32::Foundation::{ERROR_INVALID_PARAMETER, HANDLE, LUID}; -use windows::Win32::Security::{ +use windows_sys::Win32::Foundation::{ERROR_INVALID_PARAMETER, HANDLE, LUID}; +use windows_sys::Win32::Security::{ AdjustTokenPrivileges, LookupPrivilegeValueW, LUID_AND_ATTRIBUTES, SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED, TOKEN_ADJUST_PRIVILEGES, TOKEN_PRIVILEGES, }; -use windows::Win32::System::Diagnostics::Debug::ReadProcessMemory; -use windows::Win32::System::Memory::{ +use windows_sys::Win32::System::Diagnostics::Debug::ReadProcessMemory; +use windows_sys::Win32::System::Memory::{ VirtualQueryEx, MEMORY_BASIC_INFORMATION, MEM_COMMIT, PAGE_NOACCESS, }; -use windows::Win32::System::Threading::{ +use windows_sys::Win32::System::Threading::{ GetCurrentProcess, OpenProcess, OpenProcessToken, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ, }; @@ -33,24 +33,27 @@ pub fn process_memory(pid: u32) -> Result, ScanError> // PROCESS_QUERY_INFORMATION for VirtualQueryEx // PROCESS_VM_READ for ReadProcessMemory PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, - false, + 0, pid, ) }; - let handle = match res { - Ok(handle) => { - // Safety: - // - The handle is valid since the call to OpenProcess succeeded - // - The handle must be closed with `CloseHandle`. - unsafe { OwnedHandle::from_raw_handle(handle.0 as _) } - } - Err(err) if err.code() == ERROR_INVALID_PARAMETER.into() => { - return Err(ScanError::UnknownProcess); - } - Err(err) => { - return Err(ScanError::CannotListProcessRegions(err.into())); - } - }; + + if res == 0 { + let err = std::io::Error::last_os_error(); + return Err( + #[allow(clippy::cast_possible_wrap)] + if err.raw_os_error() == Some(ERROR_INVALID_PARAMETER as _) { + ScanError::UnknownProcess + } else { + ScanError::CannotListProcessRegions(err) + }, + ); + } + + // Safety: + // - The handle is valid since the call to OpenProcess succeeded + // - The handle must be closed with `CloseHandle`. + let handle = unsafe { OwnedHandle::from_raw_handle(res as _) }; Ok(Box::new(WindowsProcessMemory { handle, @@ -59,7 +62,7 @@ pub fn process_memory(pid: u32) -> Result, ScanError> })) } -fn enable_se_debug_privilege() -> Result<(), windows::core::Error> { +fn enable_se_debug_privilege() -> Result<(), std::io::Error> { let mut self_token = HANDLE::default(); // Safety: this is always safe to call. @@ -68,12 +71,28 @@ fn enable_se_debug_privilege() -> Result<(), windows::core::Error> { // - handle is valid and has PROCESS_QUERY_LIMITED_INFORMATION // permission since it was retrieve with GetCurrentProcess. // - TOKEN_ADJUST_PRIVILEGES is a valid access to ask for. - unsafe { OpenProcessToken(self_handle, TOKEN_ADJUST_PRIVILEGES, &mut self_token) }?; + let res = unsafe { OpenProcessToken(self_handle, TOKEN_ADJUST_PRIVILEGES, &mut self_token) }; + if res == 0 { + return Err(std::io::Error::last_os_error()); + } + + let mut debug_privilege_luid = LUID { + LowPart: 0, + HighPart: 0, + }; - let mut debug_privilege_luid = LUID::default(); // Safety: // - SE_DEBUG_NAME is a wide string ending with a null byte. - unsafe { LookupPrivilegeValueW(None, SE_DEBUG_NAME, &mut debug_privilege_luid) }?; + let res = unsafe { + LookupPrivilegeValueW( + std::ptr::null_mut(), + SE_DEBUG_NAME, + &mut debug_privilege_luid, + ) + }; + if res == 0 { + return Err(std::io::Error::last_os_error()); + } let cfg = TOKEN_PRIVILEGES { PrivilegeCount: 1, @@ -86,7 +105,19 @@ fn enable_se_debug_privilege() -> Result<(), windows::core::Error> { // - token is valid and opened with TOKEN_ADJUST_PRIVILEGES // - NewState is well-formed, count is 1 and the Privileges array has one element // - Rest of arguments are optional - unsafe { AdjustTokenPrivileges(self_token, false, Some(&cfg), 0, None, None) }?; + let res = unsafe { + AdjustTokenPrivileges( + self_token, + 0, + &cfg, + 0, + std::ptr::null_mut(), + std::ptr::null_mut(), + ) + }; + if res == 0 { + return Err(std::io::Error::last_os_error()); + } Ok(()) } @@ -135,7 +166,7 @@ fn query_next_region(handle: BorrowedHandle, mut next_addr: usize) -> Option(), ) @@ -190,11 +221,11 @@ impl FragmentedMemory for WindowsProcessMemory { desc.start as _, self.buffer.as_mut_ptr().cast(), self.buffer.len(), - Some(&mut nb_bytes_read), + &mut nb_bytes_read, ) }; - if res.is_err() { + if res == 0 { return None; } @@ -217,7 +248,7 @@ fn get_chunked_region(desc: RegionDescription, params: &MemoryParams) -> RegionD } fn handle_to_windows_handle(handle: BorrowedHandle) -> HANDLE { - HANDLE(handle.as_raw_handle() as _) + handle.as_raw_handle() as HANDLE } #[cfg(test)] diff --git a/boreal/tests/it/process.rs b/boreal/tests/it/process.rs index 5918d212..af05a7f3 100644 --- a/boreal/tests/it/process.rs +++ b/boreal/tests/it/process.rs @@ -58,13 +58,11 @@ fn test_process_permission_denied() { let err = checker.last_err.unwrap(); match &err { ScanError::CannotListProcessRegions(err) => { - #[cfg(windows)] + #[cfg(target_os = "macos")] { - use windows::Win32::Foundation::E_ACCESSDENIED; - - assert_eq!(err.raw_os_error(), Some(E_ACCESSDENIED.0 as _), "{:?}", err); + assert_eq!(err.kind(), std::io::ErrorKind::Other, "{:?}", err); } - #[cfg(target_os = "linux")] + #[cfg(not(target_os = "macos"))] { assert_eq!( err.kind(), @@ -73,10 +71,6 @@ fn test_process_permission_denied() { err ); } - #[cfg(target_os = "macos")] - { - assert_eq!(err.kind(), std::io::ErrorKind::Other, "{:?}", err); - } } err => panic!("Unexpected last err: {err:?}"), }