From 5a60f3f503250638f9ad378da4bf7f4760ed92cd Mon Sep 17 00:00:00 2001 From: Michael Mikovsky <77305074+Astatin3@users.noreply.github.com> Date: Fri, 20 Feb 2026 15:47:58 -0700 Subject: [PATCH] Obfuscation macros are now defined more easily --- Cargo.lock | 4 -- Cargo.toml | 3 +- src/logger/log_enabled.rs | 4 +- src/tree/symbols.rs | 22 +++---- ush-obfuscate/Cargo.toml | 17 +++-- ush-obfuscate/src/format_helper.rs | 4 +- ush-obfuscate/src/lib.rs | 43 ++++++------ ush-obfuscate/src/no_obfuscate.rs | 27 -------- ush-obfuscate/src/obfuscate/mod.rs | 2 - ush-obfuscate/src/proc_impl_switcher.rs | 66 +++++++++++++++++++ .../sym_aes_strings.rs => symbolic_aes.rs} | 3 +- ush-obfuscate/src/symbolic_ref/mod.rs | 1 + ush-payload/Cargo.toml | 2 +- ush-payload/src/main.rs | 4 +- 14 files changed, 118 insertions(+), 84 deletions(-) delete mode 100644 ush-obfuscate/src/no_obfuscate.rs create mode 100644 ush-obfuscate/src/proc_impl_switcher.rs rename ush-obfuscate/src/{obfuscate/sym_aes_strings.rs => symbolic_aes.rs} (94%) create mode 100644 ush-obfuscate/src/symbolic_ref/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 848ab2d..e206e07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -622,18 +622,14 @@ dependencies = [ name = "ush-obfuscate" version = "0.1.0" dependencies = [ - "aes", "base62", "block-padding 0.4.2", - "cbc", "getrandom", "hex", "hex-literal", "proc-macro2", "quote", "rand", - "regex", - "sha2", "static_init", "syn 2.0.114", ] diff --git a/Cargo.toml b/Cargo.toml index a45acd5..0b651bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,8 @@ default = [] log = [] log_debug = ["log"] -obfuscate = ["ush-obfuscate/obfuscate"] +obfuscate_aes = ["ush-obfuscate/obfuscate_aes"] +obfuscate_ref = ["ush-obfuscate/obfuscate_ref"] [dependencies] chrono = { workspace = true } diff --git a/src/logger/log_enabled.rs b/src/logger/log_enabled.rs index 967b608..680a578 100644 --- a/src/logger/log_enabled.rs +++ b/src/logger/log_enabled.rs @@ -2,7 +2,7 @@ macro_rules! log { ($level:expr, $fmt:tt) => {{ use $crate::obfuscate; - let log_result = obfuscate::format_obs!($fmt); + let log_result = obfuscate::sym_format!($fmt); $crate::logger::add_record( $level, @@ -18,7 +18,7 @@ macro_rules! log { }}; ($level:expr, $fmt:tt, $($arg:expr),*) => {{ use $crate::obfuscate; - let log_result = obfuscate::format_obs!($fmt, $($arg),*); + let log_result = obfuscate::sym_format!($fmt, $($arg),*); $crate::logger::add_record( $level, diff --git a/src/tree/symbols.rs b/src/tree/symbols.rs index 50ec788..cf11e19 100644 --- a/src/tree/symbols.rs +++ b/src/tree/symbols.rs @@ -1,15 +1,15 @@ -use crate::obfuscate::symbol; +use crate::obfuscate::sym; -pub const LOGGER: &'static str = symbol!("Logger"); +pub const LOGGER: &'static str = sym!("Logger"); -pub const TYPE_TREE: &'static str = symbol!("Tree"); -pub const TYPE_QUEUE: &'static str = symbol!("Queue"); +pub const TYPE_TREE: &'static str = sym!("Tree"); +pub const TYPE_QUEUE: &'static str = sym!("Queue"); -pub const CMD_GET: &'static str = symbol!("Get"); -pub const CMD_POLL: &'static str = symbol!("Poll"); -pub const CMD_GET_LENGTH: &'static str = symbol!("GetLength"); -pub const CMD_GET_CHILDREN: &'static str = symbol!("GetChildren"); +pub const CMD_GET: &'static str = sym!("Get"); +pub const CMD_POLL: &'static str = sym!("Poll"); +pub const CMD_GET_LENGTH: &'static str = sym!("GetLength"); +pub const CMD_GET_CHILDREN: &'static str = sym!("GetChildren"); -pub const ERR_UNSUPPORTED_METHOD: &'static str = symbol!("UnsupportedMethod"); -pub const ERR_INVALID_COMMAND: &'static str = symbol!("InvalidCommand"); -pub const ERR_INVALID_CHILD: &'static str = symbol!("InvalidChild"); +pub const ERR_UNSUPPORTED_METHOD: &'static str = sym!("UnsupportedMethod"); +pub const ERR_INVALID_COMMAND: &'static str = sym!("InvalidCommand"); +pub const ERR_INVALID_CHILD: &'static str = sym!("InvalidChild"); diff --git a/ush-obfuscate/Cargo.toml b/ush-obfuscate/Cargo.toml index 1a6ea04..f0b0eac 100644 --- a/ush-obfuscate/Cargo.toml +++ b/ush-obfuscate/Cargo.toml @@ -6,22 +6,25 @@ authors.workspace = true include.workspace = true [features] -obfuscate = [] +default = ["obfuscate_none"] +obfuscate_none = [] +obfuscate_aes = [] +obfuscate_ref = [] [lib] proc-macro = true [dependencies] -aes = "0.8.4" +base62 = {path = "../base62"} + +# aes = "0.8.4" block-padding = "0.4.1" -cbc = "0.1.2" +# cbc = "0.1.2" getrandom = "0.3.4" hex = "0.4.3" hex-literal = "1.1.0" -regex = "1.12.2" -sha2 = "0.10.9" - -base62 = {path = "../base62"} +# regex = "1.12.2" +# sha2 = "0.10.9" # Common static_init = { workspace = true } diff --git a/ush-obfuscate/src/format_helper.rs b/ush-obfuscate/src/format_helper.rs index a9e00fc..083e5fa 100644 --- a/ush-obfuscate/src/format_helper.rs +++ b/ush-obfuscate/src/format_helper.rs @@ -3,7 +3,7 @@ use quote::quote; use syn::parse::{Parse, ParseStream}; use syn::{Expr, Lit, Token, parse_macro_input}; -pub fn format_obs(input: TokenStream) -> TokenStream { +pub fn sym_format(input: TokenStream) -> TokenStream { let PrintlnArgs { format_str, args } = parse_macro_input!(input as PrintlnArgs); let segments = parse_format_string(&format_str); @@ -21,7 +21,7 @@ pub fn format_obs(input: TokenStream) -> TokenStream { match segment { FormatSegment::Static(text) => { parts.push(quote! { - obfuscate::symbol!(#text).to_string() + obfuscate::sym!(#text).to_string() }); } FormatSegment::Dynamic(spec, idx) => { diff --git a/ush-obfuscate/src/lib.rs b/ush-obfuscate/src/lib.rs index fd24e9a..e382eb1 100644 --- a/ush-obfuscate/src/lib.rs +++ b/ush-obfuscate/src/lib.rs @@ -1,43 +1,40 @@ #![feature(proc_macro_quote)] #![feature(proc_macro_span)] +#![allow(dead_code, unused_macros, unused_imports)] + +mod env; +mod format_helper; +mod proc_impl_switcher; + +mod obfuscate; + +// Types of symbolic reference +mod symbolic_aes; +mod symbolic_ref; use proc_macro::TokenStream; use quote::quote; -mod env; -mod format_helper; - -#[allow(dead_code, unused_imports)] -mod no_obfuscate; - -#[allow(dead_code, unused_imports)] -mod obfuscate; - -#[cfg(not(feature = "obfuscate"))] -use no_obfuscate as obs; -#[cfg(feature = "obfuscate")] -use obfuscate as obs; - -// String obfuscation +use proc_impl_switcher::proc_impl; #[proc_macro] pub fn obs(input: TokenStream) -> TokenStream { - obs::xor(input) + proc_impl::xor(input) } #[proc_macro_attribute] -pub fn obfuscated_symbol(_attr: TokenStream, item: TokenStream) -> TokenStream { - obs::aes_fn_name(_attr, item) +pub fn sym_fn(_attr: TokenStream, item: TokenStream) -> TokenStream { + proc_impl::sym_fn(item) } #[proc_macro] -pub fn symbol(input: TokenStream) -> TokenStream { - obs::aes_str(input) +pub fn sym(input: TokenStream) -> TokenStream { + proc_impl::sym(input) } #[proc_macro] pub fn junk_asm(input: TokenStream) -> TokenStream { - obs::junk_asm(input) + proc_impl::junk_asm(input) } #[proc_macro] @@ -57,6 +54,6 @@ pub fn file_symbol(_input: TokenStream) -> TokenStream { } #[proc_macro] -pub fn format_obs(input: TokenStream) -> TokenStream { - format_helper::format_obs(input) +pub fn sym_format(input: TokenStream) -> TokenStream { + format_helper::sym_format(input) } diff --git a/ush-obfuscate/src/no_obfuscate.rs b/ush-obfuscate/src/no_obfuscate.rs deleted file mode 100644 index d1ded17..0000000 --- a/ush-obfuscate/src/no_obfuscate.rs +++ /dev/null @@ -1,27 +0,0 @@ -use proc_macro::TokenStream; -use quote::quote; -use syn::{ItemFn, LitStr, parse_macro_input}; - -pub fn xor(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as LitStr); - - (quote::quote! { - String::from(#input) - }) - .into() -} -pub fn aes_fn_name(_attr: TokenStream, item: TokenStream) -> TokenStream { - let func = parse_macro_input!(item as ItemFn); - TokenStream::from(quote! { - #[unsafe(no_mangle)] - #func - }) -} - -pub fn aes_str(input: TokenStream) -> TokenStream { - input -} - -pub fn junk_asm(_input: TokenStream) -> TokenStream { - TokenStream::new() -} diff --git a/ush-obfuscate/src/obfuscate/mod.rs b/ush-obfuscate/src/obfuscate/mod.rs index ba30f46..ef3ab27 100644 --- a/ush-obfuscate/src/obfuscate/mod.rs +++ b/ush-obfuscate/src/obfuscate/mod.rs @@ -1,7 +1,5 @@ mod obs_junk_asm; mod obs_xor; -mod sym_aes_strings; pub use obs_junk_asm::junk_asm; pub use obs_xor::xor; -pub use sym_aes_strings::*; diff --git a/ush-obfuscate/src/proc_impl_switcher.rs b/ush-obfuscate/src/proc_impl_switcher.rs new file mode 100644 index 0000000..230292b --- /dev/null +++ b/ush-obfuscate/src/proc_impl_switcher.rs @@ -0,0 +1,66 @@ +/// Call some other function +macro_rules! passtrough { + ($name:tt, $ref:expr) => { + pub fn $name(input: TokenStream) -> TokenStream { + $ref(input) + } + }; +} + +/// Just return the underlying string +macro_rules! unwrap_string { + ($func:tt) => { + pub fn $func(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as LitStr); + + (quote::quote! { + #input + }) + .into() + } + }; +} + +/// Delete the content +macro_rules! delete { + ($func:tt) => { + pub fn $func(_: TokenStream) -> TokenStream { + (quote::quote! {}).into() + } + }; +} + +#[cfg(feature = "obfuscate_none")] +pub mod proc_impl { + use proc_macro::TokenStream; + use syn::{LitStr, parse_macro_input}; + + unwrap_string!(xor); + delete!(junk_asm); + + unwrap_string!(sym); + unwrap_string!(sym_fn); +} + +#[cfg(feature = "obfuscate_aes")] +pub mod proc_impl { + use proc_macro::TokenStream; + + passtrough!(xor, crate::obfuscate::xor); + passtrough!(junk_asm, crate::obfuscate::junk_asm); + + passtrough!(sym, crate::symbolic_aes::aes_str); + passtrough!(sym_fn, crate::symbolic_aes::aes_fn_name); +} + +#[cfg(feature = "obfuscate_ref")] +pub mod proc_impl { + use proc_macro::TokenStream; + use syn::{LitStr, parse_macro_input}; + + unwrap_string!(xor); + delete!(junk_asm); + + unwrap_string!(sym); + unwrap_string!(sym_fn); +} diff --git a/ush-obfuscate/src/obfuscate/sym_aes_strings.rs b/ush-obfuscate/src/symbolic_aes.rs similarity index 94% rename from ush-obfuscate/src/obfuscate/sym_aes_strings.rs rename to ush-obfuscate/src/symbolic_aes.rs index 4ed6253..02036c9 100644 --- a/ush-obfuscate/src/obfuscate/sym_aes_strings.rs +++ b/ush-obfuscate/src/symbolic_aes.rs @@ -6,9 +6,8 @@ use syn::{ItemFn, LitStr, parse_macro_input}; use crate::env::get_encryption_key; /// Obfuscate function names by encrypting in AES -pub fn aes_fn_name(_attr: TokenStream, item: TokenStream) -> TokenStream { +pub fn aes_fn_name(item: TokenStream) -> TokenStream { // Parse the input function - let func = parse_macro_input!(item as ItemFn); // Get the original function name diff --git a/ush-obfuscate/src/symbolic_ref/mod.rs b/ush-obfuscate/src/symbolic_ref/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/ush-obfuscate/src/symbolic_ref/mod.rs @@ -0,0 +1 @@ + diff --git a/ush-payload/Cargo.toml b/ush-payload/Cargo.toml index a4c973a..edaef7e 100644 --- a/ush-payload/Cargo.toml +++ b/ush-payload/Cargo.toml @@ -8,7 +8,7 @@ edition = "2024" default = ["log"] log = ["unshell/log"] log_debug = ["unshell/log_debug"] -obfuscate = ["unshell/obfuscate"] +obfuscate = ["unshell/obfuscate_aes"] [dependencies] unshell.path = "../" diff --git a/ush-payload/src/main.rs b/ush-payload/src/main.rs index 46b4cf1..d193e72 100644 --- a/ush-payload/src/main.rs +++ b/ush-payload/src/main.rs @@ -3,7 +3,7 @@ extern crate unshell; use unshell::{ Value, info, - obfuscate::{junk_asm, symbol}, + obfuscate::{junk_asm, sym}, tree::{Tree, TreeElement, symbols}, }; @@ -25,7 +25,7 @@ fn main() { fn test123(manager: &mut Tree) -> bool { let result = manager.send_message( - Value::String(symbol!("Logger").to_string()), + Value::String(sym!("Logger").to_string()), Value::String(symbols::CMD_GET.to_string()), );