rust_native_obf/
lib.rs

1use rand::Rng;
2
3pub const fn fnv1a_hash(s: &str) -> u64 {
4    let bytes = s.as_bytes();
5    let mut hash = 0xcbf29ce484222325u64;
6    let mut i = 0;
7    while i < bytes.len() {
8        hash ^= bytes[i] as u64;
9        hash = hash.wrapping_mul(0x100000001b3);
10        i += 1;
11    }
12    hash
13}
14
15#[macro_export]
16macro_rules! ct_hash {
17    ($s:expr) => {{
18        const _HASH: u64 = $crate::fnv1a_hash($s);
19        _HASH
20    }};
21}
22
23pub struct ObfStr {
24    data: Vec<u8>,
25    key: u8,
26}
27
28impl ObfStr {
29    pub fn new(s: &str) -> Self {
30        let mut rng = rand::thread_rng();
31        let key = rng.gen::<u8>();
32        let data = s.bytes().map(|b| b ^ key).collect();
33        Self { data, key }
34    }
35
36    pub fn reveal(&self) -> String {
37        let bytes: Vec<u8> = self.data.iter().map(|b| b ^ self.key).collect();
38        String::from_utf8_lossy(&bytes).to_string()
39    }
40}
41
42#[macro_export]
43macro_rules! obf_string {
44    ($s:expr) => {{
45        let obf = $crate::ObfStr::new($s);
46        obf.reveal()
47    }};
48}
49
50pub fn multilayer_encrypt(data: &[u8], layers: usize) -> Vec<u8> {
51    let mut result = data.to_vec();
52    for layer in 0..layers {
53        let mut key = 0xA7u8.wrapping_add(layer as u8);
54        for byte in result.iter_mut() {
55            *byte ^= key;
56            key = key.wrapping_mul(13).wrapping_add(47);
57        }
58    }
59    result
60}
61
62pub fn multilayer_decrypt(data: &[u8], layers: usize) -> Vec<u8> {
63    let mut result = data.to_vec();
64    for layer in (0..layers).rev() {
65        let mut key = 0xA7u8.wrapping_add(layer as u8);
66        for byte in result.iter_mut() {
67            *byte ^= key;
68            key = key.wrapping_mul(13).wrapping_add(47);
69        }
70    }
71    result
72}
73
74pub struct StackString<const N: usize> {
75    buf: [u8; N],
76    len: usize,
77}
78
79impl<const N: usize> StackString<N> {
80    pub fn new() -> Self {
81        Self {
82            buf: [0; N],
83            len: 0,
84        }
85    }
86
87    pub fn from_encrypted(encrypted: &[u8], key: u8) -> Self {
88        let mut s = Self::new();
89        for (i, &byte) in encrypted.iter().enumerate().take(N) {
90            s.buf[i] = byte ^ key;
91            s.len += 1;
92        }
93        s
94    }
95
96    pub fn as_str(&self) -> &str {
97        std::str::from_utf8(&self.buf[..self.len]).unwrap_or("")
98    }
99}
100
101pub type FnPtr = fn() -> u64;
102
103pub fn indirect_call(func: FnPtr) -> u64 {
104    let ptr = func as usize;
105    let mangled = ptr ^ 0xDEADBEEFCAFEBABE;
106    let restored = mangled ^ 0xDEADBEEFCAFEBABE;
107    let restored_fn: FnPtr = unsafe { std::mem::transmute(restored) };
108    restored_fn()
109}
110
111pub fn scramble_int(val: i32) -> i32 {
112    let mut result = val;
113    result ^= 0x5A5A5A5A;
114    result = result.wrapping_mul(0x45D9F3B);
115    result = result.rotate_left(13);
116    result ^= 0xAAAAAAAAu32 as i32;
117    result
118}
119
120pub fn unscramble_int(val: i32) -> i32 {
121    let inv = 0x119DE1F3i32;
122    let mut result = val;
123    result ^= 0xAAAAAAAAu32 as i32;
124    result = result.rotate_right(13);
125    result = result.wrapping_mul(inv);
126    result ^= 0x5A5A5A5A;
127    result
128}
129
130#[macro_export]
131macro_rules! switch_case {
132    ($val:expr, $( $case:expr => $code:expr ),* $(,)?) => {{
133        let computed = $val;
134        $(
135            if computed == $case {
136                $crate::stack_noise();
137                return $code;
138            }
139        )*
140        panic!("unhandled case");
141    }};
142}
143
144pub fn junk_code_1() -> u32 {
145    let mut x = 0u32;
146    for i in 0..100 {
147        x = x.wrapping_add(i);
148        x = x.wrapping_mul(3);
149        x ^= 0xDEADBEEF;
150    }
151    x
152}
153
154pub fn junk_code_2() -> u64 {
155    let mut val = 0x1234567890ABCDEFu64;
156    for _ in 0..50 {
157        val = val.rotate_left(7);
158        val ^= 0xFEDCBA9876543210;
159        val = val.wrapping_mul(0x123456789);
160    }
161    val
162}
163
164#[macro_export]
165macro_rules! confuse_flow {
166    ($code:block) => {{
167        let r = rand::random::<u8>() % 3;
168        match r {
169            0 => {
170                $crate::junk_code_1();
171                $code
172            }
173            1 => {
174                $crate::junk_code_2();
175                $code
176            }
177            _ => {
178                $crate::junk_code_1();
179                $crate::junk_code_2();
180                $code
181            }
182        }
183    }};
184}
185
186pub fn fake_operations(input: u64) -> u64 {
187    let mut result = input;
188    result ^= 0xAAAAAAAAAAAAAAAA;
189    result = result.wrapping_mul(0x5555555555555555);
190    result = result.rotate_left(13);
191    result ^= 0x3333333333333333;
192    result
193}
194
195#[inline(never)]
196pub fn opaque_predicate() -> bool {
197    let x = std::time::SystemTime::now()
198        .duration_since(std::time::UNIX_EPOCH)
199        .unwrap()
200        .as_nanos();
201    (x & 1) == (x & 1)
202}
203
204pub fn stack_noise() {
205    let mut buf = [0u8; 256];
206    for i in 0..256 {
207        buf[i] = (i as u8).wrapping_mul(137);
208    }
209    std::hint::black_box(&buf);
210}
211
212#[macro_export]
213macro_rules! hide_call {
214    ($func:expr) => {{
215        if $crate::opaque_predicate() {
216            $crate::stack_noise();
217            $func
218        } else {
219            unreachable!()
220        }
221    }};
222}
223
224pub fn xor_buffer(data: &mut [u8], key: u8) {
225    for byte in data.iter_mut() {
226        *byte ^= key;
227    }
228}
229
230pub fn encode_value(val: u64) -> u64 {
231    let k1 = 0x87654321DEADBEEF;
232    let k2 = 0x123456789ABCDEF0;
233    val.wrapping_mul(k1).wrapping_add(k2)
234}
235
236pub fn decode_value(val: u64) -> u64 {
237    let k1 = 0x87654321DEADBEEF;
238    let k2 = 0x123456789ABCDEF0;
239    val.wrapping_sub(k2).wrapping_mul(mod_inverse(k1))
240}
241
242fn mod_inverse(a: u64) -> u64 {
243    let mut t = 0i128;
244    let mut newt = 1i128;
245    let mut r = u64::MAX as i128 + 1;
246    let mut newr = a as i128;
247
248    while newr != 0 {
249        let quotient = r / newr;
250        let temp = t - quotient * newt;
251        t = newt;
252        newt = temp;
253        let temp = r - quotient * newr;
254        r = newr;
255        newr = temp;
256    }
257
258    if r > 1 {
259        return a;
260    }
261    if t < 0 {
262        t += u64::MAX as i128 + 1;
263    }
264    t as u64
265}
266