Skip to content

sfr-development/Lua-Obfuscator-Clyde-Protection

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Clyde-Luau-Obfuscator

Advanced Luau Obfuscator with VM-Based Protection

A high-performance Luau obfuscation toolkit featuring full language support, multi-pass AST transformations, and dual virtual machine architectures for maximum code protection.

TypeScript Node.js License Stars


Overview

Clyde is a from-scratch Luau obfuscator built entirely in TypeScript. It implements a complete Lexer > Parser > AST > Obfuscator > VM pipeline with no external parsing dependencies. Every stage — tokenization, full Luau grammar parsing (including type annotations), AST transformations, bytecode compilation, and VM code generation — is hand-written for maximum control and output quality.

Key Features

  • Full Luau Support — Complete lexer and parser covering the entire Luau grammar including type annotations, generics, if-else expressions, string interpolation, compound assignments, and continue
  • Multi-Pass Obfuscation — Identifier renaming, string encoding, and control flow scrambling applied as composable AST passes
  • Dual VM Architectures — Both stack-based and register-based virtual machines with configurable protection levels
  • Web UI — Built-in Express server with a browser-based interface for interactive obfuscation
  • CLI Tools — Scriptable command-line interface for batch processing and CI/CD integration
  • Validation — Pre-obfuscation syntax validation to catch errors early

Architecture

High-Level Pipeline

graph LR
    A["Luau Source"] --> B["Lexer"]
    B --> C["Parser"]
    C --> D["AST Transforms"]
    D --> E{"Output Mode"}
    E -->|"Direct"| F["Printer"]
    E -->|"Stack VM"| G["Stack Compiler"]
    E -->|"Register VM"| H["Register Compiler"]
    G --> I["VM Generator"]
    H --> J["Reg-VM Generator"]
    F --> K["Obfuscated Luau"]
    I --> K
    J --> K

    style A fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style B fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style C fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style D fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style E fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style F fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style G fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style H fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style I fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style J fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style K fill:#0d3b0d,stroke:#66bb6a,color:#e0e0e0
Loading

Obfuscation Passes

graph TD
    AST["Parsed AST"] --> R{"Rename Locals?"}
    R -->|Yes| REN["Identifier Renaming<br/><i>Scope-aware variable renaming</i>"]
    R -->|No| SE
    REN --> SE{"Encode Strings?"}
    SE -->|Yes| STR["String Encoding<br/><i>XOR / dynamic decoding stubs</i>"]
    SE -->|No| CF
    STR --> CF{"Scramble Control Flow?"}
    CF -->|Yes| CFS["Control Flow Scrambling<br/><i>Opaque predicates + dispatch tables</i>"]
    CF -->|No| OUT["Transformed AST"]
    CFS --> OUT

    style AST fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style R fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style REN fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style SE fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style STR fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style CF fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style CFS fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style OUT fill:#0d3b0d,stroke:#66bb6a,color:#e0e0e0
Loading

VM Compilation Flow

graph TD
    A["Obfuscated AST"] --> B["Bytecode Compiler"]
    B --> C["Instruction Stream<br/><i>opcodes + operands + constants</i>"]
    C --> D{"VM Architecture"}
    
    D -->|"Stack-Based"| E["Stack VM Generator"]
    D -->|"Register-Based"| F["Register VM Generator"]
    
    E --> G["Protection Level"]
    F --> G
    
    G -->|"Debug"| H["Readable output<br/><i>named opcodes, comments</i>"]
    G -->|"Normal"| I["Standard protection<br/><i>shuffled opcodes, encoded constants</i>"]
    G -->|"Maximum"| J["Full protection<br/><i>polymorphic dispatch, LZMA compression</i>"]
    
    H --> K["Self-Contained Luau Script"]
    I --> K
    J --> K

    style A fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style B fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style C fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style D fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style E fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style F fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style G fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style H fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style I fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style J fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style K fill:#0d3b0d,stroke:#66bb6a,color:#e0e0e0
Loading

Project Structure

graph TD
    ROOT["Clyde-Luau-Obfuscator/"] --> SRC["src/"]
    ROOT --> PUB["public/"]
    
    SRC --> LEX["lexer/<br/><i>Tokenizer + token types</i>"]
    SRC --> PAR["parser/<br/><i>Recursive descent parser + type parser</i>"]
    SRC --> AST2["ast/<br/><i>AST node type definitions</i>"]
    SRC --> OBF["obfuscator/<br/><i>Renamer, StringEncoder, ControlFlowScrambler, Printer</i>"]
    SRC --> CMP["compiler/<br/><i>Luau syntax validator</i>"]
    SRC --> VM["vm/<br/><i>Stack + Register compilers, VM generators, LZMA</i>"]
    SRC --> CLI["cli/<br/><i>CLI entry points</i>"]
    SRC --> SRV["server.ts<br/><i>Express API server</i>"]
    
    PUB --> HTML["index.html"]
    PUB --> CSS["style.css"]
    PUB --> JS["app.js"]

    style ROOT fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style SRC fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style PUB fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style LEX fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style PAR fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style AST2 fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style OBF fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style CMP fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style VM fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style CLI fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style SRV fill:#0d2137,stroke:#81d4fa,color:#e0e0e0
    style HTML fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style CSS fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
    style JS fill:#1a1a2e,stroke:#4fc3f7,color:#e0e0e0
Loading

Getting Started

Prerequisites

  • Node.js 18 or higher
  • npm 9 or higher

Installation

git clone https://github.com/sfr-development/Clyde-Luau-Obfuscator.git
cd Clyde-Luau-Obfuscator
npm install
npm run build

Web UI

Start the built-in server with live browser interface:

node dist/server.js

Open http://localhost:3000 to access the obfuscation dashboard.

CLI Usage

Obfuscate a file:

npm run obfuscate -- input.lua

Lex tokens:

npm run lex -- input.lua

Parse AST:

npm run parse -- input.lua

API Reference

The Express server exposes two endpoints:

POST /api/validate

Validates Luau source code for syntax errors.

{
  "code": "local x = 1 + 2"
}

POST /api/obfuscate

Obfuscates Luau source code with configurable options.

{
  "code": "local function greet(name) print('Hello ' .. name) end",
  "options": {
    "noRename": false,
    "noPreserve": false,
    "encodeStrings": true,
    "scramble": true,
    "oneLine": false,
    "vmType": "register",
    "vmLevel": "normal"
  }
}
Option Type Default Description
noRename boolean false Skip identifier renaming
noPreserve boolean false Don't preserve Roblox globals
encodeStrings boolean false Enable string encoding pass
scramble boolean false Enable control flow scrambling
oneLine boolean false Minify output to a single line
vmType string "none" VM type: "none", "stack", or "register"
vmLevel string "normal" Protection level: "debug", "normal", or "maximum"

Programmatic Usage

import { lex, parse, obfuscate, printChunk } from "clyde";
import { compile } from "clyde/vm/Compiler";
import { generateVM } from "clyde/vm/vm-gen";

// Basic obfuscation
const { tokens } = lex('local x = "hello world"');
const ast = parse(tokens);
const obfuscated = obfuscate(ast, { renameLocals: true, preserveGlobals: true });
const output = printChunk(obfuscated);

// VM-protected obfuscation
const bytecode = compile(obfuscated);
const vmOutput = generateVM(bytecode, { level: "normal" });

How It Works

1. Lexer

The lexer tokenizes raw Luau source into a stream of typed tokens. It handles all Luau-specific syntax including:

  • Long strings and comments ([==[...]==])
  • String interpolation (`Hello {name}`)
  • Type annotation tokens (::, ->, ?)
  • Compound operators (+=, -=, *=, etc.)

2. Parser

A hand-written recursive descent parser converts the token stream into a complete AST. It supports:

  • Full statement and expression grammar
  • Type annotations with generics (Array<{key: string}>)
  • If-else expressions (if cond then a else b)
  • Type function statements
  • Export type declarations

3. Obfuscation Passes

Pass Module Description
Identifier Renaming Obfuscator.ts Scope-aware renaming of local variables, function parameters, and loop variables. Preserves Roblox globals by default.
String Encoding StringEncoder.ts Replaces string literals with XOR-encoded equivalents and injects runtime decoding logic.
Control Flow Scrambling ControlFlowScrambler.ts Restructures linear control flow into dispatch-table loops with opaque predicates.

4. Virtual Machines

The VM layer compiles the obfuscated AST into bytecode and wraps it in a self-contained Luau script that executes at runtime:

Architecture Compiler Generator Key Traits
Stack-Based Compiler.ts vm-gen.ts Push/pop operand stack, simpler instruction set
Register-Based RegCompiler.ts reg-vm-gen.ts Register allocation, fewer instructions, polymorphic dispatch

Both VMs support three protection levels:

  • Debug — Readable output with named opcodes for development
  • Normal — Shuffled opcode mapping, encoded constants, flattened control flow
  • Maximum — Full polymorphic dispatch, LZMA-compressed bytecode, anti-tamper checks

Star History

Star History Chart

License

This project is licensed under the MIT License.

About

Advanced Luau / Lua Obfuscator - VM-based code protection, string encoding, control flow scrambling for Roblox scripts

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors