Skip to content

kusoidev/lightweight-js-obfuscator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 

Repository files navigation

Lightweight JS Semi-VM String Obfuscator

A small, practical JavaScript obfuscator that sits between basic string mangling and full VM-based obfuscation. It uses a tiny custom VM for strings, then hands off to javascript-obfuscator for the heavy lifting.

Make sure your project is using ES modules ("type": "module" in package.json) or run with a Node version/config that supports import.

Built for production use where full virtual machines are too slow and standard obfuscation is too easy to peel apart.

What this is

  • ~150 lines of ES module code

  • Custom string-decoding VM with 2 opcodes

    • XOR decode
    • Fixed offset shift
  • Random XOR key per build (1–255)

  • Per-character randomized opcode selection

  • Two-stage pipeline:

    1. Babel plugin (AST transform)
    2. javascript-obfuscator pass
  • ~1.2× runtime overhead in practice (compared to ~3–5× for full VM obfuscators)

This is not meant to be unbreakable. It’s meant to be annoying enough that reversing isn’t trivial, without killing performance.

Why this exists

  • Full VM obfuscation is usually too slow for real-world production code

  • Standard obfuscation is often too easy to pattern-match and undo

  • This aims for the middle ground:

    • Custom logic that breaks tooling assumptions
    • Low overhead
    • Simple enough to reason about and maintain

Tech stack

  • Babel – AST transforms and string replacement
  • javascript-obfuscator – control flow flattening, dead code, renaming, etc.
  • Node.js
  • ES modules

Installation

npm install

Dependencies you’ll need:

npm install @babel/core javascript-obfuscator

Node 16+ recommended.

Usage

node obfuscator.js input.js output.js

What happens:

  1. Generates a random XOR key for the build
  2. Replaces eligible string literals with VM bytecode
  3. Injects a tiny VM decoder function
  4. Runs javascript-obfuscator with a custom dictionary and control-flow options
  5. Writes the final obfuscated output

How it works (brief)

  • During the Babel pass:

    • String literals (above a minimum length and not common DOM words) are replaced

    • Each character is encoded as:

      • [1, char ^ xorKey] or
      • [2, char + 5]
    • Opcode choice is randomized per character

  • A small VM function is injected:

    • Iterates bytecode
    • Decodes characters based on opcode
    • Reconstructs the string at runtime
  • The output is then passed through javascript-obfuscator to:

    • Flatten control flow
    • Inject dead code
    • Rename identifiers using a fixed dictionary
    • Add additional noise around the VM logic

The VM is intentionally minimal to keep runtime cost low.

About

Lightweight VM-based JavaScript obfuscator - practical protection without the performance hit

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published