Skip to content

Commit

Permalink
bolts: Support dump_registers on Windows/x86 and Windows/aarch64 and …
Browse files Browse the repository at this point in the history
…fix sig_ign on Windows/x86 (AFLplusplus#2494)

* bolts: Support dump_registers on Windows/x86

* bolts: Support dump_registers on Windows/aarch64

* bolts: Fix sig_ign() on Windows/x86

* bolts: Fix format of dump_registers under Windows

* bolts: Add test for dump_register under Windows
  • Loading branch information
xdqi authored Aug 22, 2024
1 parent 1dfd225 commit 0018f7e
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 20 deletions.
160 changes: 141 additions & 19 deletions libafl_bolts/src/minibsod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,30 +454,77 @@ pub fn dump_registers<W: Write>(
}

/// 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<W: Write>(
writer: &mut BufWriter<W>,
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<W: Write>(
writer: &mut BufWriter<W>,
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<W: Write>(
writer: &mut BufWriter<W>,
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(())
}
Expand Down Expand Up @@ -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();
}
}
2 changes: 1 addition & 1 deletion libafl_bolts/src/os/windows_exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 0018f7e

Please sign in to comment.