Fix frida_gdiplus (#1045)

* fix

* I don't like prelude

* clp

* cargo make test

* poc

* one to_vec()

* fix?

* del

* fix
This commit is contained in:
Dongjia "toka" Zhang 2023-02-08 00:20:38 +09:00 committed by GitHub
parent 0173d722c6
commit b7a0b823c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 126 additions and 28 deletions

View File

@ -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" ]

View File

@ -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<HandlerHolder>; 64] = [
static mut EXCEPTION_HANDLERS: [Option<HandlerHolder>; 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<T: 'static + 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);

View File

@ -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::<<E::State as UsesInput>::Input>();
#[cfg(feature = "std")]
eprintln!("Child crashed!");
#[cfg(feature = "std")]
drop(stdout().flush());
run_observers_and_save_state::<E, EM, OF, Z>(
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<ExceptionCode> {
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::<EM>();
#[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::<<E::State as UsesInput>::Input>();
if is_crash {
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
#[cfg(feature = "std")]
eprintln!("Child crashed!");
#[cfg(feature = "std")]
drop(stdout().flush());
run_observers_and_save_state::<E, EM, OF, Z>(
executor,
state,
input,
fuzzer,
event_mgr,
ExitKind::Crash,
);
run_observers_and_save_state::<E, EM, OF, Z>(
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!");
}
}