10000 Add target 'service-worker' (#1134) · sec-js/javascript-obfuscator@54cbdf6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 54cbdf6

Browse files
authored
Add target 'service-worker' (javascript-obfuscator#1134)
1 parent c7d4f9c commit 54cbdf6

File tree

8 files changed

+268
-26
lines changed

8 files changed

+268
-26
lines changed

src/custom-code-helpers/AbstractCustomCodeHelper.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
1313

1414
import { GlobalVariableTemplate1 } from './common/templates/GlobalVariableTemplate1';
1515
import { GlobalVariableTemplate2 } from './common/templates/GlobalVariableTemplate2';
16+
import { ObfuscationTarget } from '../enums/ObfuscationTarget';
17+
import { GlobalVariableNoEvalTemplate } from './common/templates/GlobalVariableNoEvalTemplate';
18+
import { GlobalVariableServiceWorkerTemplate } from './common/templates/GlobalVariableServiceWorkerTemplate';
1619

1720
@injectable()
1821
export abstract class AbstractCustomCodeHelper <
@@ -97,9 +100,16 @@ export abstract class AbstractCustomCodeHelper <
97100
* @returns {string}
98101
*/
99102
protected getGlobalVariableTemplate (): string {
100-
return this.randomGenerator
101-
.getRandomGenerator()
102-
.pickone(AbstractCustomCodeHelper.globalVariableTemplateFunctions);
103+
switch (this.options.target) {
104+
case ObfuscationTarget.BrowserNoEval:
105+
return GlobalVariableNoEvalTemplate();
106+
case ObfuscationTarget.ServiceWorker:
107+
return GlobalVariableServiceWorkerTemplate();
108+
default:
109+
return this.randomGenerator
110+
.getRandomGenerator()
111+
.pickone(AbstractCustomCodeHelper.globalVariableTemplateFunctions);
112+
}
103113
}
104114

105115
/**
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* @returns {string}
3+
*/
4+
export function GlobalVariableServiceWorkerTemplate (): string {
5+
return `const that = typeof global === 'object' ? global : this;`;
6+
}

src/custom-code-helpers/console-output/ConsoleOutputDisableCodeHelper.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helper
99
import { IOptions } from '../../interfaces/options/IOptions';
1010
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
1111

12-
import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
1312

1413
import { ConsoleOutputDisableTemplate } from './templates/ConsoleOutputDisableTemplate';
15-
import { GlobalVariableNoEvalTemplate } from '../common/templates/GlobalVariableNoEvalTemplate';
1614

1715
import { initializable } from '../../decorators/Initializable';
1816

@@ -78,14 +76,10 @@ export class ConsoleOutputDisableCodeHelper extends AbstractCustomCodeHelper {
7876
* @returns {string}
7977
*/
8078
protected override getCodeHelperTemplate (): string {
81-
const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
82-
? this.getGlobalVariableTemplate()
83-
: GlobalVariableNoEvalTemplate();
84-
8579
return this.customCodeHelperFormatter.formatTemplate(ConsoleOutputDisableTemplate(), {
8680
callControllerFunctionName: this.callsControllerFunctionName,
8781
consoleLogDisableFunctionName: this.consoleOutputDisableFunctionName,
88-
globalVariableTemplate
82+
globalVariableTemplate: this.getGlobalVariableTemplate(),
8983
});
9084
}
9185
}

src/enums/ObfuscationTarget.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ export const ObfuscationTarget: Readonly<{
44
Browser: 'browser';
55
BrowserNoEval: 'browser-no-eval';
66
Node: 'node';
7+
ServiceWorker: 'service-worker';
78
}> = Utils.makeEnum({
89
Browser: 'browser',
910
BrowserNoEval: 'browser-no-eval',
10-
Node: 'node'
11+
Node: 'node',
12+
ServiceWorker: 'service-worker',
1113
});

src/options/Options.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ export class Options implements IOptions {
415415
/**
416416
* @type {ObfuscationTarget}
417417
*/
418-
@IsIn([ObfuscationTarget.Browser, ObfuscationTarget.BrowserNoEval, ObfuscationTarget.Node])
418+
@IsIn([ObfuscationTarget.Browser, ObfuscationTarget.BrowserNoEval, ObfuscationTarget.Node, ObfuscationTarget.ServiceWorker])
419419
public readonly target!: TTypeFromEnum<typeof ObfuscationTarget>;
420420

421421
/**

test/functional-tests/custom-code-helpers/debug-protection/templates/debug-protection-function-call-template/DebugProtectionFunctionCallTemplate.spec.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,40 @@ describe('DebugProtectionFunctionCallTemplate', function () {
149149
});
150150
});
151151

152-
describe('Variant #5: obfuscated code with removed debug protection code', () => {
152+
describe('Variant #5: correctly obfuscated code with target `ServiceWorker', () => {
153+
const expectedEvaluationResult: number = 1;
154+
155+
let obfuscatedCode: string,
156+
evaluationResult: number = 0;
157+
158+
beforeEach(() => {
159+
const code: string = readFileAsString(__dirname + '/fixtures/input.js');
160+
161+
obfuscatedCode = JavaScriptObfuscator.obfuscate(
162+
code,
163+
{
164+
...NO_ADDITIONAL_NODES_PRESET,
165+
debugProtection: true,
166+
target: ObfuscationTarget.ServiceWorker
167+
}
168+
).getObfuscatedCode();
169+
170+
return evaluateInWorker(obfuscatedCode, evaluationTimeout)
171+
.then((result: string | null) => {
172+
if (!result) {
173+
return;
174+
}
175+
176+
evaluationResult = parseInt(result, 10);
177+
});
178+
});
179+
180+
it('should correctly evaluate code with enabled debug protection', () => {
181+
assert.equal(evaluationResult, expectedEvaluationResult);
182+
});
183+
});
184+
185+
describe('Variant #6: obfuscated code with removed debug protection code', () => {
153186
const expectedEvaluationResult: number = 0;
154187

155188
let obfuscatedCode: string,
@@ -182,7 +215,7 @@ describe('DebugProtectionFunctionCallTemplate', function () {
182215
});
183216
});
184217

185-
describe('Variant #6: single call of debug protection code', () => {
218+
describe('Variant #7: single call of debug protection code', () => {
186219
const expectedEvaluationResult: number = 1;
187220

188221
let obfuscatedCode: string,

test/functional-tests/node-transformers/rename-identifiers-transformers/scope-identifiers-transformer/class-declaration/ClassDeclaration.spec.ts

Lines changed: 179 additions & 0 deletions
17A6
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,87 @@ describe('ScopeIdentifiersTransformer ClassDeclaration identifiers', () => {
227227
});
228228
});
229229
});
230+
231+
describe('Variant #3: target `service-worker', () => {
232+
describe('Variant #1: correct class name references in global scope', () => {
233+
const classNameIdentifierRegExp: RegExp = /class A *\{/;
234+
const outerClassNameReferenceRegExp: RegExp = /console\['log']\(A\);/;
235+
const innerClassNameReferenceRegExp: RegExp = /return A;/;
236+
237+
let obfuscatedCode: string;
238+
239+
before(() => {
240+
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-global-scope.js');
241+
242+
obfuscatedCode = JavaScriptObfuscator.obfuscate(
243+
code,
244+
{
245+
...NO_ADDITIONAL_NODES_PRESET,
246+
target: ObfuscationTarget.ServiceWorker
247+
}
248+
).getObfuscatedCode();
249+
});
250+
251+
it('match #1: shouldn\'t transform class name', () => {
252+
assert.match(obfuscatedCode, classNameIdentifierRegExp);
253+
});
254+
255+
it('match #2: shouldn\'t transform class name reference outside of class', () => {
256+
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
257+
});
258+
259+
it('match #3: shouldn\'t transform class name reference inside class', () => {
260+
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
261+
});
262+
});
263+
264+
describe('Variant #2: correct class name references in function scope', () => {
265+
const classNameIdentifierRegExp: RegExp = /class (_0x[a-f0-9]{4,6}) *\{/;
266+
const outerClassNameReferenceRegExp: RegExp = /console\['log']\((_0x[a-f0-9]{4,6})\);/;
267+
const innerClassNameReferenceRegExp: RegExp = /return (_0x[a-f0-9]{4,6});/;
268+
269+
let obfuscatedCode: string;
270+
let classNameIdentifier: string;
271+
let outerClassNameReferenceIdentifierName: string;
272+
let innerClassNameReferenceIdentifierName: string;
273+
274+
before(() => {
275+
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-function-scope.js');
276+
277+
obfuscatedCode = JavaScriptObfuscator.obfuscate(
278+
code,
279+
{
280+
...NO_ADDITIONAL_NODES_PRESET,
281+
target: ObfuscationTarget.ServiceWorker
282+
}
283+
).getObfuscatedCode();
284+
285+
classNameIdentifier = getRegExpMatch(obfuscatedCode, classNameIdentifierRegExp);
286+
outerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, outerClassNameReferenceRegExp);
287+
innerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, innerClassNameReferenceRegExp);
288+
});
289+
290+
it('match #1: should transform class name', () => {
291+
assert.match(obfuscatedCode, classNameIdentifierRegExp);
292+
});
293+
294+
it('match #2: should transform class name reference outside of class', () => {
295+
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
296+
});
297+
298+
it('match #3: should transform class name reference inside class', () => {
299+
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
300+
});
301+
302+
it('match #4: should generate same identifier names for class name and outer class name reference', () => {
303+
assert.equal(classNameIdentifier, outerClassNameReferenceIdentifierName);
304+
});
305+
306+
it('match #5: should generate same identifier names for class name and inner class name reference', () => {
307+
assert.equal(classNameIdentifier, innerClassNameReferenceIdentifierName);
308+
});
309+
});
310+
});
230311
});
231312

232313
describe('Variant #2: `renameGlobals` option is enabled', () => {
@@ -479,6 +560,104 @@ describe('ScopeIdentifiersTransformer ClassDeclaration identifiers', () => {
479560
});
480561
});
481562
});
563+
564+
describe('Variant #4: target: `service-worker', () => {
565+
describe('Variant #1: correct class name references in global scope', () => {
566+
const classNameIdentifierRegExp: RegExp = /class (_0x[a-f0-9]{4,6}) *\{/;
567+
const outerClassNameReferenceRegExp: RegExp = /console\['log']\((_0x[a-f0-9]{4,6})\);/;
568+
const innerClassNameReferenceRegExp: RegExp = /return (_0x[a-f0-9]{4,6});/;
569+
570+
let obfuscatedCode: string;
571+
let classNameIdentifier: string;
572+
let outerClassNameReferenceIdentifierName: string;
573+
let innerClassNameReferenceIdentifierName: string;
574+
575+
before(() => {
576+
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-global-scope.js');
577+
578+
obfuscatedCode = JavaScriptObfuscator.obfuscate(
579+
code,
580+
{
581+
...NO_ADDITIONAL_NODES_PRESET,
582+
renameGlobals: true,
583+
target: ObfuscationTarget.ServiceWorker
584+
}
585+
).getObfuscatedCode();
586+
587+
classNameIdentifier = getRegExpMatch(obfuscatedCode, classNameIdentifierRegExp);
588+
outerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, outerClassNameReferenceRegExp);
589+
innerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, innerClassNameReferenceRegExp);
590+
});
591+
592+
it('match #1: should transform class name', () => {
593+
assert.match(obfuscatedCode, classNameIdentifierRegExp);
594+
});
595+
596+
it('match #2: should transform class name reference outside of class', () => {
597+
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
598+
});
599+
600+
it('match #3: should transform class name reference inside class', () => {
601+
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
602+
});
603+
604+
it('match #4: should generate same identifier names for class name and outer class name reference', () => {
605+
assert.equal(classNameIdentifier, outerClassNameReferenceIdentifierName);
606+
});
607+
608+
it('match #5: should generate same identifier names for class name and inner class name reference', () => {
609+
assert.equal(classNameIdentifier, innerClassNameReferenceIdentifierName);
610+
});
611+
});
612+
613+
describe('Variant #2: correct class name references in function scope', () => {
614+
const classNameIdentifierRegExp: RegExp = /class (_0x[a-f0-9]{4,6}) *\{/;
615+
const outerClassNameReferenceRegExp: RegExp = /c< 8000 span class=pl-s>onsole\['log']\((_0x[a-f0-9]{4,6})\);/;
616+
const innerClassNameReferenceRegExp: RegExp = /return (_0x[a-f0-9]{4,6});/;
617+
618+
let obfuscatedCode: string;
619+
let classNameIdentifier: string;
620+
let outerClassNameReferenceIdentifierName: string;
621+
let innerClassNameReferenceIdentifierName: string;
622+
623+
before(() => {
624+
const code: string = readFileAsString(__dirname + '/fixtures/class-name-references-function-scope.js');
625+
626+
obfuscatedCode = JavaScriptObfuscator.obfuscate(
627+
code,
628+
{
629+
...NO_ADDITIONAL_NODES_PRESET,
630+
renameGlobals: true,
631+
target: ObfuscationTarget.ServiceWorker
632+
}
633+
).getObfuscatedCode();
634+
635+
classNameIdentifier = getRegExpMatch(obfuscatedCode, classNameIdentifierRegExp);
636+
outerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, outerClassNameReferenceRegExp);
637+
innerClassNameReferenceIdentifierName = getRegExpMatch(obfuscatedCode, innerClassNameReferenceRegExp);
638+
});
639+
640+
it('match #1: should transform class name', () => {
641+
assert.match(obfuscatedCode, classNameIdentifierRegExp);
642+
});
643+
644+
it('match #2: should transform class name reference outside of class', () => {
645+
assert.match(obfuscatedCode, outerClassNameReferenceRegExp);
646+
});
647+
648+
it('match #3: should transform class name reference inside class', () => {
649+
assert.match(obfuscatedCode, innerClassNameReferenceRegExp);
650+
});
651+
652+
it('match #4: should generate same identifier names for class name and outer class name reference', () => {
653+
assert.equal(classNameIdentifier, outerClassNameReferenceIdentifierName);
654+
});
655+
656+
it('match #5: should generate same identifier names for class name and inner class name reference', () => {
657+
assert.equal(classNameIdentifier, innerClassNameReferenceIdentifierName);
658+
});
659+
});
660+
});
482661
});
483662
});
484663

test/functional-tests/options/domain-lock/Validation.spec.ts

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,40 @@ describe('`domainLock` validation', () => {
5050

5151
describe('Variant #2: negative validation', () => {
5252
const expectedError: string = 'This option allowed only for obfuscation targets';
53-
5453
let testFunc: () => string;
5554

56-
beforeEach(() => {
57-
testFunc = () => JavaScriptObfuscator.obfuscate(
58-
'',
59-
{
60-
...NO_ADDITIONAL_NODES_PRESET,
61-
domainLock: ['www.example.com'],
62-
target: ObfuscationTarget.Node
63-
}
64-
).getObfuscatedCode();
55+
describe('Variant #1: obfuscation target: `node`', () => {
56+
beforeEach(() => {
57+
testFunc = () => JavaScriptObfuscator.obfuscate(
58+
'',
59+
{
60+
...NO_ADDITIONAL_NODES_PRESET,
61+
domainLock: ['www.example.com'],
62+
target: ObfuscationTarget.Node
63+
}
64+
).getObfuscatedCode();
65+
});
66+
67+
it('should not pass validation when obfuscation target is `node` and value is not default', () => {
68+
assert.throws(testFunc, expectedError);
69+
});
6570
});
6671

67-
it('should not pass validation when obfuscation target is `node` and value is not default', () => {
68-
assert.throws(testFunc, expectedError);
72+
describe('Variant #1: obfuscation target: `service-worker`', () => {
73+
beforeEach(() => {
74+
testFunc = () => JavaScriptObfuscator.obfuscate(
75+
'',
76+
{
77+
...NO_ADDITIONAL_NODES_PRESET,
78+
domainLock: ['www.example.com'],
79+
target: ObfuscationTarget.ServiceWorker
80+
}
81+
).getObfuscatedCode();
82+
});
83+
84+
it('should not pass validation when obfuscation target is `service-worker` and value is not default', () => {
85+
assert.throws(testFunc, expectedError);
86+
});
6987
});
7088
});
7189
});

0 commit comments

Comments
 (0)
0