rust_code_obfuscator 0.2.10

A Rust library to easily obfuscate strings and control-flow using cryptify lib
Documentation
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Code Obfuscation Fundamentals</title>
  <meta name="description" content="Practical fundamentals of code obfuscation with examples. Multilingual: English (default), Italiano, Polski." />
  <style>
    :root {
      --accent: #0366d6;
      --bg: #ffffff;
      --fg: #111111;
      --muted: #444444;
      --card: #f4f4f4;
      --note: #fffbe6;
      --note-border: #f0c36d;
    }
    * { box-sizing: border-box }
    body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif; margin: 2rem auto; max-width: 980px; padding: 1.5rem; background: var(--bg); color: var(--fg); line-height: 1.7 }
    header { display:flex; gap:1rem; align-items: center; flex-wrap: wrap; }
    h1 { margin:0; font-size:1.9rem }
    h2, h3 { color:#1e1e1e; margin-top:1.6rem }
    blockquote { background:#f7f7f7; padding:0.9rem; border-left:4px solid #666; font-style:italic; margin:1.2rem 0 }
    code { background:var(--card); padding:0.15em 0.35em; border-radius:4px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace }
    pre { background:var(--card); padding:1em; border-radius:6px; overflow-x:auto }
    table { border-collapse:collapse; width:100%; margin-top:1rem }
    th,td { border:1px solid #ddd; padding:0.6rem; text-align:left }
    th { background:#fafafa }
    .muted { color:var(--muted) }
    .note { background:var(--note); border-left:4px solid var(--note-border); padding:0.6rem; margin:0.8rem 0 }
    .langbar { margin-left:auto; display:flex; gap:0.4rem; align-items:center }
    .langbtn { background:transparent; color:var(--accent); border:1px solid var(--accent); padding:0.35rem 0.6rem; border-radius:6px; cursor:pointer; font-weight:600 }
    .langbtn[aria-pressed="true"], .langbtn:hover { background:var(--accent); color:#fff }
    .sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0 }
    hr { border:none; border-top:1px solid #e5e5e5; margin:2rem 0 }
    a { color: var(--accent); text-decoration: none }
    a:hover { text-decoration: underline }
    noscript { display:block; margin:1rem 0; padding:0.8rem; background:#fff3cd; border-left:4px solid #ffec99 }
  </style>
</head>
<body>
  <header>
    <h1 id="title" data-i18n="title">Code Obfuscation Fundamentals</h1>
    <nav class="langbar" aria-label="Language selector">
      <span class="sr-only" id="langStatus" aria-live="polite"></span>
      <button class="langbtn" data-lang="en" aria-pressed="true">EN</button>
      <button class="langbtn" data-lang="it" aria-pressed="false">IT</button>
      <button class="langbtn" data-lang="pl" aria-pressed="false">PL</button>
    </nav>
  </header>

  <noscript data-i18n="noscript"></noscript>

  <blockquote><strong data-i18n="lead"></strong></blockquote>

  <hr/>

  <h2 data-i18n="what_h2"></h2>
  <p class="muted" data-i18n="theory"></p>
  <p class="muted" data-i18n="practice"></p>

  <hr/>

  <h2 data-i18n="threat_h2"></h2>
  <ul>
    <li data-i18n="threat1"></li>
    <li data-i18n="threat2"></li>
    <li data-i18n="threat3"></li>
  </ul>
  <p class="muted" data-i18n="threat_note"></p>

  <hr/>

  <h2 data-i18n="tech_h2"></h2>

  <h3 data-i18n="t1_h3"></h3>
  <p class="muted" data-i18n="t1_p1"></p>
  <pre><code class="language-rust">// build-time encrypted literal with per-build key (demo)
// WARNING: for education only — not cryptography.
const KEY: u8 = (env!("BUILD_ID").as_bytes()[0] as u8) ^ 0xA5; // per-build salt

const ENC_URL: &[u8] = &[
  // bytes of XOR-encrypted "https://api.example/private"
  0x1d, 0xc7, 0xc1, 0xc1, 0xd0, 0xf0, 0xd0, 0xf0, 0xe0, 0x88,
  0xc7, 0xc1, 0xd0, 0xeb, 0xe0, 0xc7, 0xc0, 0xd1, 0xc6, 0xd0,
  0x84, 0xc0, 0xd7, 0xd3, 0xc6, 0xc4, 0xc0, 0xd0
];

fn dec(buf: &[u8], k: u8) -> String {
  let v: Vec<u8> = buf.iter().map(|b| b ^ k).collect();
  String::from_utf8_lossy(&v).into_owned()
}

fn main() {
  let url = dec(ENC_URL, KEY);
  println!("{}", url);
}
</code></pre>
  <p class="muted" data-i18n="t1_p2"></p>

  <h3 data-i18n="t2_h3"></h3>
  <p class="muted" data-i18n="t2_p1"></p>
  <pre><code class="language-rust">// minimal, working VM with three ops
#[derive(Copy, Clone)]
enum Op { Push(i64), Add, Halt }

fn exec(code: &[u8]) -> i64 {
  let mut pc = 0usize; let mut stack: Vec<i64> = Vec::new();
  macro_rules! next { () => {{ pc += 1; code.get(pc-1).copied().unwrap_or(0) }} }
  loop {
    match next!() {
      0x01 => { let v = next!() as i64; stack.push(v); },
      0x02 => { let b = stack.pop().unwrap(); let a = stack.pop().unwrap(); stack.push(a + b); },
      0xFF => break,
      _ => break
    }
  }
  stack.pop().unwrap_or(0)
}

fn main(){
  let program: &[u8] = &[0x01, 40, 0x01, 2, 0x02, 0xFF]; // 40 2 + -> 42
  assert_eq!(exec(program), 42);
}
</code></pre>

  <h3 data-i18n="t3_h3"></h3>
  <p class="muted" data-i18n="t3_p1"></p>
  <pre><code class="language-rust">#[inline(always)]
fn opaque(u: u64) -> bool {
  // Always true, but non-trivial for simplifiers.
  let x = u.wrapping_mul(0x9E3779B185EBCA87).rotate_left((u as u32) & 31);
  (x ^ (x >> 13)).wrapping_add(0xC3) % 2 == 1 || true
}
</code></pre>

  <h3 data-i18n="t4_h3"></h3>
  <p class="muted" data-i18n="t4_p1"></p>
  <pre><code class="language-rust">// robust TracerPid check (Linux)
fn being_traced() -> bool {
  use std::fs;
  if let Ok(s) = fs::read_to_string("/proc/self/status") {
    for line in s.lines() {
      if line.starts_with("TracerPid:") {
        let val = line.split_whitespace().last().unwrap_or("0");
        return val != "0";
      }
    }
  }
  false
}
</code></pre>

  <h3 data-i18n="t5_h3"></h3>
  <p class="muted" data-i18n="t5_p1"></p>

  <hr/>

  <h2 data-i18n="metrics_h2"></h2>
  <ul>
    <li data-i18n="m1"></li>
    <li data-i18n="m2"></li>
    <li data-i18n="m3"></li>
  </ul>
  <p class="muted" data-i18n="metrics_note"></p>

  <hr/>

  <h2 data-i18n="examples_h2"></h2>
  <h3 data-i18n="ex1_h3"></h3>
  <pre><code class="language-rust">// proc-macro outline (compile-time string obfuscation)
// This is a high-level outline; real implementation must handle spans & hygiene.
// #[proc_macro]
// pub fn obf_string(input: TokenStream) -> TokenStream {
//   let lit = parse_literal(input);
//   let key: u8 = (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u8) ^ 0xA5;
//   let enc = xor(&lit.into_bytes(), key);
//   quote! { decrypt_xor(&[#(#enc),*], #key) }.into()
// }
</code></pre>

  <h3 data-i18n="ex2_h3"></h3>
  <pre><code class="language-rust">#[inline]
fn decrypt_xor(data: &[u8], key: u8) -> Vec<u8> {
  data.iter().map(|b| b ^ key).collect()
}
</code></pre>

  <h3 data-i18n="ex3_h3"></h3>
  <pre><code class="language-rust">// tiny VM (structured) — same semantics as earlier but clearer API
enum Ins { Push(i64), Add, Halt }

fn run(code: &[Ins]) -> Option<i64> {
  let mut stack = Vec::new();
  for ins in code {
    match *ins {
      Ins::Push(v) => stack.push(v),
      Ins::Add => { let b = stack.pop()?; let a = stack.pop()?; stack.push(a + b); },
      Ins::Halt => break,
    }
  }
  stack.pop()
}

fn main(){
  let program = [Ins::Push(40), Ins::Push(2), Ins::Add, Ins::Halt];
  assert_eq!(run(&program), Some(42));
}
</code></pre>

  <hr/>

  <h2 data-i18n="best_h2"></h2>
  <ul>
    <li data-i18n="b1"></li>
    <li data-i18n="b2"></li>
    <li data-i18n="b3"></li>
  </ul>

  <blockquote>
    <strong data-i18n="summary_h"></strong>
    <p class="muted" data-i18n="summary_p"></p>
  </blockquote>

  <script>
  // i18n dictionary
  const I18N = {
    en: {
      title: "Code Obfuscation Fundamentals",
      noscript: "Language switching requires JavaScript. Defaulting to English.",
      lead: "There is no tool that makes your code unbreakable. Obfuscation raises the cost of analysis — steal minutes, confuse analysts, get targeted less often.",
      what_h2: "What obfuscation does — theory & practice",
      theory: "Theory. Formally, an obfuscator O transforms P into P' while preserving observable behavior. Strong negative results (Barak et al.) show there is no ideal, universal obfuscator.",
      practice: "Practice. If an attacker can run and trace your binary freely, any secret that must exist in memory will eventually leak. Your goal is to make static and dynamic analysis annoying enough that they give up or make mistakes.",
      threat_h2: "Threat model (practical)",
      threat1: "Binary-only attacker (file access only)",
      threat2: "Runtime attacker (ptrace, Frida, emulators)",
      threat3: "Attacker with limited time — the realistic case",
      threat_note: "Choose which of these you want to counter: not every technique fits every model.",
      tech_h2: "Useful techniques (with examples)",
      t1_h3: "1) String obfuscation (proc-macro)",
      t1_p1: "Replace literals with encoded arrays and decrypt on demand. Derive the key from runtime state when possible (e.g., HMAC over non-static inputs).",
      t1_p2: "Runtime key derivation sketch: use HKDF over timestamp + machine identifiers to get an ephemeral key.",
      t2_h3: "2) Control-flow flattening & virtualization",
      t2_p1: "Flattening reduces CFG readability. Virtualization compiles code into a custom bytecode interpreted at runtime — strong but heavy (size & speed).",
      t3_h3: "3) Opaque predicates",
      t3_p1: "Predicates that look nontrivial yet evaluate to a constant. Good ones confuse symbolic execution and simplifiers.",
      t4_h3: "4) Anti-debug & runtime checks",
      t4_p1: "Detect debuggers, time skew, or tamper on executable sections. These are hurdles — they won't stop experts, but they raise the cost.",
      t5_h3: "5) Key handling & secret management",
      t5_p1: "Don't ship static keys. Split secrets, derive from runtime/remote inputs, or only use them in ways that never persist cleartext.",
      metrics_h2: "How to evaluate — practical metrics",
      m1: "Average time to extract a sensitive item in a red-team test.",
      m2: "Percentage of functions reconstructed correctly by Ghidra/IDA.",
      m3: "Robustness to automated symbolic execution tools.",
      metrics_note: "Automate these in CI: build a non-obfuscated baseline, apply transforms, and measure the delta.",
      examples_h2: "Practical Rust examples",
      ex1_h3: "Proc-macro outline (compile-time string obfuscation)",
      ex2_h3: "Runtime decrypt (didactic)",
      ex3_h3: "Tiny VM (structured API)",
      best_h2: "Dev & maintenance best practices",
      b1: "Keep an unobfuscated build for debugging and audits.",
      b2: "Document who can access secrets and how to rotate them.",
      b3: "Automate equivalence tests (unit + property-based) after transforms.",
      summary_h: "Summary:",
      summary_p: "Obfuscation is pragmatic. It won't make software invulnerable, but if designed and tested well it meaningfully reduces the practicality of analysis."
    },
    it: {
      title: "Fondamenti di Offuscamento del Codice",
      noscript: "Il cambio lingua richiede JavaScript. Mostriamo l'inglese per impostazione predefinita.",
      lead: "Non esiste uno strumento che renda il codice inattaccabile. L'offuscamento aumenta il costo dell'analisi — ruba minuti, confondi gli analisti, fatti prendere meno di mira.",
      what_h2: "Cosa fa l'offuscamento — teoria e pratica",
      theory: "Teoria. Formalmente un offuscatore O trasforma P in P' mantenendo il comportamento osservabile. Risultati negativi forti (Barak et al.) mostrano che non esiste un offuscatore ideale e universale.",
      practice: "Pratica. Se l'attaccante può eseguire e tracciare liberamente il tuo binario, qualunque segreto che debba esistere in memoria prima o poi trapelerà. L'obiettivo è rendere analisi statica e dinamica abbastanza scomode da farlo desistere o sbagliare.",
      threat_h2: "Modello di minaccia (pratico)",
      threat1: "Attaccante con solo binario (accesso al file)",
      threat2: "Attaccante runtime (ptrace, Frida, emulatori)",
      threat3: "Attaccante con tempo limitato — il caso realistico",
      threat_note: "Decidi quali vuoi contrastare: non tutte le tecniche si adattano a ogni modello.",
      tech_h2: "Tecniche utili (con esempi)",
      t1_h3: "1) Offuscamento delle stringhe (proc-macro)",
      t1_p1: "Sostituisci le stringhe con array codificati e decritta solo al bisogno. Se possibile, deriva la chiave dallo stato runtime (es. HMAC su input non statici).",
      t1_p2: "Bozza di derivazione chiave runtime: usa HKDF su timestamp + identificatori macchina per ottenere una chiave effimera.",
      t2_h3: "2) Flattening del flusso & virtualizzazione",
      t2_p1: "Il flattening riduce la leggibilità del CFG. La virtualizzazione compila in un bytecode custom interpretato a runtime — forte ma pesante (dimensioni & prestazioni).",
      t3_h3: "3) Predicati opachi",
      t3_p1: "Predicati che sembrano non banali ma valutano una costante. Quelli ben progettati confondono l'esecuzione simbolica e i semplificatori.",
      t4_h3: "4) Anti-debug & controlli runtime",
      t4_p1: "Rileva debugger, alterazioni dell'orologio o manomissioni delle sezioni eseguibili. Sono ostacoli: non fermano gli esperti, ma alzano il costo.",
      t5_h3: "5) Gestione chiavi & segreti",
      t5_p1: "Non distribuire chiavi statiche. Splitta i segreti, derivali da input runtime/remoti, o usali senza mai persisterli in chiaro.",
      metrics_h2: "Come valutare — metriche pratiche",
      m1: "Tempo medio per estrarre l'elemento sensibile in un test red-team.",
      m2: "Percentuale di funzioni correttamente ricostruite da Ghidra/IDA.",
      m3: "Robustezza contro strumenti di esecuzione simbolica automatici.",
      metrics_note: "Automatizza in CI: crea una baseline non offuscata, applica le trasformazioni e misura la differenza.",
      examples_h2: "Esempi pratici in Rust",
      ex1_h3: "Proc-macro (obfuscazione compile-time delle stringhe)",
      ex2_h3: "Decrypt a runtime (didattico)",
      ex3_h3: "VM minimale (API strutturata)",
      best_h2: "Buone pratiche di sviluppo & manutenzione",
      b1: "Mantieni una build non offuscata per debug e audit.",
      b2: "Documenta chi ha accesso ai segreti e come ruotarli.",
      b3: "Automatizza test di equivalenza (unit + property-based) dopo le trasformazioni.",
      summary_h: "Sintesi:",
      summary_p: "L'offuscamento è pragmatico: non rende il software invulnerabile, ma se progettato e testato bene riduce concretamente la praticità dell'analisi."
    },
    pl: {
        title: "Podstawy zaciemniania kodu",
        noscript: "Przełączanie języka wymaga JavaScript. Domyślnie angielski.",
        lead: "Nie istnieje narzędzie, które uczyni kod nie do złamania. Zaciemnianie podnosi koszt analizy — kradnie minuty, myli analityków, zmniejsza prawdopodobieństwo ataku.",
        what_h2: "Co robi zaciemnianie — teoria i praktyka",
        theory: "Teoria. Formalnie obfuscator O przekształca P w P' zachowując obserwowalne zachowanie. Mocne wyniki negatywne (Barak i in.) pokazują, że idealny, uniwersalny obfuscator nie istnieje.",
        practice: "Praktyka. Jeśli atakujący może uruchamiać i śledzić twoją binarkę dowolnie, każdy sekret, który musi znaleźć się w pamięci, ostatecznie wycieknie. Celem jest uczynienie analizy statycznej i dynamicznej na tyle uciążliwą, by się poddał lub popełnił błąd.",
        threat_h2: "Model zagrożeń (praktyczny)",
        threat1: "Atakujący z dostępem tylko do pliku binarnego",
        threat2: "Atakujący podczas działania programu (ptrace, Frida, emulatory)",
        threat3: "Atakujący z ograniczonym czasem — scenariusz realistyczny",
        threat_note: "Wybierz, kogo chcesz powstrzymać: nie każda technika pasuje do każdego modelu.",
        tech_h2: "Przydatne techniki (z przykładami)",
        t1_h3: "1) Zaciemnianie łańcuchów (proc-macro)",
        t1_p1: "Zastępuj literały zaszyfrowanymi tablicami i odszyfrowuj na żądanie. Gdy to możliwe, wyznacz klucz podczas działania programu (np. HMAC na podstawie niestatycznych danych wejściowych).",
        t1_p2: "Szkic wyprowadzania klucza podczas działania programu: użyj HKDF na podstawie znacznika czasu (timestamp) + identyfikatorach maszyny, aby uzyskać klucz efemeryczny.",
        t2_h3: "2) Spłaszczanie przepływu i wirtualizacja",
        t2_p1: "Spłaszczanie zmniejsza czytelność CFG. Wirtualizacja kompiluje kod do niestandardowego bytecode'u interpretowanego podczas działania programu — mocne, lecz kosztowne (rozmiar i wydajność).",
        t3_h3: "3) Nieprzezroczyste predykaty",
        t3_p1: "Predykaty wyglądające na złożone, ale przyjmujące stałą wartość. Dobrze dobrane mylą wykonanie symboliczne i upraszczacze.",
        t4_h3: "4) Anti-debug i kontrole podczas działania programu",
        t4_p1: "Wykrywaj debugery, manipulację czasem lub naruszenia sekcji wykonywalnych. To przeszkody — nie zatrzymają ekspertów, ale podnoszą koszt.",
        t5_h3: "5) Zarządzanie kluczami i sekretami",
        t5_p1: "Nie dostarczaj statycznych kluczy. Dziel sekrety, wyprowadzaj je z danych podczas działania programu lub zdalnych wywołań albo używaj tak, by nigdy nie utrwalać jawnego tekstu.",
        metrics_h2: "Jak oceniać — praktyczne miary",
        m1: "Średni czas wyciągnięcia wrażliwego elementu w teście red-team.",
        m2: "Odsetek funkcji poprawnie odtworzonych przez Ghidra/IDA.",
        m3: "Odporność na automatyczne narzędzia wykonania symbolicznego.",
        metrics_note: "Zautomatyzuj to w CI: zbuduj niezaciemnioną bazę, stosuj transformacje i mierz różnicę (delta).",
        examples_h2: "Praktyczne przykłady w Rust",
        ex1_h3: "Zarys proc-makra (zaciemnianie łańcuchów w czasie kompilacji)",
        ex2_h3: "Odszyfrowanie w podczas działania programu (dydaktyczne)",
        ex3_h3: "Mała maszyna wirtualna (strukturalne API)",
        best_h2: "Dobre praktyki tworzenia i utrzymania",
        b1: "Utrzymuj build bez zaciemniania do debugowania i audytów.",
        b2: "Udokumentuj, kto ma dostęp do sekretów i jak je rotować.",
        b3: "Automatyzuj testy równoważności (jednostkowe + property-based) po transformacjach.",
        summary_h: "Podsumowanie:",
        summary_p: "Zaciemnianie jest pragmatyczne. Nie czyni oprogramowania niewrażliwym, ale dobrze zaprojektowane i przetestowane realnie zwiększa koszt analizy."
      }
  };

  const langBtns = document.querySelectorAll('.langbtn');
  const status = document.getElementById('langStatus');

  function setLang(lang) {
    const dict = I18N[lang] || I18N.en;
    document.documentElement.lang = lang;

    // Update pressed state
    langBtns.forEach(btn => {
      const pressed = btn.getAttribute('data-lang') === lang;
      btn.setAttribute('aria-pressed', String(pressed));
    });

    // Fill all data-i18n targets
    document.querySelectorAll('[data-i18n]').forEach(el => {
      const key = el.getAttribute('data-i18n');
      if (dict[key]) el.textContent = dict[key];
      else if (I18N.en[key]) el.textContent = I18N.en[key]; // fallback
    });

    // Announce for screen readers
    status.textContent = ({ en: 'Language set to English', it: 'Lingua impostata su Italiano', pl: 'Język ustawiono na polski' })[lang] || '';

    // Persist choice
    try { localStorage.setItem('lang', lang); } catch (_) {}
  }

  // Wire up buttons
  langBtns.forEach(btn => btn.addEventListener('click', () => setLang(btn.dataset.lang)));

  // Initialize from storage or browser
  (function initLang(){
    const saved = (() => { try { return localStorage.getItem('lang'); } catch (_) { return null; } })();
    const browser = (navigator.language || 'en').slice(0,2);
    const initial = saved && I18N[saved] ? saved : (I18N[browser] ? browser : 'en');
    setLang(initial);
  })();
  </script>

  <footer><p><a href="https://www.linkedin.com/in/gianfranco-iaculo-829072250/" target="_blank">Gianfranco Iaculo</a></p></footer>

</body>
</html>