mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
DictionaryIdentifierNamesGenerator refactoring
This commit is contained in:
Vendored
+15720
-1
File diff suppressed because one or more lines are too long
Vendored
+14993
-1
File diff suppressed because one or more lines are too long
@@ -261,7 +261,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
)
|
||||
.option(
|
||||
'--identifiers-dictionary <list> (comma separated, without whitespaces)',
|
||||
'Identifiers dictionary (comma separated)',
|
||||
'Identifiers dictionary (comma separated) for `--identifier-names-generator dictionary` option',
|
||||
ArraySanitizer
|
||||
)
|
||||
.option(
|
||||
|
||||
@@ -6,12 +6,17 @@ import { IOptions } from '../../../interfaces/options/IOptions';
|
||||
|
||||
import { IdentifierNamesGenerator } from '../../../enums/generators/identifier-names-generators/IdentifierNamesGenerator';
|
||||
|
||||
import { DictionaryIdentifierNamesGenerator } from '../../../generators/identifier-names-generators/DictionaryIdentifierNamesGenerator';
|
||||
import { HexadecimalIdentifierNamesGenerator } from '../../../generators/identifier-names-generators/HexadecimalIdentifierNamesGenerator';
|
||||
import { MangledIdentifierNamesGenerator } from '../../../generators/identifier-names-generators/MangledIdentifierNamesGenerator';
|
||||
import { DictionaryNamesGenerator } from '../../../generators/identifier-names-generators/DictionaryNamesGenerator';
|
||||
|
||||
export const generatorsModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
|
||||
// identifier name generators
|
||||
bind<IIdentifierNamesGenerator>(ServiceIdentifiers.IIdentifierNamesGenerator)
|
||||
.to(DictionaryIdentifierNamesGenerator)
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed(IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator);
|
||||
|
||||
bind<IIdentifierNamesGenerator>(ServiceIdentifiers.IIdentifierNamesGenerator)
|
||||
.to(HexadecimalIdentifierNamesGenerator)
|
||||
.inSingletonScope()
|
||||
@@ -22,11 +27,6 @@ export const generatorsModule: interfaces.ContainerModule = new ContainerModule(
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed(IdentifierNamesGenerator.MangledIdentifierNamesGenerator);
|
||||
|
||||
bind<IIdentifierNamesGenerator>(ServiceIdentifiers.IIdentifierNamesGenerator)
|
||||
.to(DictionaryNamesGenerator)
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed(IdentifierNamesGenerator.DictionaryNamesGenerator);
|
||||
|
||||
// identifier name generator factory
|
||||
bind<IIdentifierNamesGenerator>(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
|
||||
.toFactory<IIdentifierNamesGenerator>((context: interfaces.Context): (options: IOptions) => IIdentifierNamesGenerator => {
|
||||
@@ -40,6 +40,14 @@ export const generatorsModule: interfaces.ContainerModule = new ContainerModule(
|
||||
let identifierNamesGenerator: IIdentifierNamesGenerator;
|
||||
|
||||
switch (options.identifierNamesGenerator) {
|
||||
case IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator:
|
||||
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
|
||||
ServiceIdentifiers.IIdentifierNamesGenerator,
|
||||
IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case IdentifierNamesGenerator.MangledIdentifierNamesGenerator:
|
||||
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
|
||||
ServiceIdentifiers.IIdentifierNamesGenerator,
|
||||
@@ -47,14 +55,6 @@ export const generatorsModule: interfaces.ContainerModule = new ContainerModule(
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case IdentifierNamesGenerator.DictionaryNamesGenerator:
|
||||
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
|
||||
ServiceIdentifiers.IIdentifierNamesGenerator,
|
||||
IdentifierNamesGenerator.DictionaryNamesGenerator
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator:
|
||||
default:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export enum IdentifierNamesGenerator {
|
||||
DictionaryIdentifierNamesGenerator = 'dictionary',
|
||||
HexadecimalIdentifierNamesGenerator = 'hexadecimal',
|
||||
MangledIdentifierNamesGenerator = 'mangled',
|
||||
DictionaryNamesGenerator = 'dictionary'
|
||||
MangledIdentifierNamesGenerator = 'mangled'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
|
||||
|
||||
import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
|
||||
import { IOptions } from '../../interfaces/options/IOptions';
|
||||
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
|
||||
|
||||
import { AbstractIdentifierNamesGenerator } from './AbstractIdentifierNamesGenerator';
|
||||
|
||||
@injectable()
|
||||
export class DictionaryIdentifierNamesGenerator extends AbstractIdentifierNamesGenerator {
|
||||
/**
|
||||
* @type {IArrayUtils}
|
||||
*/
|
||||
private readonly arrayUtils: IArrayUtils;
|
||||
|
||||
/**
|
||||
* @type {string[]}
|
||||
*/
|
||||
private identifierNames: string[] = [];
|
||||
|
||||
/**
|
||||
* @type {IterableIterator<string>}
|
||||
*/
|
||||
private identifiersIterator: IterableIterator<string>;
|
||||
|
||||
/**
|
||||
* @param {IRandomGenerator} randomGenerator
|
||||
* @param {IOptions} options
|
||||
* @param {IArrayUtils} arrayUtils
|
||||
*/
|
||||
constructor (
|
||||
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
|
||||
@inject(ServiceIdentifiers.IOptions) options: IOptions,
|
||||
@inject(ServiceIdentifiers.IArrayUtils) arrayUtils: IArrayUtils,
|
||||
) {
|
||||
super(randomGenerator, options);
|
||||
|
||||
this.arrayUtils = arrayUtils;
|
||||
this.identifierNames = this.getInitialIdentifierNames(this.options.identifiersDictionary);
|
||||
this.identifiersIterator = this.identifierNames.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} identifierName
|
||||
* @returns {string | null}
|
||||
*/
|
||||
private static incrementIdentifierName (identifierName: string): string | null {
|
||||
let newIdentifierName: string = '';
|
||||
let isSuccess: boolean = false;
|
||||
|
||||
for (const character of identifierName) {
|
||||
if (!isSuccess && character === character.toUpperCase()) {
|
||||
newIdentifierName += character.toLowerCase();
|
||||
} else if (!isSuccess && character === character.toLowerCase()) {
|
||||
newIdentifierName += character.toUpperCase();
|
||||
isSuccess = true;
|
||||
} else {
|
||||
newIdentifierName += character;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSuccess) {
|
||||
return newIdentifierName;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public generate (): string {
|
||||
if (!this.identifierNames.length) {
|
||||
throw new Error('Too many identifiers in the code, add more words to identifiers dictionary');
|
||||
}
|
||||
|
||||
const iteratorResult: IteratorResult<string> = this.identifiersIterator.next();
|
||||
|
||||
if (!iteratorResult.done) {
|
||||
return iteratorResult.value;
|
||||
}
|
||||
|
||||
this.identifierNames = this.getIncrementedIdentifierNames(this.identifierNames);
|
||||
this.identifiersIterator = this.identifierNames.values();
|
||||
|
||||
return this.generate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
public generateWithPrefix (): string {
|
||||
const prefix: string = this.options.identifiersPrefix ?
|
||||
`${this.options.identifiersPrefix}_`
|
||||
: '';
|
||||
const identifierName: string = this.generate();
|
||||
|
||||
return `${prefix}${identifierName}`.replace('__', '_');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} identifierNames
|
||||
* @returns {string[]}
|
||||
*/
|
||||
private getInitialIdentifierNames (identifierNames: string[]): string[] {
|
||||
const formattedIdentifierNames: string[] = identifierNames
|
||||
.map((identifierName: string) => identifierName.toLowerCase());
|
||||
|
||||
return this.arrayUtils.shuffle(formattedIdentifierNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} identifierNames
|
||||
* @returns {string[]}
|
||||
*/
|
||||
private getIncrementedIdentifierNames (identifierNames: string[]): string[] {
|
||||
const formattedIdentifierNames: string[] = [];
|
||||
|
||||
for (const identifierName of identifierNames) {
|
||||
const newIdentifierName: string | null = DictionaryIdentifierNamesGenerator
|
||||
.incrementIdentifierName(identifierName);
|
||||
|
||||
if (newIdentifierName) {
|
||||
formattedIdentifierNames.push(newIdentifierName);
|
||||
}
|
||||
}
|
||||
|
||||
return this.arrayUtils.shuffle(formattedIdentifierNames);
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
|
||||
|
||||
import { IOptions } from '../../interfaces/options/IOptions';
|
||||
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
|
||||
|
||||
import { AbstractIdentifierNamesGenerator } from './AbstractIdentifierNamesGenerator';
|
||||
|
||||
@injectable()
|
||||
export class DictionaryNamesGenerator extends AbstractIdentifierNamesGenerator {
|
||||
/**
|
||||
* @type {string[]}
|
||||
*/
|
||||
private identifiers: string[] = [];
|
||||
|
||||
/**
|
||||
* @type {IterableIterator<string>}
|
||||
*/
|
||||
private it: IterableIterator<string>;
|
||||
|
||||
/**
|
||||
* @param {IRandomGenerator} randomGenerator
|
||||
* @param {IOptions} options
|
||||
*/
|
||||
constructor (
|
||||
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
|
||||
@inject(ServiceIdentifiers.IOptions) options: IOptions
|
||||
) {
|
||||
super(randomGenerator, options);
|
||||
for (const dict of options.identifiersDictionary) {
|
||||
this.identifiers[this.identifiers.length] = dict.toLowerCase();
|
||||
}
|
||||
this.shuffle(this.identifiers);
|
||||
this.it = this.identifiers.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {string | null}
|
||||
*/
|
||||
private static increment (str: string): string | null {
|
||||
let newString: string = "";
|
||||
let success: boolean = false;
|
||||
|
||||
for (const i of str) {
|
||||
if (!success && i === i.toUpperCase()) {
|
||||
newString += i.toLowerCase();
|
||||
} else if (!success && i === i.toLowerCase()) {
|
||||
newString += i.toUpperCase();
|
||||
success = true;
|
||||
} else {
|
||||
newString += i;
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
return newString;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} arr
|
||||
* @returns {string[]}
|
||||
*/
|
||||
private static incrementArr (arr: string[]): string[] {
|
||||
const newArr: string[] = [];
|
||||
for (const dict of arr) {
|
||||
const newDict: string | null = DictionaryNamesGenerator.increment(dict);
|
||||
if (newDict) {
|
||||
newArr[newArr.length] = newDict;
|
||||
}
|
||||
}
|
||||
|
||||
return newArr;
|
||||
}
|
||||
|
||||
public generate (): string {
|
||||
if (this.identifiers.length === 0) {
|
||||
throw new Error("identifiersDictionary is empty. Add more words to identifiersDictionary");
|
||||
}
|
||||
let itResult: IteratorResult<string> = this.it.next();
|
||||
if (itResult.done) {
|
||||
this.identifiers = DictionaryNamesGenerator.incrementArr(this.identifiers);
|
||||
this.shuffle(this.identifiers);
|
||||
this.it = this.identifiers.values();
|
||||
itResult = this.it.next();
|
||||
}
|
||||
if (itResult.done) {
|
||||
throw new Error("Too many identifiers in JS code, add more words to identifiersDictionary");
|
||||
}
|
||||
const identifierName: string = itResult.value;
|
||||
|
||||
return identifierName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
public generateWithPrefix (): string {
|
||||
const prefix: string = this.options.identifiersPrefix ?
|
||||
`${this.options.identifiersPrefix}_`
|
||||
: '';
|
||||
const identifierName: string = this.generate();
|
||||
|
||||
return `${prefix}${identifierName}`.replace('__', '_');;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} arr
|
||||
*/
|
||||
private shuffle (arr: string[]): void {
|
||||
for (let i: number = arr.length - 1; i > 0; i--) {
|
||||
const j: number = this.randomGenerator.getRandomInteger(0, i);
|
||||
[arr[i], arr[j]] = [arr[j], arr[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+1
-1
@@ -15,8 +15,8 @@ export interface IOptions {
|
||||
readonly disableConsoleOutput: boolean;
|
||||
readonly domainLock: string[];
|
||||
readonly identifierNamesGenerator: IdentifierNamesGenerator;
|
||||
readonly identifiersPrefix: string;
|
||||
readonly identifiersDictionary: string[];
|
||||
readonly identifiersPrefix: string;
|
||||
readonly inputFileName: string;
|
||||
readonly log: boolean;
|
||||
readonly renameGlobals: boolean;
|
||||
|
||||
@@ -2,6 +2,7 @@ import { inject, injectable } from 'inversify';
|
||||
import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
|
||||
|
||||
import {
|
||||
ArrayNotEmpty,
|
||||
ArrayUnique,
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
@@ -107,9 +108,9 @@ export class Options implements IOptions {
|
||||
* @type {IdentifierNamesGenerator}
|
||||
*/
|
||||
@IsIn([
|
||||
IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator,
|
||||
IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
|
||||
IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
|
||||
IdentifierNamesGenerator.DictionaryNamesGenerator
|
||||
IdentifierNamesGenerator.MangledIdentifierNamesGenerator
|
||||
])
|
||||
public readonly identifierNamesGenerator!: IdentifierNamesGenerator;
|
||||
|
||||
@@ -124,6 +125,10 @@ export class Options implements IOptions {
|
||||
@IsString({
|
||||
each: true
|
||||
})
|
||||
@ValidateIf((options: IOptions) =>
|
||||
options.identifierNamesGenerator === IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator
|
||||
)
|
||||
@ArrayNotEmpty()
|
||||
public readonly identifiersDictionary!: string[];
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,7 @@ export const DEFAULT_PRESET: TInputOptions = Object.freeze({
|
||||
exclude: [],
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
|
||||
identifiersPrefix: '',
|
||||
identifiersDictionary: ["qwertyuiop", "asdfghjkl", "zxcvbnm"],
|
||||
identifiersDictionary: [],
|
||||
inputFileName: '',
|
||||
log: false,
|
||||
renameGlobals: false,
|
||||
|
||||
@@ -17,7 +17,7 @@ export const NO_ADDITIONAL_NODES_PRESET: TInputOptions = Object.freeze({
|
||||
exclude: [],
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
|
||||
identifiersPrefix: '',
|
||||
identifiersDictionary: ["qwertyuiop", "asdfghjkl", "zxcvbnm"],
|
||||
identifiersDictionary: [],
|
||||
inputFileName: '',
|
||||
log: false,
|
||||
renameGlobals: false,
|
||||
|
||||
@@ -50,6 +50,10 @@ export class StringArrayStorage extends ArrayStorage <string> {
|
||||
public initialize (): void {
|
||||
super.initialize();
|
||||
|
||||
if (!this.options.stringArray) {
|
||||
return;
|
||||
}
|
||||
|
||||
const baseStringArrayName: string = this.identifierNamesGenerator
|
||||
.generate(StringArrayStorage.stringArrayNameLength);
|
||||
const baseStringArrayCallsWrapperName: string = this.identifierNamesGenerator
|
||||
|
||||
+5
-6
@@ -6,16 +6,15 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
|
||||
|
||||
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
var s = {
|
||||
'abcdefg': 'abcdefg'
|
||||
};
|
||||
var abc = 1;
|
||||
var cde = 1;
|
||||
var fg = 1;
|
||||
var sss = 1;
|
||||
`,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
compact: false,
|
||||
splitStrings: true,
|
||||
splitStringsChunkLength: 4,
|
||||
transformObjectKeys: true
|
||||
renameGlobals: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
|
||||
+2
-2
@@ -121,8 +121,8 @@ describe('ClassDeclarationTransformer', () => {
|
||||
});
|
||||
|
||||
describe('Variant #3: already renamed identifiers shouldn\'t be renamed twice', () => {
|
||||
const classDeclarationRegExp: RegExp = /class *d *{/;
|
||||
const variableDeclarationsRegExp: RegExp = /let *e, *f, *g, *h;/;
|
||||
const classDeclarationRegExp: RegExp = /class *b *{/;
|
||||
const variableDeclarationsRegExp: RegExp = /let *c, *d, *e, *f;/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
|
||||
+2
-2
@@ -145,8 +145,8 @@ describe('FunctionDeclarationTransformer', () => {
|
||||
|
||||
describe('Variant #5: already renamed identifiers shouldn\'t be renamed twice', () => {
|
||||
describe('Variant #1', () => {
|
||||
const functionDeclarationRegExp: RegExp = /function *d\(\) *{/;
|
||||
const variableDeclarationsRegExp: RegExp = /let *e, *f, *g, *h;/;
|
||||
const functionDeclarationRegExp: RegExp = /function *b\(\) *{/;
|
||||
const variableDeclarationsRegExp: RegExp = /let *c, *d, *e, *f;/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
|
||||
+9
-9
@@ -426,11 +426,11 @@ describe('VariableDeclarationTransformer', () => {
|
||||
|
||||
describe('Variant #13: already renamed identifiers shouldn\'t be renamed twice', () => {
|
||||
describe('Variant #1', () => {
|
||||
const variableDeclarationRegExp: RegExp = /var *d *= *0x1;/;
|
||||
const functionDeclarationRegExp1: RegExp = /function *e *\(\) *{}/;
|
||||
const functionDeclarationRegExp2: RegExp = /function *f *\(\) *{}/;
|
||||
const functionDeclarationRegExp3: RegExp = /function *g *\(\) *{}/;
|
||||
const functionDeclarationRegExp4: RegExp = /function *h *\(\) *{}/;
|
||||
const variableDeclarationRegExp: RegExp = /var *b *= *0x1;/;
|
||||
const functionDeclarationRegExp1: RegExp = /function *c *\(\) *{}/;
|
||||
const functionDeclarationRegExp2: RegExp = /function *d *\(\) *{}/;
|
||||
const functionDeclarationRegExp3: RegExp = /function *e *\(\) *{}/;
|
||||
const functionDeclarationRegExp4: RegExp = /function *f *\(\) *{}/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
@@ -468,10 +468,10 @@ describe('VariableDeclarationTransformer', () => {
|
||||
});
|
||||
|
||||
describe('Variant #2', () => {
|
||||
const variableDeclarationRegExp1: RegExp = /var *d *= *0x1;/;
|
||||
const variableDeclarationRegExp2: RegExp = /var *e;/;
|
||||
const functionDeclarationRegExp: RegExp = /function *f *\(\) *{/;
|
||||
const variableDeclarationRegExp3: RegExp = /var *f *= *function *\(\) *{}/;
|
||||
const variableDeclarationRegExp1: RegExp = /var *b *= *0x1;/;
|
||||
const variableDeclarationRegExp2: RegExp = /var *c;/;
|
||||
const functionDeclarationRegExp: RegExp = /function *d *\(\) *{/;
|
||||
const variableDeclarationRegExp3: RegExp = /var *d *= *function *\(\) *{}/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user