diff --git a/Cargo.lock b/Cargo.lock index c8529aa..80ae360 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1852,11 +1852,69 @@ dependencies = [ [[package]] name = "windows" -version = "0.44.0" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "windows-targets 0.42.2", + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1865,6 +1923,34 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -1901,21 +1987,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -1950,10 +2021,13 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" +name = "windows-threading" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] [[package]] name = "windows_aarch64_gnullvm" @@ -1967,12 +2041,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -1985,12 +2053,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -2015,12 +2077,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -2033,12 +2089,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -2051,12 +2101,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -2069,12 +2113,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 00d60b3..95a134b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ include = ["/src", "LICENSE"] default-target = "x86_64-pc-windows-msvc" [dependencies] -windows = { version = "0.44.0", features = [ +windows = { version = "0.62.2", features = [ "Win32_System_Diagnostics_Etw", "Win32_Foundation", "Win32_System_Time", diff --git a/src/lib.rs b/src/lib.rs index 9e371ee..ac1b655 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,11 +8,11 @@ #![allow(clippy::field_reassign_with_default)] use object::Object; -use windows::core::{GUID, PCSTR, PSTR}; +use windows::core::{self, GUID, PCSTR, PSTR}; use windows::Win32::Foundation::{ - CloseHandle, GetLastError, ERROR_SUCCESS, ERROR_WMI_INSTANCE_NOT_FOUND, HANDLE, - INVALID_HANDLE_VALUE, WIN32_ERROR, + CloseHandle, GetLastError, ERROR_SUCCESS, ERROR_WMI_INSTANCE_NOT_FOUND, HANDLE, WIN32_ERROR, }; +use windows::Win32::Security::SE_SYSTEM_PROFILE_NAME; use windows::Win32::Security::{ AdjustTokenPrivileges, LookupPrivilegeValueW, SE_PRIVILEGE_ENABLED, TOKEN_ADJUST_PRIVILEGES, TOKEN_PRIVILEGES, @@ -30,7 +30,6 @@ use windows::Win32::System::Diagnostics::Etw::{ WNODE_FLAG_TRACED_GUID, }; use windows::Win32::System::SystemInformation::{GetVersionExA, OSVERSIONINFOA}; -use windows::Win32::System::SystemServices::SE_SYSTEM_PROFILE_NAME; use windows::Win32::System::Threading::{ GetCurrentProcess, GetCurrentThread, OpenProcess, OpenProcessToken, SetThreadPriority, WaitForSingleObject, CREATE_SUSPENDED, PROCESS_ALL_ACCESS, THREAD_PRIORITY_TIME_CRITICAL, @@ -42,6 +41,7 @@ use std::ffi::OsString; use std::fs; use std::io::{Read, Write}; use std::mem::size_of; +use std::os::raw::c_void; use std::os::windows::ffi::OsStringExt; use std::path::PathBuf; use std::ptr::{addr_of, addr_of_mut}; @@ -88,9 +88,12 @@ impl Drop for TraceContext { fn drop(&mut self) { // SAFETY: TraceContext invariants ensure these are valid unsafe { - let ret = CloseHandle(self.target_process_handle); - if ret.0 == 0 { - panic!("TraceContext::CloseHandle error:{:?}", get_last_error("")); + if let Err(error) = CloseHandle(self.target_process_handle) { + panic!( + "TraceContext::CloseHandle error: {:?} ({})", + error.message(), + error.code() + ); } } } @@ -101,6 +104,7 @@ const MAX_STACK_DEPTH: usize = 200; #[derive(Debug)] pub enum Error { + Formatted(WIN32_ERROR, String, &'static str), /// Blondie requires administrator privileges NotAnAdmin, /// Error writing to the provided Writer @@ -112,13 +116,21 @@ pub enum Error { /// Error waiting for child, timed out WaitOnChildErrTimeout, /// A call to a windows API function returned an error and we didn't know how to handle it - Other(WIN32_ERROR, String, &'static str), + Other(core::Error), /// We require Windows 7 or greater UnsupportedOsVersion, /// This should never happen UnknownError, } + type Result = std::result::Result; + +impl From for Error { + fn from(err: core::Error) -> Self { + Error::Other(err) + } +} + impl From for Error { fn from(err: std::io::Error) -> Self { Error::Write(err) @@ -146,7 +158,7 @@ fn get_last_error(extra: &'static str) -> Error { .to_str() .unwrap_or("Invalid utf8 in error") }; - Error::Other(code, code_str.to_string(), extra) + Error::Formatted(code, code_str.to_string(), extra) } /// A wrapper around `OpenProcess` that returns a handle with all access rights @@ -171,33 +183,22 @@ fn acquire_privileges() -> Result<()> { let mut privs = TOKEN_PRIVILEGES::default(); privs.PrivilegeCount = 1; privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if unsafe { - LookupPrivilegeValueW(None, SE_SYSTEM_PROFILE_NAME, &mut privs.Privileges[0].Luid).0 == 0 - } { - return Err(get_last_error("acquire_privileges LookupPrivilegeValueA")); - } + unsafe { LookupPrivilegeValueW(None, SE_SYSTEM_PROFILE_NAME, &mut privs.Privileges[0].Luid) }?; let mut pt = HANDLE::default(); - if unsafe { OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &mut pt).0 == 0 } { - return Err(get_last_error("OpenProcessToken")); - } + unsafe { OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &mut pt) }?; let adjust = unsafe { AdjustTokenPrivileges(pt, false, Some(addr_of!(privs)), 0, None, None) }; - if adjust.0 == 0 { - let err = Err(get_last_error("AdjustTokenPrivileges")); - unsafe { - CloseHandle(pt); - } - return err; - } - let ret = unsafe { CloseHandle(pt) }; - if ret.0 == 0 { - return Err(get_last_error("acquire_privileges CloseHandle")); + if let Err(err) = adjust { + unsafe { CloseHandle(pt) }?; + return Err(err.into()); } + unsafe { CloseHandle(pt) }?; let status = unsafe { GetLastError() }; if status != ERROR_SUCCESS { return Err(Error::NotAnAdmin); } Ok(()) } + /// SAFETY: is_suspended must only be true if `target_process` is suspended unsafe fn trace_from_process_id( target_process_id: u32, @@ -206,10 +207,8 @@ unsafe fn trace_from_process_id( ) -> Result { let mut winver_info = OSVERSIONINFOA::default(); winver_info.dwOSVersionInfoSize = size_of::() as u32; - let ret = GetVersionExA(&mut winver_info); - if ret.0 == 0 { - return Err(get_last_error("TraceSetInformation interval")); - } + GetVersionExA(&mut winver_info)?; + // If we're not win7 or more, return unsupported // https://docs.microsoft.com/en-us/windows/win32/sysinfo/operating-system-version if winver_info.dwMajorVersion < 6 @@ -228,7 +227,7 @@ unsafe fn trace_from_process_id( // TODO: Parameter? interval.Interval = (1000000000 / 8000) / 100; let ret = TraceSetInformation( - None, + CONTROLTRACE_HANDLE::default(), // The value is supported on Windows 8, Windows Server 2012, and later. TraceSampledProfileIntervalInfo, addr_of!(interval).cast(), @@ -298,7 +297,7 @@ unsafe fn trace_from_process_id( { let mut event_trace_props_copy = event_trace_props.clone(); let control_stop_retcode = ControlTraceA( - None, + CONTROLTRACE_HANDLE::default(), kernel_logger_name_with_nul_pcstr, addr_of_mut!(event_trace_props_copy) as *mut _, EVENT_TRACE_CONTROL_STOP, @@ -484,15 +483,15 @@ unsafe fn trace_from_process_id( log.Anonymous2.EventRecordCallback = Some(event_record_callback); let trace_processing_handle = OpenTraceA(&mut log); - if trace_processing_handle.0 == INVALID_HANDLE_VALUE.0 as u64 { + if trace_processing_handle.Value == UINTPTR_MAX { return Err(get_last_error("OpenTraceA processing")); } let (sender, recvr) = std::sync::mpsc::channel(); std::thread::spawn(move || { // This blocks - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - ProcessTrace(&[trace_processing_handle], None, None); + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL).unwrap(); + ProcessTrace(&[trace_processing_handle], None, None).ok().unwrap(); let ret = CloseTrace(trace_processing_handle); if ret != ERROR_SUCCESS { @@ -522,7 +521,7 @@ unsafe fn trace_from_process_id( ) .expect("Could not find NtResumeProcess in ntdll.dll"); #[allow(non_snake_case)] - let NtResumeProcess: extern "system" fn(isize) -> i32 = + let NtResumeProcess: extern "system" fn(*mut c_void) -> i32 = std::mem::transmute(NtResumeProcess); NtResumeProcess(context.target_process_handle.0); } @@ -946,3 +945,8 @@ fn list_kernel_modules() -> Vec<(OsString, u64, u64)> { .collect(); kernel_module_paths } + +#[cfg(target_pointer_width = "32")] +const UINTPTR_MAX: u64 = u32::MAX as u64; +#[cfg(target_pointer_width = "64")] +const UINTPTR_MAX: u64 = u64::MAX;