From 9df3132bb72badb8ba3396c895fdd3c5a0903a91 Mon Sep 17 00:00:00 2001 From: Casper Date: Sun, 12 Mar 2023 02:50:49 +0100 Subject: [PATCH] Refactor simplify --- src/bytes.rs | 18 +++++++++--------- src/cfo.rs | 2 +- src/lib.rs | 15 +++------------ src/murmur3.rs | 3 +-- src/words.rs | 21 +++++++++++---------- src/xref.rs | 31 ++++++++++++++++--------------- 6 files changed, 41 insertions(+), 49 deletions(-) diff --git a/src/bytes.rs b/src/bytes.rs index c7feb8f..dcd38bc 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -93,12 +93,12 @@ macro_rules! __obfbytes { ($s:expr) => {{ const _OBFBYTES_STRING: &[u8] = $s; const _OBFBYTES_LEN: usize = _OBFBYTES_STRING.len(); - const _OBFBYTES_KEYSTREAM: [u8; _OBFBYTES_LEN] = $crate::bytes::keystream::<_OBFBYTES_LEN>($crate::__entropy!("key", stringify!($s)) as u32); + const _OBFBYTES_KEYSTREAM: [u8; _OBFBYTES_LEN] = $crate::bytes::keystream::<_OBFBYTES_LEN>($crate::random!(u32, "key", stringify!($s))); static _OBFBYTES_SDATA: [u8; _OBFBYTES_LEN] = $crate::bytes::obfuscate::<_OBFBYTES_LEN>(_OBFBYTES_STRING, &_OBFBYTES_KEYSTREAM); $crate::bytes::deobfuscate::<_OBFBYTES_LEN>( $crate::xref::xref::<_, - {$crate::__entropy!("offset", stringify!($s)) as usize}, - {$crate::__entropy!("xref", stringify!($s))}> + {$crate::random!(u32, "offset", stringify!($s))}, + {$crate::random!(u64, "xref", stringify!($s))}> (&_OBFBYTES_SDATA), &_OBFBYTES_KEYSTREAM) }}; @@ -111,7 +111,7 @@ const fn next_round(mut x: u32) -> u32 { x ^= x << 13; x ^= x >> 17; x ^= x << 5; - x + return x; } /// Generate the key stream for array of given length. @@ -148,7 +148,7 @@ pub const fn keystream(key: u32) -> [u8; LEN] { }, _ => (), } - keys + return keys; } /// Obfuscates the input string and given key stream. @@ -163,13 +163,13 @@ pub const fn obfuscate(s: &[u8], k: &[u8; LEN]) -> [u8; LEN] { data[i] = s[i] ^ k[i]; i += 1; } - data + return data; } /// Deobfuscates the obfuscated input string and given key stream. #[inline(always)] pub fn deobfuscate(s: &[u8; LEN], k: &[u8; LEN]) -> [u8; LEN] { - let mut buffer = [0u8; LEN]; + let mut buf = [0u8; LEN]; let mut i = 0; // Try to tickle the LLVM optimizer in _just_ the right way // Use `read_volatile` to avoid constant folding a specific read and optimize the rest @@ -177,7 +177,7 @@ pub fn deobfuscate(s: &[u8; LEN], k: &[u8; LEN]) -> [u8; LEN] // Hand optimize in chunks of 8 and 4 bytes to avoid this unsafe { let src = s.as_ptr(); - let dest = buffer.as_mut_ptr(); + let dest = buf.as_mut_ptr(); // Process in chunks of 8 bytes on 64-bit targets #[cfg(target_pointer_width = "64")] while i < LEN & !7 { @@ -219,7 +219,7 @@ pub fn deobfuscate(s: &[u8; LEN], k: &[u8; LEN]) -> [u8; LEN] _ => (), } } - buffer + return buf; } #[inline(always)] diff --git a/src/cfo.rs b/src/cfo.rs index 4cffe7c..c39ac3e 100644 --- a/src/cfo.rs +++ b/src/cfo.rs @@ -46,7 +46,7 @@ pub const fn generate(mut key: u32, mut xor: u32, stmts: &[&'s macro_rules! obfstmt { ($($stmt:stmt;)*) => {{ // Initial KEY and XOR values - const _OBFSTMT_KEY: u32 = $crate::__entropy!(stringify!($($stmt;)*)) as u32; + const _OBFSTMT_KEY: u32 = $crate::random!(u32, stringify!($($stmt;)*)); const _OBFSTMT_XOR: u32 = $crate::murmur3(b"XOR", _OBFSTMT_KEY); // Count the number of statements const _OBFSTMT_LEN: usize = <[&'static str]>::len(&[$(stringify!($stmt)),*]); diff --git a/src/lib.rs b/src/lib.rs index 2b639c6..e0dffec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,8 +81,8 @@ pub mod xref; #[macro_export] macro_rules! random { ($ty:ident $(, $seeds:expr)* $(,)?) => {{ - const _ENTROPY: u64 = $crate::entropy(concat!(file!(), ":", line!(), ":", column!() $(, ":", $seeds)*)); - const _RANDOM: $ty = $crate::__random_cast!($ty, _ENTROPY); + const _RANDOM: $ty = $crate::__random_cast!($ty, + $crate::entropy(concat!(file!(), ":", line!(), ":", column!() $(, ":", $seeds)*))); _RANDOM }}; } @@ -93,7 +93,7 @@ macro_rules! __random_cast { (u8, $seed:expr) => { $seed as u8 }; (u16, $seed:expr) => { $seed as u16 }; (u32, $seed:expr) => { $seed as u32 }; - (u64, $seed:expr) => { $seed as u64 }; + (u64, $seed:expr) => { $seed }; (usize, $seed:expr) => { $seed as usize }; (i8, $seed:expr) => { $seed as i8 }; (i16, $seed:expr) => { $seed as i16 }; @@ -183,15 +183,6 @@ pub const fn entropy(string: &str) -> u64 { splitmix(SEED ^ splitmix(hash(string) as u64)) } -/// Produces pseudorandom entropy from the argument literals. -#[doc(hidden)] -#[macro_export] -macro_rules! __entropy { - ($($seeds:expr),* $(,)?) => { - $crate::entropy(concat!(file!(), ":", line!(), ":", column!() $(, ":", $seeds)*)) - }; -} - /// Compiletime RNG seed. /// /// This value is derived from the environment variable `OBFSTR_SEED` and has a fixed value if absent. diff --git a/src/murmur3.rs b/src/murmur3.rs index 8c272d5..1870b32 100644 --- a/src/murmur3.rs +++ b/src/murmur3.rs @@ -14,7 +14,6 @@ macro_rules! murmur3 { /// MurmurHash3 (32-bit variant) keyed hash function. #[doc(hidden)] -#[inline] pub const fn murmur3(string: &[u8], seed: u32) -> u32 { let mut h = seed; const C1: u32 = 0xcc9e2d51; @@ -49,7 +48,7 @@ pub const fn murmur3(string: &[u8], seed: u32) -> u32 { fmix32(h ^ string.len() as u32) } -#[inline] +#[inline(always)] const fn fmix32(mut h: u32) -> u32 { h ^= h >> 16; h = h.wrapping_mul(0x85ebca6b); diff --git a/src/words.rs b/src/words.rs index ef262d0..bea86e9 100644 --- a/src/words.rs +++ b/src/words.rs @@ -3,6 +3,8 @@ Wide string obfuscation ======================= */ +use core::ptr::{read_volatile, write}; + /// Compiletime wide string constant obfuscation. #[macro_export] macro_rules! obfwide { @@ -29,12 +31,12 @@ macro_rules! __obfwide { ($s:expr) => {{ const _OBFWIDE_STRING: &[u16] = $crate::wide!($s); const _OBFWIDE_LEN: usize = _OBFWIDE_STRING.len(); - const _OBFWIDE_KEYSTREAM: [u16; _OBFWIDE_LEN] = $crate::words::keystream::<_OBFWIDE_LEN>($crate::__entropy!("key", stringify!($s)) as u32); + const _OBFWIDE_KEYSTREAM: [u16; _OBFWIDE_LEN] = $crate::words::keystream::<_OBFWIDE_LEN>($crate::random!(u32, "key", stringify!($s))); static _OBFWIDE_SDATA: [u16; _OBFWIDE_LEN] = $crate::words::obfuscate::<_OBFWIDE_LEN>(_OBFWIDE_STRING, &_OBFWIDE_KEYSTREAM); $crate::words::deobfuscate::<_OBFWIDE_LEN>( $crate::xref::xref::<_, - {$crate::__entropy!("offset", stringify!($s)) as usize}, - {$crate::__entropy!("xref", stringify!($s))}> + {$crate::random!(u32, "offset", stringify!($s))}, + {$crate::random!(u64, "xref", stringify!($s))}> (&_OBFWIDE_SDATA), &_OBFWIDE_KEYSTREAM) }}; @@ -47,7 +49,7 @@ const fn next_round(mut x: u32) -> u32 { x ^= x << 13; x ^= x >> 17; x ^= x << 5; - x + return x; } /// Generate the key stream for array of given length. @@ -69,7 +71,7 @@ pub const fn keystream(key: u32) -> [u16; LEN] { round_key = next_round(round_key); keys[i] = round_key as u16; } - keys + return keys; } /// Obfuscates the input string and given key stream. @@ -83,22 +85,21 @@ pub const fn obfuscate(s: &[u16], k: &[u16; LEN]) -> [u16; LEN data[i] = s[i] ^ k[i]; i += 1; } - data + return data; } /// Deobfuscates the obfuscated input string and given key stream. #[inline(always)] pub fn deobfuscate(s: &[u16; LEN], k: &[u16; LEN]) -> [u16; LEN] { - let mut buffer = [0u16; LEN]; + let mut buf = [0u16; LEN]; let mut i = 0; // Try to tickle the LLVM optimizer in _just_ the right way // Use `read_volatile` to avoid constant folding a specific read and optimize the rest // Volatile reads of any size larger than 8 bytes appears to cause a bunch of one byte reads // Hand optimize in chunks of 8 and 4 bytes to avoid this unsafe { - use ::core::ptr::{read_volatile, write}; let src = s.as_ptr(); - let dest = buffer.as_mut_ptr(); + let dest = buf.as_mut_ptr(); // Process in chunks of 8 bytes on 64-bit targets #[cfg(target_pointer_width = "64")] while i < LEN & !3 { @@ -128,7 +129,7 @@ pub fn deobfuscate(s: &[u16; LEN], k: &[u16; LEN]) -> [u16; LE write(dest.offset(i as isize), ct ^ k[i]); } } - buffer + return buf; } // Test correct processing of less than multiple of 8 lengths diff --git a/src/xref.rs b/src/xref.rs index 741205a..f56e540 100644 --- a/src/xref.rs +++ b/src/xref.rs @@ -20,24 +20,24 @@ use core::hint; macro_rules! xref { ($e:expr) => { $crate::xref::xref::<_, - {$crate::__entropy!(stringify!($e), 1) as usize}, - {$crate::__entropy!(stringify!($e), 2)}>($e) + {$crate::random!(u32, stringify!($e), "OFFSET")}, + {$crate::random!(u64, stringify!($e), "SEED")}>($e) }; } #[inline(always)] -const fn non_zero(rand: usize) -> usize { +const fn non_zero(rand: u32) -> u32 { if rand == 0 { 1 } else { rand } } #[inline(always)] -const fn obfchoice(v: usize, seed: u64) -> usize { - let rand = (seed >> 32) as i32 as usize; +const fn obfchoice(v: u32, seed: u64) -> u32 { + let rand = (seed >> 32) as u32; match seed & 7 { 0 => v.wrapping_add(rand), 1 => rand.wrapping_sub(v), 2 => v ^ rand, - 3 => v ^ v.rotate_left(non_zero(rand & 7) as u32), + 3 => v ^ v.rotate_left(non_zero(rand & 7)), 4 => !v, 5 => v ^ (v >> non_zero(rand & 31)), 6 => v.wrapping_mul(non_zero(rand)), @@ -47,7 +47,7 @@ const fn obfchoice(v: usize, seed: u64) -> usize { } #[inline(always)] -const fn obfuscate(mut v: usize) -> usize { +const fn obfuscate(mut v: u32) -> usize { let mut seed = SEED; use crate::splitmix; seed = splitmix(seed); @@ -59,17 +59,18 @@ const fn obfuscate(mut v: usize) -> usize { seed = splitmix(seed); v = obfchoice(v, seed); seed = splitmix(seed); - return obfchoice(v, seed & 0xffffffff00000000 | 3) & 0xffff + v = obfchoice(v, seed); + return (v & 0xffff) as usize } #[inline(never)] -fn inner(p: *const u8, offset: usize) -> *const u8 { +fn inner(p: *const u8, offset: u32) -> *const u8 { p.wrapping_add(obfuscate::(offset)) } /// Obfuscates the xref to data reference. #[inline(always)] -pub fn xref(p: &'static T) -> &'static T { +pub fn xref(p: &'static T) -> &'static T { unsafe { let mut p: *const T = p; // Launder the values through black_box to prevent LLVM from optimizing away the obfuscation @@ -93,19 +94,19 @@ pub fn xref(p: &'static T) -> & macro_rules! xref_mut { ($e:expr) => { $crate::xref::xref_mut::<_, - {$crate::__entropy!(stringify!($e), 1) as usize}, - {$crate::__entropy!(stringify!($e), 2)}>($e) + {$crate::random!(u32, stringify!($e), "OFFSET")}, + {$crate::random!(u64, stringify!($e), "SEED")}>($e) }; } #[inline(never)] -fn inner_mut(p: *mut u8, offset: usize) -> *mut u8 { +fn inner_mut(p: *mut u8, offset: u32) -> *mut u8 { p.wrapping_add(obfuscate::(offset)) } /// Obfuscates the xref to data reference. #[inline(always)] -pub fn xref_mut(p: &'static mut T) -> &'static mut T { +pub fn xref_mut(p: &'static mut T) -> &'static mut T { unsafe { let mut p: *mut T = p; // Launder the values through black_box to prevent LLVM from optimizing away the obfuscation @@ -128,6 +129,6 @@ fn test_xref_slice() { #[test] fn regression1() { // Caused by `v = v ^ (v >> RNG)` when RNG is zero to always be zero - let v = obfuscate::<{(-4272872662024917058i64) as u64}>(4898264233338431333usize); + let v = obfuscate::<0xC4B3B4F3D986EFBEu64>(0x3C236765u32); assert_ne!(v, 0); }