### obfstr::wide usage example Source: https://docs.rs/obfstr/latest/obfstr/macro.wide.html?search=std%3A%3Avec Example usage of obfstr::wide, showing how to create a UTF-16 encoded string constant and compare it to an expected array. ```rust let expected = &['W' as u16, 'i' as u16, 'd' as u16, 'e' as u16, 0]; assert_eq!(expected, obfstr::wide!("Wide\0")); ``` -------------------------------- ### test_example unit test Source: https://docs.rs/obfstr/latest/src/obfstr/wide.rs.html?search= Unit test verifying that the wide! macro encodes the string "example" correctly. ```rust #[test] fn test_example() { let text = &['e' as u16, 'x' as u16, 'a' as u16, 'm' as u16, 'p' as u16, 'l' as u16, 'e' as u16]; assert_eq!(text, wide!("example")); } ``` -------------------------------- ### obfstr::position! macro usage examples Source: https://docs.rs/obfstr/latest/src/obfstr/pos.rs.html?search= Shows how to use the obfstr::position! macro to find the byte range of a substring at compile time. The first example asserts the range for 'st' in 'haystack'. The second example demonstrates pooling strings in a single obfstr and reading them back using position!. ```rust assert_eq!(obfstr::position!("haystack", "st"), 3..5); assert_eq!(obfstr::position!("haystack", "haystack"), 0..8); assert_eq!(obfstr::position!("haystack", "ck"), 6..8); ``` ```rust const POOL: &str = concat!("Foo", "Bar", "Baz"); obfstr::obfstr! { let pool = POOL; } // Later, read strings from the pool let foo = &pool[obfstr::position!(POOL, "Foo")]; let bar = &pool[obfstr::position!(POOL, "Bar")]; let baz = &pool[obfstr::position!(POOL, "Baz")]; ``` -------------------------------- ### obfcstr usage example Source: https://docs.rs/obfstr/latest/obfstr/macro.obfcstr.html?search= Demonstrates using obfcstr to obfuscate a C string constant and assert its value. ```rust use std::ffi::CStr; use obfstr::obfcstr as cstr; const HELLO_WORLD: &'static CStr = c"Hello CStr"; assert_eq!(cstr!(HELLO_WORLD).to_str().unwrap(), "Hello CStr"); ``` -------------------------------- ### Macro obfstr! Source: https://docs.rs/obfstr/latest/obfstr/macro.obfstr.html?search= Documentation for the obfstr! macro, including its syntax forms and usage examples. ```APIDOC ## Macro `obfstr!` ### Description Compiletime string constant obfuscation. The macro returns the deobfuscated string as a temporary `&str` value and must be consumed in the same statement it was used. It supports multiple syntax forms to reuse obfuscated strings in outer scopes. ### Syntax ```rust macro_rules! obfstr { ($(let $name:ident = $s:expr;)*) => { ... }; ($name:ident = $s:expr) => { ... }; ($buf:ident <- $s:expr) => { ... }; ($s:expr) => { ... }; } ``` ### Usage #### Basic Usage Obfuscate a string literal and use it in the same statement: ```rust use obfstr::obfstr as s; const HELLO_WORLD: &str = "Hello 🌍"; assert_eq!(s!(HELLO_WORLD), HELLO_WORLD); ``` #### Multiple Strings Obfuscate multiple strings and bind them to variables in the outer scope: ```rust use obfstr::obfstr as s; s! { let s = "Hello world"; let another = "another"; } assert_eq!(s, "Hello world"); assert_eq!(another, "another"); ``` #### Assign to Uninitialized Variable Assign an obfuscated string to an uninitialized variable in an outer scope: ```rust use obfstr::obfstr as s; let (true_string, false_string); let string = if true { s!(true_string = "true") } else { s!(false_string = "false") }; assert_eq!(string, "true"); ``` #### Return from Function Return an obfuscated string from a function using a buffer: ```rust use obfstr::obfstr as s; fn helper(buf: &mut [u8]) -> &str { s!(buf <- "hello") } let mut buf = [0u8; 16]; assert_eq!(helper(&mut buf), "hello"); ``` ### Notes - The obfuscation is intended to make it difficult to discover original strings with automated analysis, but it is not intended to hinder a dedicated reverse engineer. - This macro should not be used to hide secrets in client binaries. ``` -------------------------------- ### Basic obfstmt usage example Source: https://docs.rs/obfstr/latest/obfstr/macro.obfstmt.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows how to use obfstmt to obfuscate a sequence of statements. Variables must be declared and initialized before the macro, and they need to be mutable. ```rust let mut tmp = 0; obfstr::obfstmt! { tmp = 2; tmp *= 22; tmp -= 12; tmp /= 3; } assert_eq!(tmp, 10); ``` -------------------------------- ### obfstr::xref_mut! macro signature and usage Source: https://docs.rs/obfstr/latest/obfstr/macro.xref_mut.html?search=u32+-%3E+bool The macro signature and a usage example for obfstr::xref_mut!. The example obfuscates a mutable reference to a static variable, and the assertion verifies the reference still points to the original data. ```rust macro_rules! xref_mut { ($e:expr) => { ... }; } ``` ```rust static mut FOO: i32 = 42; let foo = obfstr::xref_mut!(unsafe { &mut *(&raw mut FOO) }); // When looking at the disassembly the reference to `FOO` has been obfuscated. assert_eq!(foo as *mut _, &raw mut FOO); ``` -------------------------------- ### Basic obfstr usage with assertion Source: https://docs.rs/obfstr/latest/obfstr/macro.obfstr.html?search=u32+-%3E+bool Shows the simplest form of the obfstr macro, returning a temporary &str that must be consumed in the same statement. The example asserts that the deobfuscated string equals the original constant. ```rust use obfstr::obfstr as s; const HELLO_WORLD: &str = "Hello 🌍"; assert_eq!(s!(HELLO_WORLD), HELLO_WORLD); ``` -------------------------------- ### position with pooled strings Source: https://docs.rs/obfstr/latest/obfstr/macro.position.html?search=u32+-%3E+bool Example of using obfstr::position to read strings from a pooled string created with obfstr::obfstr!. The pool is defined with concat! and then indexed using the positions returned by position!. ```rust const POOL: &str = concat!("Foo", "Bar", "Baz"); obfstr::obfstr! { let pool = POOL; } // Later, read strings from the pool let foo = &pool[obfstr::position!(POOL, "Foo")]; let bar = &pool[obfstr::position!(POOL, "Bar")]; let baz = &pool[obfstr::position!(POOL, "Baz")]; ``` -------------------------------- ### Usage example for xref_mut Source: https://docs.rs/obfstr/latest/obfstr/macro.xref_mut.html Demonstrates using `xref_mut!` to obfuscate a mutable reference to a static variable. The comment notes that the reference to `FOO` is obfuscated in the disassembly, and the assertion verifies the pointer is correct. ```rust static mut FOO: i32 = 42; let foo = obfstr::xref_mut!(unsafe { &mut *(&raw mut FOO) }); // When looking at the disassembly the reference to `FOO` has been obfuscated. assert_eq!(foo as *mut _, &raw mut FOO); ``` -------------------------------- ### Using obfstr::hash with a string constant Source: https://docs.rs/obfstr/latest/obfstr/macro.hash.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Example usage of obfstr::hash on a string constant. The macro guarantees compile-time evaluation and returns a hash value (0x6E4A573D for "Hello World"). ```rust const STRING: &str = "Hello World"; assert_eq!(obfstr::hash!(STRING), 0x6E4A573D); ``` -------------------------------- ### obfstr::position const function usage example Source: https://docs.rs/obfstr/latest/src/obfstr/pos.rs.html?search= Shows the const function obfstr::position returning a std::ops::Range for a substring at compile time. The example asserts the range for 'st' in 'haystack'. ```rust const POSITION: std::ops::Range = obfstr::position("haystack", "st"); assert_eq!(POSITION, 3..5); ``` -------------------------------- ### Macros Source: https://docs.rs/obfstr/latest/obfstr?search= Compiletime macros for string constant obfuscation and related utilities. ```APIDOC ## Macro: obfstr ### Description Compiletime string constant obfuscation. ### Usage `obfstr!("literal")` ### Parameters - `literal` (string literal) - Required - The string constant to obfuscate. ### Returns Obfuscated string constant. ## Macro: obfbytes ### Description Compiletime byte string obfuscation. ### Usage `obfbytes!("literal")` ### Parameters - `literal` (byte string literal) - Required - The byte string constant to obfuscate. ### Returns Obfuscated byte string constant. ## Macro: obfcstr ### Description Compiletime cstr constant obfuscation. ### Usage `obfcstr!("literal")` ### Parameters - `literal` (C string literal) - Required - The C string constant to obfuscate. ### Returns Obfuscated C string constant. ## Macro: obfstmt ### Description Statement control flow obfuscation. ### Usage `obfstmt! { ... }` ### Parameters - `statements` (block) - Required - The statements to obfuscate. ### Returns Obfuscated statements. ## Macro: obfstring ### Description Compiletime string constant obfuscation. ### Usage `obfstring!("literal")` ### Parameters - `literal` (string literal) - Required - The string constant to obfuscate. ### Returns Obfuscated string constant. ## Macro: obfwide ### Description Compiletime wide string constant obfuscation. ### Usage `obfwide!("literal")` ### Parameters - `literal` (string literal) - Required - The wide string constant to obfuscate. ### Returns Obfuscated wide string constant. ## Macro: wide ### Description Encodes the input string as a wide string (utf-16) constant. ### Usage `wide!("literal")` ### Parameters - `literal` (string literal) - Required - The string to encode as wide string. ### Returns Wide string constant. ## Macro: xref ### Description Obfuscates the xref to data reference. ### Usage `xref!(expr)` ### Parameters - `expr` (expression) - Required - The data reference to obfuscate. ### Returns Obfuscated reference. ## Macro: xref_mut ### Description Obfuscates the xref to data reference. ### Usage `xref_mut!(expr)` ### Parameters - `expr` (expression) - Required - The mutable data reference to obfuscate. ### Returns Obfuscated mutable reference. ## Macro: position ### Description Finds the position of the needle in the haystack at compiletime. ### Usage `position!(haystack, needle)` ### Parameters - `haystack` (string literal) - Required - The string to search in. - `needle` (string literal) - Required - The substring to find. ### Returns Position of the needle in the haystack. ## Macro: random ### Description Compiletime random number generator. ### Usage `random!()` ### Parameters None. ### Returns Random number generated at compiletime. ## Macro: hash ### Description Compiletime string constant hash. ### Usage `hash!("literal")` ### Parameters - `literal` (string literal) - Required - The string to hash. ### Returns Hash value of the string. ``` -------------------------------- ### Constants Source: https://docs.rs/obfstr/latest/obfstr?search= Compiletime constants provided by the crate. ```APIDOC ## Constant: SEED ### Description Compiletime RNG seed. ### Type Integer constant. ### Usage `obfstr::SEED` ``` -------------------------------- ### Functions Source: https://docs.rs/obfstr/latest/obfstr?search= Compiletime functions for hashing and bitmixing. ```APIDOC ## Function: hash ### Description Compiletime string constant hash. ### Signature `pub const fn hash(s: &str) -> u64` ### Parameters - `s` (&str) - Required - The string to hash. ### Returns u64 - The hash value. ## Function: splitmix ### Description Compiletime bitmixing. ### Signature `pub const fn splitmix(x: u64) -> u64` ### Parameters - `x` (u64) - Required - The value to mix. ### Returns u64 - The mixed value. ``` -------------------------------- ### Full source of obfstr::pos.rs Source: https://docs.rs/obfstr/latest/src/obfstr/pos.rs.html?search= Complete implementation of the position macro, const position function, the Quicksearch-based search helper, and unit tests. The macro expands to a const block calling position; position panics at compile time if the needle is not found. ```rust use core::{ops, str}; /// Finds the position of the needle in the haystack at compiletime. /// /// Produces a const-eval error if the needle is not a substring of the haystack. /// /// # Examples /// /// ``` /// assert_eq!(obfstr::position!("haystack", "st"), 3..5); ///# assert_eq!(obfstr::position!("haystack", "haystack"), 0..8); ///# assert_eq!(obfstr::position!("haystack", "ck"), 6..8); /// ``` /// /// Use this API when pooling strings in a single obfstr: /// /// ``` /// const POOL: &str = concat!("Foo", "Bar", "Baz"); /// /// obfstr::obfstr! { let pool = POOL; } /// /// // Later, read strings from the pool /// let foo = &pool[obfstr::position!(POOL, "Foo")]; /// let bar = &pool[obfstr::position!(POOL, "Bar")]; /// let baz = &pool[obfstr::position!(POOL, "Baz")]; /// ``` #[macro_export] macro_rules! position { ($haystack:expr, $needle:expr) => { const { $crate::position($haystack, $needle) } }; } /// Finds the position of the needle in the haystack at compiletime. /// /// Produces a const-eval error if the needle is not a substring of the haystack. /// /// ``` /// const POSITION: std::ops::Range = obfstr::position("haystack", "st"); /// assert_eq!(POSITION, 3..5); /// ``` #[doc(hidden)] #[inline(always)] pub const fn position(haystack: &str, needle: &str) -> ops::Range { let start = search(haystack, needle); // Panic if substring not found if start < 0 { panic!("Needle not found in the haystack"); } let start = start as usize; start..start + needle.len() } const fn search(haystack: &str, needle: &str) -> isize { // Short-circuit empty needles if needle.len() == 0 { return 0; } let haystack = haystack.as_bytes(); let needle = needle.as_bytes(); // Avoid overflow checks later if needle.len() <= haystack.len() { // Special case for needle length of 1 if needle.len() == 1 { let needle = needle[0]; let mut offset = 0; while offset <= haystack.len() { if haystack[offset] == needle { return offset as isize; } offset += 1; } } // Full blown quicksearch else { // assumed: // needle.len() >= 2 // needle.len() <= haystack.len() // Initialize the jump table let mut jumps = [max(needle.len()); 256]; let tail = needle.len() - 1; let mut i = 0; while i < tail { jumps[needle[i] as usize] = max(tail - i); i += 1; } // Find the needle let sentinel = needle[tail]; let mut offset = 0; while offset < haystack.len() - tail { let chr = haystack[offset + tail]; if chr == sentinel && check(haystack, needle, offset) { return offset as isize; } offset += jumps[chr as usize] as usize; } } } return -1; } #[inline(always)] const fn check(haystack: &[u8], needle: &[u8], offset: usize) -> bool { let mut i = 0; while i < needle.len() { if haystack[offset + i] != needle[i] { return false; } i += 1; } return true; } #[inline(always)] const fn max(a: usize) -> u8 { if a > 255 { 255 } else { a as u8 } } #[test] fn test_position() { assert_eq!(position("ABCBC", "CBC"), 2..5); assert_eq!(position("ABCBC", "ABCBC"), 0..5); } #[test] #[should_panic] fn test_position_needle_longer_than_haystack() { let _ = position("haystack", "needleneedleneedle"); } ``` -------------------------------- ### generate Source: https://docs.rs/obfstr/latest/src/obfstr/cfo.rs.html Generates a collision-free key table for a sequence of statements. The returned table contains one key per statement plus the final exit key. The odd-increment sequence is full-period over u32, and the mixer is bijective, so keys do not repeat until the 32-bit period wraps. ```APIDOC ## generate ### Description Generates a collision-free key table for a sequence of statements. The returned table contains one key per statement plus the final exit key. The odd-increment sequence is full-period over `u32`, and the mixer is bijective, so keys do not repeat until the 32-bit period wraps. ### Signature ```rust pub const fn generate(seed: u32, stmts: &[&'static str]) -> [u32; LEN] ``` ### Parameters - **seed** (u32) - Required - Seed value used to generate the key table. - **stmts** (&[&'static str]) - Required - Slice of statement strings for which keys are generated. ### Returns - **Array of u32** - A key table of length `LEN` containing one key per statement plus the final exit key. ### Panics - Panics if `LEN == 0` or `LEN - 1 != stmts.len()`. ``` -------------------------------- ### position basic usage Source: https://docs.rs/obfstr/latest/obfstr/macro.position.html?search=u32+-%3E+bool Example showing how to use obfstr::position to find the byte range of a substring in a string literal. The result is a range (3..5) for "st" in "haystack". ```rust assert_eq!(obfstr::position!("haystack", "st"), 3..5); ``` -------------------------------- ### xref and xref_mut Source: https://docs.rs/obfstr/latest/src/obfstr/xref.rs.html?search=std%3A%3Avec Documentation for the xref and xref_mut macros and functions from the obfstr crate, which obfuscate references to data. ```APIDOC ## xref! macro ### Description Obfuscates the xref to data reference. This macro can be used for a more lightweight obfuscation that keeps the `'static` nature of string constants. ### Usage ```rust static FOO: i32 = 42; let foo = obfstr::xref!(&FOO); assert_eq!(foo as *const _, &FOO as *const _); assert_eq!(obfstr::xref!("Hello world!"), "Hello world!"); assert_eq!(obfstr::xref!(b"Byte array"), b"Byte array"); ``` ### Parameters - `$e` (expression) - Required - The expression to obfuscate the reference to. ### Returns - The same reference type as the input, with the xref obfuscated. ## xref_mut! macro ### Description Obfuscates the xref to mutable data reference. This macro is used for mutable references. ### Usage ```rust static mut FOO: i32 = 42; let foo = obfstr::xref_mut!(unsafe { &mut *(&raw mut FOO) }); assert_eq!(foo as *mut _, &raw mut FOO); ``` ### Parameters - `$e` (expression) - Required - The expression to obfuscate the mutable reference to. ### Returns - The same mutable reference type as the input, with the xref obfuscated. ## xref function ### Description Obfuscates the xref to data reference. This function is called by the `xref!` macro and can be used directly. ### Signature ```rust pub fn xref(p: &'static T) -> &'static T ``` ### Parameters - `p` (`&'static T`) - Required - The reference to obfuscate. - `OFFSET` (u32 const) - Required - The offset used for obfuscation. - `SEED` (u64 const) - Required - The seed used for obfuscation. ### Returns - `&'static T` - The obfuscated reference. ## xref_mut function ### Description Obfuscates the xref to mutable data reference. This function is called by the `xref_mut!` macro and can be used directly. ### Signature ```rust pub fn xref_mut(p: &'static mut T) -> &'static mut T ``` ### Parameters - `p` (`&'static mut T`) - Required - The mutable reference to obfuscate. - `OFFSET` (u32 const) - Required - The offset used for obfuscation. - `SEED` (u64 const) - Required - The seed used for obfuscation. ### Returns - `&'static mut T` - The obfuscated mutable reference. ``` -------------------------------- ### obfstmt! macro with default seed Source: https://docs.rs/obfstr/latest/src/obfstr/cfo.rs.html?search=std%3A%3Avec Example usage of the obfstmt! macro without an explicit seed. The macro obfuscates the relationship between statements. Variables cannot be declared inside the obfuscated statements; declare and initialize them beforehand as mutable with an initial value. ```rust let mut tmp = 0; obfstr::obfstmt! { tmp = 2; tmp *= 22; tmp -= 12; tmp /= 3; } # obfstr::obfstmt! {} assert_eq!(tmp, 10); ``` -------------------------------- ### obfstr::random! behavior inside macros Source: https://docs.rs/obfstr/latest/obfstr/macro.random.html?search= Demonstrates that obfstr::random! works as expected at top level and with unique seeds, but not when used inside macro definitions without seeds. Includes examples of using seeds and stringify! to generate distinct values. ```rust // When used as top-level input to macros, random works as expected assert_ne!(obfstr::random!(u64), obfstr::random!(u64)); // When used inside the definition of a macro, random does not work as expected macro_rules! inside { () => { assert_eq!(obfstr::random!(u64), obfstr::random!(u64)); }; } inside!(); // When provided a unique seed, random works as expected // Note that the seeds must evaluate to a literal! macro_rules! seeded { () => { assert_ne!(obfstr::random!(u64, "lhs"), obfstr::random!(u64, "rhs")); }; } seeded!(); // Repeated usage in macros, random does not work as expected macro_rules! repeated { ($($name:ident),*) => { $(let $name = obfstr::random!(u64, "seed");)* }; } repeated!(a, b); assert_eq!(a, b); // Provide additional unique seeds, random works as expected macro_rules! repeated_seeded { ($($name:ident),*) => { $(let $name = obfstr::random!(u64, "seed", stringify!($name));)* }; } repeated_seeded!(c, d); assert_ne!(c, d); ``` -------------------------------- ### obfstr::hash! Source: https://docs.rs/obfstr/latest/obfstr/macro.hash.html?search=std%3A%3Avec Compiletime string constant hash. Helper macro guarantees compiletime evaluation of the string constant hash. ```APIDOC ## Macro `obfstr::hash!` ### Description Compiletime string constant hash. Helper macro guarantees compiletime evaluation of the string constant hash. ### Signature ```rust macro_rules! hash { ($s:expr) => { ... }; } ``` ### Parameters - `$s` (expression) - Required - The string constant to hash. ### Example ```rust const STRING: &str = "Hello World"; assert_eq!(obfstr::hash!(STRING), 0x6E4A573D); ``` ``` -------------------------------- ### search function implementation Source: https://docs.rs/obfstr/latest/src/obfstr/pos.rs.html?search=std%3A%3Avec Internal const function implementing a quicksearch algorithm to find the needle offset, returning -1 if not found. ```rust const fn search(haystack: &str, needle: &str) -> isize { // Short-circuit empty needles if needle.len() == 0 { return 0; } let haystack = haystack.as_bytes(); let needle = needle.as_bytes(); // Avoid overflow checks later if needle.len() <= haystack.len() { // Special case for needle length of 1 if needle.len() == 1 { let needle = needle[0]; let mut offset = 0; while offset <= haystack.len() { if haystack[offset] == needle { return offset as isize; } offset += 1; } } // Full blown quicksearch else { // assumed: // needle.len() >= 2 // needle.len() <= haystack.len() // Initialize the jump table let mut jumps = [max(needle.len()); 256]; let tail = needle.len() - 1; let mut i = 0; while i < tail { jumps[needle[i] as usize] = max(tail - i); i += 1; } // Find the needle let sentinel = needle[tail]; let mut offset = 0; while offset < haystack.len() - tail { let chr = haystack[offset + tail]; if chr == sentinel && check(haystack, needle, offset) { return offset as isize; } offset += jumps[chr as usize] as usize; } } } return -1; } ``` -------------------------------- ### obfstmt usage with explicit seed Source: https://docs.rs/obfstr/latest/obfstr/macro.obfstmt.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows how to provide an explicit constant u32 seed to obfstmt when otherwise-identical macro invocations need different control flow. The seed is mixed with the stringified statements. ```rust let mut tmp = 0; obfstr::obfstmt! { @seed obfstr::random!(u32, "example"); tmp = 2; tmp *= 5; } assert_eq!(tmp, 10); ``` -------------------------------- ### obfstr syntax forms for outer scopes Source: https://docs.rs/obfstr/latest/obfstr/macro.obfstr.html?search=u32+-%3E+bool Demonstrates the different syntax forms supported by obfstr to reuse obfuscated strings in outer scopes: multiple let bindings, assignment to uninitialized variables, and returning from a function using a buffer. ```rust use obfstr::obfstr as s; // Obfuscate a bunch of strings s! { let s = "Hello world"; let another = "another"; } assert_eq!(s, "Hello world"); assert_eq!(another, "another"); // Assign to an uninit variable in outer scope let (true_string, false_string); let string = if true { s!(true_string = "true") } else { s!(false_string = "false") }; assert_eq!(string, "true"); // Return an obfuscated string from a function fn helper(buf: &mut [u8]) -> &str { s!(buf <- "hello") } let mut buf = [0u8; 16]; assert_eq!(helper(&mut buf), "hello"); ``` -------------------------------- ### Obfuscate data references with xref! and xref_mut! macros Source: https://docs.rs/obfstr/latest/src/obfstr/xref.rs.html The complete source of the xref.rs module, defining the xref! and xref_mut! macros and their supporting functions for obfuscating references to data. It includes the obfuscation logic using splitmix and obfstmt, and tests for slices and a regression case. ```rust use core::hint; /// Obfuscates the xref to data reference. /// /// ``` /// 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 _); /// ``` /// /// This can be used for a more lightweight obfuscation that keeps that `'static` nature of string constants: /// /// ``` /// assert_eq!(obfstr::xref!("Hello world!"), "Hello world!"); /// assert_eq!(obfstr::xref!(b"Byte array"), b"Byte array"); /// ``` #[macro_export] macro_rules! xref { ($e:expr) => { $crate::xref::xref::<_, {$crate::random!(u32, stringify!($e), "OFFSET")}, {$crate::random!(u64, stringify!($e), "SEED")}>($e) }; } #[inline(always)] const fn non_zero(rand: u32) -> u32 { if rand == 0 { 1 } else { rand } } #[inline(always)] 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)), 4 => !v, 5 => v ^ (v >> non_zero(rand & 31)), 6 => v.wrapping_mul(non_zero(rand)), 7 => v.wrapping_neg(), _ => unsafe { hint::unreachable_unchecked() } } } #[inline(always)] const fn obfuscate(mut v: u32) -> usize { use crate::{splitmix, obfstmt}; let seed1 = splitmix(SEED); let seed2 = splitmix(seed1); let seed3 = splitmix(seed2); let seed4 = splitmix(seed3); let seed5 = splitmix(seed4); // Derive the control flow seed from the xref seed obfstmt! { @seed (SEED ^ (SEED >> 32)) as u32; v = obfchoice(v, seed1); v = obfchoice(v, seed2); v = obfchoice(v, seed3); v = obfchoice(v, seed4); v = obfchoice(v, seed5); } return (v & 0xffff) as usize } #[inline(never)] 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 { unsafe { let mut p: *const T = p; // Force compiletime evaluation so the reference uses an offset relocation addend // Launder the values through black_box to prevent LLVM from optimizing away the obfuscation let val = inner::(hint::black_box((p as *const u8).wrapping_sub(const { obfuscate::(OFFSET) })), hint::black_box(OFFSET)); // set_ptr_value *(&mut p as *mut *const T as *mut *const u8) = val; &*p } } /// Obfuscates the xref to data reference. /// /// ``` /// static mut FOO: i32 = 42; /// let foo = obfstr::xref_mut!(unsafe { &mut *(&raw mut FOO) }); /// /// // When looking at the disassembly the reference to `FOO` has been obfuscated. /// assert_eq!(foo as *mut _, &raw mut FOO); /// ``` #[macro_export] macro_rules! xref_mut { ($e:expr) => { $crate::xref::xref_mut::<_, {$crate::random!(u32, stringify!($e), "OFFSET")}, {$crate::random!(u64, stringify!($e), "SEED")}>($e) }; } #[inline(never)] 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 { unsafe { let mut p: *mut T = p; // Force compiletime evaluation so the reference uses an offset relocation addend // Launder the values through black_box to prevent LLVM from optimizing away the obfuscation let val = inner_mut::(hint::black_box((p as *mut u8).wrapping_sub(const { obfuscate::(OFFSET) })), hint::black_box(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!(&FOO[..]); assert_eq!(foo as *const _, &FOO as *const _); assert_eq!(xref!("Hello world!"), "Hello world!"); assert_eq!(xref!(b"Byte array"), b"Byte array"); } #[test] fn regression1() { // Caused by `v = v ^ (v >> RNG)` when RNG is zero to always be zero let v = obfuscate::<0xC4B3B4F3D986EFBEu64>(0x3C236765u32); assert_ne!(v, 0); } ``` -------------------------------- ### MurmurHash3 implementation and macro Source: https://docs.rs/obfstr/latest/src/obfstr/murmur3.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Defines the murmur3! macro for compile-time hashing and the const fn murmur3 implementing the 32-bit MurmurHash3 algorithm. The macro supports an optional seed, defaulting to 0. The function processes input in 4-byte chunks and handles trailing bytes, using unsafe slicing due to const fn limitations. ```rust /*! Expose MurmurHash3, a keyed hash function. Not ready for public API. */ use core::slice; /// MurmurHash3 (32-bit variant) keyed hash function. #[doc(hidden)] #[macro_export] macro_rules! murmur3 { ($s:expr, $seed:expr) => { const { $crate::murmur3($s, $seed) } }; ($s:expr) => { const { $crate::murmur3($s, 0) } }; } /// MurmurHash3 (32-bit variant) keyed hash function. #[doc(hidden)] pub const fn murmur3(string: &[u8], seed: u32) -> u32 { let mut h = seed; const C1: u32 = 0xcc9e2d51; const C2: u32 = 0x1b873593; let mut s = string; while s.len() >= 4 { let mut k = u32::from_le_bytes([s[0], s[1], s[2], s[3]]); k = k.wrapping_mul(C1); k = k.rotate_left(15); k = k.wrapping_mul(C2); h ^= k; h = h.rotate_left(13); h = h.wrapping_mul(5).wrapping_add(0xe6546b64); // The slicing operator isn't stable in const fn // s = &s[4..]; s = unsafe { slice::from_raw_parts(s.as_ptr().add(4), s.len() - 4)}; } if s.len() > 0 { let k = match s.len() { 3 => u32::from_le_bytes([s[0], s[1], s[2], 0]), 2 => u32::from_le_bytes([s[0], s[1], 0, 0]), 1 => u32::from_le_bytes([s[0], 0, 0, 0]), _ => 0/*unreachable!()*/, }; h ^= k.wrapping_mul(C1).rotate_left(15).wrapping_mul(C2); } fmix32(h ^ string.len() as u32) } #[inline(always)] const fn fmix32(mut h: u32) -> u32 { h ^= h >> 16; h = h.wrapping_mul(0x85ebca6b); h ^= h >> 13; h = h.wrapping_mul(0xc2b2ae35); h ^= h >> 16; return h; } ``` -------------------------------- ### obfcstr macro definition Source: https://docs.rs/obfstr/latest/obfstr/macro.obfcstr.html?search= Shows the four syntax variants of the obfcstr macro: multiple let bindings, a single let binding, a buffer assignment, and a plain expression. ```rust macro_rules! obfcstr { ($(let $name:ident = $s:expr;)*) => { ... }; ($name:ident = $s:expr) => { ... }; ($buf:ident <- $s:expr) => { ... }; ($s:expr) => { ... }; } ``` -------------------------------- ### Macro signature for xref_mut Source: https://docs.rs/obfstr/latest/obfstr/macro.xref_mut.html Shows the macro_rules! definition signature for `xref_mut`, which takes an expression and expands to an obfuscated reference. ```rust macro_rules! xref_mut { ($e:expr) => { ... }; } ```