8000 Merge pull request #493 from javascript-obfuscator/string-array-rando… · sec-js/javascript-obfuscator@c3b0b4f · GitHub
[go: up one dir, main page]

Skip to content

Commit c3b0b4f

Browse files
authored
Merge pull request javascript-obfuscator#493 from javascript-obfuscator/string-array-random-position
`shuffleStringArray` option
2 parents 853d34b + 19d0769 commit c3b0b4f

File tree

63 files changed

+1694
-336
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1694
-336
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ Change Log
22

33
v0.23.0
44
---
5+
* **New option:** `shuffleStringArray` randomly shuffles string array items
56
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/494
67
* **Internal change:** switched AST parser from `espree` on `acorn`
8+
* **Internal refactoring:** refactoring of string array storage and related things
79

810
v0.22.1
911
---

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ Following options are available for the JS Obfuscator:
306306
rotateStringArray: true,
307307
seed: 0,
308308
selfDefending: false,
309+
shuffleStringArray: true,
309310
sourceMap: false,
310311
sourceMapBaseUrl: '',
311312
sourceMapFileName: '',
@@ -349,6 +350,7 @@ Following options are available for the JS Obfuscator:
349350
--rotate-string-array <boolean>
350351
--seed <string|number>
351352
--self-defending <boolean>
353+
--shuffle-string-array <boolean>
352354
--source-map <boolean>
353355
--source-map-base-url <string>
354356
--source-map-file-name <string>
@@ -691,6 +693,13 @@ Type: `boolean` Default: `false`
691693

692694
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.
693695

696+
### `shuffleStringArray`
697+
Type: `boolean` Default: `true`
698+
699+
##### :warning: [`stringArray`](#stringarray) must be enabled
700+
701+
Randomly shuffles the `stringArray` array items.
702+
694703
### `sourceMap`
695704
Type: `boolean` Default: `false`
696705

@@ -867,6 +876,7 @@ Performance will 50-100% slower than without obfuscation
867876
renameGlobals: false,
868877
rotateStringArray: true,
869878
selfDefending: true,
879+
shuffleStringArray: true,
870880
splitStrings: true,
871881
splitStringsChunkLength: '5',
872882
stringArray: true,
@@ -896,6 +906,7 @@ Performance will 30-35% slower than without obfuscation
896906
renameGlobals: false,
897907
rotateStringArray: true,
898908
selfDefending: true,
909+
shuffleStringArray: true,
899910
splitStrings: true,
900911
splitStringsChunkLength: '10',
901912
stringArray: true,
@@ -923,6 +934,7 @@ Performance will slightly slower than without obfuscation
923934
renameGlobals: false,
924935
rotateStringArray: true,
925936
selfDefending: true,
937+
shuffleStringArray: true,
926938
splitStrings: false,
927939
stringArray: true,
928940
stringArrayEncoding: false,

dist/index.browser.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.cli.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import { inject, injectable, } from 'inversify';
2+
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
3+
4+
import * as estraverse from 'estraverse';
5+
import * as ESTree from 'estree';
6+
7+
import { IOptions } from '../../interfaces/options/IOptions';
8+
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
9+
import { IStringArrayStorage } from '../../interfaces/storages/string-array-storage/IStringArrayStorage';
10+
import { IStringArrayStorageAnalyzer } from '../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
11+
import { IStringArrayStorageItemData } from '../../interfaces/storages/string-array-storage/IStringArrayStorageItem';
12+
13+
import { NodeGuards } from '../../node/NodeGuards';
14+
import { NodeMetadata } from '../../node/NodeMetadata';
15+
16+
/**
17+
* Adds values of literal nodes to the string array storage
18+
*/
19+
@injectable()
20+
export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
21+
/**
22+
* @type {number}
23+
*/
24+
private static readonly minimumLengthForStringArray: number = 3;
25+
26+
/**
27+
* @type {IOptions}
28+
*/
29+
private readonly options: IOptions;
30+
31+
/**
32+
* @type {randomGenerator}
33+
*/
34+
private readonly randomGenerator: IRandomGenerator;
35+
36+
/**
37+
* @type {IStringArrayStorage}
38+
*/
39+
private readonly stringArrayStorage: IStringArrayStorage;
40+
41+
/**
42+
* @type {Map<ESTree.Literal, IStringArrayStorageItemData>}
43+
*/
44+
private readonly stringArrayStorageData: Map<ESTree.Literal, IStringArrayStorageItemData> = new Map();
45+
46+
/**
47+
* @param {IStringArrayStorage} stringArrayStorage
48+
* @param {IRandomGenerator} randomGenerator
49+
* @param {IOptions} options
50+
*/
51+
constructor (
52+
@inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStringArrayStorage,
53+
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
54+
@inject(ServiceIdentifiers.IOptions) options: IOptions,
55+
) {
56+
this.stringArrayStorage = stringArrayStorage;
57+
this.randomGenerator = randomGenerator;
58+
this.options = options;
59+
}
60+
61+
/**
62+
* @param {Program} astTree
63+
*/
64+
public analyze (astTree: ESTree.Program): void {
65+
if (!this.options.stringArray) {
66+
return;
67+
}
68+
69+
estraverse.traverse(astTree, {
70+
enter: (node: ESTree.Node): estraverse.VisitorOption | void => {
71+
if (NodeMetadata.isIgnoredNode(node)) {
72+
return estraverse.VisitorOption.Skip;
73+
}
74+
75+
if (!NodeGuards.isLiteralNode(node)) {
76+
return;
77+
}
78+
79+
this.analyzeLiteralNode(node);
80+
}
81+
});
82+
}
83+
84+
/**
85+
* @param {Literal} literalNode
86+
* @returns {IStringArrayStorageItemData | undefined}
87+
*/
88+
public getItemDataForLiteralNode (literalNode: ESTree.Literal): IStringArrayStorageItemData | undefined {
89+
return this.stringArrayStorageData.get(literalNode);
90+
}
91+
92+
/**
93+
* @param {Literal} literalNode
94+
*/
95+
private analyzeLiteralNode (literalNode: ESTree.Literal): void {
96+
if (typeof literalNode.value !== 'string') {
97+
return;
98+
}
99+
100+
if (!this.shouldAddValueToStringArray(literalNode.value)) {
101+
return;
102+
}
103+
104+
this.stringArrayStorageData.set(
105+
literalNode,
106+
this.stringArrayStorage.getOrThrow(literalNode.value)
107+
);
108+
}
109+
110+
/**
111+
* @param {string} value
112+
* @returns {boolean}
113+
*/
114+
private shouldAddValueToStringArray (value: string): boolean {
115+
return value.length >= StringArrayStorageAnalyzer.minimumLengthForStringArray
116+
&& this.randomGenerator.getMathRandom() <= this.options.stringArrayThreshold;
117+
}
118+
}

src/cli/JavaScriptObfuscatorCLI.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
283283
BooleanSanitizer
284284
)
285285
.option(
286-
'--rotate-string-array <boolean>', 'Disable rotation of unicode array values during obfuscation',
286+
'--rotate-string-array <boolean>', 'Enable rotation of string array values during obfuscation',
287287
BooleanSanitizer
288288
)
289289
.option(
@@ -296,6 +296,10 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
296296
'Disables self-defending for obfuscated code',
297297
BooleanSanitizer
298298
)
299+
.option(
300+
'--shuffle-string-array <boolean>', 'Randomly shuffles string array items',
301+
BooleanSanitizer
302+
)
299303
.option(
300304
'--source-map <boolean>',
301305
'Enables source map generation',

src/container/ServiceIdentifiers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export enum ServiceIdentifiers {
4141
IRandomGenerator = 'IRandomGenerator',
4242
ISourceCode = 'ISourceCode',
4343
ISourceMapCorrector = 'ISourceMapCorrector',
44+
IStringArrayStorageAnalyzer = 'IStringArrayStorageAnalyzer',
4445
ITransformersRunner = 'ITransformersRunner',
4546
Newable__ICustomNode = 'Newable<ICustomNode>',
4647
Newable__TControlFlowStorage = 'Newable<TControlFlowStorage>',

src/container/modules/analyzers/AnalyzersModule.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
55
import { ICalleeDataExtractor } from '../../../interfaces/analyzers/calls-graph-analyzer/ICalleeDataExtractor';
66
import { ICallsGraphAnalyzer } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphAnalyzer';
77
import { IPrevailingKindOfVariablesAnalyzer } from '../../../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
8+
import { IStringArrayStorageAnalyzer } from '../../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
89

910
import { CalleeDataExtractor } from '../../../enums/analyzers/calls-graph-analyzer/CalleeDataExtractor';
1011
import { CallsGraphAnalyzer } from '../../../analyzers/calls-graph-analyzer/CallsGraphAnalyzer';
1112
import { FunctionDeclarationCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/FunctionDeclarationCalleeDataExtractor';
1213
import { FunctionExpressionCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/FunctionExpressionCalleeDataExtractor';
1314
import { ObjectExpressionCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor';
1415
import { PrevailingKindOfVariablesAnalyzer } from '../../../analyzers/prevailing-kind-of-variables-analyzer/PrevailingKindOfVariablesAnalyzer';
16+
import { StringArrayStorageAnalyzer } from '../../../analyzers/string-array-storage-analyzer/StringArrayStorageAnalyzer';
1517

1618
export const analyzersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
1719
// calls graph analyzer
@@ -24,6 +26,11 @@ export const analyzersModule: interfaces.ContainerModule = new ContainerModule((
2426
.to(PrevailingKindOfVariablesAnalyzer)
2527
.inSingletonScope();
2628

29+
// string array storage analyzer
30+
bind<IStringArrayStorageAnalyzer>(ServiceIdentifiers.IStringArrayStorageAnalyzer)
31+
.to(StringArrayStorageAnalyzer)
32+
.inSingletonScope();
33+
2734
// callee data extractors
2835
bind<ICalleeDataExtractor>(ServiceIdentifiers.ICalleeDataExtractor)
2936
.to(FunctionDeclarationCalleeDataExtractor)

src/container/modules/storages/StoragesModule.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
33

44
import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
55
import { TCustomNodeGroupStorage } from '../../../types/storages/TCustomNodeGroupStorage';
6-
import { TStringArrayStorage } from '../../../types/storages/TStringArrayStorage';
76

87
import { IOptions } from '../../../interfaces/options/IOptions';
98
import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
9+
import { IStringArrayStorage } from '../../../interfaces/storages/string-array-storage/IStringArrayStorage';
1010

1111
import { ControlFlowStorage } from '../../../storages/control-flow/ControlFlowStorage';
1212
import { CustomNodeGroupStorage } from '../../../storages/custom-node-group/CustomNodeGroupStorage';
@@ -18,7 +18,7 @@ export const storagesModule: interfaces.ContainerModule = new ContainerModule((b
1818
.to(CustomNodeGroupStorage)
1919
.inSingletonScope();
2020

21-
bind<TStringArrayStorage>(ServiceIdentifiers.TStringArrayStorage)
21+
bind<IStringArrayStorage>(ServiceIdentifiers.TStringArrayStorage)
2222
.to(StringArrayStorage)
2323
.inSingletonScope();
2424

0 commit comments

Comments
 (0)
0