Compare commits

...

1 commit

Author SHA1 Message Date
69250cf856
Added support for auto process exit when child ends 2024-11-03 14:21:23 +01:00
2 changed files with 38 additions and 18 deletions

View file

@ -8,14 +8,12 @@ use log::{debug, error, info, trace};
use path_clean::PathClean; use path_clean::PathClean;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use windows::core::{PSTR, s}; use windows::core::{PSTR, s};
use windows::Win32::Foundation::{CloseHandle, GetLastError, HANDLE}; use windows::Win32::Foundation::{CloseHandle, GetLastError, HANDLE, NTSTATUS};
use windows::Win32::System::Diagnostics::Debug::WriteProcessMemory; use windows::Win32::System::Diagnostics::Debug::WriteProcessMemory;
use windows::Win32::System::LibraryLoader::{GetModuleHandleA, GetProcAddress}; use windows::Win32::System::LibraryLoader::{GetModuleHandleA, GetProcAddress};
use windows::Win32::System::Memory::{MEM_COMMIT, MEM_RELEASE, MEM_RESERVE, PAGE_READWRITE, use windows::Win32::System::Memory::{MEM_COMMIT, MEM_RELEASE, MEM_RESERVE, PAGE_READWRITE,
VirtualAllocEx, VirtualFreeEx}; VirtualAllocEx, VirtualFreeEx};
use windows::Win32::System::Threading::{CREATE_SUSPENDED, CreateProcessA, CreateRemoteThread, use windows::Win32::System::Threading::{CREATE_SUSPENDED, CreateProcessA, CreateRemoteThread, GetExitCodeProcess, PROCESS_INFORMATION, ResumeThread, STARTUPINFOA, TerminateProcess, TerminateThread, WaitForSingleObject};
PROCESS_INFORMATION, ResumeThread, STARTUPINFOA,
TerminateProcess, TerminateThread, WaitForSingleObject};
type FarProcUnwrapped = unsafe extern "system" fn() -> isize; type FarProcUnwrapped = unsafe extern "system" fn() -> isize;
type LPThreadStartRoutine = unsafe extern "system" fn(param: *mut c_void) -> u32; type LPThreadStartRoutine = unsafe extern "system" fn(param: *mut c_void) -> u32;
@ -258,11 +256,30 @@ pub fn spawn_process<'a>(launcher: Launcher, env: Environment) -> Result<Context
debug!("Injection of dll: {inject} succeeded!"); debug!("Injection of dll: {inject} succeeded!");
} }
unsafe { unsafe { ResumeThread(proc_info.hThread); }
ResumeThread(proc_info.hThread);
CloseHandle(proc_info.hThread)?;
CloseHandle(proc_info.hProcess)?;
}
info!("Successful injection finished"); info!("Successful injection finished");
Ok(Context { proc_info, environment }) Ok(Context { proc_info, environment })
}
pub fn is_process_running(proc_info: PROCESS_INFORMATION) -> bool {
let mut exit_code = 0u32;
let result = unsafe { GetExitCodeProcess(proc_info.hProcess, &mut exit_code) };
match result {
Ok(_) => {
match NTSTATUS(exit_code as i32) {
windows::Win32::Foundation::STILL_ACTIVE => true,
_ => {
unsafe {
CloseHandle(proc_info.hThread).unwrap();
CloseHandle(proc_info.hProcess).unwrap();
}
false
}
}
}
Err(err) => {
error!("Error while getting exit result: {err:?}");
true
}
}
} }

View file

@ -1,5 +1,5 @@
use clap::Parser; use clap::Parser;
use log::{error, trace}; use log::{error, info, trace};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
@ -72,8 +72,8 @@ fn run(config_file: String) -> Result<injector::Context, Error> {
trace!("{:?}", configuration); trace!("{:?}", configuration);
Ok(injector::spawn_process( Ok(injector::spawn_process(
configuration.launcher, configuration.launcher,
configuration.environment.unwrap_or_default() configuration.environment.unwrap_or_default(),
)?) )?)
} }
@ -82,13 +82,16 @@ fn main() {
colog::default_builder() colog::default_builder()
.filter_level(args.log_level.unwrap_or_default().into_level_filter()) .filter_level(args.log_level.unwrap_or_default().into_level_filter())
.init(); .init();
match run(args.config_file) { match run(args.config_file) {
Ok(_context) => { Ok(context) => {
// Since environment pointer has to outlive the process, here we can do several things, // Since environment pointer has to outlive the process, here we can do several things,
// either we join the thread of the process, or we just wait // either we join the thread of the process, or we just wait
std::thread::sleep(std::time::Duration::from_secs(u64::MAX)) while injector::is_process_running(context.proc_info) {
}, std::thread::sleep(std::time::Duration::from_secs(1))
}
info!("Application exited");
}
Err(err) => error!("{}", err.to_string()) Err(err) => error!("{}", err.to_string())
} }
} }