@dacely/toildefender 0.1.0
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/LICENSE +661 -0
- package/NOTICE.md +16 -0
- package/README.md +380 -0
- package/cli.js +168 -0
- package/defendjs.js +7 -0
- package/docs/all-modes-output.demo.js +673 -0
- package/estest.js +49 -0
- package/esutils.js +107 -0
- package/logger.js +28 -0
- package/obfuscator.js +534 -0
- package/package.json +108 -0
- package/processors/deadCode.js +62 -0
- package/processors/flattener.js +808 -0
- package/processors/health.js +55 -0
- package/processors/identifiers.js +256 -0
- package/processors/literalObfuscator.js +40 -0
- package/processors/literals.js +233 -0
- package/processors/methods.js +332 -0
- package/processors/modules.js +231 -0
- package/processors/normalizer.js +490 -0
- package/processors/numericVm.js +950 -0
- package/processors/postprocessing.js +69 -0
- package/processors/preprocessing.js +248 -0
- package/processors/scopes.js +177 -0
- package/processors/uglifier.js +26 -0
- package/processors/variables.js +185 -0
- package/toildefender.js +7 -0
- package/traverser.js +115 -0
- package/utils.js +135 -0
package/toildefender.js
ADDED
package/traverser.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var assert = require("assert");
|
|
4
|
+
|
|
5
|
+
var estraverse = require("estraverse");
|
|
6
|
+
|
|
7
|
+
var estest = require("./estest");
|
|
8
|
+
var utils = require("./utils");
|
|
9
|
+
|
|
10
|
+
// Depth-first
|
|
11
|
+
exports.traverse = function (node, stack, processor) {
|
|
12
|
+
assert.ok(estest.isNode(node));
|
|
13
|
+
assert.ok(Array.isArray(stack));
|
|
14
|
+
assert.equal(typeof processor, "function");
|
|
15
|
+
|
|
16
|
+
exports.visitChildren(node, (child, key) => {
|
|
17
|
+
return exports.traverse(child, [ { node: node, key: key } ].concat(stack), processor);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return processor(node, [ { node: node } ].concat(stack));
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Breadth-first
|
|
24
|
+
exports.traverseEx = function (node, stack, processor) {
|
|
25
|
+
assert.ok(estest.isNode(node));
|
|
26
|
+
assert.ok(Array.isArray(stack));
|
|
27
|
+
assert.equal(typeof processor, "function");
|
|
28
|
+
|
|
29
|
+
var abort = false;
|
|
30
|
+
var controller = {
|
|
31
|
+
abort: function() {
|
|
32
|
+
abort = true;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
var queue = [];
|
|
37
|
+
exports.visitChildrenEx(node, (child, key) => {
|
|
38
|
+
var repl = processor.call(controller, child, [ { node: node } ].concat(stack));
|
|
39
|
+
if (repl == child) {
|
|
40
|
+
queue.push({
|
|
41
|
+
child: child,
|
|
42
|
+
key: key
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return repl;
|
|
46
|
+
});
|
|
47
|
+
if (!abort) {
|
|
48
|
+
queue.every(elem => {
|
|
49
|
+
exports.traverseEx.call(controller, elem.child, [ { node: node, key: elem.key } ].concat(stack), processor);
|
|
50
|
+
return !abort;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return node;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
exports.visitChildren = function (node, processor) {
|
|
57
|
+
assert.ok(estest.isNode(node));
|
|
58
|
+
assert.equal(typeof processor, "function");
|
|
59
|
+
|
|
60
|
+
var keys = estraverse.VisitorKeys[node.type] || [];
|
|
61
|
+
keys.forEach(key => {
|
|
62
|
+
if (Array.isArray(node[key])) {
|
|
63
|
+
node[key] = node[key].map(x => {
|
|
64
|
+
if (x == null) {
|
|
65
|
+
return x;
|
|
66
|
+
}
|
|
67
|
+
var repl = processor(x, key);
|
|
68
|
+
assert(repl);
|
|
69
|
+
return repl;
|
|
70
|
+
});
|
|
71
|
+
} else if (node[key]) {
|
|
72
|
+
var repl = processor(node[key], key);
|
|
73
|
+
assert(repl);
|
|
74
|
+
node[key] = repl;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
exports.visitChildrenEx = function (node, processor) {
|
|
80
|
+
assert.ok(estest.isNode(node));
|
|
81
|
+
assert.equal(typeof processor, "function");
|
|
82
|
+
|
|
83
|
+
var keys = estraverse.VisitorKeys[node.type] || [];
|
|
84
|
+
keys.forEach(key => {
|
|
85
|
+
if (Array.isArray(node[key])) {
|
|
86
|
+
let i = node[key].length;
|
|
87
|
+
while (i--) {
|
|
88
|
+
if (node[key][i] == null) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
let replacement = processor(node[key][i], key);
|
|
92
|
+
assert(replacement);
|
|
93
|
+
if (replacement.length == 1) {
|
|
94
|
+
replacement = replacement[0];
|
|
95
|
+
}
|
|
96
|
+
if (Array.isArray(replacement)) {
|
|
97
|
+
utils.splice(node[key], i, 1, replacement);
|
|
98
|
+
} else {
|
|
99
|
+
node[key][i] = replacement;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} else if (node[key]) {
|
|
103
|
+
let replacement = processor(node[key], key);
|
|
104
|
+
assert(replacement);
|
|
105
|
+
if (replacement.length == 1) {
|
|
106
|
+
replacement = replacement[0];
|
|
107
|
+
}
|
|
108
|
+
if (Array.isArray(replacement)) {
|
|
109
|
+
throw new Error("Cannot use array here: " + node.type + "." + key + "\n" + JSON.stringify(node) + "\n" + JSON.stringify(replacement));
|
|
110
|
+
} else {
|
|
111
|
+
node[key] = replacement;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
};
|
package/utils.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var assert = require("assert");
|
|
4
|
+
|
|
5
|
+
var _ = require("lodash");
|
|
6
|
+
var escodegen = require("escodegen");
|
|
7
|
+
var esprima = require("esprima");
|
|
8
|
+
|
|
9
|
+
var traverser = require("./traverser");
|
|
10
|
+
|
|
11
|
+
exports.splice = function (arr, pos, del, elems) {
|
|
12
|
+
Array.prototype.splice.apply(arr, [ pos, del ].concat(elems));
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
exports.unshift = function (arr, arr2) {
|
|
16
|
+
if (Array.isArray(arr2)) {
|
|
17
|
+
Array.prototype.unshift(arr, arr2);
|
|
18
|
+
} else {
|
|
19
|
+
arr.push(arr2);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
exports.push = function (arr, arr2) {
|
|
24
|
+
if (Array.isArray(arr2)) {
|
|
25
|
+
Array.prototype.push.apply(arr, arr2);
|
|
26
|
+
} else {
|
|
27
|
+
arr.push(arr2);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
exports.array = function (obj) {
|
|
32
|
+
return Array.isArray(obj) ? obj : [ obj ];
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
exports.cloneISwearIKnowWhatImDoing = function (obj) {
|
|
36
|
+
return JSON.parse(JSON.stringify(obj));
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Generate a random number.
|
|
41
|
+
* @param {number} Inclusive minimum
|
|
42
|
+
* @param {number} Inclusive maximum
|
|
43
|
+
* @returns {number}
|
|
44
|
+
*/
|
|
45
|
+
exports.random = function (minimum, maximum) {
|
|
46
|
+
return Math.floor(Math.random() * (maximum - minimum)) + minimum;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
exports.randomAlpha = function (length) {
|
|
50
|
+
var text = "";
|
|
51
|
+
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
52
|
+
|
|
53
|
+
for (var i=0; i < length; i++) {
|
|
54
|
+
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return text;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
exports.isResolvedReference = function (reference) {
|
|
61
|
+
return reference.resolved != null
|
|
62
|
+
&& reference.resolved.defs != null
|
|
63
|
+
&& reference.resolved.defs.length > 0;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
exports.UniqueRandom = function(max) {
|
|
67
|
+
assert(typeof max == "number");
|
|
68
|
+
if (max > 32768) {
|
|
69
|
+
console.warn(`Allocating large (${max}) UniqueRandom instance`);
|
|
70
|
+
}
|
|
71
|
+
var arr = _.shuffle(_.range(max));
|
|
72
|
+
var idx = 0;
|
|
73
|
+
|
|
74
|
+
this.get = function() {
|
|
75
|
+
if (idx < max) {
|
|
76
|
+
return arr[idx++];
|
|
77
|
+
} else {
|
|
78
|
+
throw new Error("No numbers left");
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
exports.UniqueRandomAlpha = function (len) {
|
|
84
|
+
assert(typeof len == "number");
|
|
85
|
+
var offset = Math.pow(32, len - 1);
|
|
86
|
+
var rng = new exports.UniqueRandom(offset * 31);
|
|
87
|
+
|
|
88
|
+
this.get = function() {
|
|
89
|
+
return (offset + rng.get()).toString(32);
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
exports.HashMap = function () {
|
|
94
|
+
var store = {};
|
|
95
|
+
|
|
96
|
+
this.get = function (key) {
|
|
97
|
+
return store["HashMap" + key];
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
this.set = function (key, value) {
|
|
101
|
+
return store["HashMap" + key] = value;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
this.exists = function (key) {
|
|
105
|
+
return store["HashMap" + key] !== undefined;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
this.remove = function (key) {
|
|
109
|
+
delete store["HashMap" + key];
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
exports.hash = function (obj) {
|
|
114
|
+
if (obj == null) {
|
|
115
|
+
return "x";
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (typeof obj == "string") {
|
|
119
|
+
return "s" + obj;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (typeof obj == "number") {
|
|
123
|
+
return "n" + obj.toString();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!obj.$$hash) {
|
|
127
|
+
Object.defineProperty(obj, "$$hash", {
|
|
128
|
+
configurable: false,
|
|
129
|
+
enumerable: false,
|
|
130
|
+
value: "o" + exports.randomAlpha(8)
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return obj.$$hash;
|
|
135
|
+
};
|