UNPKG

quamvoluptatem

Version:
713 lines (662 loc) 20.6 kB
import { ok } from "assert"; import presets from "./presets"; import { ProbabilityMap } from "./probability"; export interface ObfuscateOptions { /** * ### `preset` * * JS-Confuser comes with three presets built into the obfuscator. * * | Preset | Transforms | Performance Reduction | Sample | * | --- | --- | --- | --- | * | High | 21/22 | 98% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/high.js) | * | Medium | 15/22 | 52% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/medium.js) | * | Low | 10/22 | 30% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/low.js) | * * You can extend each preset or all go without them entirely. (`"high"/"medium"/"low"`) * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ preset?: "high" | "medium" | "low" | false; /** * ### `target` * * The execution context for your output. _Required_. * * 1. `"node"` * 2. `"browser"` * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ target: "node" | "browser"; /** * ### `indent` * * Controls the indentation of the output. * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ indent?: 2 | 4 | "tabs"; /** * ### `compact` * * Remove's whitespace from the final output. (`true/false`) * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ compact?: boolean; /** * ### `minify` * * Minifies redundant code. (`true/false`) * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ minify?: boolean; /** * ### `es5` * * Converts output to ES5-compatible code. (`true/false`) * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ es5?: boolean; /** * ### `renameVariables` * * Determines if variables should be renamed. (`true/false`) * - Potency High * - Resilience High * - Cost Medium * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ renameVariables?: ProbabilityMap<boolean>; /** * ### `renameGlobals` * * Renames top-level variables, turn this off for web-related scripts. Enabled by default. (`true/false`) * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ renameGlobals?: ProbabilityMap<boolean>; /** * ### `identifierGenerator` * * Determines how variables are renamed. * * | Mode | Description | Example | * | --- | --- | --- | * | `"hexadecimal"` | Random hex strings | \_0xa8db5 | * | `"randomized"` | Random characters | w$Tsu4G | * | `"zeroWidth"` | Invisible characters | U+200D | * | `"mangled"` | Alphabet sequence | a, b, c | * | `"number"` | Numbered sequence | var_1, var_2 | * | `<function>` | Write a custom name generator | See Below | * * ```js * // Custom implementation * JsConfuser.obfuscate(code, { * target: "node", * renameVariables: true, * identifierGenerator: function () { * return "$" + Math.random().toString(36).substring(7); * }, * }); * * // Numbered variables * var counter = 0; * JsConfuser.obfuscate(code, { * target: "node", * renameVariables: true, * identifierGenerator: function () { * return "var_" + (counter++); * }, * }); * ``` * * JSConfuser tries to reuse names when possible, creating very potent code. * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ identifierGenerator?: ProbabilityMap< "hexadecimal" | "randomized" | "zeroWidth" | "mangled" | "number" >; /** * ### `nameRecycling` * * Attempts to reuse released names. * * - Potency Medium * - Resilience High * - Cost Low * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ nameRecycling?: ProbabilityMap<boolean>; /** * ### `controlFlowFlattening` * * [Control-flow Flattening](https://docs.jscrambler.com/code-integrity/documentation/transformations/control-flow-flattening) obfuscates the program's control-flow by * adding opaque predicates; flattening the control-flow; and adding irrelevant code clones. (`true/false`) * * Use a number to control the percentage from 0 to 1. * * - Potency High * - Resilience High * - Cost High * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ controlFlowFlattening?: ProbabilityMap<boolean>; /** * ### `globalConcealing` * * Global Concealing hides global variables being accessed. (`true/false`) * * - Potency Medium * - Resilience High * - Cost Low * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ globalConcealing?: ProbabilityMap<boolean>; /** * ### `stringCompression` * * String Compression uses LZW's compression algorithm to reduce file size. (`true/false/0-1`) * * `"console"` -> `inflate('replaĕ!ğğuģģ<~@')` * * - Potency High * - Resilience Medium * - Cost Medium */ stringCompression?: ProbabilityMap<boolean>; /** * ### `stringConcealing` * * [String Concealing](https://docs.jscrambler.com/code-integrity/documentation/transformations/string-concealing) involves encoding strings to conceal plain-text values. (`true/false`) * * `"console"` -> `decrypt('<~@rH7+Dert~>')` * * - Potency High * - Resilience Medium * - Cost Medium */ stringConcealing?: ProbabilityMap<boolean>; /** * ### `stringEncoding` * * [String Encoding](https://docs.jscrambler.com/code-integrity/documentation/transformations/string-encoding) transforms a string into an encoded representation. (`true/false`) * * `"console"` -> `'\x63\x6f\x6e\x73\x6f\x6c\x65'` * * - Potency Low * - Resilience Low * - Cost Low * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ stringEncoding?: ProbabilityMap<boolean>; /** * ### `stringSplitting` * * [String Splitting](https://docs.jscrambler.com/code-integrity/documentation/transformations/string-splitting) splits your strings into multiple expressions. (`true/false`) * * `"console"` -> `String.fromCharCode(99) + 'ons' + 'ole'` * * - Potency Medium * - Resilience Medium * - Cost Medium * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ stringSplitting?: ProbabilityMap<boolean>; /** * ### `duplicateLiteralsRemoval` * * [Duplicate Literals Removal](https://docs.jscrambler.com/code-integrity/documentation/transformations/duplicate-literals-removal) replaces duplicate literals with a single variable name. (`true/false`) * * - Potency Medium * - Resilience Low * - Cost High * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ duplicateLiteralsRemoval?: ProbabilityMap<boolean>; /** * ### `dispatcher` * * Creates a dispatcher function to process function calls. This can conceal the flow of your program. (`true/false`) * * - Potency Medium * - Resilience Medium * - Cost High * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ dispatcher?: ProbabilityMap<boolean>; /** * ### `eval` * * #### **`Security Warning`** * * From [MDN](<(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)**>): Executing JavaScript from a string is an enormous security risk. It is far too easy * for a bad actor to run arbitrary code when you use eval(). Never use eval()! * * Wraps defined functions within eval statements. * * - **`false`** - Avoids using the `eval` function. _Default_. * - **`true`** - Wraps function's code into an `eval` statement. * * ```js * // Output.js * var Q4r1__ = { * Oo$Oz8t: eval( * "(function(YjVpAp){var gniSBq6=kHmsJrhOO;switch(gniSBq6){case'RW11Hj5x':return console;}});" * ), * }; * Q4r1__.Oo$Oz8t("RW11Hj5x"); * ``` * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ eval?: ProbabilityMap<boolean>; /** * ### `rgf` * * RGF (Runtime-Generated-Functions) uses the [`new Function(code...)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/Function) syntax to construct executable code from strings. (`"all"/true/false`) * * - **This can break your code. This is also as dangerous as `eval`.** * - **Due to the security concerns of arbitrary code execution, you must enable this yourself.** * - The arbitrary code is also obfuscated. * * | Mode | Description | * | --- | --- | * | `"all"` | Recursively applies to every scope (slow) | * | `true` | Applies to the top level only | * | `false` | Feature disabled | * * ```js * // Input * function log(x){ * console.log(x) * } * * log("Hello World") * * // Output * var C6z0jyO=[new Function('a2Fjjl',"function OqNW8x(OqNW8x){console['log'](OqNW8x)}return OqNW8x(...Array.prototype.slice.call(arguments,1))")];(function(){return C6z0jyO[0](C6z0jyO,...arguments)}('Hello World')) * ``` * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ rgf?: ProbabilityMap<boolean | "all">; /** * ### `stack` * * Local variables are consolidated into a rotating array. * * [Similar to Jscrambler's Variable Masking](https://docs.jscrambler.com/code-integrity/documentation/transformations/variable-masking) * * - Potency Medium * - Resilience Medium * - Cost Low * * ```js * // input * function add3(x, y, z){ * return x + y + z; * } * * // output * function add3(...AxaSQr){AxaSQr.length=3;return AxaSQr.shift()+AxaSQr.shift()+AxaSQr.shift()} * ``` */ stack?: ProbabilityMap<boolean>; /** * ### `objectExtraction` * * Extracts object properties into separate variables. (`true/false`) * * - Potency Low * - Resilience Low * - Cost Low * * ```js * // Input * var utils = { * isString: x=>typeof x === "string", * isBoolean: x=>typeof x === "boolean" * } * if ( utils.isString("Hello") ) { * // ... * } * * // Output * var utils_isString = x=>typeof x === "string"; * var utils_isBoolean = x=>typeof x === "boolean" * if ( utils_isString("Hello") ) { * // ... * } * ``` * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ objectExtraction?: ProbabilityMap<boolean>; /** * ### `flatten` * * Brings independent declarations to the highest scope. (`true/false`) * * - Potency Medium * - Resilience Medium * - Cost High * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ flatten?: ProbabilityMap<boolean>; /** * ### `deadCode` * * Randomly injects dead code. (`true/false/0-1`) * * Use a number to control the percentage from 0 to 1. * * - Potency Medium * - Resilience Medium * - Cost Low * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ deadCode?: ProbabilityMap<boolean>; /** * ### `calculator` * * Creates a calculator function to handle arithmetic and logical expressions. (`true/false/0-1`) * * - Potency Medium * - Resilience Medium * - Cost Low * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ calculator?: ProbabilityMap<boolean>; lock?: { /** * ### `lock.antiDebug` * * Adds `debugger` statements throughout the code. Additionally adds a background function for DevTools detection. (`true/false/0-1`) * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ antiDebug?: ProbabilityMap<boolean>; /** * ### `lock.context` * * Properties that must be present on the `window` object (or `global` for NodeJS). (`string[]`) * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ context?: string[]; /** * ### `lock.nativeFunctions` * * Set of global functions that are native. Such as `require`, `fetch`. If these variables are modified the program crashes. * Set to `true` to use the default native functions. (`string[]/true/false`) * * - Potency Low * - Resilience Medium * - Cost Medium * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ nativeFunctions?: string[] | Set<string> | boolean; /** * ### `lock.startDate` * * When the program is first able to be used. (`number` or `Date`) * * Number should be in milliseconds. * * - Potency Low * - Resilience Medium * - Cost Medium * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ startDate?: number | Date | false; /** * ### `lock.endDate` * * When the program is no longer able to be used. (`number` or `Date`) * * Number should be in milliseconds. * * - Potency Low * - Resilience Medium * - Cost Medium * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ endDate?: number | Date | false; /** * ### `lock.domainLock` * Array of regex strings that the `window.location.href` must follow. (`Regex[]` or `string[]`) * * - Potency Low * - Resilience Medium * - Cost Medium * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ domainLock?: RegExp[] | string[] | false; /** * ### `lock.integrity` * * Integrity ensures the source code is unchanged. (`true/false/0-1`) * [Learn more here](https://github.com/MichaelXF/js-confuser/blob/master/Integrity.md). * * - Potency Medium * - Resilience High * - Cost High * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ integrity?: ProbabilityMap<boolean>; /** * ### `lock.countermeasures` * * A custom callback function to invoke when a lock is triggered. (`string/false`) * * This could be due to an invalid domain, incorrect time, or code's integrity changed. * * [Learn more about the rules of your countermeasures function](https://github.com/MichaelXF/js-confuser/blob/master/Countermeasures.md). * * Otherwise, the obfuscator falls back to crashing the process. * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ countermeasures?: string | boolean; }; /** * ### `movedDeclarations` * * Moves variable declarations to the top of the context. (`true/false`) * * - Potency Medium * - Resilience Medium * - Cost Low * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ movedDeclarations?: ProbabilityMap<boolean>; /** * ### `opaquePredicates` * * An [Opaque Predicate](https://en.wikipedia.org/wiki/Opaque_predicate) is a predicate(true/false) that is evaluated at runtime, this can confuse reverse engineers * understanding your code. (`true/false`) * * - Potency Medium * - Resilience Medium * - Cost Low * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ opaquePredicates?: ProbabilityMap<boolean>; /** * ### `shuffle` * * Shuffles the initial order of arrays. The order is brought back to the original during runtime. (`"hash"/true/false/0-1`) * * - Potency Medium * - Resilience Low * - Cost Low * * | Mode | Description | * | --- | --- | * | `"hash"`| Array is shifted based on hash of the elements | * | `true`| Arrays are shifted *n* elements, unshifted at runtime | * | `false` | Feature disabled | * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ shuffle?: ProbabilityMap<boolean | "hash">; /** * ### `verbose` * * Enable logs to view the obfuscator's state. (`true/false`) * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ verbose?: boolean; /** * ### `globalVariables` * * Set of global variables. *Optional*. (`Set<string>`) * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ globalVariables?: Set<string>; /** * ### `debugComments` * * Enable debug comments. (`true/false`) * * [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options) */ debugComments?: boolean; } var validProperties = new Set([ "preset", "target", "indent", "compact", "minify", "es5", "renameVariables", "renameGlobals", "identifierGenerator", "nameRecycling", "controlFlowFlattening", "globalConcealing", "stringCompression", "stringConcealing", "stringEncoding", "stringSplitting", "duplicateLiteralsRemoval", "dispatcher", "eval", "rgf", "objectExtraction", "flatten", "deadCode", "calculator", "lock", "movedDeclarations", "opaquePredicates", "shuffle", "stack", "verbose", "debugComments", ]); export async function correctOptions( options: ObfuscateOptions ): Promise<ObfuscateOptions> { Object.keys(options).forEach((key) => { if (!validProperties.has(key)) { throw new TypeError("Invalid option: '" + key + "'"); } }); if (options.preset) { ok(presets[options.preset], "Unknown preset of '" + options.preset + "'"); // Clone and allow overriding options = Object.assign({}, presets[options.preset], options); } if (!options.hasOwnProperty("debugComments")) { options.debugComments = false; // debugComments is off by default } if (!options.hasOwnProperty("compact")) { options.compact = true; // Compact is on by default } if (!options.hasOwnProperty("renameGlobals")) { options.renameGlobals = true; // RenameGlobals is on by default } if (options.globalVariables && !(options.globalVariables instanceof Set)) { options.globalVariables = new Set(Object.keys(options.globalVariables)); } // options.globalVariables was never used. // GlobalConcealing implicitly determines a global to be a variable referenced but never defined or modified. if (!options.hasOwnProperty("globalVariables")) { options.globalVariables = new Set([]); if (options.target == "browser") { // browser [ "window", "document", "postMessage", "alert", "confirm", "location", ].forEach((x) => options.globalVariables.add(x)); } else { // node [ "global", "Buffer", "require", "process", "__dirname", "__filename", ].forEach((x) => options.globalVariables.add(x)); } [ "globalThis", "console", "parseInt", "parseFloat", "Math", "Promise", "String", "Boolean", "Function", "Object", "Array", "Proxy", "Error", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "setImmediate", "clearImmediate", "queueMicrotask", "exports", "module", "isNaN", "isFinite", ].forEach((x) => options.globalVariables.add(x)); } return options; }