chamox/
lib.rs

1//! A procedural macro for injecting obfuscated code to increase reverse engineering complexity.
2//!
3//! # Usage
4//!
5//! ```rust
6//! use chamox::obfuscate;
7//!
8//! #[obfuscate]
9//! fn my_function() {
10//!     println!("Hello world!");
11//! }
12//! ```
13//!
14//! The macro will inject random meaningless code between your function statements to:
15//! - Make the binary harder to analyze
16//! - Increase reverse engineering complexity
17//! - Preserve the original function behavior
18//!
19//! The injected code includes random operations on:
20//! - Numbers (arithmetic operations)
21//! - Booleans (logical operations)
22//! - Strings (string manipulations)
23
24extern crate proc_macro;
25use proc_macro::TokenStream;
26use quote::quote;
27use rand::Rng;
28use syn::{parse_macro_input, ItemFn};
29
30/// A procedural macro for injecting obfuscated code to increase reverse engineering complexity.
31///
32/// # Usage
33///
34/// ```rust
35/// use chamox::obfuscate;
36///
37/// #[obfuscate]
38/// fn my_function() {
39///     println!("Hello world!");
40/// }
41/// ```
42#[proc_macro_attribute]
43pub fn obfuscate(_: TokenStream, input: TokenStream) -> TokenStream {
44    let func = parse_macro_input!(input as ItemFn);
45    let func_sig = &func.sig;
46    let func_attrs = &func.attrs;
47    let func_vis = &func.vis;
48    let block = &func.block;
49    let stmts = &block.stmts;
50    let mut new_stmts = proc_macro2::TokenStream::new();
51
52    for stmt in stmts {
53        let junk = generate_junk_block();
54        new_stmts.extend(junk);
55        new_stmts.extend(quote! { #stmt });
56    }
57
58    let output = quote! {
59        #(#func_attrs)*
60        #func_vis #func_sig {
61            #new_stmts
62        }
63    };
64
65    // eprintln!("Generated function:\n{}", output.to_string());
66
67    output.into()
68}
69
70#[derive(Clone, Copy)]
71enum JunkType {
72    Number,
73    Boolean,
74    String,
75}
76
77impl JunkType {
78    fn random(rng: &mut impl Rng) -> Self {
79        match rng.random_range(0..3) {
80            0 => JunkType::Number,
81            1 => JunkType::Boolean,
82            _ => JunkType::String,
83        }
84    }
85}
86
87fn generate_junk_block() -> proc_macro2::TokenStream {
88    let mut rng = rand::rng();
89    let junk_type = JunkType::random(&mut rng);
90    let var_count = rng.random_range(100..201);
91
92    let (ty, init_value) = match junk_type {
93        JunkType::Number => (quote!(u32), quote!(42u32)),
94        JunkType::Boolean => (quote!(bool), quote!(true)),
95        JunkType::String => (quote!(String), quote!(String::from("initial"))),
96    };
97
98    let base_var = syn::Ident::new("_x", proc_macro2::Span::call_site());
99    let mut var_statements = proc_macro2::TokenStream::new();
100
101    for i in 0..var_count {
102        let var_name = format!("_v{}", i);
103        let var_ident = syn::Ident::new(&var_name, proc_macro2::Span::call_site());
104
105        let expr = match junk_type {
106            JunkType::Number => {
107                let num = rng.random::<u32>();
108                match rng.random_range(0..6) {
109                    0 => quote! { #base_var.wrapping_add(#num) },
110                    1 => quote! { #base_var.wrapping_sub(#num) },
111                    2 => quote! { #base_var.wrapping_shl(1) },
112                    3 => quote! { #base_var.wrapping_shr(1) },
113                    4 => quote! { #base_var.wrapping_mul(#num) },
114                    _ => quote! { #base_var.wrapping_rem(#num.wrapping_add(1)) },
115                }
116            }
117            JunkType::Boolean => match rng.random_range(0..3) {
118                0 => quote! { !#base_var },
119                1 => quote! { #base_var && true },
120                _ => quote! { #base_var || false },
121            },
122            JunkType::String => match rng.random_range(0..3) {
123                0 => quote! { format!("{}", #base_var) },
124                1 => quote! { #base_var.clone() + "" },
125                _ => quote! { String::from(#base_var) },
126            },
127        };
128
129        var_statements.extend(quote! {
130            let #var_ident: #ty = #expr;
131            #base_var = #var_ident;
132        });
133    }
134
135    quote! {{
136        let mut #base_var: #ty = #init_value;
137        #var_statements
138        let _ = &#base_var;
139    }}
140}