diff --git a/libafl_bolts/src/minibsod.rs b/libafl_bolts/src/minibsod.rs index b3b52b6b3d..64e958e1ec 100644 --- a/libafl_bolts/src/minibsod.rs +++ b/libafl_bolts/src/minibsod.rs @@ -454,30 +454,77 @@ pub fn dump_registers( } /// Write the content of all important registers -#[cfg(windows)] +#[cfg(all(target_os = "windows", target_arch = "x86_64"))] +#[allow(clippy::similar_names)] +pub fn dump_registers( + writer: &mut BufWriter, + context: &CONTEXT, +) -> Result<(), std::io::Error> { + write!(writer, "r8 : {:#018x}, ", context.R8)?; + write!(writer, "r9 : {:#018x}, ", context.R9)?; + write!(writer, "r10: {:#018x}, ", context.R10)?; + writeln!(writer, "r11: {:#018x}, ", context.R11)?; + write!(writer, "r12: {:#018x}, ", context.R12)?; + write!(writer, "r13: {:#018x}, ", context.R13)?; + write!(writer, "r14: {:#018x}, ", context.R14)?; + writeln!(writer, "r15: {:#018x}, ", context.R15)?; + write!(writer, "rdi: {:#018x}, ", context.Rdi)?; + write!(writer, "rsi: {:#018x}, ", context.Rsi)?; + write!(writer, "rbp: {:#018x}, ", context.Rbp)?; + writeln!(writer, "rbx: {:#018x}, ", context.Rbx)?; + write!(writer, "rdx: {:#018x}, ", context.Rdx)?; + write!(writer, "rax: {:#018x}, ", context.Rax)?; + write!(writer, "rcx: {:#018x}, ", context.Rcx)?; + writeln!(writer, "rsp: {:#018x}, ", context.Rsp)?; + write!(writer, "rip: {:#018x}, ", context.Rip)?; + writeln!(writer, "efl: {:#018x}", context.EFlags)?; + + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "windows", target_arch = "x86"))] +#[allow(clippy::similar_names)] +pub fn dump_registers( + writer: &mut BufWriter, + context: &CONTEXT, +) -> Result<(), std::io::Error> { + write!(writer, "eax: {:#010x}, ", context.Eax)?; + write!(writer, "ebx: {:#010x}, ", context.Ebx)?; + write!(writer, "ecx: {:#010x}, ", context.Ecx)?; + writeln!(writer, "edx: {:#010x}, ", context.Edx)?; + write!(writer, "edi: {:#010x}, ", context.Edi)?; + write!(writer, "esi: {:#010x}, ", context.Esi)?; + write!(writer, "esp: {:#010x}, ", context.Esp)?; + writeln!(writer, "ebp: {:#010x}, ", context.Ebp)?; + write!(writer, "eip: {:#010x}, ", context.Eip)?; + writeln!(writer, "efl: {:#010x} ", context.EFlags)?; + Ok(()) +} + +/// Write the content of all important registers +#[cfg(all(target_os = "windows", target_arch = "aarch64"))] #[allow(clippy::similar_names)] pub fn dump_registers( writer: &mut BufWriter, context: &CONTEXT, ) -> Result<(), std::io::Error> { - write!(writer, "r8 : {:#016x}, ", context.R8)?; - write!(writer, "r9 : {:#016x}, ", context.R9)?; - write!(writer, "r10: {:#016x}, ", context.R10)?; - writeln!(writer, "r11: {:#016x}, ", context.R11)?; - write!(writer, "r12: {:#016x}, ", context.R12)?; - write!(writer, "r13: {:#016x}, ", context.R13)?; - write!(writer, "r14: {:#016x}, ", context.R14)?; - writeln!(writer, "r15: {:#016x}, ", context.R15)?; - write!(writer, "rdi: {:#016x}, ", context.Rdi)?; - write!(writer, "rsi: {:#016x}, ", context.Rsi)?; - write!(writer, "rbp: {:#016x}, ", context.Rbp)?; - writeln!(writer, "rbx: {:#016x}, ", context.Rbx)?; - write!(writer, "rdx: {:#016x}, ", context.Rdx)?; - write!(writer, "rax: {:#016x}, ", context.Rax)?; - write!(writer, "rcx: {:#016x}, ", context.Rcx)?; - writeln!(writer, "rsp: {:#016x}, ", context.Rsp)?; - write!(writer, "rip: {:#016x}, ", context.Rip)?; - writeln!(writer, "efl: {:#016x}, ", context.EFlags)?; + for reg in 0..29_usize { + write!(writer, "x{:02}: 0x{:016x} ", reg, unsafe { + context.Anonymous.X[reg] + })?; + if reg % 4 == 3 || reg == 28_usize { + writeln!(writer)?; + } + } + writeln!(writer, "pc : 0x{:016x} ", context.Pc)?; + writeln!(writer, "sp : 0x{:016x} ", context.Sp)?; + writeln!(writer, "fp : 0x{:016x} ", unsafe { + context.Anonymous.Anonymous.Fp + })?; + writeln!(writer, "lr : 0x{:016x} ", unsafe { + context.Anonymous.Anonymous.Lr + })?; Ok(()) } @@ -1122,3 +1169,78 @@ mod tests { dump_registers(&mut writer, &ucontext).unwrap(); } } + +#[cfg(windows)] +#[cfg(test)] +mod tests { + + use std::io::{stdout, BufWriter}; + use std::sync::mpsc; + + use windows::Win32::{ + Foundation::{CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS}, + System::{ + Diagnostics::Debug::{ + GetThreadContext, CONTEXT, CONTEXT_FULL_AMD64, CONTEXT_FULL_ARM64, CONTEXT_FULL_X86, + }, + Threading::{GetCurrentProcess, GetCurrentThread, ResumeThread, SuspendThread}, + }, + }; + + use crate::minibsod::dump_registers; + + #[test] + #[cfg_attr(miri, ignore)] + pub fn test_dump_registers() { + let (tx, rx) = mpsc::channel(); + let (evt_tx, evt_rx) = mpsc::channel(); + let t = std::thread::spawn(move || { + let cur = unsafe { GetCurrentThread() }; + let proc = unsafe { GetCurrentProcess() }; + let mut out = Default::default(); + unsafe { + DuplicateHandle( + proc, + cur, + proc, + &mut out as *mut _, + 0, + true, + DUPLICATE_SAME_ACCESS, + ) + .unwrap() + }; + tx.send(out).unwrap(); + evt_rx.recv().unwrap(); + }); + + let thread = rx.recv().unwrap(); + eprintln!("thread: {:?}", thread); + unsafe { SuspendThread(thread) }; + + #[derive(Default)] + #[repr(align(16))] + struct Align16 { + pub ctx: CONTEXT, + } + + // https://stackoverflow.com/questions/56516445/getting-0x3e6-when-calling-getthreadcontext-for-debugged-thread + let mut c = Align16::default(); + if cfg!(target_arch = "x86") { + c.ctx.ContextFlags = CONTEXT_FULL_X86; + } else if cfg!(target_arch = "x86_64") { + c.ctx.ContextFlags = CONTEXT_FULL_AMD64; + } else if cfg!(target_arch = "aarch64") { + c.ctx.ContextFlags = CONTEXT_FULL_ARM64; + } + unsafe { GetThreadContext(thread, &mut c.ctx as *mut _).unwrap() }; + + let mut writer = BufWriter::new(stdout()); + dump_registers(&mut writer, &c.ctx).unwrap(); + + unsafe { ResumeThread(thread) }; + unsafe { CloseHandle(thread).unwrap() }; + evt_tx.send(true).unwrap(); + t.join().unwrap(); + } +} diff --git a/libafl_bolts/src/os/windows_exceptions.rs b/libafl_bolts/src/os/windows_exceptions.rs index 867b4d6917..278795f32b 100644 --- a/libafl_bolts/src/os/windows_exceptions.rs +++ b/libafl_bolts/src/os/windows_exceptions.rs @@ -512,7 +512,7 @@ pub unsafe extern "system" fn handle_exception( /// It is just casting into another type, nothing unsafe. #[must_use] pub const unsafe fn sig_ign() -> NativeSignalHandlerType { - core::mem::transmute(1u64) + core::mem::transmute(1usize) } type NativeSignalHandlerType = unsafe extern "C" fn(i32);