mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-07 20:30:08 +03:00
fix: windows, dll, pre-loading attack (#10608)
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -3077,7 +3077,7 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "hwcodec"
|
name = "hwcodec"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
source = "git+https://github.com/rustdesk-org/hwcodec#c4d6b1c5c4ddc7548868306004cf5d4eb614a36f"
|
source = "git+https://github.com/rustdesk-org/hwcodec#0ea7e709d3c48bb6446e33a9cc8fd0e0da5709b9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.59.2",
|
"bindgen 0.59.2",
|
||||||
"cc",
|
"cc",
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ impl MagInterface {
|
|||||||
s.lib_handle = LoadLibraryExA(
|
s.lib_handle = LoadLibraryExA(
|
||||||
lib_file_name_c.as_ptr() as _,
|
lib_file_name_c.as_ptr() as _,
|
||||||
NULL,
|
NULL,
|
||||||
LOAD_WITH_ALTERED_SEARCH_PATH,
|
LOAD_LIBRARY_SEARCH_SYSTEM32,
|
||||||
);
|
);
|
||||||
if s.lib_handle.is_null() {
|
if s.lib_handle.is_null() {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
diff --git a/compat/w32dlfcn.h b/compat/w32dlfcn.h
|
||||||
|
index ac20e83..1e83aa6 100644
|
||||||
|
--- a/compat/w32dlfcn.h
|
||||||
|
+++ b/compat/w32dlfcn.h
|
||||||
|
@@ -76,6 +76,7 @@ static inline HMODULE win32_dlopen(const char *name)
|
||||||
|
if (!name_w)
|
||||||
|
goto exit;
|
||||||
|
namelen = wcslen(name_w);
|
||||||
|
+ /*
|
||||||
|
// Try local directory first
|
||||||
|
path = get_module_filename(NULL);
|
||||||
|
if (!path)
|
||||||
|
@@ -91,6 +92,7 @@ static inline HMODULE win32_dlopen(const char *name)
|
||||||
|
path = new_path;
|
||||||
|
wcscpy(path + pathlen + 1, name_w);
|
||||||
|
module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||||
|
+ */
|
||||||
|
if (module == NULL) {
|
||||||
|
// Next try System32 directory
|
||||||
|
pathlen = GetSystemDirectoryW(path, pathsize);
|
||||||
|
@@ -131,7 +133,9 @@ exit:
|
||||||
|
return NULL;
|
||||||
|
module = LoadPackagedLibrary(name_w, 0);
|
||||||
|
#else
|
||||||
|
-#define LOAD_FLAGS (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32)
|
||||||
|
+// #define LOAD_FLAGS (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32)
|
||||||
|
+// Don't dynamic-link libraries from the application directory.
|
||||||
|
+ #define LOAD_FLAGS LOAD_LIBRARY_SEARCH_SYSTEM32
|
||||||
|
/* filename may be be in CP_ACP */
|
||||||
|
if (!name_w)
|
||||||
|
return LoadLibraryExA(name, NULL, LOAD_FLAGS);
|
||||||
@@ -25,6 +25,7 @@ vcpkg_from_github(
|
|||||||
patch/0007-fix-linux-configure.patch
|
patch/0007-fix-linux-configure.patch
|
||||||
patch/0008-remove-amf-loop-query.patch
|
patch/0008-remove-amf-loop-query.patch
|
||||||
patch/0009-fix-nvenc-reconfigure-blur.patch
|
patch/0009-fix-nvenc-reconfigure-blur.patch
|
||||||
|
patch/0010.disable-loading-DLLs-from-app-dir.patch
|
||||||
)
|
)
|
||||||
|
|
||||||
if(SOURCE_PATH MATCHES " ")
|
if(SOURCE_PATH MATCHES " ")
|
||||||
|
|||||||
@@ -31,7 +31,10 @@ macro_rules! my_println{
|
|||||||
pub fn core_main() -> Option<Vec<String>> {
|
pub fn core_main() -> Option<Vec<String>> {
|
||||||
crate::load_custom_client();
|
crate::load_custom_client();
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
crate::platform::windows::bootstrap();
|
if !crate::platform::windows::bootstrap() {
|
||||||
|
// return None to terminate the process
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
let mut flutter_args = Vec::new();
|
let mut flutter_args = Vec::new();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ use serde_json::json;
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
ffi::CString,
|
ffi::CString,
|
||||||
|
io::{Error as IoError, ErrorKind as IoErrorKind},
|
||||||
os::raw::{c_char, c_int, c_void},
|
os::raw::{c_char, c_int, c_void},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::{
|
sync::{
|
||||||
@@ -50,7 +51,7 @@ lazy_static::lazy_static! {
|
|||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Result<Library, LibError> = Library::open("texture_rgba_renderer_plugin.dll");
|
pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Result<Library, LibError> = load_plugin_in_app_path("texture_rgba_renderer_plugin.dll");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
@@ -65,7 +66,37 @@ lazy_static::lazy_static! {
|
|||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
pub static ref TEXTURE_GPU_RENDERER_PLUGIN: Result<Library, LibError> = Library::open("flutter_gpu_texture_renderer_plugin.dll");
|
pub static ref TEXTURE_GPU_RENDERER_PLUGIN: Result<Library, LibError> = load_plugin_in_app_path("flutter_gpu_texture_renderer_plugin.dll");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move this function into `src/platform/windows.rs` if there're more calls to load plugins.
|
||||||
|
// Load dll with full path.
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn load_plugin_in_app_path(dll_name: &str) -> Result<Library, LibError> {
|
||||||
|
match std::env::current_exe() {
|
||||||
|
Ok(exe_file) => {
|
||||||
|
if let Some(cur_dir) = exe_file.parent() {
|
||||||
|
let full_path = cur_dir.join(dll_name);
|
||||||
|
if !full_path.exists() {
|
||||||
|
Err(LibError::OpeningLibraryError(IoError::new(
|
||||||
|
IoErrorKind::NotFound,
|
||||||
|
format!("{} not found", dll_name),
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
Library::open(full_path)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(LibError::OpeningLibraryError(IoError::new(
|
||||||
|
IoErrorKind::Other,
|
||||||
|
format!(
|
||||||
|
"Invalid exe parent for {}",
|
||||||
|
exe_file.to_string_lossy().as_ref()
|
||||||
|
),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => Err(LibError::OpeningLibraryError(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FFI for rustdesk core's main entry.
|
/// FFI for rustdesk core's main entry.
|
||||||
@@ -2076,11 +2107,7 @@ pub mod sessions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) mod async_tasks {
|
pub(super) mod async_tasks {
|
||||||
use hbb_common::{
|
use hbb_common::{bail, tokio, ResultType};
|
||||||
bail,
|
|
||||||
tokio::{self, select},
|
|
||||||
ResultType,
|
|
||||||
};
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{
|
sync::{
|
||||||
|
|||||||
@@ -18,12 +18,11 @@ use hbb_common::{
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ffi::{CString, OsString},
|
ffi::{CString, OsString},
|
||||||
fs, io,
|
fs,
|
||||||
io::prelude::*,
|
io::{self, prelude::*},
|
||||||
mem,
|
mem,
|
||||||
os::windows::process::CommandExt,
|
os::windows::process::CommandExt,
|
||||||
path::*,
|
path::*,
|
||||||
process::{Command, Stdio},
|
|
||||||
ptr::null_mut,
|
ptr::null_mut,
|
||||||
sync::{atomic::Ordering, Arc, Mutex},
|
sync::{atomic::Ordering, Arc, Mutex},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
@@ -32,11 +31,13 @@ use wallpaper;
|
|||||||
use winapi::{
|
use winapi::{
|
||||||
ctypes::c_void,
|
ctypes::c_void,
|
||||||
shared::{minwindef::*, ntdef::NULL, windef::*, winerror::*},
|
shared::{minwindef::*, ntdef::NULL, windef::*, winerror::*},
|
||||||
um::sysinfoapi::{GetNativeSystemInfo, SYSTEM_INFO},
|
|
||||||
um::{
|
um::{
|
||||||
errhandlingapi::GetLastError,
|
errhandlingapi::GetLastError,
|
||||||
handleapi::CloseHandle,
|
handleapi::CloseHandle,
|
||||||
libloaderapi::{GetProcAddress, LoadLibraryA},
|
libloaderapi::{
|
||||||
|
GetProcAddress, LoadLibraryExA, LoadLibraryExW, LOAD_LIBRARY_SEARCH_SYSTEM32,
|
||||||
|
LOAD_LIBRARY_SEARCH_USER_DIRS,
|
||||||
|
},
|
||||||
minwinbase::STILL_ACTIVE,
|
minwinbase::STILL_ACTIVE,
|
||||||
processthreadsapi::{
|
processthreadsapi::{
|
||||||
GetCurrentProcess, GetCurrentProcessId, GetExitCodeProcess, OpenProcess,
|
GetCurrentProcess, GetCurrentProcessId, GetExitCodeProcess, OpenProcess,
|
||||||
@@ -44,6 +45,7 @@ use winapi::{
|
|||||||
},
|
},
|
||||||
securitybaseapi::GetTokenInformation,
|
securitybaseapi::GetTokenInformation,
|
||||||
shellapi::ShellExecuteW,
|
shellapi::ShellExecuteW,
|
||||||
|
sysinfoapi::{GetNativeSystemInfo, SYSTEM_INFO},
|
||||||
winbase::*,
|
winbase::*,
|
||||||
wingdi::*,
|
wingdi::*,
|
||||||
winnt::{
|
winnt::{
|
||||||
@@ -1563,10 +1565,63 @@ pub fn is_win_10_or_greater() -> bool {
|
|||||||
unsafe { is_windows_10_or_greater() > 0 }
|
unsafe { is_windows_10_or_greater() > 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bootstrap() {
|
pub fn bootstrap() -> bool {
|
||||||
if let Ok(lic) = get_license_from_exe_name() {
|
if let Ok(lic) = get_license_from_exe_name() {
|
||||||
*config::EXE_RENDEZVOUS_SERVER.write().unwrap() = lic.host.clone();
|
*config::EXE_RENDEZVOUS_SERVER.write().unwrap() = lic.host.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_safe_load_dll()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_safe_load_dll() -> bool {
|
||||||
|
if !unsafe { set_default_dll_directories() } {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `SetDllDirectoryW` should never fail.
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setdlldirectoryw
|
||||||
|
if unsafe { SetDllDirectoryW(wide_string("").as_ptr()) == FALSE } {
|
||||||
|
eprintln!("SetDllDirectoryW failed: {}", io::Error::last_os_error());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-setdefaultdlldirectories
|
||||||
|
unsafe fn set_default_dll_directories() -> bool {
|
||||||
|
let module = LoadLibraryExW(
|
||||||
|
wide_string("Kernel32.dll").as_ptr(),
|
||||||
|
0 as _,
|
||||||
|
LOAD_LIBRARY_SEARCH_SYSTEM32,
|
||||||
|
);
|
||||||
|
if module.is_null() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match CString::new("SetDefaultDllDirectories") {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("CString::new failed: {}", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Ok(func_name) => {
|
||||||
|
let func = GetProcAddress(module, func_name.as_ptr());
|
||||||
|
if func.is_null() {
|
||||||
|
eprintln!("GetProcAddress failed: {}", io::Error::last_os_error());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
type SetDefaultDllDirectories = unsafe extern "system" fn(DWORD) -> BOOL;
|
||||||
|
let func: SetDefaultDllDirectories = std::mem::transmute(func);
|
||||||
|
if func(LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS) == FALSE {
|
||||||
|
eprintln!(
|
||||||
|
"SetDefaultDllDirectories failed: {}",
|
||||||
|
io::Error::last_os_error()
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_shortcut(id: &str) -> ResultType<()> {
|
pub fn create_shortcut(id: &str) -> ResultType<()> {
|
||||||
@@ -2530,7 +2585,11 @@ pub fn try_kill_rustdesk_main_window_process() -> ResultType<()> {
|
|||||||
fn nt_terminate_process(process_id: DWORD) -> ResultType<()> {
|
fn nt_terminate_process(process_id: DWORD) -> ResultType<()> {
|
||||||
type NtTerminateProcess = unsafe extern "system" fn(HANDLE, DWORD) -> DWORD;
|
type NtTerminateProcess = unsafe extern "system" fn(HANDLE, DWORD) -> DWORD;
|
||||||
unsafe {
|
unsafe {
|
||||||
let h_module = LoadLibraryA(CString::new("ntdll.dll")?.as_ptr());
|
let h_module = LoadLibraryExA(
|
||||||
|
CString::new("ntdll.dll")?.as_ptr(),
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
LOAD_LIBRARY_SEARCH_SYSTEM32,
|
||||||
|
);
|
||||||
if !h_module.is_null() {
|
if !h_module.is_null() {
|
||||||
let f_nt_terminate_process: NtTerminateProcess = std::mem::transmute(GetProcAddress(
|
let f_nt_terminate_process: NtTerminateProcess = std::mem::transmute(GetProcAddress(
|
||||||
h_module,
|
h_module,
|
||||||
|
|||||||
Reference in New Issue
Block a user