#obfuscation

macro goldberg

A Rust-based obfuscation macro library!

1 unstable release

0.1.0 Apr 15, 2022

#1002 in Procedural macros

Download history 371/week @ 2023-10-24 410/week @ 2023-10-31 897/week @ 2023-11-07 282/week @ 2023-11-14 582/week @ 2023-11-21 1287/week @ 2023-11-28 846/week @ 2023-12-05 433/week @ 2023-12-12 606/week @ 2023-12-19 352/week @ 2023-12-26 282/week @ 2024-01-02 437/week @ 2024-01-09 483/week @ 2024-01-16 509/week @ 2024-01-23 305/week @ 2024-01-30 280/week @ 2024-02-06

1,641 downloads per month
Used in 4 crates (2 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