js-confuser Documentation

repository·master·Indexed 19 days ago

https://github.com/michaelxf/js-confuser

A JavaScript obfuscation tool designed to protect source code using techniques such as variable renaming, control flow flattening, string concealing, and function obfuscation. It includes security features like domain and date locks, integrity checks to detect source code tampering, and an ES5 compatibility mode for transpiling specific ES6+ features.

Tokens
10.4K
Snippets
37
Records
51
Agent score
67%

What's inside js-confuser

  1. Overview of JS Confuser features

    master

    JS-Confuser is a JavaScript obfuscation tool designed to make programs extremely difficult to read. Key obfuscation features include:

    • Variable renaming: Renames variables to obscure their purpose.
    • Control Flow obfuscation: Alters the logic flow of the code to make it harder to follow.
    • String concealing: Hides string literals within the code.
    • Function obfuscation: Obfuscates function structures and logic.
    • Locks: Implements runtime restrictions such as domainLock and date locks.
    • Integrity: Detects unauthorized changes to the source code.
  2. Supported ES6+ features for ES5 transpilation

    master

    When the es5 option is enabled, the following language features are transpiled to ES5-compatible syntax:

    • Destructuring: Converts object and array destructuring patterns into standard variable assignments.
    • Spread Operator: Converts spread syntax (e.g., ...args) into .apply() or .concat() calls.
    • Template Strings: Converts backtick template literals into string concatenation.
    • Arrow Functions: Converts arrow functions into standard function expressions.
    • Const/Let: Converts const and let declarations into var.
    • Object Getters/Setters: Transpiles getter and setter methods using Object.defineProperty.
    • Reserved Identifiers: Fixes illegal uses of reserved words as object keys or properties (e.g., converting {true: 1} to {"true": 1}).
    • Classes: Provides partial support for transpiling classes.
    • Array Method Polyfills: Automatically injects polyfills (like Array.prototype.forEach) at the top of your script if they are missing.
  3. Local Name rules for custom countermeasures

    master

    When defining a custom countermeasure callback within the locked code, you must follow these rules to prevent infinite loops:

    1. The function must be defined at the top-level of your program.
    2. The function must not rely on any scoped variables.
    3. The function cannot call functions outside its context.
  4. How Tamper Protection improves Global Concealing and RGF

    master

    Tamper Protection enhances two core security features:

    1. Global Concealing

    It detects if global functions have been monkey-patched by inspecting their .toString() value. It ensures that (1) arguments cannot be intercepted and (2) behavior cannot be altered. It also uses a secure eval invocation to obtain the real global object (for both Browser and NodeJS) to prevent scope-based hijacking.

    2. RGF (Runtime-Generated-Functions)

    Normally, RGF behavior can be altered by overriding the default Function constructor. When lock.tamperProtection is enabled, RGF switches from using the Function constructor to using eval with a strict integrity check. This ensures that even if eval is redefined, the concealed code remains inaccessible and its behavior cannot be changed.

  5. How Control Flow Flattening works

    master

    Control Flow Flattening (CFF) transforms your code into a 'goto style' structure. Since JavaScript does not natively support a goto keyword, js-confuser implements this behavior using a while-loop paired with a switch-statement.

    The Basic Mechanism

    1. State Variable: A variable (e.g., state) tracks the current execution point.
    2. Chunks: The original code is broken into discrete 'chunks' (blocks of code).
    3. Switch-Case: Each chunk is placed inside a case of a switch statement.
    4. State Transitions: Instead of direct execution flow, the code updates the state variable to the value of the next chunk, effectively performing a goto to that specific case.

    Advanced Obfuscation Techniques

    js-confuser uses several advanced techniques to make the flattened structure harder to reverse-engineer:

    • Multiple state variables: Using several variables whose sum or combination determines the next state.
    • Control objects: A central object that holds strings, numbers, and outlined expressions used by the code.
    • Mangled numbers and identifiers: Replacing literal values with complex expressions or properties of the control object.
    • Relative state assignment: Updating state variables using arithmetic (e.g., state += 839) rather than direct assignment.
    • Opaque predicates: Using complex conditional logic that always evaluates to a known value but is difficult for static analysis tools to resolve.
    • Dead code: Inserting unreachable code blocks to confuse deobfuscators.
    • Mangled test expressions: Using complex expressions within case labels.
  6. Performance impact of Control Flow Flattening

    master

    Control Flow Flattening significantly reduces the execution performance of your program due to the overhead of the while/switch loop and the complex state calculations.

    To balance security and performance, you should configure the controlFlowFlattening option as a percentage that is appropriate for your specific application's requirements.

  7. Handle Tamper Detection with `lock.countermeasures`

    master

    When Tamper Protection detects an attempt to alter the runtime (such as monkey-patching or running in Strict Mode), it triggers a response.

    • Default Behavior: If no response is configured, the program will crash.
    • Custom Behavior: You can define how the application responds to tampering using the lock.countermeasures option.
  8. Use the Template API to parse code snippets into AST subtrees

    master

    The Template API allows you to create reusable code patterns that can be parsed into AST (Abstract Syntax Tree) subtrees. This is useful for injecting custom-named functions or logic into obfuscated code. You can use three types of interpolation:

    1. Basic string interpolation: Uses {name} syntax to replace text. This is simple but does not escape strings and can lead to syntax errors if the input is not a valid identifier.
    2. AST subtree insertion: Allows you to pass a function that returns an AST Node, a Node[] array, or another Template. This is safer and more powerful than string interpolation. Note that using this method requires an additional traversal to replace plain Identifier nodes.
    3. Template subtree insertion: Allows you to pass one Template instance into another. The variables provided to the parent template are automatically passed down to the child template.
    import JsConfuser from "js-confuser"
    
    // Example of basic string interpolation
    var Base64Template = new JsConfuser.Template(`
    function {name}(str){
      return btoa(str)
    }
    `);
    
    var functionDeclaration = Base64Template.single({ 
      name: "atob" 
    });
  9. Use RGF (Recursive Guard Functions) for arbitrary code obfuscation

    master

    RGF (Recursive Guard Functions) is an obfuscation technique that applies to arbitrary code, including code passed to new Function(). When enabled, it transforms logic into complex, non-linear structures.

    Important Constraints for RGF:

    • It only applies to Function Declarations or Function Expressions.
    • The target function cannot be an async function or a generator function.
    • The function cannot rely on variables from an outside scope.
    • The function cannot use this, arguments, or eval.

    When RGF is active, even the string content inside a new Function() constructor will be obfuscated (e.g., using Control Flow Flattening).

    {
      target: "node",
      rgf: true,
      controlFlowFlattening: true
    }
  10. How Control Flow Flattening works

    master

    Control Flow Flattening works by converting standard control structures into a 'goto style' of code. It replaces high-level logic with a large, complex while loop containing a switch statement. The state of the program is managed through variable updates that determine which case in the switch statement executes next.

    This process can flatten the following statement types:

    1. If Statement
    2. For Statement
    3. While Statement / Do While Statement
    4. Switch Statement
    // Input
    if(true) {
      console.log("This code runs");
    }
    
    // Output (Conceptual)
    while (state != end) {
      switch (state) {
        case 1: 
          console.log("This code runs");
          state = 2;
          break;
        case 2: 
          // end
          break;
      }
    }
  11. Apply RGF to functions with outside scope using `flatten`

    master

    By default, RGF only works on functions that are self-contained. If a function relies on variables defined in an outer scope, RGF will skip it. To resolve this, enable the flatten option alongside rgf.

    flatten isolates functions from their original scope, allowing RGF to be applied to them by restructuring how they access external variables.

    {
      target: "node",
      rgf: true,
      flatten: true
    }
  12. Handle the JSConfuser.obfuscate() return value

    master

    In JS-Confuser 2.0+, the JSConfuser.obfuscate() method returns a Promise that resolves to an object instead of a raw string. To access the obfuscated source code, you must access the .code property on the resulting object.

    const JSConfuser = require("js-confuser");
    const sourceCode = `console.log("Hello World")`;
    const options = {
      target: "node",
      preset: "high"
    };
    
    JSConfuser.obfuscate(sourceCode, options).then(result => {
      // 'result' is an object containing the obfuscated code
      console.log(result.code);
    });