quamvoluptatem
Version:
JavaScript Obfuscation Tool.
713 lines (662 loc) • 20.6 kB
text/typescript
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;
}