1 unstable release

0.1.0 Apr 15, 2022

#953 in Procedural macros

Download history 298/week @ 2024-01-12 528/week @ 2024-01-19 299/week @ 2024-01-26 365/week @ 2024-02-02 264/week @ 2024-02-09 424/week @ 2024-02-16 373/week @ 2024-02-23 228/week @ 2024-03-01 300/week @ 2024-03-08 243/week @ 2024-03-15 303/week @ 2024-03-22 397/week @ 2024-03-29 353/week @ 2024-04-05 414/week @ 2024-04-12 415/week @ 2024-04-19 284/week @ 2024-04-26

1,552 downloads per month
Used in 5 crates (3 directly)

GPL-3.0 license

41KB
775 lines

Goldberg

Goldberg is a Rust procedural macro library for obfuscating Rust code. Its obfuscation techniques are designed to survive both compilation as well as optimization. While not intended to be a source code obfuscator, it can be used as such. It is named after Rube Goldberg machines.

Currently, the following types of obfuscation are supported:

  • code-flow obfuscation
  • string literal encryption
  • integer literal obfuscation

The documentation can be found here. For usage examples, read the tests file. The changelog history can be found here.


lib.rs:

Goldberg is a Rust obfuscation macro library.

Currently, Goldberg is capable of the following types of obfuscation:

  • code-flow obfuscation
  • string literal encryption
  • integer literal obfuscation

Of course, some caveats apply:

  • code-flow obfuscation only applies to statements that have mobility (see goldberg_stmts).
  • string literal encryption produces temporary objects (see goldberg_string).
  • integer literals must be typed (see goldberg_int).

Despite these caveats, these simple techniques produce powerfully annoying obfuscation that survives code optimization.

use goldberg::goldberg_stmts;

let result = goldberg_stmts! {
   {
      fn print(value: u32) {
         let msg = String::from("value:");
         println!("{} {}", msg, value);
      }

      let mut x: u32 = 0xDEADBEEFu32;
      print(x);
      x ^= 0xFACEBABEu32;
      print(x);
      x ^= 0xDEFACED1u32;
      print(x);
      x ^= 0xABAD1DEAu32;
      print(x);
      x
   }
};

assert_eq!(result, 0x5134d76a);

This example expands into code similar to this:

fn print(value: u32) {
    let msg = String::from(
        {
            let key_fgnliibu: Vec<u8> = vec![75u8, 87u8, 169u8, 234u8, 230u8, 38u8];
            let mut string_hkzmkgaw: Vec<u8> = vec![61u8, 54u8, 197u8, 159u8, 131u8, 28u8];
            for pulhfjddcbiztuxz in 0..string_hkzmkgaw.len() {
                string_hkzmkgaw[pulhfjddcbiztuxz] ^= key_fgnliibu[pulhfjddcbiztuxz];
            }
            String::from_utf8(string_hkzmkgaw).unwrap()
        }
        .as_str(),
    );
    println!("{} {}", msg, value);
}
struct _AssertDefault_cfygodkf
where
    u32: Default;
let mut x: u32 = u32::default();
let mut ident_gqtkhobp = 1113386507u32;
let mut key_ftudpieg = 0u32;
'loop_obfu_jmcfjvhq: loop {
    match ident_gqtkhobp {
        2158235392u32 => {
            print(x);
            key_ftudpieg = 3044081204u32;
        }
        2506875858u32 => {
            x ^= {
                struct _AssertDefault_vedfwrhy
                where
                    u32: Default;
                let mut calc_whsuusro: u32 = u32::default();
                let mut ident_tmheadmi = 1821101871u32;
                let mut key_pzediytf = 0u32;
                'loop_obfu_msqcffqh: loop {
                    match ident_tmheadmi {
                        1103538895u32 => {
                            calc_whsuusro ^= 2534362044u32;
                            key_pzediytf = 2755681459u32;
                        }
                        3757011920u32 => {
                            calc_whsuusro = calc_whsuusro.swap_bytes();
                            key_pzediytf = 849856391u32;
                        }
                        1071321848u32 => {
                            calc_whsuusro = calc_whsuusro.rotate_left(1692640787u32);
                            key_pzediytf = 1375898541u32;
                        }
                        ...

For obfuscating statements, use goldberg_stmts. For encrypting strings, use goldberg_string. For integers, use goldberg_int. To convert obfuscated statements into a string for external processing, use goldberg_stringify. For functional examples, read the test file.

Dependencies

~2MB
~40K SLoC