Skip to content

Commit b24e3ac

Browse files
committed
Move to command-line-args for argument parsing
1 parent 29a390d commit b24e3ac

File tree

7 files changed

+100
-67
lines changed

7 files changed

+100
-67
lines changed

README.md

+17-17
Original file line numberDiff line numberDiff line change
@@ -22,39 +22,39 @@ It will create a folder called `file1.js.results`; if it already exists, it will
2222
## Flags
2323

2424
<!--START_FLAGS-->
25-
--version: Show the package version
25+
--version (Boolean): Show the package version
2626

27-
--debug: Die when an emulation error occurs, even in "batch mode"
27+
--debug (Boolean): Die when an emulation error occurs, even in "batch mode"
2828

29-
--download: Actually download the payloads
29+
--download (Boolean): Actually download the payloads
3030

31-
--no-file-exists: Return `false` for Scripting.FileSystemObject.FileExists(x)
31+
--no-file-exists (Boolean): Return `false` for Scripting.FileSystemObject.FileExists(x)
3232

33-
--no-catch-rewrite: Do not rewrite try..catch clauses to make the exception global-scoped
33+
--no-catch-rewrite (Boolean): Do not rewrite try..catch clauses to make the exception global-scoped
3434

35-
--no-cc_on-rewrite: Do not rewrite `/*@cc_on <...>@*/` to `<...>`
35+
--no-cc_on-rewrite (Boolean): Do not rewrite `/*@cc_on <...>@*/` to `<...>`
3636

37-
--no-concat-simplify: Do not simplify `'a'+'b'` to `'ab'`
37+
--no-concat-simplify (Boolean): Do not simplify `'a'+'b'` to `'ab'`
3838

39-
--no-echo: When the script prints data, do not print it to the console
39+
--no-echo (Boolean): When the script prints data, do not print it to the console
4040

41-
--no-eval-rewrite: Do not rewrite `eval` so that its argument is rewritten
41+
--no-eval-rewrite (Boolean): Do not rewrite `eval` so that its argument is rewritten
4242

43-
--no-rewrite: Do not rewrite the source code at all, other than for `@cc_on` support
43+
--no-rewrite (Boolean): Do not rewrite the source code at all, other than for `@cc_on` support
4444

45-
--no-shell-error: Do not throw a fake error when executing `WScriptShell.Run` (it throws a fake error by default to pretend that the distribution sites are down, so that the script will attempt to poll every site)
45+
--no-shell-error (Boolean): Do not throw a fake error when executing `WScriptShell.Run` (it throws a fake error by default to pretend that the distribution sites are down, so that the script will attempt to poll every site)
4646

47-
--no-typeof-rewrite: Do not rewrite `typeof` (e.g. `typeof ActiveXObject`, which must return 'unknown' in the JScript standard and not 'object')
47+
--no-typeof-rewrite (Boolean): Do not rewrite `typeof` (e.g. `typeof ActiveXObject`, which must return 'unknown' in the JScript standard and not 'object')
4848

49-
--output-dir: The location on disk to write the results files and folders to (defaults to the current directory)
49+
--output-dir (String): The location on disk to write the results files and folders to (defaults to the current directory)
5050

51-
--proxy=http://1.2.3.4:1234: Use the specified proxy for downloads. This is not relevant if the --download flag is not present.
51+
--proxy (String): Use the specified proxy for downloads. This is not relevant if the --download flag is not present.
5252

53-
--timeout: The script will timeout after this many seconds (default 10)
53+
--timeout (Number): The script will timeout after this many seconds (default 10)
5454

55-
--windows-xp: Emulate Windows XP (influences the value of environment variables)
55+
--windows-xp (Boolean): Emulate Windows XP (influences the value of environment variables)
5656

57-
--experimental-neq: [experimental] rewrite `a != b` to `false`
57+
--experimental-neq (Boolean): [experimental] rewrite `a != b` to `false`
5858
<!--END_FLAGS-->
5959

6060
## Analyzing the output

_controller.js

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
1-
var fs = require("fs"),
2-
uuid = require("uuid"),
3-
request = require("sync-request");
1+
const fs = require("fs");
2+
const uuid = require("uuid");
3+
const request = require("sync-request");
4+
const path = require("path");
45

5-
const argv = require('minimist')(process.argv.slice(2));
6+
const commandLineArgs = require('command-line-args');
7+
const flags = JSON.parse(fs.readFileSync(path.join(__dirname, 'flags.json'), 'utf8'))
8+
.map(flag => {
9+
if (flag.type === "String") flag.type = String;
10+
if (flag.type === "Number") flag.type = Number;
11+
if (flag.type === "Boolean") flag.type = Boolean;
12+
return flag;
13+
}
14+
);
15+
const argv = commandLineArgs(flags);
616

717
const directory = process.argv[3];
818

_run.js

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
const argv = require('minimist')(process.argv.slice(2));
2-
const columnify = require("columnify");
1+
const commandLineArgs = require('command-line-args');
32
const cp = require("child_process");
43
const fs = require("fs");
54
const path = require("path");
@@ -14,15 +13,15 @@ Arguments:
1413
`;
1514

1615
// Read and format JSON flag documentation
17-
let flags = JSON.parse(fs.readFileSync(path.join(__dirname, 'flags.json'), 'utf8'));
18-
flags = columnify(flags, {
19-
showHeaders: false,
20-
config: {
21-
description: {
22-
maxWidth: 50
23-
}
16+
const flags = JSON.parse(fs.readFileSync(path.join(__dirname, 'flags.json'), 'utf8'))
17+
.map(flag => {
18+
if (flag.type === "String") flag.type = String;
19+
if (flag.type === "Number") flag.type = Number;
20+
if (flag.type === "Boolean") flag.type = Boolean;
21+
return flag;
2422
}
25-
});
23+
);
24+
const argv = commandLineArgs(flags);
2625

2726
if (argv.h || argv.help || argv.length === 0) {
2827
console.log(help + flags.replace(/^/mg, " "));

analyze.js

+24-16
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,19 @@ const esprima = require("esprima");
44
const fs = require("fs");
55
const path = require("path");
66
const {VM} = require("vm2");
7-
const argv = require('minimist')(process.argv)
87

9-
const filename = argv._[2];
8+
const filename = process.argv[2];
9+
10+
const commandLineArgs = require('command-line-args');
11+
const flags = JSON.parse(fs.readFileSync(path.join(__dirname, 'flags.json'), 'utf8'))
12+
.map(flag => {
13+
if (flag.type === "String") flag.type = String;
14+
if (flag.type === "Number") flag.type = Number;
15+
if (flag.type === "Boolean") flag.type = Boolean;
16+
return flag;
17+
}
18+
);
19+
const argv = commandLineArgs(flags);
1020

1121
console.log(`Analyzing ${filename}`);
1222
let code = fs.readFileSync(path.join(__dirname, "patch.js"), "utf8") + fs.readFileSync(filename, "utf8");
@@ -19,7 +29,7 @@ if (code.match("<job") || code.match("<script")) { // The sample may actually be
1929

2030
function rewrite(code) {
2131
if (code.match("@cc_on")) {
22-
if (!argv["--no-cc_on-rewrite"]) {
32+
if (!argv["no-cc_on-rewrite"]) {
2333
code = code.replace(/\/\*@cc_on/g, "");
2434
code = code.replace(/@\*\//g, "");
2535
} else {
@@ -36,10 +46,8 @@ If you run into unexpected results, try uncommenting lines that look like
3646
}
3747
}
3848

39-
console.log(argv);
40-
if (!argv["--no-rewrite"]) {
41-
console.log("Rewriting...")
42-
if (!!argv["--dumb-concat-simplify"]) {
49+
if (!argv["no-rewrite"]) {
50+
if (!!argv["dumb-concat-simplify"]) {
4351
code = code.replace(/'[ \r\n]*\+[ \r\n]*'/gm, "");
4452
code = code.replace(/"[ \r\n]*\+[ \r\n]*"/gm, "");
4553
}
@@ -74,7 +82,7 @@ cc decoder.c -o decoder
7482
process.exit(-1);
7583
return;
7684
}
77-
if (!argv["--no-concat-simplify"]) {
85+
if (!argv["no-concat-simplify"]) {
7886
traverse(tree, function(key, val) {
7987
if (!val) return;
8088
if (val.type !== "BinaryExpression") return;
@@ -89,7 +97,7 @@ cc decoder.c -o decoder
8997
};
9098
});
9199
}
92-
if (!!argv["--function-rewrite"]) {
100+
if (!!argv["function-rewrite"]) {
93101
traverse(tree, function(key, val) {
94102
if (key !== "callee") return;
95103
if (val.autogenerated) return;
@@ -102,7 +110,7 @@ cc decoder.c -o decoder
102110
});
103111
}
104112

105-
if (!argv["--no-typeof-rewrite"]) {
113+
if (!argv["no-typeof-rewrite"]) {
106114
traverse(tree, function(key, val) {
107115
if (!val) return;
108116
if (val.type !== "UnaryExpression") return;
@@ -112,7 +120,7 @@ cc decoder.c -o decoder
112120
});
113121
}
114122

115-
if (!argv["--no-eval-rewrite"]) {
123+
if (!argv["no-eval-rewrite"]) {
116124
traverse(tree, function(key, val) {
117125
if (!val) return;
118126
if (val.type !== "CallExpression") return;
@@ -122,7 +130,7 @@ cc decoder.c -o decoder
122130
});
123131
}
124132

125-
if (!argv["--no-catch-rewrite"]) {
133+
if (!argv["no-catch-rewrite"]) {
126134
traverse(tree, function(key, val) {
127135
if (!val) return;
128136
if (val.type !== "TryStatement") return;
@@ -133,7 +141,7 @@ cc decoder.c -o decoder
133141
}
134142

135143
// Replace (a !== b) with (false)
136-
if (!!argv["--experimental-neq"]) {
144+
if (!!argv["experimental-neq"]) {
137145
traverse(tree, function(key, val) {
138146
if (!val) return;
139147
if (val.type !== "BinaryExpression") return;
@@ -149,7 +157,7 @@ cc decoder.c -o decoder
149157
code = escodegen.generate(tree);
150158

151159
// The modifications may have resulted in more concatenations, eg. "a" + ("foo", "b") + "c" -> "a" + "b" + "c"
152-
if (!!argv["--dumb-concat-simplify"]) {
160+
if (!!argv["dumb-concat-simplify"]) {
153161
code = code.replace(/'[ \r\n]*\+[ \r\n]*'/gm, "");
154162
code = code.replace(/"[ \r\n]*\+[ \r\n]*"/gm, "");
155163
}
@@ -222,7 +230,7 @@ const sandbox = {
222230
},
223231
line: 1,
224232
writeline: text => {
225-
if (!!argv["--no-echo"]) return;
233+
if (!!argv["no-echo"]) return;
226234
console.log("Script wrote:", text);
227235
console.log("Add flag --no-echo to disable this.");
228236
}
@@ -268,7 +276,7 @@ const sandbox = {
268276
case "scriptfullname":
269277
return "(ScriptFullName)";
270278
case "echo":
271-
if (!!argv["--no-echo"])
279+
if (!!argv["no-echo"])
272280
return () => {};
273281
return x => {
274282
console.log("Script wrote:", x);

flags.json

+34-17
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,87 @@
11
[
22
{
3-
"flag": "--version",
3+
"name": "version",
4+
"type": "Boolean",
45
"description": "Show the package version"
56
},
67
{
7-
"flag": "--debug",
8+
"name": "debug",
9+
"type": "Boolean",
810
"description": "Die when an emulation error occurs, even in \"batch mode\""
911
},
1012
{
11-
"flag": "--download",
13+
"name": "download",
14+
"type": "Boolean",
1215
"description": "Actually download the payloads"
1316
},
1417
{
15-
"flag": "--no-file-exists",
18+
"name": "no-file-exists",
19+
"type": "Boolean",
1620
"description": "Return `false` for Scripting.FileSystemObject.FileExists(x)"
1721
},
1822
{
19-
"flag": "--no-catch-rewrite",
23+
"name": "no-catch-rewrite",
24+
"type": "Boolean",
2025
"description": "Do not rewrite try..catch clauses to make the exception global-scoped"
2126
},
2227
{
23-
"flag": "--no-cc_on-rewrite",
28+
"name": "no-cc_on-rewrite",
29+
"type": "Boolean",
2430
"description": "Do not rewrite `/*@cc_on <...>@*/` to `<...>`"
2531
},
2632
{
27-
"flag": "--no-concat-simplify",
33+
"name": "no-concat-simplify",
34+
"type": "Boolean",
2835
"description": "Do not simplify `'a'+'b'` to `'ab'`"
2936
},
3037
{
31-
"flag": "--no-echo",
38+
"name": "no-echo",
39+
"type": "Boolean",
3240
"description": "When the script prints data, do not print it to the console"
3341
},
3442
{
35-
"flag": "--no-eval-rewrite",
43+
"name": "no-eval-rewrite",
44+
"type": "Boolean",
3645
"description": "Do not rewrite `eval` so that its argument is rewritten"
3746
},
3847
{
39-
"flag": "--no-rewrite",
48+
"name": "no-rewrite",
49+
"type": "Boolean",
4050
"description": "Do not rewrite the source code at all, other than for `@cc_on` support"
4151
},
4252
{
43-
"flag": "--no-shell-error",
53+
"name": "no-shell-error",
54+
"type": "Boolean",
4455
"description": "Do not throw a fake error when executing `WScriptShell.Run` (it throws a fake error by default to pretend that the distribution sites are down, so that the script will attempt to poll every site)"
4556
},
4657
{
47-
"flag": "--no-typeof-rewrite",
58+
"name": "no-typeof-rewrite",
59+
"type": "Boolean",
4860
"description": "Do not rewrite `typeof` (e.g. `typeof ActiveXObject`, which must return 'unknown' in the JScript standard and not 'object')"
4961
},
5062
{
51-
"flag": "--output-dir",
63+
"name": "output-dir",
64+
"type": "String",
5265
"description": "The location on disk to write the results files and folders to (defaults to the current directory)"
5366
},
5467
{
55-
"flag": "--proxy=http://1.2.3.4:1234",
68+
"name": "proxy",
69+
"type": "String",
5670
"description": "Use the specified proxy for downloads. This is not relevant if the --download flag is not present."
5771
},
5872
{
59-
"flag": "--timeout",
73+
"name": "timeout",
74+
"type": "Number",
6075
"description": "The script will timeout after this many seconds (default 10)"
6176
},
6277
{
63-
"flag": "--windows-xp",
78+
"name": "windows-xp",
79+
"type": "Boolean",
6480
"description": "Emulate Windows XP (influences the value of environment variables)"
6581
},
6682
{
67-
"flag": "--experimental-neq",
83+
"name": "experimental-neq",
84+
"type": "Boolean",
6885
"description": "[experimental] rewrite `a != b` to `false`"
6986
}
7087
]

package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
"iconv-lite": "*",
1111
"walk": "*",
1212
"async": "*",
13-
"minimist": "*",
14-
"columnify": "*",
13+
"command-line-args": "*",
1514
"vm2": "*"
1615
},
1716
"devDependencies": {

update-docs.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const fs = require("fs");
22
const flags = JSON.parse(fs.readFileSync("flags.json", "utf8"));
3-
const text = flags.map(item => item.flag + ": " + item.description).join("\n\n");
3+
const text = flags.map(item => `--${item.name} (${item.type}): ${item.description}`).join("\n\n");
44
const README = fs.readFileSync("README.md", "utf8");
55
fs.writeFileSync(
66
"README.md",

0 commit comments

Comments
 (0)