8000 Merge pull request #580 from javascript-obfuscator/string-transformer · sec-js/javascript-obfuscator@58cb940 · GitHub
[go: up one dir, main page]

Skip to content

Commit 58cb940

Browse files
authored
Merge pull request javascript-obfuscator#580 from javascript-obfuscator/string-transformer
Code transformers. HashbangOperatorTransformer
2 parents 70428d0 + e7a6186 commit 58cb940

36 files changed

+637
-171
lines changed

dist/index.browser.js

Lines changed: 6 additions & 6 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.

src/JavaScriptObfuscator.ts

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as ESTree from 'estree';
77

88
import { TObfuscatedCodeFactory } from './types/container/source-code/TObfuscatedCodeFactory';
99

10+
import { ICodeTransformersRunner } from './interfaces/code-transformers/ICodeTransformersRunner';
1011
import { IGeneratorOutput } from './interfaces/IGeneratorOutput';
1112
import { IJavaScriptObfuscator } from './interfaces/IJavaScriptObfsucator';
1213
import { ILogger } from './interfaces/logger/ILogger';
@@ -15,6 +16,8 @@ import { IOptions } from './interfaces/options/IOptions';
1516
import { IRandomGenerator } from './interfaces/utils/IRandomGenerator';
1617
import { INodeTransformersRunner } from './interfaces/node-transformers/INodeTransformersRunner';
1718

19+
import { CodeTransformer } from './enums/code-transformers/CodeTransformer';
20+
import { CodeTransformationStage } from './enums/code-transformers/CodeTransformationStage';
1821
import { LoggingMessage } from './enums/logger/LoggingMessage';
1922
import { NodeTransformer } from './enums/node-transformers/NodeTransformer';
2023
import { NodeTransformationStage } from './enums/node-transformers/NodeTransformationStage';
@@ -48,10 +51,17 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
4851
sourceMapWithCode: true
4952
};
5053

54+
/**
55+
* @type {CodeTransformer[]}
56+
*/
57+
private static readonly codeTransformersList: CodeTransformer[] = [
58+
CodeTransformer.HashbangOperatorTransformer
59+
];
60+
5161
/**
5262
* @type {NodeTransformer[]}
5363
*/
54-
private static readonly transformersList: NodeTransformer[] = [
64+
private static readonly nodeTransformersList: NodeTransformer[] = [
5565
NodeTransformer.BlockStatementControlFlowTransformer,
5666
NodeTransformer.CommentsTransformer,
5767
NodeTransformer.CustomCodeHelpersTransformer,
@@ -73,6 +83,11 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
7383
NodeTransformer.VariablePreserveTransformer
7484
];
7585

86+
/**
87+
* @type {ICodeTransformersRunner}
88+
*/
89+
private readonly codeTransformersRunner: ICodeTransformersRunner;
90+
7691
/**
7792
* @type {ILogger}
7893
*/
@@ -96,23 +111,26 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
96111
/**
97112
* @type {INodeTransformersRunner}
98113
*/
99-
private readonly transformersRunner: INodeTransformersRunner;
114+
private readonly nodeTransformersRunner: INodeTransformersRunner;
100115

101116
/**
102-
* @param {INodeTransformersRunner} transformersRunner
117+
* @param {ICodeTransformersRunner} codeTransformersRunner
118+
* @param {INodeTransformersRunner} nodeTransformersRunner
103119
* @param {IRandomGenerator} randomGenerator
104120
* @param {TObfuscatedCodeFactory} obfuscatedCodeFactory
105121
* @param {ILogger} logger
106122
* @param {IOptions} options
107123
*/
108124
public constructor (
109-
@inject(ServiceIdentifiers.ITransformersRunner) transformersRunner: INodeTransformersRunner,
125+
@inject(ServiceIdentifiers.ICodeTransformersRunner) codeTransformersRunner: ICodeTransformersRunner,
126+
@inject(ServiceIdentifiers.INodeTransformersRunner) nodeTransformersRunner: INodeTransformersRunner,
110127
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
111128
@inject(ServiceIdentifiers.Factory__IObfuscatedCode) obfuscatedCodeFactory: TObfuscatedCodeFactory,
112129
@inject(ServiceIdentifiers.ILogger) logger: ILogger,
113130
@inject(ServiceIdentifiers.IOptions) options: IOptions
114131
) {
115-
this.transformersRunner = transformersRunner;
132+
this.codeTransformersRunner = codeTransformersRunner;
133+
this.nodeTransformersRunner = nodeTransformersRunner;
116134
this.randomGenerator = randomGenerator;
117135
this.obfuscatedCodeFactory = obfuscatedCodeFactory;
118136
this.logger = logger;
@@ -129,6 +147,9 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
129147
this.logger.info(LoggingMessage.ObfuscationStarted);
130148
this.logger.info(LoggingMessage.RandomGeneratorSeed, this.randomGenerator.getInputSeed());
131149

150+
// preparing code transformations
151+
sourceCode = this.runCodeTransformationStage(sourceCode, CodeTransformationStage.PreparingTransformers);
152+
132153
// parse AST tree
133154
const astTree: ESTree.Program = this.parseCode(sourceCode);
134155

@@ -138,6 +159,9 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
138159
// generate code
139160
const generatorOutput: IGeneratorOutput = this.generateCode(sourceCode, obfuscatedAstTree);
140161

162+
// finalizing code transformations
163+
generatorOutput.code = this.runCodeTransformationStage(generatorOutput.code, CodeTransformationStage.FinalizingTransformers);
164+
141165
const obfuscationTime: number = (Date.now() - timeStart) / 1000;
142166
this.logger.success(LoggingMessage.ObfuscationCompleted, obfuscationTime);
143167

@@ -157,7 +181,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
157181
* @returns {Program}
158182
*/
159183
private transformAstTree (astTree: ESTree.Program): ESTree.Program {
160-
astTree = this.runTransformationStage(astTree, NodeTransformationStage.Initializing);
184+
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Initializing);
161185

162186
const isEmptyAstTree: boolean = NodeGuards.isProgramNode(astTree)
163187
&& !astTree.body.length
@@ -170,19 +194,19 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
170194
return astTree;
171195
}
172196

173-
astTree = this.runTransformationStage(astTree, NodeTransformationStage.Preparing);
197+
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Preparing);
174198

175199
if (this.options.deadCodeInjection) {
176-
astTree = this.runTransformationStage(astTree, NodeTransformationStage.DeadCodeInjection);
200+
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.DeadCodeInjection);
177201
}
178202

179203
if (this.options.controlFlowFlattening) {
180-
astTree = this.runTransformationStage(astTree, NodeTransformationStage.ControlFlowFlattening);
204+
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.ControlFlowFlattening);
181205
}
182206

183-
astTree = this.runTransformationStage(astTree, NodeTransformationStage.Converting);
184-
astTree = this.runTransformationStage(astTree, NodeTransformationStage.Obfuscating);
185-
astTree = this.runTransformationStage(astTree, NodeTransformationStage.Finalizing);
207+
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Converting);
208+
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Obfuscating);
209+
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Finalizing);
186210

187211
return astTree;
188212
}
@@ -222,17 +246,32 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
222246
return this.obfuscatedCodeFactory(generatorOutput.code, generatorOutput.map);
223247
}
224248

249+
/**
250+
* @param {string} code
251+
* @param {CodeTransformationStage} codeTransformationStage
252+
* @returns {string}
253+
*/
254+
private runCodeTransformationStage (code: string, codeTransformationStage: CodeTransformationStage): string {
255+
this.logger.info(LoggingMessage.CodeTransformationStage, codeTransformationStage);
256+
257+
return this.codeTransformersRunner.transform(
258+
code,
259+
JavaScriptObfuscator.codeTransformersList,
260+
codeTransformationStage
261+
);
262+
}
263+
225264
/**
226265
* @param {Program} astTree
227266
* @param {NodeTransformationStage} nodeTransformationStage
228267
* @returns {Program}
229268
*/
230-
private runTransformationStage (astTree: ESTree.Program, nodeTransformationStage: NodeTransformationStage): ESTree.Program {
231-
this.logger.info(LoggingMessage.TransformationStage, nodeTransformationStage);
269+
private runNodeTransformationStage (astTree: ESTree.Program, nodeTransformationStage: NodeTransformationStage): ESTree.Program {
270+
this.logger.info(LoggingMessage.NodeTransformationStage, nodeTransformationStage);
232271

233-
return this.transformersRunner.transform(
272+
return this.nodeTransformersRunner.transform(
234273
astTree,
235-
JavaScriptObfuscator.transformersList,
274+
JavaScriptObfuscator.nodeTransformersList,
236275
nodeTransformationStage
237276
);
238277
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { inject, injectable } from 'inversify';
2+
import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
3+
4+
import { ICodeTransformer } from '../interfaces/code-transformers/ICodeTransformer';
5+
import { IOptions } from '../interfaces/options/IOptions';
6+
import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
7+
8+
import { CodeTransformer } from '../enums/code-transformers/CodeTransformer';
9+
import { CodeTransformationStage } from '../enums/code-transformers/CodeTransformationStage';
10+
11+
@injectable()
12+
export abstract class AbstractCodeTransformer implements ICodeTransformer {
13+
/**
14+
* @type {CodeTransformer[]}
15+
*/
16+
public readonly runAfter: CodeTransformer[] | undefined;
17+
18+
/**
19+
* @type {IOptions}
20+
*/
21+
protected readonly options: IOptions;
22+
23+
/**
24+
* @type {IRandomGenerator}
25+
*/
26+
protected readonly randomGenerator: IRandomGenerator;
27+
28+
/**
29+
* @param {IRandomGenerator} randomGenerator
30+
* @param {IOptions} options
31+
*/
32+
protected constructor (
33+
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
34+
@inject(ServiceIdentifiers.IOptions) options: IOptions
35+
) {
36+
this.randomGenerator = randomGenerator;
37+
this.options = options;
38+
}
39+
40+
/**
41+
* @param {string} code
42+
* @param {CodeTransformationStage} codeTransformationStage
43+
* @returns {string}
44+
*/
45+
public abstract transformCode (code: string, codeTransformationStage: CodeTransformationStage): string;
46+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { injectable } from 'inversify';
2+
3+
import { ICodeTransformer } from '../interfaces/code-transformers/ICodeTransformer';
4+
5+
import { CodeTransformer } from '../enums/code-transformers/CodeTransformer';
6+
7+
import { AbstractTransformerNamesGroupsBuilder } from '../utils/AbstractTransformerNamesGroupsBuilder';
8+
9+
@injectable()
10+
export class CodeTransformerNamesGroupsBuilder extends AbstractTransformerNamesGroupsBuilder<
11+
CodeTransformer,
12+
ICodeTransformer
13+
> {}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { inject, injectable } from 'inversify';
2+
3+
import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
4+
5+
import { TCodeTransformerFactory } from '../types/container/code-transformers/TCodeTransformerFactory';
6+
import { TObject } from '../types/TObject';
7+
8+
import { ICodeTransformer } from '../interfaces/code-transformers/ICodeTransformer';
9+
import { ICodeTransformersRunner } from '../interfaces/code-transformers/ICodeTransformersRunner';
10+
import { ITransformerNamesGroupsBuilder } from '../interfaces/utils/ITransformerNamesGroupsBuilder';
11+
12+
import { CodeTransformer } from '../enums/code-transformers/CodeTransformer';
13+
import { CodeTransformationStage } from '../enums/code-transformers/CodeTransformationStage';
14+
15+
@injectable()
16+
export class CodeTransformersRunner implements ICodeTransformersRunner {
17+
/**
18+
* @type {TCodeTransformerFactory}
19+
*/
20+
private readonly codeTransformerFactory: TCodeTransformerFactory;
21+
22+
/**
23+
* @type {ITransformerNamesGroupsBuilder}
24+
*/
25+
private readonly codeTransformerNamesGroupsBuilder: ITransformerNamesGroupsBuilder<
26+
CodeTransformer,
27+
ICodeTransformer
28+
>;
29+
30+
/**
31+
* @param {TNodeTransformerFactory} codeTransformerFactory
32+
* @param {ITransformerNamesGroupsBuilder} codeTransformerNamesGroupsBuilder
33+
*/
34+
public constructor (
35+
@inject(ServiceIdentifiers.Factory__ICodeTransformer)
36+
codeTransformerFactory: TCodeTransformerFactory,
37+
@inject(ServiceIdentifiers.ICodeTransformerNamesGroupsBuilder)
38+
codeTransformerNamesGroupsBuilder: ITransformerNamesGroupsBuilder<
39+
CodeTransformer,
40+
ICodeTransformer
41+
>,
42+
) {
43+
this.codeTransformerFactory = codeTransformerFactory;
44+
this.codeTransformerNamesGroupsBuilder = codeTransformerNamesGroupsBuilder;
45+
}
46+
47+
/**
48+
* @param {string} code
49+
* @param {CodeTransformer[]} codeTransformerNames
50+
* @param {CodeTransformationStage} codeTransformationStage
51+
* @returns {string}
52+
*/
53+
public transform (
54+
code: string,
55+
codeTransformerNames: CodeTransformer[],
56+
codeTransformationStage: CodeTransformationStage
57+
): string {
58+
if (!codeTransformerNames.length) {
59+
return code;
60+
}
61+
62+
const normalizedCodeTransformers: TObject<ICodeTransformer> =
63+
this.buildNormalizedCodeTransformers(codeTransformerNames, codeTransformationStage);
64+
const codeTransformerNamesGroups: CodeTransformer[][] =
65+
this.codeTransformerNamesGroupsBuilder.build(normalizedCodeTransformers);
66+
67+
for (const nodeTransformerNamesGroup of codeTransformerNamesGroups) {
68+
for (const nodeTransformerName of nodeTransformerNamesGroup) {
69+
const codeTransformer: ICodeTransformer = normalizedCodeTransformers[nodeTransformerName];
70+
71+
code = codeTransformer.transformCode(code, codeTransformationStage);
72+
}
73+
}
74+
75+
return code;
76+
}
77+
78+
/**
79+
* @param {NodeTransformer[]} codeTransformerNames
80+
* @param {NodeTransformationStage} codeTransformationStage
81+
* @returns {TObject<INodeTransformer>}
82+
*/
83+
private buildNormalizedCodeTransformers (
84+
codeTransformerNames: CodeTransformer[],
85+
codeTransformationStage: CodeTransformationStage
86+
): TObject<ICodeTransformer> {
87+
return codeTransformerNames
88+
.reduce<TObject<ICodeTransformer>>(
89+
(acc: TObject<ICodeTransformer>, codeTransformerName: CodeTransformer) => {
90+
const codeTransformer: ICodeTransformer = this.codeTransformerFactory(codeTransformerName);
91+
92+
return {
93+
...acc,
94+
[codeTransformerName]: codeTransformer
95+
};
96+
},
97+
{}
98+
);
99+
}
100+
}

0 commit comments

Comments
 (0)
0