Extracted step-by-step inspection into own function
This commit is contained in:
parent
cd8ae69d7f
commit
72470c5435
81
src/main.rs
81
src/main.rs
|
|
@ -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}");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue