mirror of
https://github.com/Astatin3/syscall-stream-rs.git
synced 2026-06-09 00:18:01 -06:00
Work on adding a puppet for the server side aswell
This commit is contained in:
+154
@@ -0,0 +1,154 @@
|
||||
use libc::forkpty;
|
||||
use nix::sys::wait::wait;
|
||||
use nix::{
|
||||
errno::Errno,
|
||||
sys::{ptrace::Options, signal::Signal},
|
||||
};
|
||||
use std::{
|
||||
env::args,
|
||||
os::unix::process::CommandExt,
|
||||
process::{self, Command},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use nix::{
|
||||
sys::{
|
||||
ptrace,
|
||||
wait::{self, WaitStatus},
|
||||
},
|
||||
unistd::{ForkResult, Pid, fork},
|
||||
};
|
||||
|
||||
// pub type Error = Result<(), std::fmt::Error>;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum HavocError {
|
||||
Wait,
|
||||
Register(Errno),
|
||||
Ptrace(Errno),
|
||||
}
|
||||
|
||||
fn main() -> Result<(), std::fmt::Error> {
|
||||
pretty_env_logger::formatted_builder()
|
||||
.filter_level(log::LevelFilter::Trace)
|
||||
.init();
|
||||
|
||||
let args = &(args().collect::<Vec<String>>())[1..];
|
||||
|
||||
match unsafe { fork() } {
|
||||
Ok(ForkResult::Child) => run_child(args),
|
||||
Ok(ForkResult::Parent { child }) => run_parent(child),
|
||||
Err(e) => panic!("Could not fork main process: {}", e),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_child(args: &[String]) {
|
||||
info!("havoc child process executing as {}", process::id());
|
||||
info!("Running: {:?}", args);
|
||||
ptrace::traceme().expect("OS could not be bothered to trace me");
|
||||
|
||||
// loop {
|
||||
// println!("test");
|
||||
// thread::sleep(Duration::from_secs(1));
|
||||
// }
|
||||
// unsafe { exit(0) };
|
||||
let e = Command::new(args.join(" ")).exec();
|
||||
}
|
||||
|
||||
fn run_parent(pid: Pid) {
|
||||
// wait for our child process to be ready
|
||||
let ws = wait().expect("Parent failed waiting for child");
|
||||
// info!("Child process ready with signal: {ws:?}, will ask it to continue untill syscall");
|
||||
|
||||
setup_tracing(pid).expect(format!("Parent failed to set up tracing for {pid:?}").as_str());
|
||||
// trace_syscall(pid, None).expect(format!("Parent failed tracing for {pid:?}").as_str());
|
||||
|
||||
loop {
|
||||
match ptrace::syscall(pid, None).map_err(HavocError::Ptrace) {
|
||||
Ok(_) => { /* nop */ }
|
||||
Err(e) => {
|
||||
error!("error: {:?}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("pid: {}", pid);
|
||||
}
|
||||
fn wait_for_signal() -> Result<(), HavocError> {
|
||||
match wait() {
|
||||
Ok(WaitStatus::Stopped(pid_t, sig_num)) => handle_child_stopped(sig_num, pid_t),
|
||||
|
||||
Ok(WaitStatus::Exited(pid, exit_status)) => {
|
||||
debug!("Child with pid: {} exited with status {}", pid, exit_status);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Ok(status) => {
|
||||
warn!("Received unhandled wait status: {:?}", status);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Err(err) => {
|
||||
error!("An error occurred: {:?}", err);
|
||||
Err(HavocError::Wait)
|
||||
}
|
||||
}
|
||||
}
|
||||
fn handle_sigtrap(pid_t: Pid) -> Result<(), HavocError> {
|
||||
let regs = ptrace::getregs(pid_t).map_err(HavocError::Register)?;
|
||||
if regs.orig_rax == libc::SYS_msync as u64 {
|
||||
if regs.rax == -libc::ENOSYS as u64 {
|
||||
info!("Entry of syscall in {pid_t} : {}", regs.orig_rax);
|
||||
} else {
|
||||
info!("Exit of syscall in {pid_t} : {}", regs.orig_rax);
|
||||
// handle_msync(msync_counter, regs, pid_t)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn handle_child_stopped(sig_num: Signal, pid_t: Pid) -> Result<(), HavocError> {
|
||||
match sig_num {
|
||||
Signal::SIGTRAP => {
|
||||
handle_sigtrap(pid_t)?;
|
||||
trace_syscall(pid_t, None)
|
||||
}
|
||||
Signal::SIGSTOP => trace_syscall(pid_t, Some(Signal::SIGSTOP)),
|
||||
// ... some corner cases like SIGWINCH
|
||||
_ => trace_syscall(pid_t, Some(sig_num)),
|
||||
}
|
||||
}
|
||||
fn trace_syscall(pid: Pid, sig_num: Option<Signal>) -> Result<(), HavocError> {
|
||||
ptrace::syscall(pid, None).map_err(HavocError::Ptrace)?;
|
||||
trace!("{} -> {:?}", pid, sig_num);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Setup the preace options to also trace fork, clone and vfork
|
||||
fn setup_tracing(pid: Pid) -> Result<(), HavocError> {
|
||||
// ptrace::setoptions(
|
||||
// pid,
|
||||
// Options::PTRACE_O_TRACEFORK
|
||||
// .union(Options::PTRACE_O_TRACECLONE)
|
||||
// .union(Options::PTRACE_O_TRACEVFORK),
|
||||
// )
|
||||
ptrace::attach(pid).map_err(HavocError::Ptrace)
|
||||
}
|
||||
|
||||
// fn next_syscall(child_pid: libc::pid_t) -> Result<i64, OsError> {
|
||||
// match WaitPID::from_process(child_pid)? {
|
||||
// WaitPID::SysCall { .. } => (),
|
||||
// x => {
|
||||
// return Err(OsError::new(
|
||||
// ErrorKind::Other,
|
||||
// format!("Expected syscall event, got {:?} instead", x),
|
||||
// ));
|
||||
// }
|
||||
// }
|
||||
// let number = get_syscall_number(child_pid)?;
|
||||
// p_trace_syscall(child_pid, None)?;
|
||||
// Ok(number)
|
||||
// }
|
||||
Reference in New Issue
Block a user