From b7a0b823c685edfdaa92600609e895ea51d1945e Mon Sep 17 00:00:00 2001 From: "Dongjia \"toka\" Zhang" Date: Wed, 8 Feb 2023 00:20:38 +0900 Subject: [PATCH] Fix frida_gdiplus (#1045) * fix * I don't like prelude * clp * cargo make test * poc * one to_vec() * fix? * del * fix --- fuzzers/frida_gdiplus/Makefile.toml | 66 +++++++++++++++++++++++ libafl/src/bolts/os/windows_exceptions.rs | 25 +++++++-- libafl/src/executors/inprocess.rs | 63 +++++++++++++--------- 3 files changed, 126 insertions(+), 28 deletions(-) create mode 100644 fuzzers/frida_gdiplus/Makefile.toml diff --git a/fuzzers/frida_gdiplus/Makefile.toml b/fuzzers/frida_gdiplus/Makefile.toml new file mode 100644 index 0000000000..8320e25521 --- /dev/null +++ b/fuzzers/frida_gdiplus/Makefile.toml @@ -0,0 +1,66 @@ +# Variables +[env] +CARGO_TARGET_DIR = { value = "target", condition = { env_not_set = ["CARGO_TARGET_DIR"] } } +FUZZER_NAME={ source = "${CARGO_MAKE_RUST_TARGET_OS}", default_value = "frida_gdiplus", mapping = {"linux" = "frida_gdiplus", "macos" = "frida_gdiplus", "windows" = "frida_gdiplus.exe"} } + + +[tasks.unsupported] +script_runner="@shell" +script=''' +echo "Cargo-make not integrated yet on this" +''' + +# Harness +[tasks.harness] +linux_alias = "unsupported" +mac_alias = "unsupported" +windows_alias = "harness_windows" + + +[tasks.harness_windows] +script_runner="@shell" +script=''' +cl.exe /LD harness.cc /link /dll gdiplus.lib ole32.lib +''' + +# Fuzzer +[tasks.fuzzer] +linux_alias = "unsupported" +mac_alias = "unsupported" +windows_alias = "fuzzer_windows" + +[tasks.fuzzer_windows] +script_runner="@shell" +script=''' +cargo build --release +cp ./target/release/${FUZZER_NAME} . +''' + +# Run the fuzzer +[tasks.run] +linux_alias = "unsupported" +mac_alias = "unsupported" +windows_alias = "run_windows" + +[tasks.run_windows] +script_runner = "@shell" +script=''' +./${FUZZER_NAME} -H harness.dll -i corpus -o output --libs-to-instrument gdi32.dll --libs-to-instrument gdi32full.dll --libs-to-instrument gdiplus.dll --libs-to-instrument WindowsCodecs.dll --disable-excludes +''' +dependencies = [ "fuzzer", "harness" ] + +# Test +[tasks.test] +linux_alias = "unsupported" +mac_alias = "unsupported" +windows_alias = "test_windows" + +[tasks.test_windows] +script_runner = "@shell" +script=''' +start "" "frida_gdiplus.exe" -H harness.dll -i corpus -o output --libs-to-instrument gdi32.dll --libs-to-instrument gdi32full.dll --libs-to-instrument gdiplus.dll --libs-to-instrument WindowsCodecs.dll --disable-excludes +#ping is for timeout +ping -n 10 127.0.0.1>NUL && taskkill /im frida_gdiplus.exe /F +>nul 2>nul dir /a-d "corpus_discovered\*" && (echo Files exist) || (exit /b 1337) +''' +dependencies = [ "fuzzer", "harness" ] \ No newline at end of file diff --git a/libafl/src/bolts/os/windows_exceptions.rs b/libafl/src/bolts/os/windows_exceptions.rs index fe57d6eeff..346e06c909 100644 --- a/libafl/src/bolts/os/windows_exceptions.rs +++ b/libafl/src/bolts/os/windows_exceptions.rs @@ -27,7 +27,7 @@ use crate::Error; const EXCEPTION_CONTINUE_EXECUTION: c_long = -1; // For VEH -//const EXCEPTION_CONTINUE_SEARCH: c_long = 0; +const EXCEPTION_CONTINUE_SEARCH: c_long = 0; // For SEH //const EXCEPTION_EXECUTE_HANDLER: c_long = 1; @@ -297,10 +297,12 @@ struct HandlerHolder { handler: UnsafeCell<*mut dyn Handler>, } +pub const EXCEPTION_HANDLERS_SIZE: usize = 64; + unsafe impl Send for HandlerHolder {} /// Keep track of which handler is registered for which exception -static mut EXCEPTION_HANDLERS: [Option; 64] = [ +static mut EXCEPTION_HANDLERS: [Option; EXCEPTION_HANDLERS_SIZE] = [ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, @@ -321,7 +323,15 @@ unsafe fn internal_handle_exception( handler.handle(exception_code, exception_pointers); EXCEPTION_CONTINUE_EXECUTION } - None => EXCEPTION_CONTINUE_EXECUTION, + None => { + // Go to Default one + let handler_holder = &EXCEPTION_HANDLERS[EXCEPTION_HANDLERS_SIZE - 1] + .as_ref() + .unwrap(); + let handler = &mut **handler_holder.handler.get(); + handler.handle(exception_code, exception_pointers); + EXCEPTION_CONTINUE_SEARCH + } } } @@ -339,7 +349,7 @@ pub unsafe extern "system" fn handle_exception( .unwrap() .ExceptionCode; let exception_code = ExceptionCode::try_from(code.0).unwrap(); - // println!("Received {}", exception_code); + // println!("Received exception; code: {exception_code}"); internal_handle_exception(exception_code, exception_pointers) } @@ -374,6 +384,13 @@ pub unsafe fn setup_exception_handler(handler: &mut T) -> }), ); } + + write_volatile( + &mut EXCEPTION_HANDLERS[EXCEPTION_HANDLERS_SIZE - 1], + Some(HandlerHolder { + handler: UnsafeCell::new(handler as *mut dyn Handler), + }), + ); compiler_fence(Ordering::SeqCst); if catch_assertions { signal(SIGABRT, handle_signal); diff --git a/libafl/src/executors/inprocess.rs b/libafl/src/executors/inprocess.rs index 41d48f0aef..f1dea312cd 100644 --- a/libafl/src/executors/inprocess.rs +++ b/libafl/src/executors/inprocess.rs @@ -929,11 +929,6 @@ pub mod windows_asan_handler { // Make sure we don't crash in the crash handler forever. let input = data.take_current_input::<::Input>(); - #[cfg(feature = "std")] - eprintln!("Child crashed!"); - #[cfg(feature = "std")] - drop(stdout().flush()); - run_observers_and_save_state::( executor, state, @@ -971,7 +966,7 @@ mod windows_exception_handler { use crate::{ bolts::os::windows_exceptions::{ - ExceptionCode, Handler, CRASH_EXCEPTIONS, EXCEPTION_POINTERS, + ExceptionCode, Handler, CRASH_EXCEPTIONS, EXCEPTION_HANDLERS_SIZE, EXCEPTION_POINTERS, }, events::{EventFirer, EventRestarter}, executors::{ @@ -1007,7 +1002,9 @@ mod windows_exception_handler { } fn exceptions(&self) -> Vec { - CRASH_EXCEPTIONS.to_vec() + let crash_list = CRASH_EXCEPTIONS.to_vec(); + assert!(crash_list.len() < EXCEPTION_HANDLERS_SIZE - 1); + crash_list } } @@ -1161,6 +1158,8 @@ mod windows_exception_handler { compiler_fence(Ordering::SeqCst); } + // Is this really crash? + let mut is_crash = true; #[cfg(feature = "std")] if let Some(exception_pointers) = exception_pointers.as_mut() { let code = ExceptionCode::try_from( @@ -1172,7 +1171,14 @@ mod windows_exception_handler { .0, ) .unwrap(); - eprintln!("Crashed with {code}"); + + let exception_list = data.exceptions(); + if exception_list.contains(&code) { + eprintln!("Crashed with {code}"); + } else { + // eprintln!("Exception code received, but {code} is not in CRASH_EXCEPTIONS"); + is_crash = false; + } } else { eprintln!("Crashed without exception (probably due to SIGABRT)"); }; @@ -1216,28 +1222,37 @@ mod windows_exception_handler { let event_mgr = data.event_mgr_mut::(); #[cfg(feature = "std")] - eprintln!("Child crashed!"); + if is_crash { + eprintln!("Child crashed!"); + } else { + // eprintln!("Exception received!"); + } + #[cfg(feature = "std")] drop(stdout().flush()); // Make sure we don't crash in the crash handler forever. - let input = data.take_current_input::<::Input>(); + if is_crash { + let input = data.take_current_input::<::Input>(); - #[cfg(feature = "std")] - eprintln!("Child crashed!"); - #[cfg(feature = "std")] - drop(stdout().flush()); - - run_observers_and_save_state::( - executor, - state, - input, - fuzzer, - event_mgr, - ExitKind::Crash, - ); + run_observers_and_save_state::( + executor, + state, + input, + fuzzer, + event_mgr, + ExitKind::Crash, + ); + } else { + // This is not worth saving + } } - ExitProcess(1); + + if is_crash { + println!("Exiting!"); + ExitProcess(1); + } + // println!("Not Exiting!"); } }