shuffleStringArray option

This commit is contained in:
sanex3339
2020-01-12 19:55:41 +03:00
parent b764844696
commit 1edf96c0a0
28 changed files with 392 additions and 88 deletions
+2
View File
@@ -2,7 +2,9 @@ Change Log
v0.23.0
---
* **New option:** `shuffleStringArray` randomly shuffles string array items
* **Internal change:** switched AST parser from `espree` on `acorn`
* **Internal refactoring:** refactoring of string array storage and related things
v0.22.1
---
+12
View File
@@ -306,6 +306,7 @@ Following options are available for the JS Obfuscator:
rotateStringArray: true,
seed: 0,
selfDefending: false,
shuffleStringArray: true,
sourceMap: false,
sourceMapBaseUrl: '',
sourceMapFileName: '',
@@ -349,6 +350,7 @@ Following options are available for the JS Obfuscator:
--rotate-string-array <boolean>
--seed <string|number>
--self-defending <boolean>
--shuffle-string-array <boolean>
--source-map <boolean>
--source-map-base-url <string>
--source-map-file-name <string>
@@ -691,6 +693,13 @@ Type: `boolean` Default: `false`
This option makes the output code resilient against formatting and variable renaming. If one tries to use a JavaScript beautifier on the obfuscated code, the code won't work anymore, making it harder to understand and modify it.
### `shuffleStringArray`
Type: `boolean` Default: `true`
##### :warning: [`stringArray`](#stringarray) must be enabled
Randomly shuffles the `stringArray` array items.
### `sourceMap`
Type: `boolean` Default: `false`
@@ -867,6 +876,7 @@ Performance will 50-100% slower than without obfuscation
renameGlobals: false,
rotateStringArray: true,
selfDefending: true,
shuffleStringArray: true,
splitStrings: true,
splitStringsChunkLength: '5',
stringArray: true,
@@ -896,6 +906,7 @@ Performance will 30-35% slower than without obfuscation
renameGlobals: false,
rotateStringArray: true,
selfDefending: true,
shuffleStringArray: true,
splitStrings: true,
splitStringsChunkLength: '10',
stringArray: true,
@@ -923,6 +934,7 @@ Performance will slightly slower than without obfuscation
renameGlobals: false,
rotateStringArray: true,
selfDefending: true,
shuffleStringArray: true,
splitStrings: false,
stringArray: true,
stringArrayEncoding: false,
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
@@ -4,10 +4,9 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { TStringArrayStorage } from '../../types/storages/TStringArrayStorage';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IStringArrayStorage } from '../../interfaces/storages/string-array-storage/IStringArrayStorage';
import { IStringArrayStorageAnalyzer } from '../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
@@ -35,9 +34,9 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
private readonly randomGenerator: IRandomGenerator;
/**
* @type {TStringArrayStorage}
* @type {IStringArrayStorage}
*/
private readonly stringArrayStorage: TStringArrayStorage;
private readonly stringArrayStorage: IStringArrayStorage;
/**
* @type {Map<ESTree.Literal, IStringArrayStorageItemData>}
@@ -45,12 +44,12 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
private readonly stringArrayStorageData: Map<ESTree.Literal, IStringArrayStorageItemData> = new Map();
/**
* @param {TStringArrayStorage} stringArrayStorage
* @param {IStringArrayStorage} stringArrayStorage
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
*/
constructor (
@inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: TStringArrayStorage,
@inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStringArrayStorage,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions,
) {
+5 -1
View File
@@ -283,7 +283,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
BooleanSanitizer
)
.option(
'--rotate-string-array <boolean>', 'Disable rotation of unicode array values during obfuscation',
'--rotate-string-array <boolean>', 'Enable rotation of string array values during obfuscation',
BooleanSanitizer
)
.option(
@@ -296,6 +296,10 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
'Disables self-defending for obfuscated code',
BooleanSanitizer
)
.option(
'--shuffle-string-array <boolean>', 'Randomly shuffles string array items',
BooleanSanitizer
)
.option(
'--source-map <boolean>',
'Enables source map generation',
@@ -3,10 +3,10 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
import { TCustomNodeGroupStorage } from '../../../types/storages/TCustomNodeGroupStorage';
import { TStringArrayStorage } from '../../../types/storages/TStringArrayStorage';
import { IOptions } from '../../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
import { IStringArrayStorage } from '../../../interfaces/storages/string-array-storage/IStringArrayStorage';
import { ControlFlowStorage } from '../../../storages/control-flow/ControlFlowStorage';
import { CustomNodeGroupStorage } from '../../../storages/custom-node-group/CustomNodeGroupStorage';
@@ -18,7 +18,7 @@ export const storagesModule: interfaces.ContainerModule = new ContainerModule((b
.to(CustomNodeGroupStorage)
.inSingletonScope();
bind<TStringArrayStorage>(ServiceIdentifiers.TStringArrayStorage)
bind<IStringArrayStorage>(ServiceIdentifiers.TStringArrayStorage)
.to(StringArrayStorage)
.inSingletonScope();
@@ -3,11 +3,11 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
import { TStatement } from '../../types/node/TStatement';
import { TStringArrayStorage } from '../../types/storages/TStringArrayStorage';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
import { IStringArrayStorage } from '../../interfaces/storages/string-array-storage/IStringArrayStorage';
import { initializable } from '../../decorators/Initializable';
@@ -15,15 +15,14 @@ import { StringArrayTemplate } from '../../templates/string-array-nodes/string-a
import { AbstractCustomNode } from '../AbstractCustomNode';
import { NodeUtils } from '../../node/NodeUtils';
import { StringArrayStorage } from '../../storages/string-array/StringArrayStorage';
@injectable()
export class StringArrayNode extends AbstractCustomNode {
/**
* @type {TStringArrayStorage}
* @type {IStringArrayStorage}
*/
@initializable()
private stringArrayStorage!: TStringArrayStorage;
private stringArrayStorage!: IStringArrayStorage;
/**
* @type {string}
@@ -31,12 +30,6 @@ export class StringArrayNode extends AbstractCustomNode {
@initializable()
private stringArrayName!: string;
/**
* @type {number}
*/
@initializable()
private stringArrayRotateValue!: number;
/**
* @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
* @param {ICustomNodeFormatter} customNodeFormatter
@@ -54,27 +47,15 @@ export class StringArrayNode extends AbstractCustomNode {
}
/**
* @param {TStringArrayStorage} stringArrayStorage
* @param {IStringArrayStorage} stringArrayStorage
* @param {string} stringArrayName
* @param {number} stringArrayRotateValue
*/
public initialize (
stringArrayStorage: TStringArrayStorage,
stringArrayName: string,
stringArrayRotateValue: number
stringArrayStorage: IStringArrayStorage,
stringArrayName: string
): void {
this.stringArrayStorage = stringArrayStorage;
this.stringArrayName = stringArrayName;
this.stringArrayRotateValue = stringArrayRotateValue;
}
/**
* @returns {TStatement[]}
*/
public getNode (): TStatement[] {
(<StringArrayStorage>this.stringArrayStorage).rotateStorage(this.stringArrayRotateValue);
return super.getNode();
}
/**
@@ -38,7 +38,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
* @param {number}
*/
@initializable()
private stringArrayRotateValue!: number;
private stringArrayRotationAmount!: number;
/**
* @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
@@ -62,14 +62,14 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
/**
* @param {string} stringArrayName
* @param {number} stringArrayRotateValue
* @param {number} stringArrayRotationAmount
*/
public initialize (
stringArrayName: string,
stringArrayRotateValue: number
stringArrayRotationAmount: number
): void {
this.stringArrayName = stringArrayName;
this.stringArrayRotateValue = stringArrayRotateValue;
this.stringArrayRotationAmount = stringArrayRotationAmount;
}
/**
@@ -103,7 +103,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
code,
timesName,
stringArrayName: this.stringArrayName,
stringArrayRotateValue: NumberUtils.toHex(this.stringArrayRotateValue),
stringArrayRotationAmount: NumberUtils.toHex(this.stringArrayRotationAmount),
whileFunctionName
}),
{
@@ -5,12 +5,12 @@ import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCusto
import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
import { TInitialData } from '../../../types/TInitialData';
import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
import { TStringArrayStorage } from '../../../types/storages/TStringArrayStorage';
import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
import { IStringArrayStorage } from '../../../interfaces/storages/string-array-storage/IStringArrayStorage';
import { initializable } from '../../../decorators/Initializable';
@@ -42,20 +42,20 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
private readonly customNodeFactory: TCustomNodeFactory;
/**
* @type {TStringArrayStorage}
* @type {IStringArrayStorage}
*/
private readonly stringArrayStorage: TStringArrayStorage;
private readonly stringArrayStorage: IStringArrayStorage;
/**
* @param {TCustomNodeFactory} customNodeFactory
* @param {TStringArrayStorage} stringArrayStorage
* @param {IStringArrayStorage} stringArrayStorage
* @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
*/
constructor (
@inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
@inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: TStringArrayStorage,
@inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStringArrayStorage,
@inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@@ -106,21 +106,13 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
const stringArrayRotateFunctionNode: ICustomNode<TInitialData<StringArrayRotateFunctionNode>> =
this.customNodeFactory(CustomNode.StringArrayRotateFunctionNode);
const stringArrayStorageId: string = this.stringArrayStorage.getStorageId();
const stringArrayName: string = this.stringArrayStorage.getStorageName();
const stringArrayCallsWrapperName: string = this.stringArrayStorage.getStorageCallsWrapperName();
const stringArrayRotationAmount: number = this.stringArrayStorage.getRotationAmount();
const [stringArrayName, stringArrayCallsWrapperName]: string[] = stringArrayStorageId.split('|');
let stringArrayRotateValue: number;
if (this.options.rotateStringArray) {
stringArrayRotateValue = this.randomGenerator.getRandomInteger(100, 500);
} else {
stringArrayRotateValue = 0;
}
stringArrayNode.initialize(this.stringArrayStorage, stringArrayName, stringArrayRotateValue);
stringArrayNode.initialize(this.stringArrayStorage, stringArrayName);
stringArrayCallsWrapper.initialize(stringArrayName, stringArrayCallsWrapperName);
stringArrayRotateFunctionNode.initialize(stringArrayName, stringArrayRotateValue);
stringArrayRotateFunctionNode.initialize(stringArrayName, stringArrayRotationAmount);
this.customNodes.set(CustomNode.StringArrayNode, stringArrayNode);
this.customNodes.set(CustomNode.StringArrayCallsWrapper, stringArrayCallsWrapper);
+1
View File
@@ -27,6 +27,7 @@ export interface IOptions {
readonly rotateStringArray: boolean;
readonly seed: string | number;
readonly selfDefending: boolean;
readonly shuffleStringArray: boolean;
readonly sourceMap: boolean;
readonly sourceMapBaseUrl: string;
readonly sourceMapFileName: string;
@@ -0,0 +1,24 @@
import { IStringArrayStorageItemData } from './IStringArrayStorageItem';
import { IMapStorage } from '../IMapStorage';
export interface IStringArrayStorage extends IMapStorage <string, IStringArrayStorageItemData> {
/**
* @returns {number}
*/
getRotationAmount (): number;
/**
* @returns {string}
*/
getStorageName (): string;
/**
* @returns {string}
*/
getStorageCallsWrapperName (): string;
rotateStorage (): void;
shuffleStorage (): void;
}
@@ -1,15 +1,17 @@
import { inject, injectable, } from 'inversify';
import { inject, injectable, postConstruct } from 'inversify';
import { ServiceIdentifiers } from '../../../../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { TStringArrayStorage } from '../../../../types/storages/TStringArrayStorage';
import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
import { IInitializable } from '../../../../interfaces/IInitializable';
import { IOptions } from '../../../../interfaces/options/IOptions';
import { IStringArrayStorage } from '../../../../interfaces/storages/string-array-storage/IStringArrayStorage';
import { IStringArrayStorageAnalyzer } from '../../../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
import { IStringArrayStorageItemData } from '../../../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
import { initializable } from '../../../../decorators/Initializable';
import { StringArrayEncoding } from '../../../../enums/StringArrayEncoding';
import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
@@ -19,7 +21,7 @@ import { NumberUtils } from '../../../../utils/NumberUtils';
import { Utils } from '../../../../utils/Utils';
@injectable()
export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplacer {
export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplacer implements IInitializable {
/**
* @type {IEscapeSequenceEncoder}
*/
@@ -30,6 +32,11 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
*/
private readonly nodesCache: Map <string, ESTree.Node> = new Map();
/**
* @type {IStringArrayStorage}
*/
private readonly stringArrayStorage: IStringArrayStorage;
/**
* @type {IStringArrayStorageAnalyzer}
*/
@@ -38,26 +45,26 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
/**
* @type {string}
*/
private readonly stringArrayStorageCallsWrapperName: string;
@initializable()
private stringArrayStorageCallsWrapperName!: string;
/**
* @param {TStringArrayStorage} stringArrayStorage
* @param {IStringArrayStorage} stringArrayStorage
* @param {IStringArrayStorageAnalyzer} stringArrayStorageAnalyzer
* @param {IEscapeSequenceEncoder} escapeSequenceEncoder
* @param {IOptions} options
*/
constructor (
@inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: TStringArrayStorage,
@inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStringArrayStorage,
@inject(ServiceIdentifiers.IStringArrayStorageAnalyzer) stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer,
@inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(options);
this.stringArrayStorage = stringArrayStorage;
this.stringArrayStorageAnalyzer = stringArrayStorageAnalyzer;
this.escapeSequenceEncoder = escapeSequenceEncoder;
this.stringArrayStorageCallsWrapperName = stringArrayStorage.getStorageId().split('|')[1];
}
/**
@@ -84,6 +91,19 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
return rc4KeyLiteralNode;
}
@postConstruct()
public initialize (): void {
this.stringArrayStorageCallsWrapperName = this.stringArrayStorage.getStorageCallsWrapperName();
if (this.options.shuffleStringArray) {
this.stringArrayStorage.shuffleStorage();
}
if (this.options.rotateStringArray) {
this.stringArrayStorage.rotateStorage();
}
}
/**
* @param {SimpleLiteral} literalNode
* @returns {Node}
+6
View File
@@ -188,6 +188,12 @@ export class Options implements IOptions {
@IsBoolean()
public readonly selfDefending!: boolean;
/**
* @type {boolean}
*/
@IsBoolean()
public readonly shuffleStringArray!: boolean;
/**
* @type {boolean}
*/
@@ -11,6 +11,7 @@ export const StringArrayRule: TOptionsNormalizerRule = (options: IOptions): IOpt
options = {
...options,
rotateStringArray: false,
shuffleStringArray: false,
stringArray: false,
stringArrayEncoding: false,
stringArrayThreshold: 0
+1
View File
@@ -27,6 +27,7 @@ export const DEFAULT_PRESET: TInputOptions = Object.freeze({
rotateStringArray: true,
seed: 0,
selfDefending: false,
shuffleStringArray: true,
sourceMap: false,
sourceMapBaseUrl: '',
sourceMapFileName: '',
+1
View File
@@ -26,6 +26,7 @@ export const NO_ADDITIONAL_NODES_PRESET: TInputOptions = Object.freeze({
rotateStringArray: false,
seed: 0,
selfDefending: false,
shuffleStringArray: false,
sourceMap: false,
sourceMapBaseUrl: '',
sourceMapFileName: '',
@@ -10,14 +10,17 @@ import { IEncodedValue } from '../../interfaces/IEncodedValue';
import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IStringArrayStorage } from '../../interfaces/storages/string-array-storage/IStringArrayStorage';
import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
import { initializable } from '../../decorators/Initializable';
import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
import { MapStorage } from '../MapStorage';
@injectable()
export class StringArrayStorage extends MapStorage <string, IStringArrayStorageItemData> {
export class StringArrayStorage extends MapStorage <string, IStringArrayStorageItemData> implements IStringArrayStorage {
/**
* @type {number}
*/
@@ -58,6 +61,23 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
*/
private readonly rc4Keys: string[];
/**
* @type {number}
*/
private rotationAmount: number = 0;
/**
* @type {string}
*/
@initializable()
private stringArrayStorageName!: string;
/**
* @type {string}
*/
@initializable()
private stringArrayStorageCallsWrapperName!: string;
/**
* @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
* @param {IArrayUtils} arrayUtils
@@ -99,10 +119,13 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
.generate(StringArrayStorage.stringArrayNameLength);
const baseStringArrayCallsWrapperName: string = this.identifierNamesGenerator
.generate(StringArrayStorage.stringArrayNameLength);
const stringArrayName: string = `${this.options.identifiersPrefix}${baseStringArrayName}`;
const stringArrayCallsWrapperName: string = `${this.options.identifiersPrefix}${baseStringArrayCallsWrapperName}`;
this.storageId = `${stringArrayName}|${stringArrayCallsWrapperName}`;
this.stringArrayStorageName = `${this.options.identifiersPrefix}${baseStringArrayName}`;
this.stringArrayStorageCallsWrapperName = `${this.options.identifiersPrefix}${baseStringArrayCallsWrapperName}`;
this.rotationAmount = this.options.rotateStringArray
? this.randomGenerator.getRandomInteger(100, 500)
: 0;
}
/**
@@ -114,26 +137,76 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
}
/**
* @param {number} rotationAmount
* @returns {number}
*/
public rotateStorage (rotationAmount: number): void {
public getRotationAmount (): number {
return this.rotationAmount;
}
/**
* @returns {string}
*/
public getStorageId (): string {
return this.stringArrayStorageName;
}
/**
* @returns {string}
*/
public getStorageName (): string {
return this.getStorageId();
}
/**
* @returns {string}
*/
public getStorageCallsWrapperName (): string {
return this.stringArrayStorageCallsWrapperName;
}
public rotateStorage (): void {
if (!this.getLength()) {
return;
}
this.storage = new Map(
this.arrayUtils.rotate(
Array.from(this.storage.entries()),
rotationAmount
this.rotationAmount
)
);
}
public shuffleStorage (): void {
this.storage = new Map(
this.arrayUtils
.shuffle(Array.from(this.storage.entries()))
.map<[string, IStringArrayStorageItemData]>(
(
[value, stringArrayStorageItemData]: [string, IStringArrayStorageItemData],
index: number
) => {
stringArrayStorageItemData.index = index;
return [value, stringArrayStorageItemData];
}
)
.sort((
[, stringArrayStorageItemDataA]: [string, IStringArrayStorageItemData],
[, stringArrayStorageItemDataB]: [string, IStringArrayStorageItemData]
) => stringArrayStorageItemDataA.index - stringArrayStorageItemDataB.index)
);
}
/**
* @returns {string}
*/
public toString (): string {
return Array
.from(this.storage.values())
.map((item: IStringArrayStorageItemData) => {
.map((stringArrayStorageItemData: IStringArrayStorageItemData) => {
return `'${this.escapeSequenceEncoder.encode(
item.encodedValue,
stringArrayStorageItemData.encodedValue,
this.options.unicodeEscapeSequence
)}'`;
}).toString();
@@ -11,6 +11,6 @@ export function StringArrayRotateFunctionTemplate (): string {
};
{code}
})({stringArrayName}, 0x{stringArrayRotateValue});
})({stringArrayName}, 0x{stringArrayRotationAmount});
`;
}
-5
View File
@@ -1,5 +0,0 @@
import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
import { IMapStorage } from '../../interfaces/storages/IMapStorage';
export type TStringArrayStorage = IMapStorage <string, IStringArrayStorageItemData>;
+5 -1
View File
@@ -11,11 +11,15 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
var bar = 'bar';
var baz = 'baz';
var bark = 'bark';
console.log(foo, bar, baz, bark);
`,
{
...NO_ADDITIONAL_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1
stringArrayThreshold: 1,
rotateStringArray: true,
shuffleStringArray: true
}
).getObfuscatedCode();
@@ -1,6 +1,8 @@
import { assert } from 'chai';
import { TypeFromEnum } from '@gradecam/tsenum';
import { TInputOptions } from '../../../src/types/options/TInputOptions';
import { IObfuscatedCode } from '../../../src/interfaces/source-code/IObfuscatedCode';
import { SourceMapMode } from '../../../src/enums/source-map/SourceMapMode';
@@ -15,7 +17,6 @@ import { IdentifierNamesGenerator } from '../../../src/enums/generators/identifi
import { buildLargeCode } from '../../helpers/buildLargeCode';
import { getRegExpMatch } from '../../helpers/getRegExpMatch';
import { readFileAsString } from '../../helpers/readFileAsString';
import { TInputOptions } from '../../../src/types/options/TInputOptions';
describe('JavaScriptObfuscator', () => {
describe('obfuscate', () => {
@@ -541,6 +541,7 @@ describe('OptionsNormalizer', () => {
before(() => {
optionsPreset = getNormalizedOptions({
...getDefaultOptions(),
shuffleStringArray: true,
stringArray: false,
stringArrayEncoding: StringArrayEncoding.Rc4,
stringArrayThreshold: 0.5,
@@ -549,6 +550,7 @@ describe('OptionsNormalizer', () => {
expectedOptionsPreset = {
...getDefaultOptions(),
shuffleStringArray: false,
stringArray: false,
stringArrayEncoding: false,
stringArrayThreshold: 0,
@@ -584,6 +586,7 @@ describe('OptionsNormalizer', () => {
optionsPreset = getNormalizedOptions({
...getDefaultOptions(),
rotateStringArray: true,
shuffleStringArray: true,
stringArray: true,
stringArrayThreshold: 0
});
@@ -591,6 +594,7 @@ describe('OptionsNormalizer', () => {
expectedOptionsPreset = {
...getDefaultOptions(),
rotateStringArray: false,
shuffleStringArray: false,
stringArray: false,
stringArrayThreshold: 0
};
+3
View File
@@ -29,6 +29,9 @@ import './unit-tests/node/node-lexical-scope-utils/NodeLexicalScopeUtils.spec';
import './unit-tests/node/node-statement-utils/NodeStatementUtils.spec';
import './unit-tests/node/node-utils/NodeUtils.spec';
import './unit-tests/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.spec';
import './unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/BooleanLiteralObfuscatingReplacer.spec';
import './unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/NumberLiteralObfuscatingReplacer.spec';
import './unit-tests/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/StringLiteralObfuscatingReplacer.spec';
import './unit-tests/options/ValidationErrorsFormatter.spec';
import './unit-tests/source-code/ObfuscatedCode.spec';
import './unit-tests/storages/ArrayStorage.spec';
@@ -0,0 +1,60 @@
import 'reflect-metadata';
import { assert } from 'chai';
import * as ESTree from 'estree';
import { IInversifyContainerFacade } from '../../../../../../src/interfaces/container/IInversifyContainerFacade';
import { IObfuscatingReplacer } from '../../../../../../src/interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IObfuscatingReplacer';
import { LiteralObfuscatingReplacer } from '../../../../../../src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/LiteralObfuscatingReplacer';
import { ServiceIdentifiers } from '../../../../../../src/container/ServiceIdentifiers';
import { InversifyContainerFacade } from '../../../../../../src/container/InversifyContainerFacade';
import { NodeFactory } from '../../../../../../src/node/NodeFactory';
describe('BooleanLiteralObfuscatingReplacer', () => {
describe('replace', () => {
let inversifyContainerFacade: IInversifyContainerFacade,
obfuscatingReplacer: IObfuscatingReplacer;
before(() => {
inversifyContainerFacade = new InversifyContainerFacade();
inversifyContainerFacade.load('', '', {});
obfuscatingReplacer = inversifyContainerFacade
.getNamed(ServiceIdentifiers.IObfuscatingReplacer, LiteralObfuscatingReplacer.BooleanLiteralObfuscatingReplacer);
});
describe('Variant #1: literal value type check', () => {
describe('Variant #1: literal values is a `boolean` value', () => {
let testFunc: () => void;
before(() => {
const literalNode: ESTree.Literal = NodeFactory.literalNode(true);
testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
});
it('should not throw an error if literal values is a `boolean` value', () => {
assert.doesNotThrow(testFunc,);
});
});
describe('Variant #2: literal values is not a `boolean` value', () => {
const expectedError: ErrorConstructor = Error;
let testFunc: () => void;
before(() => {
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
});
it('should throw an error if literal values is not a `boolean` value', () => {
assert.throws(testFunc, expectedError);
});
});
});
});
});
@@ -0,0 +1,60 @@
import 'reflect-metadata';
import { assert } from 'chai';
import * as ESTree from 'estree';
import { IInversifyContainerFacade } from '../../../../../../src/interfaces/container/IInversifyContainerFacade';
import { IObfuscatingReplacer } from '../../../../../../src/interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IObfuscatingReplacer';
import { LiteralObfuscatingReplacer } from '../../../../../../src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/LiteralObfuscatingReplacer';
import { ServiceIdentifiers } from '../../../../../../src/container/ServiceIdentifiers';
import { InversifyContainerFacade } from '../../../../../../src/container/InversifyContainerFacade';
import { NodeFactory } from '../../../../../../src/node/NodeFactory';
describe('NumberLiteralObfuscatingReplacer', () => {
describe('replace', () => {
let inversifyContainerFacade: IInversifyContainerFacade,
obfuscatingReplacer: IObfuscatingReplacer;
before(() => {
inversifyContainerFacade = new InversifyContainerFacade();
inversifyContainerFacade.load('', '', {});
obfuscatingReplacer = inversifyContainerFacade
.getNamed(ServiceIdentifiers.IObfuscatingReplacer, LiteralObfuscatingReplacer.NumberLiteralObfuscatingReplacer);
});
describe('Variant #1: literal value type check', () => {
describe('Variant #1: literal values is a `number` value', () => {
let testFunc: () => void;
before(() => {
const literalNode: ESTree.Literal = NodeFactory.literalNode(1);
testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
});
it('should not throw an error if literal values is a `number` value', () => {
assert.doesNotThrow(testFunc,);
});
});
describe('Variant #2: literal values is not a `number` value', () => {
const expectedError: ErrorConstructor = Error;
let testFunc: () => void;
before(() => {
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
});
it('should throw an error if literal values is not a `number` value', () => {
assert.throws(testFunc, expectedError);
});
});
});
});
});
@@ -0,0 +1,60 @@
import 'reflect-metadata';
import { assert } from 'chai';
import * as ESTree from 'estree';
import { IInversifyContainerFacade } from '../../../../../../src/interfaces/container/IInversifyContainerFacade';
import { IObfuscatingReplacer } from '../../../../../../src/interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IObfuscatingReplacer';
import { LiteralObfuscatingReplacer } from '../../../../../../src/enums/node-transformers/obfuscating-transformers/obfuscating-replacers/LiteralObfuscatingReplacer';
import { ServiceIdentifiers } from '../../../../../../src/container/ServiceIdentifiers';
import { InversifyContainerFacade } from '../../../../../../src/container/InversifyContainerFacade';
import { NodeFactory } from '../../../../../../src/node/NodeFactory';
describe('StringLiteralObfuscatingReplacer', () => {
describe('replace', () => {
let inversifyContainerFacade: IInversifyContainerFacade,
obfuscatingReplacer: IObfuscatingReplacer;
before(() => {
inversifyContainerFacade = new InversifyContainerFacade();
inversifyContainerFacade.load('', '', {});
obfuscatingReplacer = inversifyContainerFacade
.getNamed(ServiceIdentifiers.IObfuscatingReplacer, LiteralObfuscatingReplacer.StringLiteralObfuscatingReplacer);
});
describe('Variant #1: literal value type check', () => {
describe('Variant #1: literal values is a `string` value', () => {
let testFunc: () => void;
before(() => {
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
});
it('should not throw an error if literal values is a `string` value', () => {
assert.doesNotThrow(testFunc,);
});
});
describe('Variant #2: literal values is not a `string` value', () => {
const expectedError: ErrorConstructor = Error;
let testFunc: () => void;
before(() => {
const literalNode: ESTree.Literal = NodeFactory.literalNode(1);
testFunc = () => <ESTree.Identifier>obfuscatingReplacer.replace(literalNode);
});
it('should throw an error if literal values is not a `string` value', () => {
assert.throws(testFunc, expectedError);
});
});
});
});
});