Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor simplify #53

Merged
merged 1 commit into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions src/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}};
Expand All @@ -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.
Expand Down Expand Up @@ -148,7 +148,7 @@ pub const fn keystream<const LEN: usize>(key: u32) -> [u8; LEN] {
},
_ => (),
}
keys
return keys;
}

/// Obfuscates the input string and given key stream.
Expand All @@ -163,21 +163,21 @@ pub const fn obfuscate<const LEN: usize>(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<const LEN: usize>(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
// 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 {
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 {
Expand Down Expand Up @@ -219,7 +219,7 @@ pub fn deobfuscate<const LEN: usize>(s: &[u8; LEN], k: &[u8; LEN]) -> [u8; LEN]
_ => (),
}
}
buffer
return buf;
}

#[inline(always)]
Expand Down
2 changes: 1 addition & 1 deletion src/cfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub const fn generate<const LEN: usize>(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)),*]);
Expand Down
15 changes: 3 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}};
}
Expand All @@ -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 };
Expand Down Expand Up @@ -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.
Expand Down
3 changes: 1 addition & 2 deletions src/murmur3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
21 changes: 11 additions & 10 deletions src/words.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Wide string obfuscation
=======================
*/

use core::ptr::{read_volatile, write};

/// Compiletime wide string constant obfuscation.
#[macro_export]
macro_rules! obfwide {
Expand All @@ -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)
}};
Expand All @@ -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.
Expand All @@ -69,7 +71,7 @@ pub const fn keystream<const LEN: usize>(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.
Expand All @@ -83,22 +85,21 @@ pub const fn obfuscate<const LEN: usize>(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<const LEN: usize>(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 {
Expand Down Expand Up @@ -128,7 +129,7 @@ pub fn deobfuscate<const LEN: usize>(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
Expand Down
31 changes: 16 additions & 15 deletions src/xref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand All @@ -47,7 +47,7 @@ const fn obfchoice(v: usize, seed: u64) -> usize {
}

#[inline(always)]
const fn obfuscate<const SEED: u64>(mut v: usize) -> usize {
const fn obfuscate<const SEED: u64>(mut v: u32) -> usize {
let mut seed = SEED;
use crate::splitmix;
seed = splitmix(seed);
Expand All @@ -59,17 +59,18 @@ const fn obfuscate<const SEED: u64>(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<const SEED: u64>(p: *const u8, offset: usize) -> *const u8 {
fn inner<const SEED: u64>(p: *const u8, offset: u32) -> *const u8 {
p.wrapping_add(obfuscate::<SEED>(offset))
}

/// Obfuscates the xref to data reference.
#[inline(always)]
pub fn xref<T: ?Sized, const OFFSET: usize, const SEED: u64>(p: &'static T) -> &'static T {
pub fn xref<T: ?Sized, const OFFSET: u32, const SEED: u64>(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
Expand All @@ -93,19 +94,19 @@ pub fn xref<T: ?Sized, const OFFSET: usize, const SEED: u64>(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<const SEED: u64>(p: *mut u8, offset: usize) -> *mut u8 {
fn inner_mut<const SEED: u64>(p: *mut u8, offset: u32) -> *mut u8 {
p.wrapping_add(obfuscate::<SEED>(offset))
}

/// Obfuscates the xref to data reference.
#[inline(always)]
pub fn xref_mut<T: ?Sized, const OFFSET: usize, const SEED: u64>(p: &'static mut T) -> &'static mut T {
pub fn xref_mut<T: ?Sized, const OFFSET: u32, const SEED: u64>(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
Expand All @@ -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);
}