X Tutup
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Change Log

v1.6.0
---
* **New option:** `numbersToExpressions` enables numbers conversion to expressions

v1.5.2
---
* Prevented mutation of the name sequences of `mangled` identifier name generators
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ Following options are available for the JS Obfuscator:
identifiersPrefix: '',
inputFileName: '',
log: false,
numbersToExpressions: false,
renameGlobals: false,
renameProperties: false,
reservedNames: [],
Expand Down Expand Up @@ -375,6 +376,7 @@ Following options are available for the JS Obfuscator:
--identifiers-dictionary '<list>' (comma separated)
--identifiers-prefix <string>
--log <boolean>
--numbers-to-expressions <boolean>
--rename-globals <boolean>
--rename-properties <boolean>
--reserved-names '<list>' (comma separated)
Expand Down Expand Up @@ -667,6 +669,20 @@ Type: `boolean` Default: `false`

Enables logging of the information to the console.

### `numbersToExpressions`
Type: `boolean` Default: `false`

Enables numbers conversion to expressions

Example:
```ts
// input
const foo = 1234;

// output
const foo=-0xd93+-0x10b4+0x41*0x67+0x84e*0x3+-0xff8;
```

### `renameGlobals`
Type: `boolean` Default: `false`

Expand Down Expand Up @@ -985,6 +1001,7 @@ Performance will 50-100% slower than without obfuscation
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
rotateStringArray: true,
selfDefending: true,
Expand Down Expand Up @@ -1016,6 +1033,7 @@ Performance will 30-35% slower than without obfuscation
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: false,
renameGlobals: false,
rotateStringArray: true,
selfDefending: true,
Expand Down Expand Up @@ -1045,6 +1063,7 @@ Performance will slightly slower than without obfuscation
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: false,
renameGlobals: false,
rotateStringArray: true,
selfDefending: true,
Expand Down
14 changes: 7 additions & 7 deletions 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.

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": "1.5.2",
"version": "1.6.0",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand Down Expand Up @@ -54,7 +54,7 @@
"@types/mkdirp": "1.0.1",
"@types/mocha": "7.0.2",
"@types/multimatch": "4.0.0",
"@types/node": "14.0.20",
"@types/node": "14.0.22",
"@types/rimraf": "3.0.0",
"@types/sinon": "9.0.4",
"@types/string-template": "1.0.2",
Expand All @@ -65,7 +65,7 @@
"coveralls": "3.1.0",
"eslint": "7.4.0",
"eslint-plugin-import": "2.22.0",
"eslint-plugin-jsdoc": "29.1.2",
"eslint-plugin-jsdoc": "29.1.3",
"eslint-plugin-no-null": "1.0.2",
"eslint-plugin-prefer-arrow": "1.2.1",
"eslint-plugin-unicorn": "20.1.0",
Expand All @@ -83,7 +83,7 @@
"typescript": "3.9.6",
"webpack": "4.43.0",
"webpack-cli": "3.3.12",
"webpack-node-externals": "2.3.0"
"webpack-node-externals": "2.5.0"
},
"repository": {
"type": "git",
Expand Down
1 change: 1 addition & 0 deletions src/JavaScriptObfuscator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
NodeTransformer.MemberExpressionTransformer,
NodeTransformer.MetadataTransformer,
NodeTransformer.MethodDefinitionTransformer,
NodeTransformer.NumberToNumericalExpressionTransformer,
NodeTransformer.ObfuscatingGuardsTransformer,
NodeTransformer.ObjectExpressionKeysTransformer,
NodeTransformer.ObjectExpressionTransformer,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { injectable, inject } from 'inversify';

import { TNumberNumericalExpressionData } from '../../types/analyzers/number-numerical-expression-analyzer/TNumberNumericalExpressionData';

import { INumberNumericalExpressionAnalyzer } from '../../interfaces/analyzers/number-numerical-expression-analyzer/INumberNumericalExpressionAnalyzer';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';

import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';

import { NumberUtils } from '../../utils/NumberUtils';

/**
* Based on https://gist.github.com/da411d/0e59f79dcf4603cdabf0024a10eeb6fe
*/
@injectable()
export class NumberNumericalExpressionAnalyzer implements INumberNumericalExpressionAnalyzer {
/**
* @type {number}
*/
private static readonly additionalParts: number = 3;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea: make additionalParts random from range 1..4

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may move this under option in the future releases


/**
* @type {Map<number, number[]>}
*/
private readonly numberFactorsMap: Map<number, number[]> = new Map();

/**
* @type {IRandomGenerator}
*/
private readonly randomGenerator: IRandomGenerator;

/**
* @param {IRandomGenerator} randomGenerator
*/
public constructor (
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
) {
this.randomGenerator = randomGenerator;
}

/**
* @param {number} number
* @returns {TNumberNumericalExpressionData}
*/
public analyze (number: number): TNumberNumericalExpressionData {
if (isNaN(number)) {
throw new Error('Given value is NaN');
}

if (NumberUtils.isUnsafeNumber(number)) {
return [number];
}

const additionParts: number[] = this.generateAdditionParts(number);

return additionParts.map((addition: number) => this.mixWithMultiplyParts(addition));
}

/**
* @param {number} number
* @returns {number[]}
*/
private generateAdditionParts (number: number): number[] {
const additionParts = [];

const upperNumberLimit: number = Math.min(Math.abs(number * 2), Number.MAX_SAFE_INTEGER);

const from: number = Math.min(-10000, -upperNumberLimit);
const to: number = Math.max(10000, upperNumberLimit);

let temporarySum = 0;

for (let i = 0; i < NumberNumericalExpressionAnalyzer.additionalParts; i++) {
if (i < NumberNumericalExpressionAnalyzer.additionalParts - 1) {
// trailing parts

let addition: number = this.randomGenerator.getRandomInteger(from, to);
const isUnsafeCombination: boolean = NumberUtils.isUnsafeNumber(temporarySum + addition);

// we have to flip sign if total expression sum overflows over safe integer limits
if (isUnsafeCombination) {
addition = -addition;
}

additionParts.push(addition);
temporarySum += addition;
} else {
const combination: number = number - temporarySum;
const isUnsafeCombination: boolean = NumberUtils.isUnsafeNumber(combination);

// last part
if (isUnsafeCombination) {
additionParts.push(0 - temporarySum);
additionParts.push(number);
} else {
additionParts.push(combination);
}
}
}

return additionParts;
}

/**
* @param {number} number
* @returns {number | number[]}
*/
private mixWithMultiplyParts (number: number): number | number[] {
const shouldMixWithMultiplyParts: boolean = this.randomGenerator.getMathRandom() > 0.5;

if (!shouldMixWithMultiplyParts || number === 0) {
return number;
}

let factors: number[] | null = this.numberFactorsMap.get(number) ?? null;

if (!factors) {
factors = NumberUtils.getFactors(number);
this.numberFactorsMap.set(number, factors);
}

if (!factors.length) {
return number;
}

const factor: number = factors[this.randomGenerator.getRandomInteger(0, factors.length - 1)];

return [factor, number / factor];
}
}
4 changes: 4 additions & 0 deletions src/cli/JavaScriptObfuscatorCLI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
'--log <boolean>', 'Enables logging of the information to the console',
BooleanSanitizer
)
.option(
'--numbers-to-expressions <boolean>', 'Enables numbers conversion to expressions',
BooleanSanitizer
)
.option(
'--reserved-names <list> (comma separated, without whitespaces)',
'Disables obfuscation and generation of identifiers, which being matched by passed RegExp patterns (comma separated)',
Expand Down
1 change: 1 addition & 0 deletions src/container/ServiceIdentifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export enum ServiceIdentifiers {
INodeGuard = 'INodeGuard',
INodeTransformer = 'INodeTransformer',
INodeTransformerNamesGroupsBuilder = 'INodeTransformerNamesGroupsBuilder',
INumberNumericalExpressionAnalyzer = 'INumberNumericalExpressionAnalyzer',
IObfuscationEventEmitter = 'IObfuscationEventEmitter',
IObfuscatedCode = 'IObfuscatedCode',
IOptions = 'IOptions',
Expand Down
7 changes: 7 additions & 0 deletions src/container/modules/analyzers/AnalyzersModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';

import { ICalleeDataExtractor } from '../../../interfaces/analyzers/calls-graph-analyzer/ICalleeDataExtractor';
import { ICallsGraphAnalyzer } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphAnalyzer';
import { INumberNumericalExpressionAnalyzer } from '../../../interfaces/analyzers/number-numerical-expression-analyzer/INumberNumericalExpressionAnalyzer';
import { IPrevailingKindOfVariablesAnalyzer } from '../../../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
import { IScopeAnalyzer } from '../../../interfaces/analyzers/scope-analyzer/IScopeAnalyzer';
import { IStringArrayStorageAnalyzer } from '../../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
Expand All @@ -12,6 +13,7 @@ import { CalleeDataExtractor } from '../../../enums/analyzers/calls-graph-analyz
import { CallsGraphAnalyzer } from '../../../analyzers/calls-graph-analyzer/CallsGraphAnalyzer';
import { FunctionDeclarationCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/FunctionDeclarationCalleeDataExtractor';
import { FunctionExpressionCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/FunctionExpressionCalleeDataExtractor';
import { NumberNumericalExpressionAnalyzer } from '../../../analyzers/number-numerical-expression-analyzer/NumberNumericalExpressionAnalyzer';
import { ObjectExpressionCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor';
import { PrevailingKindOfVariablesAnalyzer } from '../../../analyzers/prevailing-kind-of-variables-analyzer/PrevailingKindOfVariablesAnalyzer';
import { ScopeAnalyzer } from '../../../analyzers/scope-analyzer/ScopeAnalyzer';
Expand All @@ -23,6 +25,11 @@ export const analyzersModule: interfaces.ContainerModule = new ContainerModule((
.to(CallsGraphAnalyzer)
.inSingletonScope();

// number numerical expression analyzer
bind<INumberNumericalExpressionAnalyzer>(ServiceIdentifiers.INumberNumericalExpressionAnalyzer)
.to(NumberNumericalExpressionAnalyzer)
.inSingletonScope();

// prevailing kind of variables analyzer
bind<IPrevailingKindOfVariablesAnalyzer>(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
.to(PrevailingKindOfVariablesAnalyzer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import { IObjectExpressionExtractor } from '../../../interfaces/node-transformer
import { NodeTransformer } from '../../../enums/node-transformers/NodeTransformer';
import { ObjectExpressionExtractor } from '../../../enums/node-transformers/converting-transformers/properties-extractors/ObjectExpressionExtractor';

import { BasePropertiesExtractor } from '../../../node-transformers/converting-transformers/object-expression-extractors/BasePropertiesExtractor';
import { ObjectExpressionToVariableDeclarationExtractor } from '../../../node-transformers/converting-transformers/object-expression-extractors/ObjectExpressionToVariableDeclarationExtractor';
import { MemberExpressionTransformer } from '../../../node-transformers/converting-transformers/MemberExpressionTransformer';
import { MethodDefinitionTransformer } from '../../../node-transformers/converting-transformers/MethodDefinitionTransformer';
import { NumberToNumericalExpressionTransformer } from '../../../node-transformers/converting-transformers/NumberToNumericalExpressionTransformer';
import { ObjectExpressionKeysTransformer } from '../../../node-transformers/converting-transformers/ObjectExpressionKeysTransformer';
import { ObjectExpressionTransformer } from '../../../node-transformers/converting-transformers/ObjectExpressionTransformer';
import { SplitStringTransformer } from '../../../node-transformers/converting-transformers/SplitStringTransformer';
import { TemplateLiteralTransformer } from '../../../node-transformers/converting-transformers/TemplateLiteralTransformer';
import { BasePropertiesExtractor } from '../../../node-transformers/converting-transformers/object-expression-extractors/BasePropertiesExtractor';

export const convertingTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
// converting transformers
Expand All @@ -27,6 +28,11 @@ export const convertingTransformersModule: interfaces.ContainerModule = new Cont
.to(MethodDefinitionTransformer)
.whenTargetNamed(NodeTransformer.MethodDefinitionTransformer);


bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
.to(NumberToNumericalExpressionTransformer)
.whenTargetNamed(NodeTransformer.NumberToNumericalExpressionTransformer);

bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
.to(ObjectExpressionKeysTransformer)
.whenTargetNamed(NodeTransformer.ObjectExpressionKeysTransformer);
Expand Down
2 changes: 2 additions & 0 deletions src/custom-code-helpers/CustomCodeHelperObfuscator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export class CustomCodeHelperObfuscator implements ICustomCodeHelperObfuscator {
...NO_ADDITIONAL_NODES_PRESET,
identifierNamesGenerator: this.options.identifierNamesGenerator,
identifiersDictionary: this.options.identifiersDictionary,
numbersToExpressions: this.options.numbersToExpressions,
simplify: this.options.simplify,
seed: this.randomGenerator.getRawSeed(),
...additionalOptions
}
Expand Down
1 change: 1 addition & 0 deletions src/enums/node-transformers/NodeTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum NodeTransformer {
MemberExpressionTransformer = 'MemberExpressionTransformer',
MetadataTransformer = 'MetadataTransformer',
MethodDefinitionTransformer = 'MethodDefinitionTransformer',
NumberToNumericalExpressionTransformer = 'NumberToNumericalExpressionTransformer',
ObfuscatingGuardsTransformer = 'ObfuscatingGuardsTransformer',
ObjectExpressionKeysTransformer = 'ObjectExpressionKeysTransformer',
ObjectExpressionTransformer = 'ObjectExpressionTransformer',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { TNumberNumericalExpressionData } from '../../../types/analyzers/number-numerical-expression-analyzer/TNumberNumericalExpressionData';

export interface INumberNumericalExpressionAnalyzer {
/**
* @param {number} number
* @returns {TNumberNumericalExpressionData}
*/
analyze (number: number): TNumberNumericalExpressionData;
}
1 change: 1 addition & 0 deletions src/interfaces/options/IOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface IOptions {
readonly identifiersPrefix: string;
readonly inputFileName: string;
readonly log: boolean;
readonly numbersToExpressions: boolean;
readonly renameGlobals: boolean;
readonly renameProperties: boolean;
readonly reservedNames: string[];
Expand Down
Loading
X Tutup