js-confuser 1.7.1 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +12 -27
- package/dist/compiler.js +2 -8
- package/dist/constants.js +17 -10
- package/dist/index.js +7 -30
- package/dist/obfuscator.js +15 -62
- package/dist/options.js +21 -38
- package/dist/order.js +4 -7
- package/dist/parser.js +5 -13
- package/dist/precedence.js +6 -8
- package/dist/presets.js +4 -6
- package/dist/probability.js +13 -24
- package/dist/templates/bufferToString.js +100 -5
- package/dist/templates/crash.js +51 -9
- package/dist/templates/es5.js +125 -6
- package/dist/templates/functionLength.js +24 -6
- package/dist/templates/globals.js +9 -0
- package/dist/templates/template.js +71 -30
- package/dist/transforms/antiTooling.js +26 -22
- package/dist/transforms/calculator.js +18 -54
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +236 -333
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
- package/dist/transforms/deadCode.js +528 -27
- package/dist/transforms/dispatcher.js +106 -110
- package/dist/transforms/es5/antiClass.js +70 -44
- package/dist/transforms/es5/antiDestructuring.js +14 -38
- package/dist/transforms/es5/antiES6Object.js +39 -48
- package/dist/transforms/es5/antiSpreadOperator.js +5 -14
- package/dist/transforms/es5/antiTemplate.js +10 -19
- package/dist/transforms/es5/es5.js +7 -40
- package/dist/transforms/extraction/classExtraction.js +83 -0
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +41 -80
- package/dist/transforms/extraction/objectExtraction.js +24 -56
- package/dist/transforms/finalizer.js +6 -20
- package/dist/transforms/flatten.js +51 -99
- package/dist/transforms/identifier/globalAnalysis.js +8 -26
- package/dist/transforms/identifier/globalConcealing.js +35 -54
- package/dist/transforms/identifier/movedDeclarations.js +66 -38
- package/dist/transforms/identifier/renameVariables.js +29 -68
- package/dist/transforms/identifier/variableAnalysis.js +21 -48
- package/dist/transforms/lock/antiDebug.js +20 -25
- package/dist/transforms/lock/integrity.js +48 -47
- package/dist/transforms/lock/lock.js +62 -113
- package/dist/transforms/minify.js +77 -108
- package/dist/transforms/opaquePredicates.js +11 -48
- package/dist/transforms/preparation.js +17 -50
- package/dist/transforms/renameLabels.js +5 -22
- package/dist/transforms/rgf.js +93 -69
- package/dist/transforms/shuffle.js +41 -46
- package/dist/transforms/stack.js +35 -98
- package/dist/transforms/string/encoding.js +73 -27
- package/dist/transforms/string/stringCompression.js +44 -68
- package/dist/transforms/string/stringConcealing.js +125 -134
- package/dist/transforms/string/stringEncoding.js +6 -26
- package/dist/transforms/string/stringSplitting.js +5 -30
- package/dist/transforms/transform.js +50 -100
- package/dist/traverse.js +11 -18
- package/dist/util/compare.js +27 -29
- package/dist/util/gen.js +32 -86
- package/dist/util/guard.js +0 -1
- package/dist/util/identifiers.js +9 -72
- package/dist/util/insert.js +27 -77
- package/dist/util/math.js +0 -3
- package/dist/util/object.js +3 -7
- package/dist/util/random.js +5 -36
- package/dist/util/scope.js +6 -3
- package/package.json +3 -3
- package/src/constants.ts +12 -0
- package/src/options.ts +13 -0
- package/src/order.ts +2 -2
- package/src/templates/bufferToString.ts +49 -11
- package/src/templates/functionLength.ts +21 -3
- package/src/templates/globals.ts +3 -0
- package/src/templates/template.ts +85 -25
- package/src/transforms/antiTooling.ts +33 -11
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +2 -2
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
- package/src/transforms/deadCode.ts +0 -16
- package/src/transforms/dispatcher.ts +91 -69
- package/src/transforms/es5/antiClass.ts +10 -1
- package/src/transforms/extraction/classExtraction.ts +168 -0
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -10
- package/src/transforms/extraction/objectExtraction.ts +4 -15
- package/src/transforms/flatten.ts +20 -5
- package/src/transforms/identifier/globalConcealing.ts +29 -65
- package/src/transforms/identifier/movedDeclarations.ts +90 -24
- package/src/transforms/minify.ts +27 -12
- package/src/transforms/rgf.ts +94 -5
- package/src/transforms/stack.ts +12 -3
- package/src/transforms/string/encoding.ts +85 -51
- package/src/transforms/string/stringCompression.ts +5 -8
- package/src/transforms/string/stringConcealing.ts +139 -113
- package/src/transforms/string/stringEncoding.ts +1 -2
- package/src/transforms/string/stringSplitting.ts +1 -2
- package/src/transforms/transform.ts +30 -1
- package/src/util/compare.ts +39 -5
- package/src/util/gen.ts +10 -3
- package/src/util/insert.ts +17 -0
- package/src/util/scope.ts +14 -2
- package/test/code/Cash.test.ts +10 -4
- package/test/code/StrictMode.src.js +65 -0
- package/test/code/StrictMode.test.js +37 -0
- package/test/compare.test.ts +62 -2
- package/test/options.test.ts +111 -55
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +37 -18
- package/test/transforms/dispatcher.test.ts +55 -0
- package/test/transforms/extraction/classExtraction.test.ts +86 -0
- package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +8 -0
- package/test/transforms/extraction/objectExtraction.test.ts +2 -0
- package/test/transforms/identifier/globalConcealing.test.ts +19 -0
- package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
- package/test/transforms/minify.test.ts +37 -0
- package/test/transforms/rgf.test.ts +50 -0
- package/dist/transforms/controlFlowFlattening/choiceFlowObfuscation.js +0 -62
- package/dist/transforms/controlFlowFlattening/controlFlowObfuscation.js +0 -159
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +0 -106
- package/dist/transforms/eval.js +0 -84
- package/dist/transforms/hexadecimalNumbers.js +0 -63
- package/dist/transforms/hideInitializingCode.js +0 -270
- package/dist/transforms/identifier/nameRecycling.js +0 -218
- package/dist/transforms/label.js +0 -67
- package/dist/transforms/preparation/nameConflicts.js +0 -116
- package/dist/transforms/preparation/preparation.js +0 -188
|
@@ -1,19 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
placeholderVariablePrefix,
|
|
3
|
+
predictableFunctionTag,
|
|
4
|
+
} from "../constants";
|
|
1
5
|
import Template from "./template";
|
|
2
6
|
|
|
3
|
-
export const
|
|
4
|
-
function
|
|
7
|
+
export const GetGlobalTemplate = Template(`
|
|
8
|
+
function ${placeholderVariablePrefix}CFG__getGlobalThis${predictableFunctionTag}(){
|
|
9
|
+
return globalThis
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function ${placeholderVariablePrefix}CFG__getGlobal${predictableFunctionTag}(){
|
|
13
|
+
return global
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function ${placeholderVariablePrefix}CFG__getWindow${predictableFunctionTag}(){
|
|
17
|
+
return window
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function ${placeholderVariablePrefix}CFG__getThisFunction${predictableFunctionTag}(){
|
|
21
|
+
return new Function("return this")()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function {getGlobalFnName}(array = [
|
|
25
|
+
${placeholderVariablePrefix}CFG__getGlobalThis${predictableFunctionTag},
|
|
26
|
+
${placeholderVariablePrefix}CFG__getGlobal${predictableFunctionTag},
|
|
27
|
+
${placeholderVariablePrefix}CFG__getWindow${predictableFunctionTag},
|
|
28
|
+
${placeholderVariablePrefix}CFG__getThisFunction${predictableFunctionTag}
|
|
29
|
+
]){
|
|
30
|
+
var bestMatch
|
|
31
|
+
var itemsToSearch = []
|
|
5
32
|
try {
|
|
6
|
-
|
|
7
|
-
|
|
33
|
+
bestMatch = Object
|
|
34
|
+
itemsToSearch["push"](("")["__proto__"]["constructor"]["name"])
|
|
35
|
+
} catch(e) {
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
A: for(var i = 0; i < array["length"]; i++) {
|
|
8
39
|
try {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
40
|
+
bestMatch = array[i]()
|
|
41
|
+
for(var j = 0; j < itemsToSearch["length"]; j++) {
|
|
42
|
+
if(typeof bestMatch[itemsToSearch[j]] === "undefined") continue A;
|
|
43
|
+
}
|
|
44
|
+
return bestMatch
|
|
45
|
+
} catch(e) {}
|
|
13
46
|
}
|
|
47
|
+
|
|
48
|
+
return bestMatch || this;
|
|
14
49
|
}
|
|
50
|
+
`);
|
|
15
51
|
|
|
16
|
-
|
|
52
|
+
export const BufferToStringTemplate = Template(`
|
|
53
|
+
|
|
54
|
+
${GetGlobalTemplate.source}
|
|
55
|
+
|
|
56
|
+
var __globalObject = {getGlobalFnName}() || {};
|
|
17
57
|
var __TextDecoder = __globalObject["TextDecoder"];
|
|
18
58
|
var __Uint8Array = __globalObject["Uint8Array"];
|
|
19
59
|
var __Buffer = __globalObject["Buffer"];
|
|
@@ -63,6 +103,4 @@ export const BufferToStringTemplate = Template(`
|
|
|
63
103
|
return utf8ArrayToStr(buffer);
|
|
64
104
|
}
|
|
65
105
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
106
|
`);
|
|
@@ -3,12 +3,30 @@ import Template from "./template";
|
|
|
3
3
|
/**
|
|
4
4
|
* Helper function to set `function.length` property.
|
|
5
5
|
*/
|
|
6
|
-
export const FunctionLengthTemplate = Template(
|
|
6
|
+
export const FunctionLengthTemplate = Template(
|
|
7
|
+
`
|
|
7
8
|
function {name}(functionObject, functionLength){
|
|
8
|
-
|
|
9
|
+
{ObjectDefineProperty}(functionObject, "length", {
|
|
9
10
|
"value": functionLength,
|
|
10
11
|
"configurable": true
|
|
11
12
|
});
|
|
12
13
|
return functionObject;
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
+
`,
|
|
16
|
+
`
|
|
17
|
+
function {name}(functionObject, functionLength){
|
|
18
|
+
return {ObjectDefineProperty}(functionObject, "length", {
|
|
19
|
+
"value": functionLength,
|
|
20
|
+
"configurable": true
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
`,
|
|
24
|
+
`
|
|
25
|
+
function {name}(functionObject, functionLength){
|
|
26
|
+
return {ObjectDefineProperty}["call"](null, functionObject, "length", {
|
|
27
|
+
"value": functionLength,
|
|
28
|
+
"configurable": true
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
`
|
|
32
|
+
);
|
|
@@ -1,57 +1,103 @@
|
|
|
1
1
|
import { Node } from "../util/gen";
|
|
2
2
|
import { parseSnippet, parseSync } from "../parser";
|
|
3
|
+
import { ok } from "assert";
|
|
4
|
+
import { choice } from "../util/random";
|
|
5
|
+
import { placeholderVariablePrefix } from "../constants";
|
|
3
6
|
|
|
4
7
|
export interface ITemplate {
|
|
5
|
-
fill(variables?: { [name: string]: string | number }):
|
|
8
|
+
fill(variables?: { [name: string]: string | number }): {
|
|
9
|
+
output: string;
|
|
10
|
+
template: string;
|
|
11
|
+
};
|
|
6
12
|
|
|
7
13
|
compile(variables?: { [name: string]: string | number }): Node[];
|
|
8
14
|
|
|
9
15
|
single(variables?: { [name: string]: string | number }): Node;
|
|
10
16
|
|
|
17
|
+
variables(variables): ITemplate;
|
|
18
|
+
|
|
19
|
+
ignoreMissingVariables(): ITemplate;
|
|
20
|
+
|
|
21
|
+
templates: string[];
|
|
11
22
|
source: string;
|
|
12
23
|
}
|
|
13
24
|
|
|
14
|
-
export default function Template(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
export default function Template(...templates: string[]): ITemplate {
|
|
26
|
+
ok(templates.length);
|
|
27
|
+
|
|
28
|
+
var requiredVariables = new Set<string>();
|
|
29
|
+
var providedVariables = {};
|
|
30
|
+
var defaultVariables: { [key: string]: string } = Object.create(null);
|
|
31
|
+
|
|
32
|
+
// This may picked up "$mb[pP`x]" from String Encoding function
|
|
33
|
+
// ignoreMissingVariables() prevents this
|
|
34
|
+
var matches = templates[0].match(/{[$A-z0-9_]+}/g);
|
|
35
|
+
if (matches !== null) {
|
|
36
|
+
matches.forEach((variable) => {
|
|
37
|
+
var name = variable.slice(1, -1);
|
|
38
|
+
|
|
39
|
+
// $ variables are for default variables
|
|
40
|
+
if (name.startsWith("$")) {
|
|
41
|
+
defaultVariables[name] =
|
|
42
|
+
placeholderVariablePrefix +
|
|
43
|
+
"td_" +
|
|
44
|
+
Object.keys(defaultVariables).length;
|
|
45
|
+
} else {
|
|
46
|
+
requiredVariables.add(name);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
18
49
|
}
|
|
19
|
-
var vars = Object.create(null);
|
|
20
|
-
new Array(neededVariables + 1).fill(0).forEach((x, i) => {
|
|
21
|
-
vars["\\$" + i] = "temp_" + i;
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
function fill(variables?: { [name: string]: string | number }): string {
|
|
25
|
-
if (!variables) {
|
|
26
|
-
variables = Object.create(null);
|
|
27
|
-
}
|
|
28
50
|
|
|
29
|
-
|
|
51
|
+
function fill(
|
|
52
|
+
variables: { [name: string]: string | number } = Object.create(null)
|
|
53
|
+
) {
|
|
54
|
+
var userVariables = { ...providedVariables, ...variables };
|
|
55
|
+
|
|
56
|
+
// Validate all variables were passed in
|
|
57
|
+
for (var requiredVariable of requiredVariables) {
|
|
58
|
+
if (typeof userVariables[requiredVariable] === "undefined") {
|
|
59
|
+
throw new Error(
|
|
60
|
+
templates[0] +
|
|
61
|
+
" missing variable: " +
|
|
62
|
+
requiredVariable +
|
|
63
|
+
" from " +
|
|
64
|
+
JSON.stringify(userVariables)
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
30
68
|
|
|
31
|
-
var
|
|
69
|
+
var template = choice(templates);
|
|
70
|
+
var output = template;
|
|
71
|
+
var allVariables = {
|
|
72
|
+
...defaultVariables,
|
|
73
|
+
...userVariables,
|
|
74
|
+
};
|
|
32
75
|
|
|
33
|
-
Object.keys(
|
|
34
|
-
var bracketName = "{" + name + "}";
|
|
35
|
-
var value =
|
|
76
|
+
Object.keys(allVariables).forEach((name) => {
|
|
77
|
+
var bracketName = "{" + name.replace("$", "\\$") + "}";
|
|
78
|
+
var value = allVariables[name] + "";
|
|
36
79
|
|
|
37
80
|
var reg = new RegExp(bracketName, "g");
|
|
38
81
|
|
|
39
|
-
|
|
82
|
+
output = output.replace(reg, value);
|
|
40
83
|
});
|
|
41
84
|
|
|
42
|
-
return
|
|
85
|
+
return { output, template };
|
|
43
86
|
}
|
|
44
87
|
|
|
45
88
|
function compile(variables: { [name: string]: string | number }): Node[] {
|
|
46
|
-
var
|
|
89
|
+
var { output, template } = fill(variables);
|
|
47
90
|
try {
|
|
48
|
-
var program = parseSnippet(
|
|
91
|
+
var program = parseSnippet(output);
|
|
49
92
|
|
|
50
93
|
return program.body;
|
|
51
94
|
} catch (e) {
|
|
52
95
|
console.error(e);
|
|
53
96
|
console.error(template);
|
|
54
|
-
|
|
97
|
+
console.error({ ...providedVariables, ...variables });
|
|
98
|
+
throw new Error(
|
|
99
|
+
"Template failed to parse: OUTPUT= " + output + " SOURCE= " + template
|
|
100
|
+
);
|
|
55
101
|
}
|
|
56
102
|
}
|
|
57
103
|
|
|
@@ -60,11 +106,25 @@ export default function Template(template: string): ITemplate {
|
|
|
60
106
|
return nodes[0];
|
|
61
107
|
}
|
|
62
108
|
|
|
109
|
+
function variables(newVariables) {
|
|
110
|
+
Object.assign(providedVariables, newVariables);
|
|
111
|
+
return obj;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function ignoreMissingVariables() {
|
|
115
|
+
defaultVariables = Object.create(null);
|
|
116
|
+
requiredVariables.clear();
|
|
117
|
+
return obj;
|
|
118
|
+
}
|
|
119
|
+
|
|
63
120
|
var obj: ITemplate = {
|
|
64
121
|
fill,
|
|
65
122
|
compile,
|
|
66
123
|
single,
|
|
67
|
-
|
|
124
|
+
templates,
|
|
125
|
+
variables,
|
|
126
|
+
ignoreMissingVariables,
|
|
127
|
+
source: templates[0],
|
|
68
128
|
};
|
|
69
129
|
|
|
70
130
|
return obj;
|
|
@@ -1,32 +1,51 @@
|
|
|
1
1
|
import { ObfuscateOrder } from "../order";
|
|
2
|
+
import Template from "../templates/template";
|
|
2
3
|
import { isBlock } from "../traverse";
|
|
3
4
|
import {
|
|
5
|
+
Node,
|
|
4
6
|
ExpressionStatement,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
CallExpression,
|
|
8
|
+
Identifier,
|
|
7
9
|
} from "../util/gen";
|
|
8
|
-
import {
|
|
10
|
+
import { prepend } from "../util/insert";
|
|
9
11
|
import Transform from "./transform";
|
|
10
12
|
|
|
11
13
|
// JsNice.org tries to separate sequence expressions into multiple lines, this stops that.
|
|
12
14
|
export default class AntiTooling extends Transform {
|
|
15
|
+
fnName: string;
|
|
16
|
+
|
|
13
17
|
constructor(o) {
|
|
14
18
|
super(o, ObfuscateOrder.AntiTooling);
|
|
15
19
|
}
|
|
16
20
|
|
|
21
|
+
apply(tree: Node) {
|
|
22
|
+
super.apply(tree);
|
|
23
|
+
|
|
24
|
+
if (typeof this.fnName === "string") {
|
|
25
|
+
prepend(
|
|
26
|
+
tree,
|
|
27
|
+
Template(`
|
|
28
|
+
function {fnName}(){
|
|
29
|
+
}
|
|
30
|
+
`).single({ fnName: this.fnName })
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
17
35
|
match(object, parents) {
|
|
18
36
|
return isBlock(object) || object.type == "SwitchCase";
|
|
19
37
|
}
|
|
20
38
|
|
|
21
39
|
transform(object, parents) {
|
|
22
40
|
return () => {
|
|
23
|
-
var exprs = [];
|
|
24
|
-
var deleteExprs = [];
|
|
41
|
+
var exprs: Node[] = [];
|
|
42
|
+
var deleteExprs: Node[] = [];
|
|
25
43
|
|
|
26
|
-
var body =
|
|
44
|
+
var body: Node[] =
|
|
45
|
+
object.type == "SwitchCase" ? object.consequent : object.body;
|
|
27
46
|
|
|
28
47
|
const end = () => {
|
|
29
|
-
function flatten(expr) {
|
|
48
|
+
function flatten(expr: Node) {
|
|
30
49
|
if (expr.type == "ExpressionStatement") {
|
|
31
50
|
flatten(expr.expression);
|
|
32
51
|
} else if (expr.type == "SequenceExpression") {
|
|
@@ -41,13 +60,16 @@ export default class AntiTooling extends Transform {
|
|
|
41
60
|
|
|
42
61
|
if (flattened.length > 1) {
|
|
43
62
|
flattened[0] = { ...flattened[0] };
|
|
63
|
+
|
|
64
|
+
if (!this.fnName) {
|
|
65
|
+
this.fnName = this.getPlaceholder();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// (expr1,expr2,expr3) -> F(expr1, expr2, expr3)
|
|
44
69
|
this.replace(
|
|
45
70
|
exprs[0],
|
|
46
71
|
ExpressionStatement(
|
|
47
|
-
|
|
48
|
-
choice(["typeof", "void", "!"]),
|
|
49
|
-
SequenceExpression(flattened)
|
|
50
|
-
)
|
|
72
|
+
CallExpression(Identifier(this.fnName), [...flattened])
|
|
51
73
|
)
|
|
52
74
|
);
|
|
53
75
|
|
|
@@ -47,9 +47,8 @@ import {
|
|
|
47
47
|
import { chance, choice, getRandomInteger, shuffle } from "../../util/random";
|
|
48
48
|
import Transform from "../transform";
|
|
49
49
|
import ExpressionObfuscation from "./expressionObfuscation";
|
|
50
|
-
import { isModuleSource } from "../string/stringConcealing";
|
|
51
50
|
import { reservedIdentifiers } from "../../constants";
|
|
52
|
-
import { isDirective } from "../../util/compare";
|
|
51
|
+
import { isDirective, isModuleSource } from "../../util/compare";
|
|
53
52
|
|
|
54
53
|
const flattenStructures = new Set([
|
|
55
54
|
"IfStatement",
|
|
@@ -1571,6 +1570,7 @@ export default class ControlFlowFlattening extends Transform {
|
|
|
1571
1570
|
!this.isDebug &&
|
|
1572
1571
|
o.type === "Identifier" &&
|
|
1573
1572
|
this.mangleIdentifiers &&
|
|
1573
|
+
!reservedIdentifiers.has(o.name) &&
|
|
1574
1574
|
chance(50 - this.mangledExpressionsMade / 100) &&
|
|
1575
1575
|
!p.find((x) => isVarContext(x))
|
|
1576
1576
|
) {
|
|
@@ -1,15 +1,48 @@
|
|
|
1
|
+
import { criticalFunctionTag } from "../../constants";
|
|
2
|
+
import Template from "../../templates/template";
|
|
1
3
|
import { isBlock } from "../../traverse";
|
|
2
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
CallExpression,
|
|
6
|
+
Identifier,
|
|
7
|
+
Node,
|
|
8
|
+
SequenceExpression,
|
|
9
|
+
} from "../../util/gen";
|
|
10
|
+
import { prepend } from "../../util/insert";
|
|
3
11
|
import Transform from "../transform";
|
|
4
12
|
|
|
5
13
|
/**
|
|
6
14
|
* Expression Obfuscation runs before Control Flow Flattening
|
|
7
15
|
*/
|
|
8
16
|
export default class ExpressionObfuscation extends Transform {
|
|
17
|
+
fnName: string;
|
|
18
|
+
|
|
9
19
|
constructor(o) {
|
|
10
20
|
super(o);
|
|
11
21
|
}
|
|
12
22
|
|
|
23
|
+
apply(tree: Node): void {
|
|
24
|
+
super.apply(tree);
|
|
25
|
+
|
|
26
|
+
if (typeof this.fnName === "string") {
|
|
27
|
+
prepend(
|
|
28
|
+
tree,
|
|
29
|
+
Template(`
|
|
30
|
+
function {fnName}(...args){
|
|
31
|
+
return args[args["length"] - 1]
|
|
32
|
+
}
|
|
33
|
+
`).single({ fnName: this.fnName })
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
createSequenceExpression(expressions: Node[]): Node {
|
|
39
|
+
if (!this.fnName) {
|
|
40
|
+
this.fnName = this.getPlaceholder() + criticalFunctionTag;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return CallExpression(Identifier(this.fnName), [...expressions]);
|
|
44
|
+
}
|
|
45
|
+
|
|
13
46
|
match(object, parents) {
|
|
14
47
|
return isBlock(object);
|
|
15
48
|
}
|
|
@@ -54,12 +87,12 @@ export default class ExpressionObfuscation extends Transform {
|
|
|
54
87
|
stmt.test.left.argument.type === "Identifier"
|
|
55
88
|
) // typeof is special
|
|
56
89
|
) {
|
|
57
|
-
stmt.test.left.argument =
|
|
90
|
+
stmt.test.left.argument = this.createSequenceExpression([
|
|
58
91
|
...exprs,
|
|
59
92
|
{ ...stmt.test.left.argument },
|
|
60
93
|
]);
|
|
61
94
|
} else {
|
|
62
|
-
stmt.test.left =
|
|
95
|
+
stmt.test.left = this.createSequenceExpression([
|
|
63
96
|
...exprs,
|
|
64
97
|
{ ...stmt.test.left },
|
|
65
98
|
]);
|
|
@@ -70,12 +103,15 @@ export default class ExpressionObfuscation extends Transform {
|
|
|
70
103
|
stmt.test.operator !== "**" &&
|
|
71
104
|
stmt.test.left.left.type == "UnaryExpression"
|
|
72
105
|
) {
|
|
73
|
-
stmt.test.left.left.argument =
|
|
106
|
+
stmt.test.left.left.argument = this.createSequenceExpression([
|
|
74
107
|
...exprs,
|
|
75
108
|
{ ...stmt.test.left.left.argument },
|
|
76
109
|
]);
|
|
77
110
|
} else {
|
|
78
|
-
stmt.test =
|
|
111
|
+
stmt.test = this.createSequenceExpression([
|
|
112
|
+
...exprs,
|
|
113
|
+
{ ...stmt.test },
|
|
114
|
+
]);
|
|
79
115
|
}
|
|
80
116
|
deleteExprs.push(...exprs);
|
|
81
117
|
} else if (
|
|
@@ -88,7 +124,7 @@ export default class ExpressionObfuscation extends Transform {
|
|
|
88
124
|
|
|
89
125
|
if (init) {
|
|
90
126
|
if (init.type == "VariableDeclaration") {
|
|
91
|
-
init.declarations[0].init =
|
|
127
|
+
init.declarations[0].init = this.createSequenceExpression([
|
|
92
128
|
...exprs,
|
|
93
129
|
{
|
|
94
130
|
...(init.declarations[0].init || Identifier("undefined")),
|
|
@@ -96,7 +132,7 @@ export default class ExpressionObfuscation extends Transform {
|
|
|
96
132
|
]);
|
|
97
133
|
deleteExprs.push(...exprs);
|
|
98
134
|
} else if (init.type == "AssignmentExpression") {
|
|
99
|
-
init.right =
|
|
135
|
+
init.right = this.createSequenceExpression([
|
|
100
136
|
...exprs,
|
|
101
137
|
{
|
|
102
138
|
...(init.right || Identifier("undefined")),
|
|
@@ -106,7 +142,7 @@ export default class ExpressionObfuscation extends Transform {
|
|
|
106
142
|
}
|
|
107
143
|
}
|
|
108
144
|
} else if (stmt.type == "VariableDeclaration") {
|
|
109
|
-
stmt.declarations[0].init =
|
|
145
|
+
stmt.declarations[0].init = this.createSequenceExpression([
|
|
110
146
|
...exprs,
|
|
111
147
|
{
|
|
112
148
|
...(stmt.declarations[0].init || Identifier("undefined")),
|
|
@@ -114,13 +150,13 @@ export default class ExpressionObfuscation extends Transform {
|
|
|
114
150
|
]);
|
|
115
151
|
deleteExprs.push(...exprs);
|
|
116
152
|
} else if (stmt.type == "ThrowStatement") {
|
|
117
|
-
stmt.argument =
|
|
153
|
+
stmt.argument = this.createSequenceExpression([
|
|
118
154
|
...exprs,
|
|
119
155
|
{ ...stmt.argument },
|
|
120
156
|
]);
|
|
121
157
|
deleteExprs.push(...exprs);
|
|
122
158
|
} else if (stmt.type == "ReturnStatement") {
|
|
123
|
-
stmt.argument =
|
|
159
|
+
stmt.argument = this.createSequenceExpression([
|
|
124
160
|
...exprs,
|
|
125
161
|
{ ...(stmt.argument || Identifier("undefined")) },
|
|
126
162
|
]);
|
|
@@ -188,10 +188,6 @@ function setCookie(cname, cvalue, exdays) {
|
|
|
188
188
|
return true;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
/**
|
|
192
|
-
* @param {TreeNode} root
|
|
193
|
-
* @return {boolean}
|
|
194
|
-
*/
|
|
195
191
|
function isBalanced(root) {
|
|
196
192
|
const height = getHeightBalanced(root);
|
|
197
193
|
return height !== Infinity;
|
|
@@ -426,9 +422,6 @@ function setCookie(cname, cvalue, exdays) {
|
|
|
426
422
|
console.log(maximumGap);
|
|
427
423
|
`),
|
|
428
424
|
Template(`
|
|
429
|
-
/**
|
|
430
|
-
* @param {number} capacity
|
|
431
|
-
*/
|
|
432
425
|
var LRUCache = function(capacity) {
|
|
433
426
|
this.capacity = capacity;
|
|
434
427
|
this.length = 0;
|
|
@@ -437,10 +430,6 @@ function setCookie(cname, cvalue, exdays) {
|
|
|
437
430
|
this.tail = null;
|
|
438
431
|
};
|
|
439
432
|
|
|
440
|
-
/**
|
|
441
|
-
* @param {number} key
|
|
442
|
-
* @return {number}
|
|
443
|
-
*/
|
|
444
433
|
LRUCache.prototype.get = function(key) {
|
|
445
434
|
var node = this.map[key];
|
|
446
435
|
if (node) {
|
|
@@ -452,11 +441,6 @@ function setCookie(cname, cvalue, exdays) {
|
|
|
452
441
|
}
|
|
453
442
|
};
|
|
454
443
|
|
|
455
|
-
/**
|
|
456
|
-
* @param {number} key
|
|
457
|
-
* @param {number} value
|
|
458
|
-
* @return {void}
|
|
459
|
-
*/
|
|
460
444
|
LRUCache.prototype.put = function(key, value) {
|
|
461
445
|
if (this.map[key]) {
|
|
462
446
|
this.remove(this.map[key]);
|