-
Notifications
You must be signed in to change notification settings - Fork 41
/
bulldozer.js
executable file
·83 lines (67 loc) · 4.64 KB
/
bulldozer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const { parseScript } = require('shift-parser');
const { program } = require('commander');
const { decompile } = require('./cfg/graph');
const { get_eligible_functions, switch_structure_analyzer, replace_loop } = require('./parsers/preprocessor');
const codegen = require('./helpers/codegen');
const globals = require('./helpers/globals');
const { literals_descrambler } = require('./transforms/literals_descrambler');
let splash =
`
▐██████
███████████████▄ █▀ ▄
█▐██ ▒▌ ██▌ ▐█ ▌ █▌ ▀█▌
█▐██ ▒▌ ██▌ ▐█ ▌ ▒█▌ █▌ ▌▐█
▄▄███████████▌ ▐██▌▌███▌██▌▌▌██▌██▄
▄██████████████▌ ▐██████████████████▌
▄ ████████████████▄▄████▒ █████▌▀█
▄██▌▄▄▄▄▄ ██████▀▀▀▀██████████████▒ ██████ ██ ▄
████ ▀▀▀███▌▄▄▒██▀▄██████▄▄▀▀█████████▄ ██████ ▐█▌ ██▄
▄████▌ ▐▌▀▀▀▀▒▄███▒██▒▀▒████▄▄▀▀██████▌▄ ██████▄ ▐█ █████▄
▄█████▌ ▄▄▄▄█▌▄▄▄▄██▀▐██▀▀██ ▀█████▌▄▄▒▀▀▀▒███████▌ ▀▌ ████████
██████████████▄▐▀▀▒▄██▀ ██████ ▀▀▀████████▄▄▄▒▀█▄▄▄██ ▐█████████▌
▀████▀▀▀▀███████▀▄██▒ ▒▒▒ ▀██████▄▒▒███▄███████████
████▄ ▀█████████████████████████████████▌█████████▄▄██████████████▌
▀████ ▐███▀▀███▀▀███▀▀███▀▀███▀▀███▀▀█████████████▄▒██████████████▄
▀██▄ ▀██▄▄███▄▄███▄▄███▄▄███▄▄███▄▄████▀ ▀▀▀██████████▄
▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▒██▒▀
Welcome to bulldozer!
`
program
.option('-d, --debug', 'enable debugging output (quite chatty)', false)
.requiredOption('-s, --source <collina.js>', 'collina.js source file to read');
program.parse(process.argv);
const options = program.opts();
globals.debug = options.debug;
console.log(splash)
if (!fs.existsSync(options.source)) {
console.log("[!] Couldn't find specified file!");
process.exit(1)
}
console.log(`[*] Reading source file: ${options.source}`);
const collina_src = fs.readFileSync(options.source, "utf-8");
let tree, statements;
tree = parseScript(collina_src);
console.log("[*] Searching eligible functions");
let functions_list = get_eligible_functions(tree);
for (let fun of functions_list) {
console.log(`[*] Analyzing function ${fun.name.name}`);
let state_machine_data = switch_structure_analyzer(fun);
statements = decompile(fun, state_machine_data);
console.log(`[#] There were ${globals.ABNORMAL_LOOP_ENTRIES.length} abnormal loop entries in total:`, globals.ABNORMAL_LOOP_ENTRIES); // TODO add "(they were replaced with ifs)" once done
globals.ABNORMAL_LOOP_ENTRIES = [] // Reset global
replace_loop(fun, literals_descrambler(statements)); // Replace obfuscated code with new code
}
console.log("[*] Generating and writing code to file");
let filename;
let i = 1;
filename = options.source.split('.').slice(0, -1).join('.') + "_unflattened.js";
while (fs.existsSync(filename)) {
// Avoid file collisions
filename = options.source.split('.').slice(0, -1).join('.') + "_unflattened.js" + i.toString();
i++;
}
fs.writeFileSync(filename, codegen(tree));
console.log("[*] Done, saved to", filename);