mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Merge pull request #532 from javascript-obfuscator/sanitize-of-class-scopes
Added class scope sanitizing
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
Change Log
|
||||
|
||||
v0.24.1
|
||||
---
|
||||
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/531
|
||||
|
||||
v0.24.0
|
||||
---
|
||||
* **Internal refactoring:** completely new mechanism to rename variable names
|
||||
|
||||
Vendored
+5
-5
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "javascript-obfuscator",
|
||||
"version": "0.24.0",
|
||||
"version": "0.24.1",
|
||||
"description": "JavaScript obfuscator",
|
||||
"keywords": [
|
||||
"obfuscator",
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import { inject, injectable, } from 'inversify';
|
||||
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
|
||||
import { injectable, } from 'inversify';
|
||||
|
||||
import * as eslintScope from 'eslint-scope';
|
||||
import * as estraverse from 'estraverse';
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { IOptions } from '../../interfaces/options/IOptions';
|
||||
import { IScopeAnalyzer } from '../../interfaces/analyzers/scope-analyzer/IScopeAnalyzer';
|
||||
|
||||
import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
|
||||
|
||||
import { ecmaVersion } from '../../constants/EcmaVersion';
|
||||
|
||||
import { NodeGuards } from '../../node/NodeGuards';
|
||||
@@ -37,25 +33,11 @@ export class ScopeAnalyzer implements IScopeAnalyzer {
|
||||
*/
|
||||
private static readonly emptyRangeValue: number = 0;
|
||||
|
||||
/**
|
||||
* @type {IOptions}
|
||||
*/
|
||||
private readonly options: IOptions;
|
||||
|
||||
/**
|
||||
* @type {eslintScope.ScopeManager | null}
|
||||
*/
|
||||
private scopeManager: eslintScope.ScopeManager | null = null;
|
||||
|
||||
/**
|
||||
* @param {IOptions} options
|
||||
*/
|
||||
constructor (
|
||||
@inject(ServiceIdentifiers.IOptions) options: IOptions
|
||||
) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* `eslint-scope` reads `ranges` property of a nodes
|
||||
* Should attach that property to the some custom nodes
|
||||
@@ -97,7 +79,6 @@ export class ScopeAnalyzer implements IScopeAnalyzer {
|
||||
try {
|
||||
this.scopeManager = eslintScope.analyze(astTree, {
|
||||
...ScopeAnalyzer.eslintScopeOptions,
|
||||
nodejsScope: this.options.target === ObfuscationTarget.Node,
|
||||
sourceType: ScopeAnalyzer.sourceTypes[i]
|
||||
});
|
||||
|
||||
@@ -132,6 +113,35 @@ export class ScopeAnalyzer implements IScopeAnalyzer {
|
||||
throw new Error('Cannot acquire scope for node');
|
||||
}
|
||||
|
||||
this.sanitizeScopes(scope);
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Scope} scope
|
||||
*/
|
||||
private sanitizeScopes (scope: eslintScope.Scope): void {
|
||||
scope.childScopes.forEach((childScope: eslintScope.Scope) => {
|
||||
// fix of class scopes
|
||||
// trying to move class scope references to the parent scope
|
||||
if (childScope.type === 'class' && childScope.upper) {
|
||||
const upperVariable: eslintScope.Variable | undefined = childScope.upper.variables
|
||||
.find((variable: eslintScope.Variable) => {
|
||||
// class name variable is always first
|
||||
const classNameVariable: eslintScope.Variable = childScope.variables[0];
|
||||
const isValidClassNameVariable: boolean = classNameVariable.defs
|
||||
.some((definition: eslintScope.Definition) => definition.type === 'ClassName');
|
||||
|
||||
return isValidClassNameVariable && variable.name === classNameVariable.name;
|
||||
});
|
||||
|
||||
upperVariable?.references.push(...childScope.variables[0].references);
|
||||
}
|
||||
});
|
||||
|
||||
for (const childScope of scope.childScopes) {
|
||||
this.sanitizeScopes(childScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-3
@@ -7,13 +7,33 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
|
||||
|
||||
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
var passthrough = value => value;
|
||||
var foo = 1, bar = {baz: passthrough(foo)}
|
||||
class A {
|
||||
foo() {
|
||||
return A;
|
||||
}
|
||||
|
||||
bar() {
|
||||
var A = 1;
|
||||
return A;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(A);
|
||||
|
||||
function foo () {
|
||||
class B {
|
||||
foo() {
|
||||
return B;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(B);
|
||||
}
|
||||
`,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
compact: false,
|
||||
transformObjectKeys: true
|
||||
target: 'node'
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
|
||||
+378
-16
@@ -1,12 +1,14 @@
|
||||
import { assert } from 'chai';
|
||||
|
||||
import { IdentifierNamesGenerator } from '../../../../../../src/enums/generators/identifier-names-generators/IdentifierNamesGenerator';
|
||||
import { ObfuscationTarget } from '../../../../../../src/enums/ObfuscationTarget';
|
||||
|
||||
import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
|
||||
|
||||
import { getRegExpMatch } from '../../../../../helpers/getRegExpMatch';
|
||||
import { readFileAsString } from '../../../../../helpers/readFileAsString';
|
||||
|
||||
import { JavaScriptObfuscator } from '../../../../../../src/JavaScriptObfuscatorFacade';
|
||||
import { IdentifierNamesGenerator } from '../../../../../../src/enums/generators/identifier-names-generators/IdentifierNamesGenerator';
|
||||
|
||||
describe('ScopeIdentifiersTransformer ClassDeclaration identifiers', () => {
|
||||
describe('transformation of `classDeclaration` node names', () => {
|
||||
@@ -38,28 +40,192 @@ describe('ScopeIdentifiersTransformer ClassDeclaration identifiers', () => {
|
||||
|
||||
describe('Variant #2: `classDeclaration` parent block scope is a `ProgramNode`', () => {
|
||||
describe('Variant #1: `renameGlobals` option is disabled', () => {
|
||||
const classNameIdentifierRegExp: RegExp = /class *Foo *\{/;
|
||||
const classCallIdentifierRegExp: RegExp = /new *Foo *\( *\);/;
|
||||
describe('Variant #1: base', () => {
|
||||
const classNameIdentifierRegExp: RegExp = /class *Foo *\{/;
|
||||
const classCallIdentifierRegExp: RegExp = /new *Foo *\( *\);/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/parent-block-scope-is-program-node.js');
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/parent-block-scope-is-program-node.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: shouldn\'t transform class name', () => {
|
||||
assert.match(obfuscatedCode, classNameIdentifierRegExp);
|
||||
});
|
||||
|
||||
it('match #2: shouldn\'t transform class name', () => {
|
||||
assert.match(obfuscatedCode, classCallIdentifierRegExp);
|
||||
});
|
||||
});
|
||||
|
||||
it('match #1: shouldn\'t transform class name', () => {
|
||||
assert.match(obfuscatedCode, classNameIdentifierRegExp);
|
||||
describe('Variant #2: target `browser', () => {
|
||||
describe('Variant #1: correct class name references in global scope', () => {
|
||||
const classNameIdentifierRegExp: RegExp = /class A *\{/;
|
||||
const outerClassNameReferenceRegExp: RegExp = /console\['log']\(A\);/;
|
||||
const innerClassNameReferenceRegExp: RegExp = /return A;/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-global-scope.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
target: ObfuscationTarget.Browser
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: shouldn\'t transform class name', () => {
|
||||
assert.match(obfuscatedCode, classNameIdentifierRegExp);
|
||||
});
|
||||
|
||||
it('match #2: shouldn\'t transform class name reference outside of class', () => {
|
||||
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #3: shouldn\'t transform class name reference inside class', () => {
|
||||
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: correct class name references in function scope', () => {
|
||||
const classNameIdentifierRegExp: RegExp = /class (_0x[a-f0-9]{4,6}) *\{/;
|
||||
const outerClassNameReferenceRegExp: RegExp = /console\['log']\((_0x[a-f0-9]{4,6})\);/;
|
||||
const innerClassNameReferenceRegExp: RegExp = /return (_0x[a-f0-9]{4,6});/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
let classNameIdentifier: string;
|
||||
let outerClassNameReferenceIdentifierName: string;
|
||||
let innerClassNameReferenceIdentifierName: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-function-scope.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
target: ObfuscationTarget.Browser
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
classNameIdentifier = getRegExpMatch(obfuscatedCode, classNameIdentifierRegExp);
|
||||
outerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
innerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #1: should transform class name', () => {
|
||||
assert.match(obfuscatedCode, classNameIdentifierRegExp);
|
||||
});
|
||||
|
||||
it('match #2: should transform class name reference outside of class', () => {
|
||||
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #3: should transform class name reference inside class', () => {
|
||||
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #4: should generate same identifier names for class name and outer class name reference', () => {
|
||||
assert.equal(classNameIdentifier, outerClassNameReferenceIdentifierName);
|
||||
});
|
||||
|
||||
it('match #5: should generate same identifier names for class name and inner class name reference', () => {
|
||||
assert.equal(classNameIdentifier, innerClassNameReferenceIdentifierName);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('match #2: shouldn\'t transform class name', () => {
|
||||
assert.match(obfuscatedCode, classCallIdentifierRegExp);
|
||||
describe('Variant #3: target `node', () => {
|
||||
describe('Variant #1: correct class name references in global scope', () => {
|
||||
const classNameIdentifierRegExp: RegExp = /class A *\{/;
|
||||
const outerClassNameReferenceRegExp: RegExp = /console\['log']\(A\);/;
|
||||
const innerClassNameReferenceRegExp: RegExp = /return A;/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-global-scope.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
target: ObfuscationTarget.Node
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: shouldn\'t transform class name', () => {
|
||||
assert.match(obfuscatedCode, classNameIdentifierRegExp);
|
||||
});
|
||||
|
||||
it('match #2: shouldn\'t transform class name reference outside of class', () => {
|
||||
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #3: shouldn\'t transform class name reference inside class', () => {
|
||||
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: correct class name references in function scope', () => {
|
||||
const classNameIdentifierRegExp: RegExp = /class (_0x[a-f0-9]{4,6}) *\{/;
|
||||
const outerClassNameReferenceRegExp: RegExp = /console\['log']\((_0x[a-f0-9]{4,6})\);/;
|
||||
const innerClassNameReferenceRegExp: RegExp = /return (_0x[a-f0-9]{4,6});/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
let classNameIdentifier: string;
|
||||
let outerClassNameReferenceIdentifierName: string;
|
||||
let innerClassNameReferenceIdentifierName: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-function-scope.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
target: ObfuscationTarget.Node
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
classNameIdentifier = getRegExpMatch(obfuscatedCode, classNameIdentifierRegExp);
|
||||
outerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
innerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #1: should transform class name', () => {
|
||||
assert.match(obfuscatedCode, classNameIdentifierRegExp);
|
||||
});
|
||||
|
||||
it('match #2: should transform class name reference outside of class', () => {
|
||||
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #3: should transform class name reference inside class', () => {
|
||||
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #4: should generate same identifier names for class name and outer class name reference', () => {
|
||||
assert.equal(classNameIdentifier, outerClassNameReferenceIdentifierName);
|
||||
});
|
||||
|
||||
it('match #5: should generate same identifier names for class name and inner class name reference', () => {
|
||||
assert.equal(classNameIdentifier, innerClassNameReferenceIdentifierName);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -117,6 +283,202 @@ describe('ScopeIdentifiersTransformer ClassDeclaration identifiers', () => {
|
||||
assert.match(obfuscatedCode, identifierRegExp2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: target: `browser', () => {
|
||||
describe('Variant #1: correct class name references in global scope', () => {
|
||||
const classNameIdentifierRegExp: RegExp = /class (_0x[a-f0-9]{4,6}) *\{/;
|
||||
const outerClassNameReferenceRegExp: RegExp = /console\['log']\((_0x[a-f0-9]{4,6})\);/;
|
||||
const innerClassNameReferenceRegExp: RegExp = /return (_0x[a-f0-9]{4,6});/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
let classNameIdentifier: string;
|
||||
let outerClassNameReferenceIdentifierName: string;
|
||||
let innerClassNameReferenceIdentifierName: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-global-scope.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
renameGlobals: true,
|
||||
target: ObfuscationTarget.Browser
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
classNameIdentifier = getRegExpMatch(obfuscatedCode, classNameIdentifierRegExp);
|
||||
outerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
innerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #1: should transform class name', () => {
|
||||
assert.match(obfuscatedCode, classNameIdentifierRegExp);
|
||||
});
|
||||
|
||||
it('match #2: should transform class name reference outside of class', () => {
|
||||
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #3: should transform class name reference inside class', () => {
|
||||
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #4: should generate same identifier names for class name and outer class name reference', () => {
|
||||
assert.equal(classNameIdentifier, outerClassNameReferenceIdentifierName);
|
||||
});
|
||||
|
||||
it('match #5: should generate same identifier names for class name and inner class name reference', () => {
|
||||
assert.equal(classNameIdentifier, innerClassNameReferenceIdentifierName);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: correct class name references in function scope', () => {
|
||||
const classNameIdentifierRegExp: RegExp = /class (_0x[a-f0-9]{4,6}) *\{/;
|
||||
const outerClassNameReferenceRegExp: RegExp = /console\['log']\((_0x[a-f0-9]{4,6})\);/;
|
||||
const innerClassNameReferenceRegExp: RegExp = /return (_0x[a-f0-9]{4,6});/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
let classNameIdentifier: string;
|
||||
let outerClassNameReferenceIdentifierName: string;
|
||||
let innerClassNameReferenceIdentifierName: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-function-scope.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
renameGlobals: true,
|
||||
target: ObfuscationTarget.Browser
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
classNameIdentifier = getRegExpMatch(obfuscatedCode, classNameIdentifierRegExp);
|
||||
outerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
innerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #1: should transform class name', () => {
|
||||
assert.match(obfuscatedCode, classNameIdentifierRegExp);
|
||||
});
|
||||
|
||||
it('match #2: should transform class name reference outside of class', () => {
|
||||
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #3: should transform class name reference inside class', () => {
|
||||
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #4: should generate same identifier names for class name and outer class name reference', () => {
|
||||
assert.equal(classNameIdentifier, outerClassNameReferenceIdentifierName);
|
||||
});
|
||||
|
||||
it('match #5: should generate same identifier names for class name and inner class name reference', () => {
|
||||
assert.equal(classNameIdentifier, innerClassNameReferenceIdentifierName);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: target: `node', () => {
|
||||
describe('Variant #1: correct class name references in global scope', () => {
|
||||
const classNameIdentifierRegExp: RegExp = /class (_0x[a-f0-9]{4,6}) *\{/;
|
||||
const outerClassNameReferenceRegExp: RegExp = /console\['log']\((_0x[a-f0-9]{4,6})\);/;
|
||||
const innerClassNameReferenceRegExp: RegExp = /return (_0x[a-f0-9]{4,6});/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
let classNameIdentifier: string;
|
||||
let outerClassNameReferenceIdentifierName: string;
|
||||
let innerClassNameReferenceIdentifierName: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-global-scope.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
renameGlobals: true,
|
||||
target: ObfuscationTarget.Node
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
classNameIdentifier = getRegExpMatch(obfuscatedCode, classNameIdentifierRegExp);
|
||||
outerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
innerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #1: should transform class name', () => {
|
||||
assert.match(obfuscatedCode, classNameIdentifierRegExp);
|
||||
});
|
||||
|
||||
it('match #2: should transform class name reference outside of class', () => {
|
||||
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #3: should transform class name reference inside class', () => {
|
||||
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #4: should generate same identifier names for class name and outer class name reference', () => {
|
||||
assert.equal(classNameIdentifier, outerClassNameReferenceIdentifierName);
|
||||
});
|
||||
|
||||
it('match #5: should generate same identifier names for class name and inner class name reference', () => {
|
||||
assert.equal(classNameIdentifier, innerClassNameReferenceIdentifierName);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: correct class name references in function scope', () => {
|
||||
const classNameIdentifierRegExp: RegExp = /class (_0x[a-f0-9]{4,6}) *\{/;
|
||||
const outerClassNameReferenceRegExp: RegExp = /console\['log']\((_0x[a-f0-9]{4,6})\);/;
|
||||
const innerClassNameReferenceRegExp: RegExp = /return (_0x[a-f0-9]{4,6});/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
let classNameIdentifier: string;
|
||||
let outerClassNameReferenceIdentifierName: string;
|
||||
let innerClassNameReferenceIdentifierName: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-function-scope.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
renameGlobals: true,
|
||||
target: ObfuscationTarget.Node
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
classNameIdentifier = getRegExpMatch(obfuscatedCode, classNameIdentifierRegExp);
|
||||
outerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
innerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #1: should transform class name', () => {
|
||||
assert.match(obfuscatedCode, classNameIdentifierRegExp);
|
||||
});
|
||||
|
||||
it('match #2: should transform class name reference outside of class', () => {
|
||||
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #3: should transform class name reference inside class', () => {
|
||||
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
|
||||
});
|
||||
|
||||
it('match #4: should generate same identifier names for class name and outer class name reference', () => {
|
||||
assert.equal(classNameIdentifier, outerClassNameReferenceIdentifierName);
|
||||
});
|
||||
|
||||
it('match #5: should generate same identifier names for class name and inner class name reference', () => {
|
||||
assert.equal(classNameIdentifier, innerClassNameReferenceIdentifierName);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
function foo () {
|
||||
class B {
|
||||
foo() {
|
||||
return B;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(B);
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class A {
|
||||
foo() {
|
||||
return A;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(A);
|
||||
Reference in New Issue
Block a user