mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
String array improvement: fixed bugs
This commit is contained in:
+11
-6
@@ -17,7 +17,7 @@ export class NumberNumericalExpressionAnalyzer implements INumberNumericalExpres
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
private static readonly additionalParts: number = 3;
|
||||
public static readonly defaultAdditionalPartsCount: number = 3;
|
||||
|
||||
/**
|
||||
* @type {Map<number, number[]>}
|
||||
@@ -40,9 +40,13 @@ export class NumberNumericalExpressionAnalyzer implements INumberNumericalExpres
|
||||
|
||||
/**
|
||||
* @param {number} number
|
||||
* @param {number} additionalPartsCount
|
||||
* @returns {TNumberNumericalExpressionData}
|
||||
*/
|
||||
public analyze (number: number): TNumberNumericalExpressionData {
|
||||
public analyze (
|
||||
number: number,
|
||||
additionalPartsCount: number
|
||||
): TNumberNumericalExpressionData {
|
||||
if (isNaN(number)) {
|
||||
throw new Error('Given value is NaN');
|
||||
}
|
||||
@@ -51,16 +55,17 @@ export class NumberNumericalExpressionAnalyzer implements INumberNumericalExpres
|
||||
return [number];
|
||||
}
|
||||
|
||||
const additionParts: number[] = this.generateAdditionParts(number);
|
||||
const additionParts: number[] = this.generateAdditionParts(number, additionalPartsCount);
|
||||
|
||||
return additionParts.map((addition: number) => this.mixWithMultiplyParts(addition));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} number
|
||||
* @param {number} additionalPartsCount
|
||||
* @returns {number[]}
|
||||
*/
|
||||
private generateAdditionParts (number: number): number[] {
|
||||
private generateAdditionParts (number: number, additionalPartsCount: number): number[] {
|
||||
const additionParts = [];
|
||||
|
||||
const upperNumberLimit: number = Math.min(Math.abs(number * 2), Number.MAX_SAFE_INTEGER);
|
||||
@@ -70,8 +75,8 @@ export class NumberNumericalExpressionAnalyzer implements INumberNumericalExpres
|
||||
|
||||
let temporarySum = 0;
|
||||
|
||||
for (let i = 0; i < NumberNumericalExpressionAnalyzer.additionalParts; i++) {
|
||||
if (i < NumberNumericalExpressionAnalyzer.additionalParts - 1) {
|
||||
for (let i = 0; i < additionalPartsCount; i++) {
|
||||
if (i < additionalPartsCount - 1) {
|
||||
// trailing parts
|
||||
|
||||
let addition: number = this.randomGenerator.getRandomInteger(from, to);
|
||||
|
||||
@@ -86,19 +86,11 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Literal} literalNode
|
||||
* @returns {IStringArrayStorageItemData | undefined}
|
||||
*/
|
||||
public getItemDataForLiteralNode (literalNode: ESTree.Literal): IStringArrayStorageItemData | undefined {
|
||||
return this.stringArrayStorageData.get(literalNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Literal} literalNode
|
||||
* @param {Node} parentNode
|
||||
*/
|
||||
private analyzeLiteralNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void {
|
||||
public analyzeLiteralNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void {
|
||||
if (!NodeLiteralUtils.isStringLiteralNode(literalNode)) {
|
||||
return;
|
||||
}
|
||||
@@ -111,12 +103,27 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
|
||||
return;
|
||||
}
|
||||
|
||||
this.addItemDataForLiteralNode(literalNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {(SimpleLiteral & {value: string}) | (RegExpLiteral & {value: string})} literalNode
|
||||
*/
|
||||
public addItemDataForLiteralNode (literalNode: ESTree.Literal & {value: string}): void {
|
||||
this.stringArrayStorageData.set(
|
||||
literalNode,
|
||||
this.stringArrayStorage.getOrThrow(literalNode.value)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Literal} literalNode
|
||||
* @returns {IStringArrayStorageItemData | undefined}
|
||||
*/
|
||||
public getItemDataForLiteralNode (literalNode: ESTree.Literal): IStringArrayStorageItemData | undefined {
|
||||
return this.stringArrayStorageData.get(literalNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {(SimpleLiteral & {value: string})} literalNode
|
||||
* @returns {boolean}
|
||||
|
||||
+5
-4
@@ -33,14 +33,15 @@ export function StringArrayBase64DecodeTemplate (
|
||||
{stringArrayCallsWrapperName}.${initializedIdentifier} = true;
|
||||
}
|
||||
|
||||
const ignoreCache = {stringArrayName}[-1];
|
||||
const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
|
||||
const firstValue = {stringArrayName}[0];
|
||||
const cacheKey = index + firstValue;
|
||||
const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[cacheKey];
|
||||
|
||||
if (ignoreCache || cachedValue === undefined) {
|
||||
if (cachedValue === undefined) {
|
||||
{selfDefendingCode}
|
||||
|
||||
value = {stringArrayCallsWrapperName}.${base64DecodeFunctionIdentifier}(value);
|
||||
{stringArrayCallsWrapperName}.${dataIdentifier}[index] = value;
|
||||
{stringArrayCallsWrapperName}.${dataIdentifier}[cacheKey] = value;
|
||||
} else {
|
||||
value = cachedValue;
|
||||
}
|
||||
|
||||
+5
-4
@@ -26,10 +26,11 @@ export function StringArrayRC4DecodeTemplate (
|
||||
{stringArrayCallsWrapperName}.${initializedIdentifier} = true;
|
||||
}
|
||||
|
||||
const ignoreCache = {stringArrayName}[-1];
|
||||
const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
|
||||
const firstValue = {stringArrayName}[0];
|
||||
const cacheKey = index + firstValue;
|
||||
const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[cacheKey];
|
||||
|
||||
if (ignoreCache || cachedValue === undefined) {
|
||||
if (cachedValue === undefined) {
|
||||
if ({stringArrayCallsWrapperName}.${onceIdentifier} === undefined) {
|
||||
{selfDefendingCode}
|
||||
|
||||
@@ -37,7 +38,7 @@ export function StringArrayRC4DecodeTemplate (
|
||||
}
|
||||
|
||||
value = {stringArrayCallsWrapperName}.${rc4Identifier}(value, key);
|
||||
{stringArrayCallsWrapperName}.${dataIdentifier}[index] = value;
|
||||
{stringArrayCallsWrapperName}.${dataIdentifier}[cacheKey] = value;
|
||||
} else {
|
||||
value = cachedValue;
|
||||
}
|
||||
|
||||
-3
@@ -4,14 +4,11 @@
|
||||
export function StringArrayRotateFunctionTemplate (): string {
|
||||
return `
|
||||
(function (array, comparisonValue) {
|
||||
array[-1] = true;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const expression = {comparisonExpressionCode};
|
||||
|
||||
if (expression === comparisonValue) {
|
||||
array[-1] = false;
|
||||
break;
|
||||
} else {
|
||||
array['push'](array['shift']());
|
||||
|
||||
+6
-2
@@ -2,10 +2,14 @@ import { TNumberNumericalExpressionData } from '../../../types/analyzers/number-
|
||||
|
||||
import { IAnalyzer } from '../IAnalyzer';
|
||||
|
||||
export interface INumberNumericalExpressionAnalyzer extends IAnalyzer<[number], TNumberNumericalExpressionData> {
|
||||
export interface INumberNumericalExpressionAnalyzer extends IAnalyzer<[number, number], TNumberNumericalExpressionData> {
|
||||
/**
|
||||
* @param {number} number
|
||||
* @param {number} additionalPartsCount
|
||||
* @returns {TNumberNumericalExpressionData}
|
||||
*/
|
||||
analyze (number: number): TNumberNumericalExpressionData;
|
||||
analyze (
|
||||
number: number,
|
||||
additionalPartsCount: number
|
||||
): TNumberNumericalExpressionData;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,17 @@ export interface IStringArrayStorageAnalyzer extends IAnalyzer<[ESTree.Program],
|
||||
*/
|
||||
analyze (astTree: ESTree.Program): void;
|
||||
|
||||
/**
|
||||
* @param {Literal} literalNode
|
||||
* @param {Node} parentNode
|
||||
*/
|
||||
analyzeLiteralNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void;
|
||||
|
||||
/**
|
||||
* @param {(SimpleLiteral & {value: string}) | (RegExpLiteral & {value: string})} literalNode
|
||||
*/
|
||||
addItemDataForLiteralNode (literalNode: ESTree.Literal & {value: string}): void;
|
||||
|
||||
/**
|
||||
* @param {Literal} literalNode
|
||||
* @returns {IStringArrayStorageItemData | undefined}
|
||||
|
||||
+5
-1
@@ -15,6 +15,7 @@ import { NodeTransformationStage } from '../../enums/node-transformers/NodeTrans
|
||||
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
|
||||
import { NodeGuards } from '../../node/NodeGuards';
|
||||
import { NodeFactory } from '../../node/NodeFactory';
|
||||
import { NumberNumericalExpressionAnalyzer } from '../../analyzers/number-numerical-expression-analyzer/NumberNumericalExpressionAnalyzer';
|
||||
import { NumericalExpressionDataToNodeConverter } from '../../node/NumericalExpressionDataToNodeConverter';
|
||||
|
||||
/**
|
||||
@@ -85,7 +86,10 @@ export class NumberToNumericalExpressionTransformer extends AbstractNodeTransfor
|
||||
return literalNode;
|
||||
}
|
||||
|
||||
const numberNumericalExpressionData: TNumberNumericalExpressionData = this.numberNumericalExpressionAnalyzer.analyze(literalNode.value);
|
||||
const numberNumericalExpressionData: TNumberNumericalExpressionData = this.numberNumericalExpressionAnalyzer.analyze(
|
||||
literalNode.value,
|
||||
NumberNumericalExpressionAnalyzer.defaultAdditionalPartsCount
|
||||
);
|
||||
|
||||
return NumericalExpressionDataToNodeConverter.convert(
|
||||
numberNumericalExpressionData,
|
||||
|
||||
+73
-21
@@ -15,6 +15,7 @@ import { INumberNumericalExpressionAnalyzer } from '../../interfaces/analyzers/n
|
||||
import { IOptions } from '../../interfaces/options/IOptions';
|
||||
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
|
||||
import { IStringArrayStorage } from '../../interfaces/storages/string-array-transformers/IStringArrayStorage';
|
||||
import { IStringArrayStorageAnalyzer } from '../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
|
||||
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
|
||||
|
||||
import { CustomCodeHelper } from '../../enums/custom-code-helpers/CustomCodeHelper';
|
||||
@@ -45,6 +46,11 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
|
||||
NodeTransformer.ScopeIdentifiersTransformer
|
||||
];
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
private static readonly comparisonExpressionAdditionalPartsCount: number = 7;
|
||||
|
||||
/**
|
||||
* @type {INumberNumericalExpressionAnalyzer}
|
||||
*/
|
||||
@@ -55,6 +61,11 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
|
||||
*/
|
||||
private readonly stringArrayStorage: IStringArrayStorage;
|
||||
|
||||
/**
|
||||
* @type {IStringArrayStorageAnalyzer}
|
||||
*/
|
||||
private readonly stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer;
|
||||
|
||||
/**
|
||||
* @type {TCustomCodeHelperFactory}
|
||||
*/
|
||||
@@ -70,6 +81,7 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
|
||||
* @param {IOptions} options
|
||||
* @param {INodeTransformersRunner} transformersRunner
|
||||
* @param {IStringArrayStorage} stringArrayStorage
|
||||
* @param {IStringArrayStorageAnalyzer} stringArrayStorageAnalyzer
|
||||
* @param {TCustomCodeHelperFactory} customCodeHelperFactory
|
||||
* @param {INumberNumericalExpressionAnalyzer} numberNumericalExpressionAnalyzer
|
||||
*/
|
||||
@@ -78,6 +90,7 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
|
||||
@inject(ServiceIdentifiers.IOptions) options: IOptions,
|
||||
@inject(ServiceIdentifiers.INodeTransformersRunner) transformersRunner: INodeTransformersRunner,
|
||||
@inject(ServiceIdentifiers.IStringArrayStorage) stringArrayStorage: IStringArrayStorage,
|
||||
@inject(ServiceIdentifiers.IStringArrayStorageAnalyzer) stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer,
|
||||
@inject(ServiceIdentifiers.Factory__ICustomCodeHelper) customCodeHelperFactory: TCustomCodeHelperFactory,
|
||||
@inject(ServiceIdentifiers.INumberNumericalExpressionAnalyzer)
|
||||
numberNumericalExpressionAnalyzer: INumberNumericalExpressionAnalyzer
|
||||
@@ -85,11 +98,38 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
|
||||
super(randomGenerator, options);
|
||||
|
||||
this.stringArrayStorage = stringArrayStorage;
|
||||
this.stringArrayStorageAnalyzer = stringArrayStorageAnalyzer;
|
||||
this.transformersRunner = transformersRunner;
|
||||
this.customCodeHelperFactory = customCodeHelperFactory;
|
||||
this.numberNumericalExpressionAnalyzer = numberNumericalExpressionAnalyzer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this transformer runs BEFORE string array analyzer we can't check string array storage length.
|
||||
* So we have to traverse over program node and check if it has any string literal node.
|
||||
*
|
||||
* @param {Program} programNode
|
||||
* @returns {boolean}
|
||||
*/
|
||||
private static isProgramNodeHasStringLiterals (programNode: ESTree.Program): boolean {
|
||||
let hasStringLiterals: boolean = false;
|
||||
|
||||
estraverse.traverse(programNode, {
|
||||
enter: (node: ESTree.Node): estraverse.VisitorOption | void => {
|
||||
if (
|
||||
NodeGuards.isLiteralNode(node)
|
||||
&& NodeLiteralUtils.isStringLiteralNode(node)
|
||||
) {
|
||||
hasStringLiterals = true;
|
||||
|
||||
return estraverse.VisitorOption.Break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return hasStringLiterals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NodeTransformationStage} nodeTransformationStage
|
||||
* @returns {IVisitor | null}
|
||||
@@ -102,12 +142,16 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
|
||||
switch (nodeTransformationStage) {
|
||||
case NodeTransformationStage.StringArray:
|
||||
return {
|
||||
enter: (node: ESTree.Node): ESTree.Node | undefined => {
|
||||
if (NodeGuards.isProgramNode(node)) {
|
||||
this.transformNode(node);
|
||||
enter: (node: ESTree.Node): ESTree.Node | estraverse.VisitorOption => {
|
||||
if (!NodeGuards.isProgramNode(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return node;
|
||||
if (!StringArrayRotateFunctionTransformer.isProgramNodeHasStringLiterals(node)) {
|
||||
return estraverse.VisitorOption.Break;
|
||||
}
|
||||
|
||||
return this.transformNode(node);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -149,17 +193,21 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
|
||||
estraverse.traverse(wrappedStringArrayRotateFunctionNode, {
|
||||
enter: (node: ESTree.Node): void => {
|
||||
if (
|
||||
NodeGuards.isLiteralNode(node)
|
||||
&& NodeLiteralUtils.isStringLiteralNode(node)
|
||||
&& !/\d/.test(node.value)
|
||||
!NodeGuards.isLiteralNode(node)
|
||||
|| !NodeLiteralUtils.isStringLiteralNode(node)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (/\d/.test(node.value)) {
|
||||
this.stringArrayStorageAnalyzer.addItemDataForLiteralNode(node);
|
||||
} else {
|
||||
NodeMetadata.set(node, {ignoredNode: true});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
NodeAppender.prepend(programNode, [stringArrayRotateFunctionNode]);
|
||||
NodeUtils.parentizeNode(stringArrayRotateFunctionNode, programNode);
|
||||
|
||||
return programNode;
|
||||
}
|
||||
@@ -170,24 +218,28 @@ export class StringArrayRotateFunctionTransformer extends AbstractNodeTransforme
|
||||
private getStringArrayRotateFunctionNode (): TStatement {
|
||||
const comparisonValue: number = this.randomGenerator.getRandomInteger(100000, 1_000_000);
|
||||
const comparisonExpressionNumberNumericalExpressionData: TNumberNumericalExpressionData =
|
||||
this.numberNumericalExpressionAnalyzer.analyze(comparisonValue);
|
||||
this.numberNumericalExpressionAnalyzer.analyze(
|
||||
comparisonValue,
|
||||
StringArrayRotateFunctionTransformer.comparisonExpressionAdditionalPartsCount
|
||||
);
|
||||
|
||||
const comparisonExpressionNode: ESTree.Expression = NumericalExpressionDataToNodeConverter.convert(
|
||||
comparisonExpressionNumberNumericalExpressionData,
|
||||
((number: number, isPositiveNumber) => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode(number.toString());
|
||||
|
||||
return NodeFactory.callExpressionNode(
|
||||
NodeFactory.identifierNode('parseInt'),
|
||||
[
|
||||
isPositiveNumber
|
||||
? literalNode
|
||||
: NodeFactory.unaryExpressionNode(
|
||||
'-',
|
||||
literalNode
|
||||
)
|
||||
]
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode(
|
||||
`${number}${this.randomGenerator.getRandomString(6)}`
|
||||
);
|
||||
const parseIntCallExpression: ESTree.CallExpression = NodeFactory.callExpressionNode(
|
||||
NodeFactory.identifierNode('parseInt'),
|
||||
[literalNode]
|
||||
);
|
||||
|
||||
return isPositiveNumber
|
||||
? parseIntCallExpression
|
||||
: NodeFactory.unaryExpressionNode(
|
||||
'-',
|
||||
parseIntCallExpression
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -299,7 +299,7 @@ export class Options implements IOptions {
|
||||
*/
|
||||
@IsNumber()
|
||||
@ValidateIf((options: IOptions) => Boolean(options.splitStrings))
|
||||
@Min(3)
|
||||
@Min(1)
|
||||
public readonly splitStringsChunkLength!: number;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user