Extracted step-by-step inspection into own function

This commit is contained in:
Elnath 2025-04-18 19:49:13 +02:00
parent cd8ae69d7f
commit 72470c5435
1 changed files with 33 additions and 48 deletions

View File

@ -1,63 +1,48 @@
mod child; mod child;
use nix::libc::user_regs_struct;
use nix::sys::ptrace::*; use nix::sys::ptrace::*;
use nix::sys::wait::waitpid; use nix::sys::wait::{waitpid, WaitStatus};
use nix::unistd::{fork, ForkResult}; use nix::unistd::{fork, ForkResult, Pid};
use std::ffi::CString; use std::ffi::CString;
use std::process::ExitCode; use std::process::ExitCode;
fn single_step_all(child_pid: Pid) -> ExitCode {
let mut instruction_number = 0;
loop {
let wait_status = waitpid(child_pid, None);
match wait_status {
Ok(WaitStatus::Stopped(_, _)) => {
instruction_number += 1;
let regs = getregs(child_pid).unwrap();
println!(
"🔎 [==> {}] rip= 0x{:016X}, rax = 0x{rax:X} ({rax})",
instruction_number,
regs.rip,
rax = regs.rax
);
step(child_pid, None).unwrap();
}
Ok(WaitStatus::Exited(_, exit_code)) => {
println!("👋 Child exited with code {exit_code}");
return ExitCode::SUCCESS;
}
other => {
println!("⚠️ Other (unexpected) wait status: {other:?}");
return ExitCode::FAILURE;
}
}
}
}
fn main() -> ExitCode { fn main() -> ExitCode {
let child_exec_path = CString::new(env!("TEST_PROG_PATH")).unwrap(); let child_exec_path = CString::new(env!("TEST_PROG_PATH")).unwrap();
match unsafe { fork() } { match unsafe { fork() } {
Ok(ForkResult::Child) => child::starti(child_exec_path), Ok(ForkResult::Child) => child::starti(child_exec_path),
Ok(ForkResult::Parent { child: child_pid }) => { Ok(ForkResult::Parent { child: child_pid }) => {
println!("✔️ Started child {child_pid}"); println!("✔️ Created child {child_pid}");
return single_step_all(child_pid);
let mut before_instruction = 0; // todo!("Something interesting");
loop {
use nix::sys::signal::Signal::*;
use nix::sys::wait::WaitStatus::*;
match waitpid(child_pid, None) {
Err(e) => {
println!("❌ Wait failed: {e}");
return ExitCode::FAILURE;
}
Ok(status) => match status {
Exited(_pid, exit_code) => {
println!("👋 Child exited with code {exit_code}");
return ExitCode::SUCCESS;
}
Signaled(_, signal, _) => match signal {
SIGKILL => {
println!("💀 Child killed by SIGKILL");
return ExitCode::SUCCESS;
}
s => println!("💡 Child received signal {s:?}"),
},
Stopped(_pid, _signal) => {
let regs = getregs(child_pid).unwrap();
println!(
"🔎 [{}] rip= 0x{:016X}, rax = 0x{rax:X} ({rax})",
before_instruction,
regs.rip,
rax = regs.rax
);
if regs.rax == 60 {
println!("Let's change a register!");
let new_regs = user_regs_struct { rdi: 54, ..regs };
setregs(child_pid, new_regs).unwrap();
}
before_instruction += 1;
step(child_pid, None).unwrap();
}
status => {
println!("⚠️ Other (unexpected) wait status: {status:?}");
}
},
}
}
} }
Err(e) => { Err(e) => {
println!("❌ Fork failed: {e}"); println!("❌ Fork failed: {e}");