Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f087100
Identifier names cache option prototype
sanex3339 May 29, 2021
bee043c
Identifier names cache option prototype #2. Added readme.
sanex3339 May 29, 2021
23a9ce7
README.md update: `identifierNamesCache` option fixes
sanex3339 May 29, 2021
128e91b
Added `storeThroughName` method to the IIdentifierReplacer
sanex3339 May 30, 2021
b62f493
Added `ScopeThroughIdentifiersTransformer` tests
sanex3339 May 30, 2021
18f72a8
Added ThroughIdentifierReplacer for code separate between ScopeIdenti…
sanex3339 May 30, 2021
a921f34
Updated README.md
sanex3339 May 30, 2021
442cd7b
Renamed `getAsDictionary` method of IMapStorage to the `getStorageAsD…
sanex3339 May 30, 2021
aa64a55
Some refactoring. Added IdentifierNamesCacheStorage tests
sanex3339 May 30, 2021
f3c4be2
Renamed `obfuscatedCode` => `obfuscationResult` variables
sanex3339 May 30, 2021
e7d9c71
Added more tests for identifier names cache code generation
sanex3339 May 30, 2021
51d4ea0
Added `exports` field as reserved property name
sanex3339 May 30, 2021
f32bcf2
Changed identifier names cache structure to store multiple identifier…
sanex3339 May 30, 2021
4be162a
Added property cache implementation
sanex3339 May 30, 2021
eee1545
Dependencies update. Added tests for property identifier names cache.
sanex3339 May 31, 2021
1f044e9
Renamed some CLI classes to achieve more consistent naming
sanex3339 May 31, 2021
c89ba21
Internal fields of `TIdentifierNamesCache` now are optional. Fixed op…
sanex3339 May 31, 2021
9b3b164
Slightly simplified validation of identifier names cache. Updated REA…
sanex3339 May 31, 2021
b0ff4d8
Added tests for `readFile` method of IdentifierNamesCacheFileUtils
sanex3339 May 31, 2021
13a7302
Added tests for `writeFile` method of IdentifierNamesCacheFileUtils
sanex3339 May 31, 2021
a04dd87
Added missing IdentifierNamesCacheFileUtils tests
sanex3339 May 31, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Change Log

v2.14.0
---
* Added `identifierNamesCache` option for reading and writing identifier names cache. See `README.md`.
* **CLI**: Added `--identifier-names-cache-path` option for reading and writing identifier names cache. See `README.md`.

v2.13.0
---
* Fixed invalid code generation for start/middle rest arguments when `controlFlowFlattenig` option is enabled. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/920
Expand Down
85 changes: 84 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ function _0x1054 (_0x14a2a4, _0x5a6b22) {
Returns `ObfuscationResult` object which contains two public methods:

* `getObfuscatedCode()` - returns `string` with obfuscated code;
* `getSourceMap()` - if [`sourceMap`](#sourcemap) option is enabled - returns `string` with source map or an empty string if [`sourceMapMode`](#sourcemapmode) option is set as `inline`.
* `getSourceMap()` - if [`sourceMap`](#sourcemap) option is enabled - returns `string` with source map or an empty string if [`sourceMapMode`](#sourcemapmode) option is set as `inline`;
* `getIdentifierNamesCache()` - returns object with identifier names cache if `identifierNamesCache` option is enabled, `null` overwise.

Calling `toString()` for `ObfuscationResult` object will return `string` with obfuscated code.

Expand Down Expand Up @@ -361,6 +362,7 @@ Following options are available for the JS Obfuscator:
disableConsoleOutput: false,
domainLock: [],
forceTransformStrings: [],
identifierNamesCache: null,
identifierNamesGenerator: 'hexadecimal',
identifiersDictionary: [],
identifiersPrefix: '',
Expand Down Expand Up @@ -421,6 +423,7 @@ Following options are available for the JS Obfuscator:
--domain-lock '<list>' (comma separated)
--exclude '<list>' (comma separated)
--force-transform-strings '<list>' (comma separated)
--identifier-names-cache-path <string>
--identifier-names-generator <string> [dictionary, hexadecimal, mangled, mangled-shuffled]
--identifiers-dictionary '<list>' (comma separated)
--identifiers-prefix <string>
Expand Down Expand Up @@ -712,6 +715,84 @@ Example:
}
```

### `identifierNamesCache`
Type: `Object | null` Default: `null`

The main goal for this option is the ability to use the same identifier names during obfuscation of multiple sources/files.

Currently the two types of the identifiers are supported:
- Global identifiers:
* All global identifiers will be written to the cache;
* All matched **undeclared** global identifiers will be replaced by the values from the cache.
- Property identifiers, only when `renameProperties` option is enabled:
* All property identifiers will be written to the cache;
* All matched property identifiers will be replaced by the values from the cache.

#### Node.js API
If a `null` value is passed, completely disables the cache.

If an empty object (`{}`) is passed, enables the writing identifier names to the cache-object (`TIdentifierNamesCache` type). This cache-object will be accessed through the `getIdentifierNamesCache` method call of `ObfuscationResult` object.

The resulting cache-object can be next used as `identifierNamesGenerator` option value for using these names during obfuscation of all matched identifier names of next sources.

Example:
```
const source1ObfuscationResult = JavaScriptObfuscator.obfuscate(
`
function foo(arg) {
console.log(arg)
}

function bar() {
var bark = 2;
}
`,
{
compact: false,
identifierNamesCache: {},
renameGlobals: true
}
)

console.log(source1ObfuscationResult.getIdentifierNamesCache());
/*{
globalIdentifiers: {
foo: '_0x5de86d',
bar: '_0x2a943b'
}
}*/



const source2ObfuscationResult = JavaScriptObfuscator.obfuscate(
`
// Expecting that these global functions are defined in another obfuscated file
foo(1);
bar();

// Expecting that this global function is defined in third-party package
baz();
`,
{
compact: false,
identifierNamesCache: source1ObfuscationResult.getIdentifierNamesCache(),
renameGlobals: true
}
)

console.log(source2ObfuscationResult.getObfuscatedCode());
// _0x5de86d(0x1);
// _0x2a943b();
// baz();
```

#### CLI
CLI has a different option `--identifier-names-cache-path` that allows defining a path to the existing `.json` file that will be used to read and write identifier names cache.

If a path to the empty file will be passed - identifier names cache will be written to that file.

This file with existing cache can be used again as `--identifier-names-cache-path` option value for using these names during obfuscation of all matched identifier names of the next files.

### `identifierNamesGenerator`
Type: `string` Default: `hexadecimal`

Expand Down Expand Up @@ -834,6 +915,8 @@ Specifies `renameProperties` option mode:
* `safe` - default behaviour after `2.11.0` release. Trying to rename properties in a more safe way to prevent runtime errors. With this mode some properties will be excluded from renaming.
* `unsafe` - default behaviour before `2.11.0` release. Renames properties in an unsafe way without any restrictions.

If one file is using properties from other file, use [`identifierNamesCache`](#identifiernamescache) option to keep the same property names between these files.

### `reservedNames`
Type: `string[]` Default: `[]`

Expand Down
2 changes: 1 addition & 1 deletion dist/index.browser.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.cli.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import { TInputOptions } from './src/types/options/TInputOptions';
import { TObfuscationResultsObject } from './src/types/TObfuscationResultsObject';
import { TOptionsPreset } from './src/types/options/TOptionsPreset';

import { IObfuscatedCode } from './src/interfaces/source-code/IObfuscatedCode';
import { IObfuscationResult } from './src/interfaces/source-code/IObfuscationResult';

export type ObfuscatorOptions = TInputOptions;

export interface ObfuscatedCode extends IObfuscatedCode {}
export interface ObfuscationResult extends IObfuscationResult {}

/**
* @param {string} sourceCode
* @param {ObfuscatorOptions} inputOptions
* @returns {ObfuscatedCode}
*/
export function obfuscate (sourceCode: string, inputOptions?: ObfuscatorOptions): ObfuscatedCode;
export function obfuscate (sourceCode: string, inputOptions?: ObfuscatorOptions): ObfuscationResult;

/**
* @param {TSourceCodesObject} sourceCodesObject
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "2.13.0",
"version": "2.14.0",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand All @@ -24,7 +24,7 @@
"@javascript-obfuscator/escodegen": "2.2.0",
"@javascript-obfuscator/estraverse": "5.3.0",
"@nuxtjs/opencollective": "0.3.2",
"acorn": "8.2.4",
"acorn": "8.3.0",
"assert": "2.0.0",
"chalk": "4.1.1",
"chance": "1.1.7",
Expand Down Expand Up @@ -68,8 +68,8 @@
"chai-exclude": "2.0.3",
"cross-env": "7.0.3",
"eslint": "7.27.0",
"eslint-plugin-import": "2.23.3",
"eslint-plugin-jsdoc": "35.0.0",
"eslint-plugin-import": "2.23.4",
"eslint-plugin-jsdoc": "35.1.0",
"eslint-plugin-no-null": "1.0.2",
"eslint-plugin-prefer-arrow": "1.2.3",
"eslint-plugin-unicorn": "32.0.1",
Expand Down
27 changes: 14 additions & 13 deletions src/JavaScriptObfuscator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import * as acorn from 'acorn';
import * as escodegen from '@javascript-obfuscator/escodegen';
import * as ESTree from 'estree';

import { TObfuscatedCodeFactory } from './types/container/source-code/TObfuscatedCodeFactory';
import { TObfuscationResultFactory } from './types/container/source-code/TObfuscationResultFactory';

import { ICodeTransformersRunner } from './interfaces/code-transformers/ICodeTransformersRunner';
import { IGeneratorOutput } from './interfaces/IGeneratorOutput';
import { IJavaScriptObfuscator } from './interfaces/IJavaScriptObfsucator';
import { ILogger } from './interfaces/logger/ILogger';
import { IObfuscatedCode } from './interfaces/source-code/IObfuscatedCode';
import { IObfuscationResult } from './interfaces/source-code/IObfuscationResult';
import { IOptions } from './interfaces/options/IOptions';
import { IRandomGenerator } from './interfaces/utils/IRandomGenerator';
import { INodeTransformersRunner } from './interfaces/node-transformers/INodeTransformersRunner';
Expand Down Expand Up @@ -87,6 +87,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
NodeTransformer.ObjectPatternPropertiesTransformer,
NodeTransformer.ParentificationTransformer,
NodeTransformer.ScopeIdentifiersTransformer,
NodeTransformer.ScopeThroughIdentifiersTransformer,
NodeTransformer.SplitStringTransformer,
NodeTransformer.StringArrayRotateFunctionTransformer,
NodeTransformer.StringArrayScopeCallsWrapperTransformer,
Expand All @@ -108,9 +109,9 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
private readonly logger: ILogger;

/**
* @type {TObfuscatedCodeFactory}
* @type {TObfuscationResultFactory}
*/
private readonly obfuscatedCodeFactory: TObfuscatedCodeFactory;
private readonly obfuscationResultFactory: TObfuscationResultFactory;

/**
* @type {IOptions}
Expand All @@ -131,31 +132,31 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
* @param {ICodeTransformersRunner} codeTransformersRunner
* @param {INodeTransformersRunner} nodeTransformersRunner
* @param {IRandomGenerator} randomGenerator
* @param {TObfuscatedCodeFactory} obfuscatedCodeFactory
* @param {TObfuscationResultFactory} obfuscatedCodeFactory
* @param {ILogger} logger
* @param {IOptions} options
*/
public constructor (
@inject(ServiceIdentifiers.ICodeTransformersRunner) codeTransformersRunner: ICodeTransformersRunner,
@inject(ServiceIdentifiers.INodeTransformersRunner) nodeTransformersRunner: INodeTransformersRunner,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.Factory__IObfuscatedCode) obfuscatedCodeFactory: TObfuscatedCodeFactory,
@inject(ServiceIdentifiers.Factory__IObfuscationResult) obfuscatedCodeFactory: TObfuscationResultFactory,
@inject(ServiceIdentifiers.ILogger) logger: ILogger,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
this.codeTransformersRunner = codeTransformersRunner;
this.nodeTransformersRunner = nodeTransformersRunner;
this.randomGenerator = randomGenerator;
this.obfuscatedCodeFactory = obfuscatedCodeFactory;
this.obfuscationResultFactory = obfuscatedCodeFactory;
this.logger = logger;
this.options = options;
}

/**
* @param {string} sourceCode
* @returns {IObfuscatedCode}
* @returns {IObfuscationResult}
*/
public obfuscate (sourceCode: string): IObfuscatedCode {
public obfuscate (sourceCode: string): IObfuscationResult {
if (typeof sourceCode !== 'string') {
sourceCode = '';
}
Expand Down Expand Up @@ -183,7 +184,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
const obfuscationTime: number = (Date.now() - timeStart) / 1000;
this.logger.success(LoggingMessage.ObfuscationCompleted, obfuscationTime);

return this.getObfuscatedCode(generatorOutput);
return this.getObfuscationResult(generatorOutput);
}

/**
Expand Down Expand Up @@ -268,10 +269,10 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {

/**
* @param {IGeneratorOutput} generatorOutput
* @returns {IObfuscatedCode}
* @returns {IObfuscationResult}
*/
private getObfuscatedCode (generatorOutput: IGeneratorOutput): IObfuscatedCode {
return this.obfuscatedCodeFactory(generatorOutput.code, generatorOutput.map);
private getObfuscationResult (generatorOutput: IGeneratorOutput): IObfuscationResult {
return this.obfuscationResultFactory(generatorOutput.code, generatorOutput.map);
}

/**
Expand Down
10 changes: 5 additions & 5 deletions src/JavaScriptObfuscatorFacade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { TOptionsPreset } from './types/options/TOptionsPreset';

import { IInversifyContainerFacade } from './interfaces/container/IInversifyContainerFacade';
import { IJavaScriptObfuscator } from './interfaces/IJavaScriptObfsucator';
import { IObfuscatedCode } from './interfaces/source-code/IObfuscatedCode';
import { IObfuscationResult } from './interfaces/source-code/IObfuscationResult';

import { InversifyContainerFacade } from './container/InversifyContainerFacade';
import { Options } from './options/Options';
Expand All @@ -24,20 +24,20 @@ class JavaScriptObfuscatorFacade {
/**
* @param {string} sourceCode
* @param {TInputOptions} inputOptions
* @returns {IObfuscatedCode}
* @returns {IObfuscationResult}
*/
public static obfuscate (sourceCode: string, inputOptions: TInputOptions = {}): IObfuscatedCode {
public static obfuscate (sourceCode: string, inputOptions: TInputOptions = {}): IObfuscationResult {
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();

inversifyContainerFacade.load(sourceCode, '', inputOptions);

const javaScriptObfuscator: IJavaScriptObfuscator = inversifyContainerFacade
.get<IJavaScriptObfuscator>(ServiceIdentifiers.IJavaScriptObfuscator);
const obfuscatedCode: IObfuscatedCode = javaScriptObfuscator.obfuscate(sourceCode);
const obfuscationResult: IObfuscationResult = javaScriptObfuscator.obfuscate(sourceCode);

inversifyContainerFacade.unload();

return obfuscatedCode;
return obfuscationResult;
}

/**
Expand Down
Loading