1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
use core::ffi::c_void;
use std::io;
use std::os::windows::io::AsRawHandle;
use std::ptr;
use windows_sys::Win32::{
Foundation::{ERROR_SUCCESS, LocalFree},
Security::{
Authorization::{GetSecurityInfo, SE_FILE_OBJECT},
IsWellKnownSid, OWNER_SECURITY_INFORMATION, SECURITY_DESCRIPTOR, SID,
WinBuiltinAdministratorsSid, WinLocalSystemSid,
},
};
/// Return whether a file handle is owned by either SYSTEM or the built-in administrators account
pub fn is_admin_owned<T: AsRawHandle>(handle: T) -> io::Result<bool> {
let mut security_descriptor: *mut SECURITY_DESCRIPTOR = ptr::null_mut();
let mut owner: *mut SID = ptr::null_mut();
// SAFETY: `handle` is a valid handle
let result = unsafe {
GetSecurityInfo(
handle.as_raw_handle(),
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
(&mut owner) as *mut *mut SID as *mut *mut c_void,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
(&mut security_descriptor) as *mut *mut SECURITY_DESCRIPTOR as *mut *mut c_void,
)
};
if result != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(result as i32));
}
// SAFETY: `owner` is valid since `security_descriptor` still is, and the well-known type is a valid argument
let is_system_owned = unsafe { IsWellKnownSid(owner as _, WinLocalSystemSid) != 0 };
// SAFETY: `owner` is valid since `security_descriptor` still is, and the well-known type is a valid argument
let is_admin_owned = unsafe { IsWellKnownSid(owner as _, WinBuiltinAdministratorsSid) != 0 };
// SAFETY: Since we no longer need the descriptor (or owner), it may be freed
unsafe { LocalFree(security_descriptor.cast()) };
Ok(is_system_owned || is_admin_owned)
}
#[cfg(test)]
mod test {
use std::os::windows::fs::OpenOptionsExt;
use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_BACKUP_SEMANTICS;
use super::is_admin_owned;
#[test]
pub fn test_is_admin_owned() {
// The kernel image is owned by "TrustedInstaller", so we expect the function to return 'false'
let path = std::fs::File::open(r"C:\Windows\System32\ntoskrnl.exe").unwrap();
let result = is_admin_owned(path);
assert!(
matches!(result, Ok(false)),
"expected ntoskrnl.exe to be owned by TrustedInstaller (false), got {result:?}"
);
// The Windows system temp directory is owned by SYSTEM, so we expect 'true'
let path = std::fs::File::options()
.read(true)
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
.open(r"C:\Windows\Temp")
.unwrap();
let result = is_admin_owned(path);
assert!(
matches!(result, Ok(true)),
"expected TEMP to be owned by SYSTEM (true), got {result:?}"
);
}
}
|