diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..6f9aacc --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = ['i686-pc-windows-msvc','x86_64-pc-windows-msvc'] \ No newline at end of file diff --git a/.gitignore b/.gitignore index c640ca5..96ef6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /target Cargo.lock -.vscode diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..28151fb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "rust-analyzer.checkOnSave.command": "clippy", + "[rust]": { + "editor.formatOnSave": true + }, + "rust-analyzer.linkedProjects": [ + "Cargo.toml", + "tests/helpers/test_payload/Cargo.toml", + "tests/helpers/test_target/Cargo.toml", + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..5b576a4 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Test on Windows", + "type": "shell", + "command": "pwsh ./scripts/test.ps1", + "problemMatcher": [] + }, + { + "label": "Clean", + "type": "shell", + "command": "pwsh ./scripts/clean.ps1", + "problemMatcher": [] + }, + { + "label": "Test on Wine (See Readme)", + "type": "shell", + "command": "pwsh ./scripts/test-wine.ps1", + "problemMatcher": [] + }, + ] +} \ No newline at end of file diff --git a/README.md b/README.md index b233341..725ea70 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,11 @@ A windows dll injection library written in Rust. ## Supported scenarios + +> [!WARNING] +> Although tests currently pass, some uses of 64-bit into 32-bit may potentially fail on +> Linux (WINE) due to [Wine Bug #56362](https://bugs.winehq.org/show_bug.cgi?id=56362). + | Injector Process | Target Process | Supported? | | ---------------- | -------------- | ------------------------------------------ | | 32-bit | 32-bit | Yes | @@ -42,11 +47,11 @@ syringe.eject(injected_payload).unwrap(); ## Remote Procedure Calls (RPC) This crate supports two mechanisms for rpc. Both only work one-way for calling exported functions in the target process and are only intended for one-time initialization usage. For extended communication a dedicated rpc library should be used. -| | `RemotePayloadProcedure` | `RemoteRawProcedure` | -| ---------------- | ------------------------------ | ------------------------------------------ | -| Feature | `rpc-payload` | `rpc-raw` | -| Argument and Return Requirements | `Serialize + DeserializeOwned` | `Copy`, Argument size has to be smaller than `usize` in target process | -| Function Definition | Using macro `payload_procedure!` | Any `extern "system"` or `extern "C"` with `#[no_mangle]` | +| | `RemotePayloadProcedure` | `RemoteRawProcedure` | +| -------------------------------- | -------------------------------- | ---------------------------------------------------------------------- | +| Feature | `rpc-payload` | `rpc-raw` | +| Argument and Return Requirements | `Serialize + DeserializeOwned` | `Copy`, Argument size has to be smaller than `usize` in target process | +| Function Definition | Using macro `payload_procedure!` | Any `extern "system"` or `extern "C"` with `#[no_mangle]` | ### RemotePayloadProcedure A rpc mechanism based on [`bincode`](https://crates.io/crates/bincode). @@ -119,6 +124,36 @@ syringe.eject(injected_payload).unwrap(); ## License Licensed under MIT license ([LICENSE](https://github.com/OpenByteDev/dll-syringe/blob/master/LICENSE) or http://opensource.org/licenses/MIT) +## Instructions for Contributors + +### Prerequisites + +You will need the nightly toolchains of Rust and Cargo to build/test this project. + +``` +rustup target add x86_64-pc-windows-msvc --toolchain nightly +rustup target add i686-pc-windows-msvc --toolchain nightly +``` + +> [!NOTE] +> Also applies to developing on Linux, you'll need it for your IDE (i.e. rust-analyzer or RustRover) to work properly. + +### Run Tests + +Run the `./scripts/test.ps1` script from PowerShell. + +### Running Tests on Linux + +You'll need `cargo xwin` to build the MSVC targets on Linux: + +``` +cargo install cargo-xwin +``` + +After that, you can run the tests with `./scripts/test-wine.ps1` PowerShell script. +(As opposed to `./scripts/test.ps1`) + +Make sure you have Wine installed! + ## Attribution Inspired by [Reloaded.Injector](https://github.com/Reloaded-Project/Reloaded.Injector) from [Sewer](https://github.com/Sewer56). - diff --git a/clean.ps1 b/clean.ps1 deleted file mode 100644 index b5e7270..0000000 --- a/clean.ps1 +++ /dev/null @@ -1,9 +0,0 @@ -cargo clean - -Set-Location .\tests\helpers\test_payload -cargo clean -Set-Location ..\..\.. - -Set-Location .\tests\helpers\test_target -cargo clean -Set-Location ..\..\.. diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..271800c --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" \ No newline at end of file diff --git a/scripts/clean.ps1 b/scripts/clean.ps1 new file mode 100644 index 0000000..4c6df25 --- /dev/null +++ b/scripts/clean.ps1 @@ -0,0 +1,11 @@ +# Navigate up one folder from the current script location +Set-Location "$PSScriptRoot\.." +cargo clean + +Set-Location "./tests/helpers/test_payload" +cargo clean +Set-Location "../../.." + +Set-Location "./tests/helpers/test_target" +cargo clean +Set-Location "../../.." diff --git a/scripts/test-wine.ps1 b/scripts/test-wine.ps1 new file mode 100644 index 0000000..2518492 --- /dev/null +++ b/scripts/test-wine.ps1 @@ -0,0 +1,17 @@ +# Navigate up one folder from the current script location +Set-Location "$PSScriptRoot\.." + +# Testing +$env:CROSS_SYSROOT = "." # pretend we cross + +# Prebuild dummy projects. +cargo +nightly xwin rustc --manifest-path "tests/helpers/test_target/Cargo.toml" --target i686-pc-windows-msvc --xwin-arch x86 --xwin-cache-dir "target/cache/x86" +cargo +nightly xwin rustc --manifest-path "tests/helpers/test_payload/Cargo.toml" --target i686-pc-windows-msvc --xwin-arch x86 --xwin-cache-dir "target/cache/x86" +cargo +nightly xwin rustc --manifest-path "tests/helpers/test_target/Cargo.toml" --target x86_64-pc-windows-msvc --xwin-arch x86_64 --xwin-cache-dir "target/cache/x64" +cargo +nightly xwin rustc --manifest-path "tests/helpers/test_payload/Cargo.toml" --target x86_64-pc-windows-msvc --xwin-arch x86_64 --xwin-cache-dir "target/cache/x64" + +# Windows/MSVC x86 +cargo +nightly xwin test --target i686-pc-windows-msvc --xwin-arch x86 --xwin-cache-dir "target/cache/x86" + +# Windows/MSVC x64 +cargo +nightly xwin test --target x86_64-pc-windows-msvc --xwin-arch x86_64 --xwin-cache-dir "target/cache/x64" \ No newline at end of file diff --git a/scripts/test.ps1 b/scripts/test.ps1 new file mode 100644 index 0000000..a6c1e6c --- /dev/null +++ b/scripts/test.ps1 @@ -0,0 +1,8 @@ +# Navigate up one folder from the current script location +Set-Location "$PSScriptRoot\.." + +# Windows/MSVC x86 +cargo test --target i686-pc-windows-msvc -- --nocapture + +# Windows/MSVC x64 +cargo test --target x86_64-pc-windows-msvc -- --nocapture \ No newline at end of file diff --git a/src/process/memory/buffer.rs b/src/process/memory/buffer.rs index 5ebb334..be746f8 100644 --- a/src/process/memory/buffer.rs +++ b/src/process/memory/buffer.rs @@ -338,6 +338,12 @@ impl<'a> ProcessMemorySlice<'a> { } let mut bytes_written = 0; + if buf.is_empty() { + // This works around a discrepancy between Wine and actual Windows. + // On Wine, a 0 sized write fails, on Windows this suceeds. Will file as bug soon. + return Ok(()); + } + let result = unsafe { WriteProcessMemory( self.process.as_raw_handle(), diff --git a/src/rpc/raw.rs b/src/rpc/raw.rs index b6abdff..6ac23ca 100644 --- a/src/rpc/raw.rs +++ b/src/rpc/raw.rs @@ -165,6 +165,7 @@ where Self::build_call_stub_x64(self.ptr, result.as_ptr().as_ptr(), float_mask).unwrap() }; let code = self.remote_allocator.alloc_and_copy_buf(code.as_slice())?; + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] code.memory().flush_instruction_cache()?; Ok(RemoteRawProcedureStub { diff --git a/src/rpc/rpc_core.rs b/src/rpc/rpc_core.rs index 3d33e67..f1cf76f 100644 --- a/src/rpc/rpc_core.rs +++ b/src/rpc/rpc_core.rs @@ -1,5 +1,4 @@ -use iced_x86::{code_asm::*, IcedError}; - +use iced_x86::code_asm::*; use std::{ ffi::CString, mem, @@ -83,6 +82,7 @@ impl Syringe { .unwrap() }; let function_stub = self.remote_allocator.alloc_and_copy_buf(code.as_slice())?; + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] function_stub.memory().flush_instruction_cache()?; Ok(RemoteProcedureStub { diff --git a/src/syringe.rs b/src/syringe.rs index 4351c01..6a4d5b5 100644 --- a/src/syringe.rs +++ b/src/syringe.rs @@ -116,6 +116,28 @@ impl Syringe { } } + /// Creates a new syringe for the given suspended target process. + pub fn for_suspended_process(process: OwnedProcess) -> Result { + let syringe = Self::for_process(process); + + // If we are injecting into a 'suspended' process, then said process is said to not be fully + // initialized. This means: + // - We can't use `EnumProcessModulesEx` and friends. + // - So we can't locate Kernel32.dll in 32-bit process (from 64-bit process) + // - And therefore calling LoadLibrary is not possible. + + // Thankfully we can 'initialize' this suspended process without running any end user logic + // (e.g. a game's entry point) by creating a dummy method and invoking it. + let ret: u8 = 0xC3; + let bx = syringe.remote_allocator.alloc_and_copy(&ret)?; + syringe.process().run_remote_thread( + unsafe { mem::transmute(bx.as_raw_ptr()) }, + std::ptr::null::() as *mut u8, + )?; + + Ok(syringe) + } + /// Returns the target process for this syringe. pub fn process(&self) -> BorrowedProcess<'_> { self.remote_allocator.process() diff --git a/test.ps1 b/test.ps1 deleted file mode 100644 index bf8ab5c..0000000 --- a/test.ps1 +++ /dev/null @@ -1,2 +0,0 @@ -cargo test --target i686-pc-windows-msvc -- --nocapture -cargo test --target x86_64-pc-windows-msvc -- --nocapture diff --git a/tests/common/mod.rs b/tests/common/mod.rs index d666d51..657172c 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,44 +1,41 @@ +use core::iter::once; +use dll_syringe::process::OwnedProcess; +use dll_syringe::process::Process; +use std::ffi::CString; +use std::ffi::OsStr; +use std::mem::zeroed; +use std::os::windows::io::FromRawHandle; +use std::os::windows::io::OwnedHandle; +use std::os::windows::prelude::OsStrExt; +use std::path::Path; +use std::ptr::null_mut; use std::{ + env::{current_dir, var}, error::Error, + fs::{canonicalize, remove_file, File}, + io::{copy, ErrorKind}, path::PathBuf, process::{Command, Stdio}, str::FromStr, + sync::Mutex, }; +use winapi::um::processthreadsapi::{CreateProcessW, PROCESS_INFORMATION, STARTUPINFOW}; +use winapi::um::winbase::CREATE_SUSPENDED; pub fn build_test_payload_x86() -> Result> { - build_helper_crate( - "test_payload", - Some(&find_x86_variant_of_target()), - false, - "dll", - ) + build_helper_crate("test_payload", &find_x86_variant_of_target(), false, "dll") } pub fn build_test_target_x86() -> Result> { - build_helper_crate( - "test_target", - Some(&find_x86_variant_of_target()), - false, - "exe", - ) + build_helper_crate("test_target", &find_x86_variant_of_target(), false, "exe") } pub fn build_test_payload_x64() -> Result> { - build_helper_crate( - "test_payload", - Some(&find_x64_variant_of_target()), - false, - "dll", - ) + build_helper_crate("test_payload", &find_x64_variant_of_target(), false, "dll") } pub fn build_test_target_x64() -> Result> { - build_helper_crate( - "test_target", - Some(&find_x64_variant_of_target()), - false, - "exe", - ) + build_helper_crate("test_target", &find_x64_variant_of_target(), false, "exe") } fn find_x64_variant_of_target() -> String { @@ -51,7 +48,7 @@ fn find_x86_variant_of_target() -> String { pub fn build_helper_crate( crate_name: &str, - target: Option<&str>, + target: &str, release: bool, ext: &str, ) -> Result> { @@ -59,37 +56,84 @@ pub fn build_helper_crate( .join(crate_name) .canonicalize()?; - let mut command = Command::new("cargo"); - command - .arg("build") - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()); - if let Some(target) = target { - command.arg("--target").arg(target); + // For cross/wine testing, we precompile in external script. + if !is_cross() { + let mut command = Command::new("cargo"); + command + .arg("build") + .arg("--target") + .arg(target) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()); + + let exit_code = command.current_dir(&payload_crate_path).spawn()?.wait()?; + assert!( + exit_code.success(), + "Failed to build helper crate {} for target {}", + crate_name, + target + ); } - let exit_code = command.current_dir(&payload_crate_path).spawn()?.wait()?; - assert!( - exit_code.success(), - "Failed to build helper crate {} for target {}", - crate_name, - target.unwrap_or("default") - ); let mut payload_artifact_path = payload_crate_path; payload_artifact_path.push("target"); - - if let Some(target) = target { - payload_artifact_path.push(target); - } - + payload_artifact_path.push(target); payload_artifact_path.push(if release { "release" } else { "debug" }); payload_artifact_path.push(format!("{crate_name}.{ext}")); - assert!(&payload_artifact_path.exists()); + assert!( + &payload_artifact_path.exists(), + "Artifact doesn't exist! {:?}", + &payload_artifact_path + ); Ok(payload_artifact_path) } +/// Detects cross-rs. +/// +/// Remarks: +/// +/// I wish I could install Rust itself via `Rustup` here, but the Ubuntu image that ships with +/// `cross` doesn't have the right packages to support encryption, thus we can't download toolchains +/// (I tried). And I also didn't have good luck with pre-build step and downloading extra packages. +/// +/// So as a compromise, we build the test binaries outside for testing from Linux. +fn is_cross() -> bool { + var("CROSS_SYSROOT").is_ok() +} + +pub(crate) fn start_suspended_process(path: &Path) -> OwnedProcess { + unsafe { + let mut startup_info: STARTUPINFOW = zeroed(); + let mut process_info: PROCESS_INFORMATION = zeroed(); + startup_info.cb = std::mem::size_of::() as u32; + + let target_path_wide: Vec = OsStr::new(path.to_str().unwrap()) + .encode_wide() + .chain(once(0)) // null terminator + .collect(); + + if CreateProcessW( + target_path_wide.as_ptr(), + null_mut(), // Command line + null_mut(), // Process security attributes + null_mut(), // Thread security attributes + 0, // Inherit handles + CREATE_SUSPENDED, // Creation flags + null_mut(), // Environment + null_mut(), // Current directory + &mut startup_info, + &mut process_info, + ) == 0 + { + panic!("Failed to create suspended process"); + } else { + OwnedProcess::from_handle_unchecked(OwnedHandle::from_raw_handle(process_info.hProcess)) + } + } +} + #[macro_export] macro_rules! syringe_test { (fn $test_name:ident ($process:ident : OwnedProcess, $payload_path:ident : &Path $(,)?) $body:block) => { @@ -98,8 +142,8 @@ macro_rules! syringe_test { use dll_syringe::process::OwnedProcess; use std::{ path::Path, - process::{Command, Stdio}, }; + use $crate::common::start_suspended_process; #[test] #[cfg(any( @@ -126,21 +170,59 @@ macro_rules! syringe_test { payload_path: impl AsRef, target_path: impl AsRef, ) { - let dummy_process: OwnedProcess = Command::new(target_path.as_ref()) - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .spawn().unwrap() - .into(); + let proc = start_suspended_process(target_path.as_ref()); + let _guard = proc.try_clone().unwrap().kill_on_drop(); + test(proc, payload_path.as_ref()); + } - let _guard = dummy_process.try_clone().unwrap().kill_on_drop(); + fn test( + $process : OwnedProcess, + $payload_path : &Path, + ) $body + } + }; +} + +#[macro_export] +macro_rules! suspended_process_test { + (fn $test_name:ident ($process:ident : OwnedProcess $(,)?) $body:block) => { + mod $test_name { + use super::*; + use dll_syringe::process::OwnedProcess; + use std::{ + path::Path + }; + use $crate::common::start_suspended_process; - test(dummy_process, payload_path.as_ref()) + #[test] + #[cfg(any( + target_arch = "x86", + all(target_arch = "x86_64", feature = "into-x86-from-x64") + ))] + fn x86() { + test_with_setup( + common::build_test_target_x86().unwrap(), + ) + } + + #[test] + #[cfg(target_arch = "x86_64")] + fn x86_64() { + test_with_setup( + common::build_test_target_x64().unwrap(), + ) + } + + fn test_with_setup( + target_path: impl AsRef, + ) { + let proc = start_suspended_process(target_path.as_ref()); + let _guard = proc.try_clone().unwrap().kill_on_drop(); + test(proc) } fn test( $process : OwnedProcess, - $payload_path : &Path, ) $body } }; @@ -154,7 +236,8 @@ macro_rules! process_test { use dll_syringe::process::OwnedProcess; use std::{ path::Path, - process::{Command, Stdio}, + process::Command, + process::Stdio, }; #[test] @@ -188,7 +271,6 @@ macro_rules! process_test { .into(); let _guard = dummy_process.try_clone().unwrap().kill_on_drop(); - test(dummy_process) } diff --git a/tests/eject.rs b/tests/eject.rs index e3f8ffd..5e7f3b5 100644 --- a/tests/eject.rs +++ b/tests/eject.rs @@ -10,7 +10,7 @@ syringe_test! { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); syringe.eject(module).unwrap(); } @@ -21,7 +21,7 @@ syringe_test! { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); syringe.process().kill().unwrap(); diff --git a/tests/inject.rs b/tests/inject.rs index 3ad6b69..86db93b 100644 --- a/tests/inject.rs +++ b/tests/inject.rs @@ -10,16 +10,16 @@ syringe_test! { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); syringe.inject(payload_path).unwrap(); } } -process_test! { +suspended_process_test! { fn inject_with_invalid_path_fails_with_remote_io( process: OwnedProcess, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let result = syringe.inject("invalid path"); assert!(result.is_err()); let err = result.unwrap_err(); @@ -37,7 +37,7 @@ syringe_test! { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); syringe.process().kill().unwrap(); let result = syringe.inject(payload_path); diff --git a/tests/module.rs b/tests/module.rs index a424263..190a0e1 100644 --- a/tests/module.rs +++ b/tests/module.rs @@ -33,7 +33,7 @@ syringe_test! { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); assert!(module.guess_is_loaded()); } @@ -45,7 +45,7 @@ syringe_test! { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); syringe.eject(module).unwrap(); assert!(!module.try_guess_is_loaded().unwrap()); @@ -58,7 +58,7 @@ syringe_test! { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); syringe.process().kill().unwrap(); assert!(!module.try_guess_is_loaded().unwrap()); diff --git a/tests/process.rs b/tests/process.rs index a190905..abf7858 100644 --- a/tests/process.rs +++ b/tests/process.rs @@ -1,5 +1,10 @@ +use core::mem::{size_of, zeroed}; use dll_syringe::process::{BorrowedProcess, OwnedProcess, Process}; -use std::{fs, mem, time::Duration}; +use std::{ffi::CString, fs, mem, process::Command, time::Duration}; +use winapi::um::{ + libloaderapi::{GetProcAddress, LoadLibraryA}, + winnt::OSVERSIONINFOW, +}; #[allow(unused)] mod common; @@ -28,7 +33,7 @@ process_test! { } } -process_test! { +suspended_process_test! { fn list_module_handles_on_crashed_does_not_hang( process: OwnedProcess ) { @@ -38,7 +43,7 @@ process_test! { } } -process_test! { +suspended_process_test! { fn is_alive_is_true_for_running( process: OwnedProcess ) { @@ -48,7 +53,7 @@ process_test! { } } -process_test! { +suspended_process_test! { fn is_alive_is_false_for_killed( process: OwnedProcess ) { @@ -76,7 +81,7 @@ process_test! { } } -process_test! { +suspended_process_test! { fn kill_guard_kills_process_on_drop( process: OwnedProcess ) { @@ -87,10 +92,15 @@ process_test! { } } -process_test! { +suspended_process_test! { fn long_process_paths_are_supported( process: OwnedProcess ) { + if is_running_under_wine() || is_older_than_windows_10() { + println!("Test skipped due to running under an environment with unsupported long paths. (Wine or older than Windows 10)."); + return; + } + let process_path = process.path().unwrap(); process.kill().unwrap(); @@ -138,3 +148,32 @@ fn current_pseudo_process_eq_current_process() { assert_eq!(pseudo.try_to_owned().unwrap(), normal); assert_eq!(pseudo, normal.try_clone().unwrap()); } + +fn is_running_under_wine() -> bool { + unsafe { + let ntdll = CString::new("ntdll.dll").unwrap(); + let lib = LoadLibraryA(ntdll.as_ptr()); + if !lib.is_null() { + let func_name = CString::new("wine_get_version").unwrap(); + let func = GetProcAddress(lib, func_name.as_ptr()); + !func.is_null() + } else { + false + } + } +} + +// winapi crate doesn't have this. +// This is in ntdll, so already loaded for every Windows process. +extern "system" { + fn RtlGetVersion(lpVersionInformation: &mut OSVERSIONINFOW) -> u32; +} + +fn is_older_than_windows_10() -> bool { + unsafe { + let mut os_info: OSVERSIONINFOW = zeroed(); + os_info.dwOSVersionInfoSize = size_of::() as u32; + RtlGetVersion(&mut os_info); + os_info.dwMajorVersion < 10 + } +} diff --git a/tests/rpc.rs b/tests/rpc.rs index d96b026..f7dd569 100644 --- a/tests/rpc.rs +++ b/tests/rpc.rs @@ -9,11 +9,11 @@ mod core { pub use super::*; use std::time::Duration; - process_test! { + suspended_process_test! { fn get_procedure_address_of_win32_fn( process: OwnedProcess, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.process().wait_for_module_by_name("kernel32.dll", Duration::from_secs(1)).unwrap().unwrap(); let open_process = syringe.get_procedure_address( @@ -29,7 +29,7 @@ mod core { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let dll_main = syringe.get_procedure_address(module, "DllMain").unwrap(); @@ -37,11 +37,11 @@ mod core { } } - process_test! { + suspended_process_test! { fn get_procedure_address_of_invalid( process: OwnedProcess, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.process().wait_for_module_by_name("kernel32.dll", Duration::from_secs(1)).unwrap().unwrap(); let invalid = syringe.get_procedure_address(module, "ProcedureThatDoesNotExist").unwrap(); assert!(invalid.is_none()); @@ -59,7 +59,7 @@ mod payload { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_add = unsafe { syringe.get_payload_procedure:: u32>(module, "add") }.unwrap().unwrap(); @@ -73,7 +73,7 @@ mod payload { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_sum = unsafe { syringe.get_payload_procedure::) -> u64>(module, "sum") }.unwrap().unwrap(); @@ -87,7 +87,7 @@ mod payload { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_does_panic = unsafe { syringe.get_payload_procedure::(module, "does_panic") }.unwrap().unwrap(); @@ -114,7 +114,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_add = unsafe { syringe.get_raw_procedure:: u32>(module, "add_raw") }.unwrap().unwrap(); @@ -128,7 +128,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_sub = unsafe { syringe.get_raw_procedure:: u32>(module, "sub_raw") }.unwrap().unwrap(); @@ -142,7 +142,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_add = unsafe { syringe.get_raw_procedure:: u16>(module, "add_smol_raw") }.unwrap().unwrap(); @@ -156,7 +156,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_sum = unsafe { syringe.get_raw_procedure:: u32>(module, "sum_5_raw") }.unwrap().unwrap(); @@ -170,7 +170,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_sum = unsafe { syringe.get_raw_procedure:: u32>(module, "sum_10_raw") }.unwrap().unwrap(); @@ -184,7 +184,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_sub = unsafe { syringe.get_raw_procedure:: f32>(module, "sub_float_raw") }.unwrap().unwrap(); @@ -198,7 +198,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_add = unsafe { syringe.get_raw_procedure:: u32>(module, "add_raw_c") }.unwrap().unwrap(); @@ -212,7 +212,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_sum = unsafe { syringe.get_raw_procedure:: u32>(module, "sum_10_raw_c") }.unwrap().unwrap(); @@ -226,7 +226,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_add = unsafe { syringe.get_raw_procedure:: u32>(module, "add_raw_c") }.unwrap().unwrap(); syringe.eject(module).unwrap(); @@ -240,7 +240,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_add = unsafe { syringe.get_raw_procedure:: u32>(module, "add_raw_c") }.unwrap().unwrap(); syringe.process().kill().unwrap(); @@ -254,7 +254,7 @@ mod raw { process: OwnedProcess, payload_path: &Path, ) { - let syringe = Syringe::for_process(process); + let syringe = Syringe::for_suspended_process(process).unwrap(); let module = syringe.inject(payload_path).unwrap(); let remote_add = unsafe { syringe.get_raw_procedure::(module, "crash") }.unwrap().unwrap(); let add_err = remote_add.call().unwrap_err();