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