use crate::{*, job};
use firehazard::*;
use abistr::*;
use winapi::um::winbase::*;
pub fn all() {
let _alt_desktop = create_desktop_a(cstr!("max_sandbox_desktop"), (), None, None, access::GENERIC_ALL, None).unwrap();
for target in settings::Target::list() { one(target) }
}
pub fn one(target: settings::Target) {
assert!(target.spawn.integrity >= target.lockdown.integrity, "target.lockdown.integrity cannot be more permissive than spawn integrity");
let tokens = tokens::create(&target);
let exe = &target.exe;
let mut command_line = exe_to_command_line_0(exe);
let (_read, write) = io::create_pipe(Some(&security::Attributes::new(None, true)), 0).unwrap();
let job = job::create();
let attribute_list = attribute::List::new(&target, &job, vec![(&write).into()]);
let mut si = process::StartupInfoExW::default();
si.startup_info.desktop = Some(cstr16!("max_sandbox_desktop")).filter(|_| !target.allow.same_desktop);
si.startup_info.flags = STARTF_UNTRUSTEDSOURCE | STARTF_USESTDHANDLES;
si.startup_info.std_output = Some((&write).into());
si.startup_info.std_error = Some((&write).into());
si.attribute_list = Some(attribute_list.to_list());
let environment = format!(
concat!(
"WRITE_HANDLE={write}\0",
"READ_HANDLE_NOINHERIT={read}\0",
"\0"
),
write = write.as_handle_nn().as_ptr() as usize,
read = _read.as_handle_nn().as_ptr() as usize,
);
let pi = create_process_as_user_w(
&tokens.restricted, (), Some(&mut command_line[..]), None, None, true,
process::DEBUG_PROCESS | process::CREATE_SEPARATE_WOW_VDM | process::CREATE_SUSPENDED | process::EXTENDED_STARTUPINFO_PRESENT,
environment, (), &si
).unwrap_or_else(|err| panic!("process {exe:?} failed: {err:?}"));
set_thread_token(&pi.thread, &tokens.permissive).unwrap();
job::relimit(&job, 0);
resume_thread(&pi.thread).unwrap();
#[cfg(std)] let conio = {
use std::io::{BufReader, BufRead};
let thread_id = pi.thread_id;
let process_id = pi.process_id;
std::thread::spawn(move || -> io::Result<()> {
let read = BufReader::new(_read);
for line in read.lines() {
println!("[{process_id}:{thread_id}] console i/o: {}", line?); }
Ok(())
})
};
debugger::debug_loop(&tokens, &pi);
let exit = wait_for_process(&pi.process).unwrap();
drop(si);
drop(write); #[cfg(std)] match conio.join().unwrap() {
Err(err) if err.kind() == io::ErrorKind::BrokenPipe => {},
other => other.unwrap(),
}
assert!(exit == 0, "exit code: 0x{exit:08x} {}", Error::from(exit).friendly());
}