1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//! [Goldberg](https://github.com/frank2/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`](goldberg_stmts!)).
//! * string literal encryption produces temporary objects (see [`goldberg_string`](goldberg_string!)).
//! * integer literals must be typed (see [`goldberg_int`](goldberg_int!)).
//!
//! Despite these caveats, these simple techniques produce powerfully annoying obfuscation that survives code
//! optimization.
//!
//! ```rust
//! 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:
//! ```no_run
//! 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`](goldberg_stmts!). For encrypting strings, use [`goldberg_string`](goldberg_string!).
//! For integers, use [`goldberg_int`](goldberg_int!). To convert obfuscated statements into a string for external processing,
//! use [`goldberg_stringify`](goldberg_stringify!). For functional examples, read
//! [the test file](https://github.com/frank2/goldberg/blob/main/tests/tests.rs).
extern crate proc_macro;
use Moisture;
use ;
use ToTokens;
use LitStr;
/// Obfuscate a series of statements.
///
/// This implicitly applies [`goldberg_string`](goldberg_string!) and [`goldberg_int`](goldberg_int!)
/// obfuscation to corresponding string literals and integer literals as well as code-flow obfuscation.
///
/// Statements are obfuscated by randomizing their apparent order with loop/match obfuscation. This
/// determines order with a rolling encryption key which identifies which statement to execute. To accomplish
/// this, a statement in the statements must be *mobile*. A statement is mobile if:
///
/// * It is not the last expression in the series of statements
/// * It is not an [item](https://doc.rust-lang.org/reference/items.html).
/// * It is a typed `let` statement (e.g., `let x: u32 = 0`) and the type implements the [Default](std::default::Default) trait.
/// Obfuscate with the [`goldberg_stmts`](goldberg_stmts!) macro, but return the code as a string.
///
/// Note that [syn](syn) and [proc-macro2](proc_macro2) don't pretty-format the code.
/// For that, you'll need to run the string through
/// [`rustfmt`](https://doc.rust-lang.org/book/appendix-04-useful-development-tools.html#automatic-formatting-with-rustfmt).
/// Obfuscate an integer literal.
///
/// This requires that the integer literal has a type suffix (i.e., the `u32` in `0xDEADBEEFu32`). Obfuscation
/// will not take effect on an integer without a type.
/// Obfuscate (or rather, encrypt) a string literal.
///
/// Due to the nature of string literals, in order for this to work, the macro must return a *temporary object* back
/// to the call site. Therefore, the obfuscated string literal must be used right away (e.g., an argument to a
/// function call). For long-lasting obfuscated string literals, wrap the macro in [`String::from`](String::from).