8000 String array calls transform fix by sanex3339 · Pull Request #1050 · javascript-obfuscator/javascript-obfuscator · GitHub
[go: up one dir, main page]

Skip to content

String array calls transform fix #1050

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 7, 2022
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Change Log

v3.2.3
---
* Fixed missing transformation of string array calls in some cases
* Fixed generation of reserved identifier names like `Map` or `Set` for `mangled` and `mangled-shuffled` identifier names generators

v3.2.2
---
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1039
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "3.2.2",
"version": "3.2.3",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand Down
11 changes: 11 additions & 0 deletions src/constants/ReservedIdentifierNames.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const reservedIdentifierNames = [
// reserved identifiers
'byte', 'case', 'char', 'do', 'else', 'enum', 'eval', 'for', 'goto',
'if', 'in', 'int', 'let', 'long', 'new', 'null', 'this', 'true', 'try',
'var', 'void', 'with',

// reserved global object identifiers
'Array', 'Attr', 'Audio', 'Blob', 'Cache', 'Date', 'Error', 'Event',
'Feed', 'File', 'Hz', 'Image', 'Intl', 'Lock', 'Map', 'Math', 'Node',
'Proxy', 'Range', 'Rect', 'Set', 'Table', 'Text', 'Touch'
];
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ export abstract class AbstractIdentifierNamesGenerator implements IIdentifierNam
* @returns {boolean}
*/
public isValidIdentifierName (name: string): boolean {
return this.notReservedName(name) && !this.preservedNamesSet.has(name);
return !this.isReservedName(name)
&& !this.preservedNamesSet.has(name);
}

/**
Expand Down Expand Up @@ -112,12 +113,12 @@ export abstract class AbstractIdentifierNamesGenerator implements IIdentifierNam
* @param {string} name
* @returns {boolean}
*/
private notReservedName (name: string): boolean {
private isReservedName (name: string): boolean {
return this.options.reservedNames.length
? !this.options.reservedNames.some((reservedName: string) =>
? this.options.reservedNames.some((reservedName: string) =>
new RegExp(reservedName, 'g').exec(name) !== null
)
: true;
: false;

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { ISetUtils } from '../../interfaces/utils/ISetUtils';

import { numbersString } from '../../constants/NumbersString';
import { alphabetString } from '../../constants/AlphabetString';
import { alphabetStringUppercase } from '../../constants/AlphabetStringUppercase';
import { numbersString } from '../../constants/NumbersString';
import { reservedIdentifierNames } from '../../constants/ReservedIdentifierNames';

import { AbstractIdentifierNamesGenerator } from './AbstractIdentifierNamesGenerator';
import { NodeLexicalScopeUtils } from '../../node/NodeLexicalScopeUtils';
Expand Down Expand Up @@ -40,14 +41,11 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene

/**
* Reserved JS words with length of 2-4 symbols that can be possible generated with this replacer
* + reserved DOM names like `Set`, `Map`, `Date`, etc
*
* @type {Set<string>}
*/
private static readonly reservedNamesSet: Set<string> = new Set([
'byte', 'case', 'char', 'do', 'else', 'enum', 'eval', 'for', 'goto',
'if', 'in', 'int', 'let', 'long', 'new', 'null', 'this', 'true', 'try',
'var', 'void', 'with'
]);
private static readonly reservedNamesSet: Set<string> = new Set(reservedIdentifierNames);

/**
* @type {WeakMap<string, string>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from '../../types/container/node-transformers/TControlFlowStorageFactoryCreator';
import { TNodeWithStatements } from '../../types/node/TNodeWithStatements';

import { IControlFlowStorage } from '../../interfaces/storages/control-flow-transformers/IControlFlowStorage';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
Expand All @@ -23,7 +24,6 @@ import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';

import { FunctionControlFlowTransformer } from './FunctionControlFlowTransformer';
import { NodeGuards } from '../../node/NodeGuards';
import { IControlFlowStorage } from '../../interfaces/storages/control-flow-transformers/IControlFlowStorage';

@injectable()
export class StringArrayControlFlowTransformer extends FunctionControlFlowTransformer {
Expand Down Expand Up @@ -120,12 +120,20 @@ export class StringArrayControlFlowTransformer extends FunctionControlFlowTransf
&& this.controlFlowStorageNodes.has(node);

if (isControlFlowStorageNode) {
return estraverse.VisitorOption.Break;
return estraverse.VisitorOption.Skip;
}

return super.transformFunctionBodyNode(node, parentNode, functionNode, controlFlowStorage);
}

/**
* @param {TNodeWithStatements} hostNode
* @returns {TControlFlowStorage}
*/
protected override getControlFlowStorage (hostNode: TNodeWithStatements): IControlFlowStorage {
return this.controlFlowStorageFactory();
}

/**
* @param {TNodeWithStatements} hostNode
* @param {VariableDeclaration} controlFlowStorageNode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { IPropertyIdentifierNamesCacheStorage } from '../../../interfaces/storag
import { IRenamePropertiesReplacer } from '../../../interfaces/node-transformers/rename-properties-transformers/replacer/IRenamePropertiesReplacer';

// eslint-disable-next-line import/no-internal-modules
import ReservedDomProperties from './ReservedDomProperties.json';
import ReservedDomProperties from '../../../constants/ReservedDomProperties.json';

import { NodeGuards } from '../../../node/NodeGuards';
import { NodeFactory } from '../../../node/NodeFactory';
Expand Down
49 changes: 39 additions & 10 deletions test/dev/dev.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,55 @@
'use strict';

import { StringArrayWrappersType } from '../../src/enums/node-transformers/string-array-transformers/StringArrayWrappersType';

(function () {
const JavaScriptObfuscator: any = require('../../index');

let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
async function xyzzy(a,b)
{
if (a) {
return await foo(a) ;
console.log(a) ;
} else {
return await bar(b) ;
console.log(b) ;
function foo () {
function bar() {
var string1 = 'string1';
var string2 = 'string2';
var string3 = 'string3';
var string4 = 'string4';
var string5 = 'string5';
var string6 = 'string6';

function bark () {
var string1 = 'string1';
var string2 = 'string2';
var string3 = 'string3';
var string4 = 'string4';
var string5 = 'string5';
var string6 = 'string6';
}
}

bar()
}

console.log(foo());
`,
{
identifierNamesGenerator: 'mangled',
compact: false,
simplify: true,
stringArray: false
controlFlowFlattening: false,
controlFlowFlatteningThreshold: 1,
simplify: false,
stringArrayRotate: false,
stringArray: true,
stringArrayIndexesType: [
'hexadecimal-number',
'hexadecimal-numeric-string'
],
stringArrayThreshold: 1,
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 1,
rotateStringArray: true,
stringArrayWrappersType: StringArrayWrappersType.Function,
transformObjectKeys: false,
seed: 1
}
).getObfuscatedCode();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,43 @@ describe('StringArrayControlFlowTransformer', function () {
assert.match(obfuscatedCode, regexp);
});
});

describe('Variant #5 - multiple `control flow storages` on the same block scope', () => {
const regexp: RegExp = new RegExp(
`var ${hexadecimalVariableMatch} *= *\\{` +
`${hexadecimalVariableMatch} *: *0x0, *` +
`${hexadecimalVariableMatch} *: *0x1 *` +
`\\}; *` +
`var ${hexadecimalVariableMatch} *= *\\{` +

`${hexadecimalVariableMatch} *: *0x2, *` +
`${hexadecimalVariableMatch} *: *0x3 *` +
`\\};`
);

let obfuscatedCode: string;

before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/multiple-storages-1.js');

obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1,
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 1
}
).getObfuscatedCode();

console.log(obfuscatedCode);
});

it('should add `control flow storage` node with multiple items to the obfuscated code', () => {
assert.match(obfuscatedCode, regexp);
});
});
});

describe('Variant #2 - negative cases', function () {
Expand Down Expand Up @@ -320,7 +357,7 @@ describe('StringArrayControlFlowTransformer', function () {
let obfuscatedCode: string;

before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/multiple-storages.js');
const code: string = readFileAsString(__dirname + '/fixtures/multiple-storages-2.js');

obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(function () {
var variable1 = 'foo' + 'bar';

function foo (arg) {
var variable2 = 'baz' + 'bark';
}
})();
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,33 @@ describe('MangledShuffledIdentifierNamesGenerator', () => {
assert.isTrue(isSuccessComparison);
});
});

describe('isValidIdentifierName', () => {
describe('Variant #1: reserved dom property name', () => {
let identifierNamesGenerator: IIdentifierNamesGenerator,
isValidName1: boolean,
isValidName2: boolean,
isValidName3: boolean;

beforeEach(() => {
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();

inversifyContainerFacade.load('', '', {} );
identifierNamesGenerator = inversifyContainerFacade.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.MangledShuffledIdentifierNamesGenerator
);

isValidName1 = identifierNamesGenerator.isValidIdentifierName('Set');
isValidName2 = identifierNamesGenerator.isValidIdentifierName('Array');
isValidName3 = identifierNamesGenerator.isValidIdentifierName('WeakSet');
});

it('should generate first identifier', () => {
assert.isFalse(isValidName1);
assert.isFalse(isValidName2);
assert.isTrue(isValidName3);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -312,5 +312,32 @@ describe('MangledIdentifierNamesGenerator', () => {
assert.equal(secondMangledIdentifierName, expectedSecondIdentifier);
});
});

describe('Variant #3: reserved dom property name', () => {
let identifierNamesGenerator: IIdentifierNamesGenerator,
isValidName1: boolean,
isValidName2: boolean,
isValidName3: boolean;

beforeEach(() => {
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();

inversifyContainerFacade.load('', '', {} );
identifierNamesGenerator = inversifyContainerFacade.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.MangledIdentifierNamesGenerator
);

isValidName1 = identifierNamesGenerator.isValidIdentifierName('Set');
isValidName2 = identifierNamesGenerator.isValidIdentifierName('Array');
isValidName3 = identifierNamesGenerator.isValidIdentifierName('WeakSet');
});

it('should generate first identifier', () => {
assert.isFalse(isValidName1);
assert.isFalse(isValidName2);
assert.isTrue(isValidName3);
});
});
});
});
0