1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
use core::ptr;
/// Obfuscates the xref to static data.
///
/// ```
/// static FOO: i32 = 42;
/// let foo = obfstr::xref!(&FOO);
///
/// // When looking at the disassembly the reference to `FOO` has been obfuscated.
/// assert_eq!(foo as *const _, &FOO as *const _);
/// ```
#[macro_export]
macro_rules! xref {
($e:expr) => { $crate::xref($e, $crate::random!(usize) & 0xffff) };
}
/// Obfuscates the xref to static data.
///
/// The offset can be initialized with [`random!`] for a compiletime random value.
///
/// ```
/// static FOO: i32 = 42;
/// let foo = obfstr::xref(&FOO, 0x123);
///
/// // When looking at the disassembly the reference to `FOO` has been obfuscated.
/// assert_eq!(foo as *const _, &FOO as *const _);
/// ```
#[inline(always)]
pub fn xref<T: ?Sized>(p: &'static T, offset: usize) -> &'static T {
unsafe {
let mut p: *const T = p;
// To avoid LLMV optimizing away the obfuscation, launder it through read_volatile
let val = ptr::read_volatile(&(p as *const u8).wrapping_sub(offset)).wrapping_add(offset);
// set_ptr_value
*(&mut p as *mut *const T as *mut *const u8) = val;
&*p
}
}
/// Obfuscates the xref to static data.
///
/// ```
/// static mut FOO: i32 = 42;
/// let foo = obfstr::xref_mut!(unsafe { &mut FOO });
///
/// // When looking at the disassembly the reference to `FOO` has been obfuscated.
/// assert_eq!(foo as *mut _, unsafe { &mut FOO } as *mut _);
/// ```
#[macro_export]
macro_rules! xref_mut {
($e:expr) => { $crate::xref_mut($e, $crate::random!(usize) & 0xffff) };
}
/// Obfuscates the xref to static data.
///
/// The offset can be initialized with [`random!`] for a compiletime random value.
///
/// ```
/// static mut FOO: i32 = 42;
/// let foo = obfstr::xref_mut(unsafe { &mut FOO }, 0x321);
///
/// // When looking at the disassembly the reference to `FOO` has been obfuscated.
/// assert_eq!(foo as *mut _, unsafe { &mut FOO } as *mut _);
/// ```
#[inline(always)]
pub fn xref_mut<T: ?Sized>(p: &'static mut T, offset: usize) -> &'static mut T {
unsafe {
let mut p: *mut T = p;
// To avoid LLMV optimizing away the obfuscation, launder it through read_volatile
let val = ptr::read_volatile(&(p as *mut u8).wrapping_sub(offset)).wrapping_add(offset);
// set_ptr_value
*(&mut p as *mut *mut T as *mut *mut u8) = val;
&mut *p
}
}
#[test]
fn test_xref_slice() {
static FOO: [i32; 42] = [13; 42];
let foo = xref::<[i32]>(&FOO[..], 0x1000);
assert_eq!(foo as *const _, &FOO as *const _);
}