mirror of
https://github.com/Astatin3/unshell.git
synced 2026-06-08 22:38:01 -06:00
Improve Rust code clarity across the workspace
Document public APIs and non-obvious control flow so the protocol, simulator, and macro crates are easier to follow. Tighten a few helper paths and feature gates while preserving behavior and keeping the workspace warning-free.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
const ENV_KEY_NAME: &str = "OBFUSCATION_KEY";
|
||||
const BACKUP_ENV_KEY: &str = "OBFUSCATION_KEY_DO_NOT_USE";
|
||||
|
||||
/// Returns the obfuscation key used by the proc macros.
|
||||
///
|
||||
/// The fallback keeps macro expansion deterministic when the environment variable is absent.
|
||||
pub fn get_encryption_key() -> String {
|
||||
if let Ok(key) = std::env::var(ENV_KEY_NAME) {
|
||||
key
|
||||
|
||||
@@ -3,6 +3,7 @@ use quote::quote;
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
use syn::{Expr, Lit, Token, parse_macro_input};
|
||||
|
||||
/// Expands `sym_format!` into a string builder that obfuscates static segments only.
|
||||
pub fn sym_format(input: TokenStream) -> TokenStream {
|
||||
let PrintlnArgs { format_str, args } = parse_macro_input!(input as PrintlnArgs);
|
||||
|
||||
@@ -42,9 +43,6 @@ pub fn sym_format(input: TokenStream) -> TokenStream {
|
||||
quote! { #full_spec }
|
||||
};
|
||||
|
||||
// quote! {
|
||||
// println!(#fmt_spec, #arg);
|
||||
// }
|
||||
parts.push(quote! {
|
||||
format!(#fmt_spec, #arg)
|
||||
});
|
||||
@@ -105,9 +103,13 @@ impl Parse for PrintlnArgs {
|
||||
#[derive(Debug)]
|
||||
enum FormatSegment {
|
||||
Static(String),
|
||||
Dynamic(String, usize), // format spec, arg index
|
||||
Dynamic(String, usize),
|
||||
}
|
||||
|
||||
/// Splits a Rust formatting string into literal and replacement segments.
|
||||
///
|
||||
/// This only handles the subset needed by `sym_format!`: positional replacements in order,
|
||||
/// plus escaped braces.
|
||||
fn parse_format_string(fmt: &str) -> Vec<FormatSegment> {
|
||||
let mut segments = Vec::new();
|
||||
let mut current_static = String::new();
|
||||
@@ -122,13 +124,11 @@ fn parse_format_string(fmt: &str) -> Vec<FormatSegment> {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Save current static segment
|
||||
if !current_static.is_empty() {
|
||||
segments.push(FormatSegment::Static(current_static.clone()));
|
||||
current_static.clear();
|
||||
}
|
||||
|
||||
// Parse format spec
|
||||
let mut spec = String::new();
|
||||
while let Some(&next_ch) = chars.peek() {
|
||||
if next_ch == '}' {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/// Call some other function
|
||||
macro_rules! passtrough {
|
||||
macro_rules! passthrough {
|
||||
($name:tt, $ref:expr) => {
|
||||
pub fn $name(input: TokenStream) -> TokenStream {
|
||||
$ref(input)
|
||||
@@ -42,25 +42,27 @@ pub mod proc_impl {
|
||||
unwrap_string!(sym_fn);
|
||||
}
|
||||
|
||||
#[cfg(feature = "obfuscate_aes")]
|
||||
#[cfg(all(feature = "obfuscate_aes", not(feature = "obfuscate_ref")))]
|
||||
pub mod proc_impl {
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
passtrough!(xor, crate::obfuscate::xor);
|
||||
passtrough!(junk_asm, crate::obfuscate::junk_asm);
|
||||
passthrough!(xor, crate::obfuscate::xor);
|
||||
passthrough!(junk_asm, crate::obfuscate::junk_asm);
|
||||
|
||||
passtrough!(sym, crate::symbolic_aes::aes_str);
|
||||
passtrough!(sym_fn, crate::symbolic_aes::aes_fn_name);
|
||||
passthrough!(sym, crate::symbolic_aes::aes_str);
|
||||
passthrough!(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};
|
||||
|
||||
passtrough!(xor, crate::obfuscate::xor);
|
||||
passtrough!(junk_asm, crate::obfuscate::junk_asm);
|
||||
passthrough!(xor, crate::obfuscate::xor);
|
||||
passthrough!(junk_asm, crate::obfuscate::junk_asm);
|
||||
|
||||
passtrough!(sym, crate::symbolic_ref::sym_ref);
|
||||
passtrough!(sym_fn, crate::symbolic_ref::sym_ref_fn);
|
||||
// `sym` and `sym_fn` need one concrete strategy. When both feature flags are enabled,
|
||||
// prefer symbolic references so `cargo clippy --all-features` still selects a single,
|
||||
// deterministic implementation.
|
||||
passthrough!(sym, crate::symbolic_ref::sym_ref);
|
||||
passthrough!(sym_fn, crate::symbolic_ref::sym_ref_fn);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use base62::{Base62, hash};
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
@@ -10,11 +8,13 @@ use crate::env::get_encryption_key;
|
||||
static mut SYM_COUNTER: Vec<String> = Vec::new();
|
||||
|
||||
#[allow(static_mut_refs)]
|
||||
/// Returns how many unique symbols have been registered in this macro process.
|
||||
pub fn get_symbol_number() -> usize {
|
||||
unsafe { SYM_COUNTER.len() }
|
||||
}
|
||||
|
||||
#[allow(static_mut_refs)]
|
||||
/// Returns the stable numeric ID for `text`, inserting it on first use.
|
||||
pub fn get_symbol(text: &str) -> usize {
|
||||
unsafe {
|
||||
if let Some(n) = SYM_COUNTER.iter().position(|r| r == text) {
|
||||
@@ -27,47 +27,40 @@ pub fn get_symbol(text: &str) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn ref_string(input: String) -> String {
|
||||
let n = get_symbol(&input);
|
||||
fn encode_symbol_reference(symbol: String) -> String {
|
||||
let symbol_index = get_symbol(&symbol);
|
||||
|
||||
let data = base62::encode_usize(n);
|
||||
let key = hash(&get_encryption_key().as_bytes());
|
||||
let data = base62::encode_usize(symbol_index);
|
||||
let key = hash(get_encryption_key().as_bytes());
|
||||
|
||||
let encoded = format!("_{}_", Base62::encode_full(&data, &key));
|
||||
|
||||
println!("Aliased '{}' as '{encoded}'", input);
|
||||
// Macro expansion logs make it easier to correlate exported symbols with their aliases.
|
||||
println!("Aliased '{}' as '{encoded}'", symbol);
|
||||
|
||||
encoded
|
||||
}
|
||||
|
||||
/// Replaces a string literal with its symbolic reference alias.
|
||||
pub fn sym_ref(input: TokenStream) -> TokenStream {
|
||||
// Parse the input as a string literal
|
||||
let lit_str = parse_macro_input!(input as LitStr);
|
||||
let original_name = lit_str.value();
|
||||
|
||||
let encoded = ref_string(original_name);
|
||||
let encoded = encode_symbol_reference(original_name);
|
||||
|
||||
// Expand to a static string literal
|
||||
TokenStream::from(quote! {
|
||||
#encoded
|
||||
})
|
||||
}
|
||||
|
||||
/// Re-exports a function under a symbolic reference alias.
|
||||
pub fn sym_ref_fn(input: TokenStream) -> TokenStream {
|
||||
// Parse the input function
|
||||
let func = parse_macro_input!(input as ItemFn);
|
||||
|
||||
// Get the original function name
|
||||
let fn_name = func.sig.ident.to_string();
|
||||
|
||||
// Generate the new, obfuscated name
|
||||
let obfuscated_name = ref_string(fn_name);
|
||||
|
||||
// Create a new string literal for the name
|
||||
let obfuscated_name = encode_symbol_reference(fn_name);
|
||||
let new_name_lit = LitStr::new(&obfuscated_name, func.sig.ident.span());
|
||||
|
||||
// Re-build the function, but add #[no_mangle]
|
||||
// and rename the *exported* symbol via #[export_name]
|
||||
TokenStream::from(quote! {
|
||||
#[unsafe(export_name = #new_name_lit)]
|
||||
#func
|
||||
|
||||
Reference in New Issue
Block a user