mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Add Pro API support to CLI including support for large files obfuscation (#1381)
This commit is contained in:
@@ -8,6 +8,8 @@ import { TInputOptions } from '../types/options/TInputOptions';
|
||||
import { IFileData } from '../interfaces/cli/IFileData';
|
||||
import { IInitializable } from '../interfaces/IInitializable';
|
||||
import { IObfuscationResult } from '../interfaces/source-code/IObfuscationResult';
|
||||
import { ProApiClient } from '../pro-api/ProApiClient';
|
||||
import { IProObfuscationResult } from '../interfaces/pro-api/IProApiClient';
|
||||
|
||||
import { initializable } from '../decorators/Initializable';
|
||||
|
||||
@@ -34,6 +36,9 @@ import { Logger } from '../logger/Logger';
|
||||
import { ObfuscatedCodeFileUtils } from './utils/ObfuscatedCodeFileUtils';
|
||||
import { SourceCodeFileUtils } from './utils/SourceCodeFileUtils';
|
||||
import { Utils } from '../utils/Utils';
|
||||
import { VMTargetFunctionsMode } from '../pro-api/enums/VMTargetFunctionsMode';
|
||||
import { VMBytecodeFormat } from '../pro-api/enums/VMBytecodeFormat';
|
||||
import { StrictModeSanitizer } from './sanitizers/StrictModeSanitizer';
|
||||
|
||||
export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
/**
|
||||
@@ -155,7 +160,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
);
|
||||
}
|
||||
|
||||
public run(): void {
|
||||
public async run(): Promise<void> {
|
||||
const canShowHelp: boolean = !this.arguments.length || this.arguments.includes('--help');
|
||||
|
||||
if (canShowHelp) {
|
||||
@@ -166,7 +171,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
|
||||
const sourceCodeData: IFileData[] = this.sourceCodeFileUtils.readSourceCode();
|
||||
|
||||
this.processSourceCodeData(sourceCodeData);
|
||||
await this.processSourceCodeData(sourceCodeData);
|
||||
}
|
||||
|
||||
private configureCommands(): void {
|
||||
@@ -210,7 +215,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
)
|
||||
.option(
|
||||
'--domain-lock-redirect-url <string>',
|
||||
'Allows the browser to be redirected to a passed URL if the source code isn\'t run on the domains specified by --domain-lock'
|
||||
"Allows the browser to be redirected to a passed URL if the source code isn't run on the domains specified by --domain-lock"
|
||||
)
|
||||
.option(
|
||||
'--exclude <list> (comma separated, without whitespaces)',
|
||||
@@ -390,6 +395,153 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
'Allows to enable/disable string conversion to unicode escape sequence',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--pro-api-token <string>',
|
||||
'API token for Pro obfuscation via obfuscator.io (enables VM obfuscation via cloud API)'
|
||||
)
|
||||
.option('--pro-api-version <string>', 'Obfuscator version to use with Pro API (e.g., "5.0.0")')
|
||||
.option(
|
||||
'--vm-obfuscation <boolean>',
|
||||
'Enables VM-based bytecode obfuscation for functions',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-obfuscation-threshold <number>',
|
||||
'The probability that VM obfuscation will be applied to a function (Default: 1, Min: 0, Max: 1)',
|
||||
parseFloat
|
||||
)
|
||||
.option(
|
||||
'--vm-preprocess-identifiers <boolean>',
|
||||
'Preprocesses identifiers before VM transformation (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-dynamic-opcodes <boolean>',
|
||||
'Dynamically assembles VM dispatcher with shuffled case order and filters unused opcodes based on code analysis',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-target-functions <list> (comma separated, without whitespaces)',
|
||||
'List of specific function names to apply VM obfuscation to (comma separated)',
|
||||
ArraySanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-exclude-functions <list> (comma separated, without whitespaces)',
|
||||
'List of function names to exclude from VM obfuscation (comma separated)',
|
||||
ArraySanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-target-functions-mode <string>',
|
||||
'Controls how functions are selected for VM obfuscation. ' +
|
||||
`Values: ${CLIUtils.stringifyOptionAvailableValues(VMTargetFunctionsMode)}. ` +
|
||||
`Default: ${VMTargetFunctionsMode.Root}`
|
||||
)
|
||||
.option(
|
||||
'--vm-wrap-top-level-initializers <boolean>',
|
||||
'Wraps top-level variable initializers in IIFEs so they can be VM-obfuscated (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-opcode-shuffle <boolean>',
|
||||
'Randomizes the numeric values assigned to each opcode (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-bytecode-encoding <boolean>',
|
||||
'Enables bytecode encryption with per-function keys (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-bytecode-array-encoding <boolean>',
|
||||
'Enables encrypted bytecode array with lazy decryption (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option('--vm-bytecode-array-encoding-key <string>', 'Custom static key for bytecode array encoding')
|
||||
.option(
|
||||
'--vm-bytecode-array-encoding-key-getter <string>',
|
||||
'Custom key getter function code for bytecode array encoding'
|
||||
)
|
||||
.option(
|
||||
'--vm-instruction-shuffle <boolean>',
|
||||
'Shuffles instruction order within basic blocks (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-jumps-encoding <boolean>',
|
||||
'Enables jump target encoding to prevent CFG reconstruction (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-decoy-opcodes <boolean>',
|
||||
'Enables insertion of decoy opcodes and dead instructions (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-dead-code-injection <boolean>',
|
||||
'Enables dead code injection with opaque predicates in bytecode (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-split-dispatcher <boolean>',
|
||||
'Splits the VM interpreter into multiple category-based dispatchers (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-macro-ops <boolean>',
|
||||
'Enables macro-op fusion to combine common instruction sequences (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-debug-protection <boolean>',
|
||||
'Enables anti-debugging measures with state corruption (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-runtime-opcode-derivation <boolean>',
|
||||
'Enables runtime opcode derivation from seeds instead of static mappings (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-stateful-opcodes <boolean>',
|
||||
'Enables position-based stateful opcode decoding to prevent pattern matching (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-stack-encoding <boolean>',
|
||||
'Enables stack value encoding to prevent stack inspection (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-randomize-keys <boolean>',
|
||||
'Randomizes bytecode property keys to prevent pattern matching (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-indirect-dispatch <boolean>',
|
||||
'Uses indirect dispatch via handler function table instead of switch statement (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-compact-dispatcher <boolean>',
|
||||
'Uses a single unified dispatcher for both sync and generator execution, reducing code size (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--vm-bytecode-format <string>',
|
||||
'Sets the bytecode storage format. ' +
|
||||
`Values: ${CLIUtils.stringifyOptionAvailableValues(VMBytecodeFormat)}. ` +
|
||||
`Default: ${VMBytecodeFormat.Binary}`
|
||||
)
|
||||
.option(
|
||||
'--parse-html <boolean>',
|
||||
'Enables obfuscation of JavaScript within HTML <script> tags (Default: false)',
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--strict-mode <boolean | null>',
|
||||
'Allows to specify how the obfuscator should treat code regarding JavaScript strict mode (Default: null)',
|
||||
StrictModeSanitizer
|
||||
)
|
||||
.parse(this.rawArguments);
|
||||
}
|
||||
|
||||
@@ -408,20 +560,21 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
/**
|
||||
* @param {IFileData[]} sourceCodeData
|
||||
*/
|
||||
private processSourceCodeData(sourceCodeData: IFileData[]): void {
|
||||
sourceCodeData.forEach(({ filePath, content }: IFileData, index: number) => {
|
||||
private async processSourceCodeData(sourceCodeData: IFileData[]): Promise<void> {
|
||||
for (let index = 0; index < sourceCodeData.length; index++) {
|
||||
const { filePath, content } = sourceCodeData[index];
|
||||
const outputCodePath: string = this.obfuscatedCodeFileUtils.getOutputCodePath(filePath);
|
||||
|
||||
try {
|
||||
Logger.log(Logger.colorInfo, LoggingPrefix.CLI, `Obfuscating file: ${filePath}...`);
|
||||
|
||||
this.processSourceCode(content, filePath, outputCodePath, index);
|
||||
await this.processSourceCode(content, filePath, outputCodePath, index);
|
||||
} catch (error) {
|
||||
Logger.log(Logger.colorInfo, LoggingPrefix.CLI, `Error in file: ${filePath}...`);
|
||||
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -430,12 +583,12 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
* @param {string} outputCodePath
|
||||
* @param {number | null} sourceCodeIndex
|
||||
*/
|
||||
private processSourceCode(
|
||||
private async processSourceCode(
|
||||
sourceCode: string,
|
||||
inputCodePath: string,
|
||||
outputCodePath: string,
|
||||
sourceCodeIndex: number | null
|
||||
): void {
|
||||
): Promise<void> {
|
||||
const options: TInputOptions = {
|
||||
...this.inputCLIOptions,
|
||||
identifierNamesCache: this.identifierNamesCacheFileUtils.readFile(),
|
||||
@@ -448,6 +601,15 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
})
|
||||
};
|
||||
|
||||
// Use Pro API if token is provided and Pro features are enabled
|
||||
const proApiToken = this.inputCLIOptions.proApiToken;
|
||||
|
||||
if (proApiToken) {
|
||||
await this.processSourceCodeWithProApi(sourceCode, outputCodePath, options, proApiToken);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.sourceMap) {
|
||||
this.processSourceCodeWithSourceMap(sourceCode, outputCodePath, options);
|
||||
} else {
|
||||
@@ -455,6 +617,41 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process source code using Pro API (cloud-based VM obfuscation)
|
||||
*/
|
||||
private async processSourceCodeWithProApi(
|
||||
sourceCode: string,
|
||||
outputCodePath: string,
|
||||
options: TInputOptions,
|
||||
apiToken: string
|
||||
): Promise<void> {
|
||||
const proApiVersion = this.inputCLIOptions.proApiVersion;
|
||||
|
||||
const client = new ProApiClient({
|
||||
apiToken,
|
||||
version: proApiVersion
|
||||
});
|
||||
|
||||
const result: IProObfuscationResult = await client.obfuscate(sourceCode, options, (message: string) => {
|
||||
Logger.log(Logger.colorInfo, LoggingPrefix.CLI, message);
|
||||
});
|
||||
|
||||
this.obfuscatedCodeFileUtils.writeFile(outputCodePath, result.getObfuscatedCode());
|
||||
|
||||
// Write source map if enabled and available
|
||||
if (options.sourceMap && result.getSourceMap()) {
|
||||
const outputSourceMapPath: string = this.obfuscatedCodeFileUtils.getOutputSourceMapPath(
|
||||
outputCodePath,
|
||||
options.sourceMapFileName ?? ''
|
||||
);
|
||||
|
||||
if (options.sourceMapMode === SourceMapMode.Separate) {
|
||||
this.obfuscatedCodeFileUtils.writeFile(outputSourceMapPath, result.getSourceMap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} sourceCode
|
||||
* @param {string} outputCodePath
|
||||
|
||||
Reference in New Issue
Block a user