Skip to main content

libinject/cmp/
wrappers.rs

1//! **`dr_wrap` wrapper functions for external compare symbols:** (e.g. `memcmp`) found in the loaded module
2//! space. These wrapper functions collect byte-by-byte coverage information on the comparisons.
3//! The calls to the wrapped functions are **not** skipped, hence the application logic is
4//! unaffected.
5
6use crate::{
7    cli, cmp,
8    drcore::{self, log},
9    drwrap, ffi,
10};
11use std::os::raw::c_void;
12
13/// Helper function to be called within a dr_wrap wrapper function. Obtains and returns a pointer
14/// to the AFL coverage bitmap and a suitable bitmap index corresponding to the wrapped function (the index is generated from the program
15/// address of the wrapped function, via hashing and masking).
16unsafe fn setup(wrapctx: *mut c_void) -> Option<(*mut u8, usize)> {
17    unsafe {
18        // Only instrument when the callsite is in the target module.
19        let cli_args = cli::get_args().expect("args were parsed in libinject_init");
20        let retaddr = ffi::drwrap_get_retaddr(wrapctx);
21        if !drcore::app_pc_is_in_target_module(retaddr, cli_args) {
22            return None;
23        }
24
25        let afl_cmp_area = match cmp::utils::get_afl_cmp_area() {
26            Ok(cmp_area_ptr) => cmp_area_ptr,
27            Err(reason) => {
28                log(&reason);
29                return None;
30            }
31        };
32
33        // Use the memcmp callsite (in the target module) to generate the hashed and masked
34        // base_idx used to index intot the afl bitmap.
35        let base_idx = cmp::utils::base_idx_of_app_pc(retaddr);
36        Some((afl_cmp_area, base_idx))
37    }
38}
39
40#[unsafe(no_mangle)]
41pub extern "C" fn pre_wmemcmp(wrapctx: *mut c_void, _user_data: *mut *mut c_void) {
42    unsafe {
43        let a = drwrap::get_arg(wrapctx, 0) as *const u8;
44        let b = drwrap::get_arg(wrapctx, 1) as *const u8;
45        // Multiple the number of wide characters by 2 to get number of bytes (on Windows wide
46        // characters are UTF-16.
47        let n = drwrap::get_arg(wrapctx, 2) as usize * 2;
48
49        let (afl_cmp_area, base_idx) = match setup(wrapctx) {
50            Some(x) => x,
51            None => return,
52        };
53
54        match cmp::utils::compare_ptrs("wmemcmp", afl_cmp_area, base_idx, a, b, n) {
55            Ok(()) => (),
56            Err(reason) => log(&format!(
57                "[wmemcmp] Failed to write cmp data to afl bitmap: {:?}",
58                reason
59            )),
60        };
61    }
62}
63
64#[unsafe(no_mangle)]
65pub extern "C" fn pre_memcmp(wrapctx: *mut c_void, _user_data: *mut *mut c_void) {
66    unsafe {
67        let a = drwrap::get_arg(wrapctx, 0) as *const u8;
68        let b = drwrap::get_arg(wrapctx, 1) as *const u8;
69        let n = drwrap::get_arg(wrapctx, 2) as usize;
70
71        let (afl_cmp_area, base_idx) = match setup(wrapctx) {
72            Some(x) => x,
73            None => return,
74        };
75
76        match cmp::utils::compare_ptrs("memcmp", afl_cmp_area, base_idx, a, b, n) {
77            Ok(()) => (),
78            Err(reason) => log(&format!(
79                "[memcmp] Failed to write cmp data to afl bitmap: {:?}",
80                reason
81            )),
82        };
83    }
84}
85
86#[unsafe(no_mangle)]
87pub extern "C" fn pre_strcmp(wrapctx: *mut c_void, _user_data: *mut *mut c_void) {
88    unsafe {
89        let a = drwrap::get_arg(wrapctx, 0) as *const u8;
90        let b = drwrap::get_arg(wrapctx, 1) as *const u8;
91
92        let (afl_cmp_area, base_idx) = match setup(wrapctx) {
93            Some(x) => x,
94            None => return,
95        };
96
97        // strcmp compares until '\0', so include the terminator
98        let len_a = libc::strlen(a as *const libc::c_char);
99        let len_b = libc::strlen(b as *const libc::c_char);
100        let n = core::cmp::min(len_a, len_b) + 1;
101
102        match cmp::utils::compare_ptrs("strcmp", afl_cmp_area, base_idx, a, b, n) {
103            Ok(()) => (),
104            Err(reason) => log(&format!(
105                "[strcmp] Failed to write cmp data to afl bitmap: {:?}",
106                reason
107            )),
108        };
109    }
110}