@dacely/toildefender 0.1.0 → 0.1.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/LICENSE +661 -661
- package/NOTICE.md +16 -16
- package/README.md +467 -380
- package/cli.js +168 -168
- package/defendjs.js +6 -6
- package/docs/all-modes-output.demo.js +673 -673
- package/estest.js +49 -49
- package/esutils.js +107 -107
- package/logger.js +28 -28
- package/obfuscator.js +534 -534
- package/package.json +108 -108
- package/processors/deadCode.js +62 -62
- package/processors/flattener.js +808 -808
- package/processors/health.js +55 -55
- package/processors/identifiers.js +256 -256
- package/processors/literalObfuscator.js +40 -40
- package/processors/literals.js +233 -233
- package/processors/methods.js +332 -332
- package/processors/modules.js +231 -231
- package/processors/normalizer.js +490 -490
- package/processors/numericVm.js +950 -950
- package/processors/postprocessing.js +69 -69
- package/processors/preprocessing.js +248 -248
- package/processors/scopes.js +177 -177
- package/processors/uglifier.js +25 -25
- package/processors/variables.js +185 -185
- package/toildefender.js +7 -7
- package/traverser.js +115 -115
- package/utils.js +135 -135
package/cli.js
CHANGED
|
@@ -1,168 +1,168 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var fs = require("fs");
|
|
4
|
-
var os = require("os");
|
|
5
|
-
var path = require("path");
|
|
6
|
-
|
|
7
|
-
var _ = require("lodash");
|
|
8
|
-
|
|
9
|
-
var toildefender = require("./obfuscator");
|
|
10
|
-
|
|
11
|
-
exports.run = function () {
|
|
12
|
-
|
|
13
|
-
var argv = require("minimist")(process.argv.slice(2));
|
|
14
|
-
if (argv.help) {
|
|
15
|
-
console.info(
|
|
16
|
-
"# Usage\n" +
|
|
17
|
-
"\n" +
|
|
18
|
-
"toildefender --input [directory] --output [directory] --features [features] --preprocessor [variable]\n" +
|
|
19
|
-
"\n" +
|
|
20
|
-
"# Parameters\n" +
|
|
21
|
-
"\n" +
|
|
22
|
-
"--input\n" +
|
|
23
|
-
"\tPath to input directory or file. Can be repeated multiple times.\n" +
|
|
24
|
-
"\n" +
|
|
25
|
-
"--output\n" +
|
|
26
|
-
"\tPath to output directory.\n" +
|
|
27
|
-
"\n" +
|
|
28
|
-
"--features\n" +
|
|
29
|
-
"\tComma-separated list of features. (available features: " + _.join(_.keys(toildefender.features), ", ") + ")\n" +
|
|
30
|
-
"\te.g. --features scope,control_flow,compress\n" +
|
|
31
|
-
"\n" +
|
|
32
|
-
"--preprocessor\n" +
|
|
33
|
-
"\tPreprocessor variable declaration or assignment.\n" +
|
|
34
|
-
(() => { switch (os.platform()) {
|
|
35
|
-
case "win32":
|
|
36
|
-
return "\te.g. --preprocessor PLATFORM_WINDOWS --preprocessor PLATFORM_WINDOWS_VERSION=10\n";
|
|
37
|
-
case "darwin":
|
|
38
|
-
return "\te.g. --preprocessor PLATFORM_MACOS --preprocessor PLATFORM_MACOS_VERSION=10.12\n";
|
|
39
|
-
default:
|
|
40
|
-
return "\te.g. --preprocessor PLATFORM_LINUX --preprocessor PLATFORM_LINUX_VERSION=4.8\n";
|
|
41
|
-
} })() +
|
|
42
|
-
"\n" +
|
|
43
|
-
"# Example\n" +
|
|
44
|
-
"\n" +
|
|
45
|
-
(() => { switch (os.platform()) { // bit of a pointless feature, but its neat
|
|
46
|
-
case "win32":
|
|
47
|
-
return "toildefender --input \"D:\\project\\src\" --output \"D:\\project\\dist\" --features scope,control_flow,compress --preprocessor PLATFORM_WINDOWS\n";
|
|
48
|
-
case "darwin":
|
|
49
|
-
return "toildefender --input \"~/project/src\" --output \"~/project/dist\" --features scope,control_flow,compress --preprocessor PLATFORM_MACOS\n";
|
|
50
|
-
default:
|
|
51
|
-
return "toildefender --input \"~/project/src\" --output \"~/project/dist\" --features scope,control_flow,compress --preprocessor PLATFORM_LINUX\n";
|
|
52
|
-
} })() +
|
|
53
|
-
"\n"
|
|
54
|
-
);
|
|
55
|
-
process.exit(0);
|
|
56
|
-
}
|
|
57
|
-
if (!Array.isArray(argv.input)) {
|
|
58
|
-
argv.input = [ argv.input ];
|
|
59
|
-
}
|
|
60
|
-
if (!Array.isArray(argv.preprocessor)) {
|
|
61
|
-
argv.preprocessor = [ argv.preprocessor ];
|
|
62
|
-
}
|
|
63
|
-
if (!argv.input) {
|
|
64
|
-
console.error(
|
|
65
|
-
"Missing --input"
|
|
66
|
-
);
|
|
67
|
-
process.exit(0);
|
|
68
|
-
}
|
|
69
|
-
if (!argv.output) {
|
|
70
|
-
console.error(
|
|
71
|
-
"Missing --output"
|
|
72
|
-
);
|
|
73
|
-
process.exit(0);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
let files = [];
|
|
77
|
-
argv.input.forEach(item => {
|
|
78
|
-
let stat = fs.lstatSync(item);
|
|
79
|
-
if (stat.isDirectory()) {
|
|
80
|
-
readdirRecursiveSync(item)
|
|
81
|
-
.filter(
|
|
82
|
-
file => !/(^|[\/\\])(\.git|node_modules)($|[\/\\])/.test(file)
|
|
83
|
-
)
|
|
84
|
-
.forEach(
|
|
85
|
-
file => files[file] = fs.readFileSync(path.join(item, file), "utf8")
|
|
86
|
-
);
|
|
87
|
-
} else if (stat.isFile()) {
|
|
88
|
-
files[item] = fs.readFileSync(item, "utf8");
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
let mainFiles = getMainFiles(files);
|
|
93
|
-
|
|
94
|
-
let features = _.mapValues(toildefender.features, (value, key) => _.includes(argv.features, key));
|
|
95
|
-
|
|
96
|
-
let preprocessorVariables = _.fromPairs(_.map(argv.preprocessor, decl => {
|
|
97
|
-
let [, variable, value] = /^\s*([\w\d]+)\s*(?:=\s*([\w\d]+))?\s*$/.exec(decl) || [];
|
|
98
|
-
return [variable, value || null];
|
|
99
|
-
}));
|
|
100
|
-
|
|
101
|
-
let results = _.fromPairs(_.map(mainFiles, key => {
|
|
102
|
-
console.info(`Obfuscating ${key} ...`);
|
|
103
|
-
return [key, toildefender.do({
|
|
104
|
-
code: files[key],
|
|
105
|
-
modulesCode: _.pickBy(files, (value, _key) => key != _key && isCodeFile(_key) && !mainFiles[_key]),
|
|
106
|
-
features: features,
|
|
107
|
-
preprocessorVariables: preprocessorVariables
|
|
108
|
-
})];
|
|
109
|
-
}));
|
|
110
|
-
|
|
111
|
-
_.each(results, (result, key) => {
|
|
112
|
-
let target = path.join(argv.output, key);
|
|
113
|
-
if (!pathExists(path.dirname(target))) {
|
|
114
|
-
fs.mkdirSync(path.dirname(target));
|
|
115
|
-
}
|
|
116
|
-
if (pathExists(target)) {
|
|
117
|
-
fs.unlinkSync(target);
|
|
118
|
-
}
|
|
119
|
-
fs.writeFileSync(target, result.code);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
function readdirRecursiveSync(dir) {
|
|
123
|
-
let results = [];
|
|
124
|
-
let files = fs.readdirSync(dir);
|
|
125
|
-
files.forEach(function(file) {
|
|
126
|
-
let stat = fs.statSync(dir + "/" + file);
|
|
127
|
-
if (stat.isDirectory()) {
|
|
128
|
-
readdirRecursiveSync(dir + "/" + file).forEach(subfile => results.push(file + "/" + subfile));
|
|
129
|
-
} else {
|
|
130
|
-
results.push(file);
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
return results;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function isSourceFile(name) {
|
|
137
|
-
return _.includes([ ".js", ".json" ], path.extname(name));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function isCodeFile(name) {
|
|
141
|
-
return path.extname(name) == ".js";
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function pathExists(path) {
|
|
145
|
-
try {
|
|
146
|
-
let stat = fs.lstatSync(path);
|
|
147
|
-
return stat.isFile() || stat.isDirectory();
|
|
148
|
-
} catch (e) {
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function getMainFiles(files) {
|
|
154
|
-
let _package = files["package.json"] && JSON.parse(files["package.json"]);
|
|
155
|
-
if (_package && _package.toildefender && _package.toildefender.mainFiles) {
|
|
156
|
-
return _package.toildefender.mainFiles;
|
|
157
|
-
} else if (_package && _package.defendjs && _package.defendjs.mainFiles) {
|
|
158
|
-
return _package.defendjs.mainFiles;
|
|
159
|
-
} else if (_package && _package.main) {
|
|
160
|
-
return [ _package.main ];
|
|
161
|
-
} else if (Object.keys(files).filter(isSourceFile).length == 1) {
|
|
162
|
-
return [ Object.keys(files).filter(isSourceFile)[0] ];
|
|
163
|
-
} else {
|
|
164
|
-
return [ "app.js", "main.js", "index.js" ].filter(x => files[x] != null).slice(0, 1);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var fs = require("fs");
|
|
4
|
+
var os = require("os");
|
|
5
|
+
var path = require("path");
|
|
6
|
+
|
|
7
|
+
var _ = require("lodash");
|
|
8
|
+
|
|
9
|
+
var toildefender = require("./obfuscator");
|
|
10
|
+
|
|
11
|
+
exports.run = function () {
|
|
12
|
+
|
|
13
|
+
var argv = require("minimist")(process.argv.slice(2));
|
|
14
|
+
if (argv.help) {
|
|
15
|
+
console.info(
|
|
16
|
+
"# Usage\n" +
|
|
17
|
+
"\n" +
|
|
18
|
+
"toildefender --input [directory] --output [directory] --features [features] --preprocessor [variable]\n" +
|
|
19
|
+
"\n" +
|
|
20
|
+
"# Parameters\n" +
|
|
21
|
+
"\n" +
|
|
22
|
+
"--input\n" +
|
|
23
|
+
"\tPath to input directory or file. Can be repeated multiple times.\n" +
|
|
24
|
+
"\n" +
|
|
25
|
+
"--output\n" +
|
|
26
|
+
"\tPath to output directory.\n" +
|
|
27
|
+
"\n" +
|
|
28
|
+
"--features\n" +
|
|
29
|
+
"\tComma-separated list of features. (available features: " + _.join(_.keys(toildefender.features), ", ") + ")\n" +
|
|
30
|
+
"\te.g. --features scope,control_flow,compress\n" +
|
|
31
|
+
"\n" +
|
|
32
|
+
"--preprocessor\n" +
|
|
33
|
+
"\tPreprocessor variable declaration or assignment.\n" +
|
|
34
|
+
(() => { switch (os.platform()) {
|
|
35
|
+
case "win32":
|
|
36
|
+
return "\te.g. --preprocessor PLATFORM_WINDOWS --preprocessor PLATFORM_WINDOWS_VERSION=10\n";
|
|
37
|
+
case "darwin":
|
|
38
|
+
return "\te.g. --preprocessor PLATFORM_MACOS --preprocessor PLATFORM_MACOS_VERSION=10.12\n";
|
|
39
|
+
default:
|
|
40
|
+
return "\te.g. --preprocessor PLATFORM_LINUX --preprocessor PLATFORM_LINUX_VERSION=4.8\n";
|
|
41
|
+
} })() +
|
|
42
|
+
"\n" +
|
|
43
|
+
"# Example\n" +
|
|
44
|
+
"\n" +
|
|
45
|
+
(() => { switch (os.platform()) { // bit of a pointless feature, but its neat
|
|
46
|
+
case "win32":
|
|
47
|
+
return "toildefender --input \"D:\\project\\src\" --output \"D:\\project\\dist\" --features scope,control_flow,compress --preprocessor PLATFORM_WINDOWS\n";
|
|
48
|
+
case "darwin":
|
|
49
|
+
return "toildefender --input \"~/project/src\" --output \"~/project/dist\" --features scope,control_flow,compress --preprocessor PLATFORM_MACOS\n";
|
|
50
|
+
default:
|
|
51
|
+
return "toildefender --input \"~/project/src\" --output \"~/project/dist\" --features scope,control_flow,compress --preprocessor PLATFORM_LINUX\n";
|
|
52
|
+
} })() +
|
|
53
|
+
"\n"
|
|
54
|
+
);
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
if (!Array.isArray(argv.input)) {
|
|
58
|
+
argv.input = [ argv.input ];
|
|
59
|
+
}
|
|
60
|
+
if (!Array.isArray(argv.preprocessor)) {
|
|
61
|
+
argv.preprocessor = [ argv.preprocessor ];
|
|
62
|
+
}
|
|
63
|
+
if (!argv.input) {
|
|
64
|
+
console.error(
|
|
65
|
+
"Missing --input"
|
|
66
|
+
);
|
|
67
|
+
process.exit(0);
|
|
68
|
+
}
|
|
69
|
+
if (!argv.output) {
|
|
70
|
+
console.error(
|
|
71
|
+
"Missing --output"
|
|
72
|
+
);
|
|
73
|
+
process.exit(0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let files = [];
|
|
77
|
+
argv.input.forEach(item => {
|
|
78
|
+
let stat = fs.lstatSync(item);
|
|
79
|
+
if (stat.isDirectory()) {
|
|
80
|
+
readdirRecursiveSync(item)
|
|
81
|
+
.filter(
|
|
82
|
+
file => !/(^|[\/\\])(\.git|node_modules)($|[\/\\])/.test(file)
|
|
83
|
+
)
|
|
84
|
+
.forEach(
|
|
85
|
+
file => files[file] = fs.readFileSync(path.join(item, file), "utf8")
|
|
86
|
+
);
|
|
87
|
+
} else if (stat.isFile()) {
|
|
88
|
+
files[item] = fs.readFileSync(item, "utf8");
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
let mainFiles = getMainFiles(files);
|
|
93
|
+
|
|
94
|
+
let features = _.mapValues(toildefender.features, (value, key) => _.includes(argv.features, key));
|
|
95
|
+
|
|
96
|
+
let preprocessorVariables = _.fromPairs(_.map(argv.preprocessor, decl => {
|
|
97
|
+
let [, variable, value] = /^\s*([\w\d]+)\s*(?:=\s*([\w\d]+))?\s*$/.exec(decl) || [];
|
|
98
|
+
return [variable, value || null];
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
let results = _.fromPairs(_.map(mainFiles, key => {
|
|
102
|
+
console.info(`Obfuscating ${key} ...`);
|
|
103
|
+
return [key, toildefender.do({
|
|
104
|
+
code: files[key],
|
|
105
|
+
modulesCode: _.pickBy(files, (value, _key) => key != _key && isCodeFile(_key) && !mainFiles[_key]),
|
|
106
|
+
features: features,
|
|
107
|
+
preprocessorVariables: preprocessorVariables
|
|
108
|
+
})];
|
|
109
|
+
}));
|
|
110
|
+
|
|
111
|
+
_.each(results, (result, key) => {
|
|
112
|
+
let target = path.join(argv.output, key);
|
|
113
|
+
if (!pathExists(path.dirname(target))) {
|
|
114
|
+
fs.mkdirSync(path.dirname(target));
|
|
115
|
+
}
|
|
116
|
+
if (pathExists(target)) {
|
|
117
|
+
fs.unlinkSync(target);
|
|
118
|
+
}
|
|
119
|
+
fs.writeFileSync(target, result.code);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
function readdirRecursiveSync(dir) {
|
|
123
|
+
let results = [];
|
|
124
|
+
let files = fs.readdirSync(dir);
|
|
125
|
+
files.forEach(function(file) {
|
|
126
|
+
let stat = fs.statSync(dir + "/" + file);
|
|
127
|
+
if (stat.isDirectory()) {
|
|
128
|
+
readdirRecursiveSync(dir + "/" + file).forEach(subfile => results.push(file + "/" + subfile));
|
|
129
|
+
} else {
|
|
130
|
+
results.push(file);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
return results;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function isSourceFile(name) {
|
|
137
|
+
return _.includes([ ".js", ".json" ], path.extname(name));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function isCodeFile(name) {
|
|
141
|
+
return path.extname(name) == ".js";
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function pathExists(path) {
|
|
145
|
+
try {
|
|
146
|
+
let stat = fs.lstatSync(path);
|
|
147
|
+
return stat.isFile() || stat.isDirectory();
|
|
148
|
+
} catch (e) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function getMainFiles(files) {
|
|
154
|
+
let _package = files["package.json"] && JSON.parse(files["package.json"]);
|
|
155
|
+
if (_package && _package.toildefender && _package.toildefender.mainFiles) {
|
|
156
|
+
return _package.toildefender.mainFiles;
|
|
157
|
+
} else if (_package && _package.defendjs && _package.defendjs.mainFiles) {
|
|
158
|
+
return _package.defendjs.mainFiles;
|
|
159
|
+
} else if (_package && _package.main) {
|
|
160
|
+
return [ _package.main ];
|
|
161
|
+
} else if (Object.keys(files).filter(isSourceFile).length == 1) {
|
|
162
|
+
return [ Object.keys(files).filter(isSourceFile)[0] ];
|
|
163
|
+
} else {
|
|
164
|
+
return [ "app.js", "main.js", "index.js" ].filter(x => files[x] != null).slice(0, 1);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
};
|
package/defendjs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
if (require.main === module) {
|
|
4
|
-
require("./cli").run();
|
|
5
|
-
} else {
|
|
6
|
-
module.exports = require("./obfuscator");
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
if (require.main === module) {
|
|
4
|
+
require("./cli").run();
|
|
5
|
+
} else {
|
|
6
|
+
module.exports = require("./obfuscator");
|
|
7
7
|
}
|