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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140(async function() {
const log = console.log;
const arg = require("arg");
const path = require("path");
const readline = require("readline");
const chalk = require("chalk");
const {fork} = require("child_process");
const services = require(path.join(__dirname, "services.json"));
function errorAndDie(err) {
log(chalk.red.bold(`[!] Fatal error: ${err.message || err}`));
process.exit(1);
}
process.on("uncaughtException", errorAndDie);
process.on("unhandledRejection", errorAndDie);
const args = arg({
'--help': Boolean,
'--version': Boolean,
'--name': String,
'--batch': Boolean,
'--output': String,
'-v': '--version',
'-n': '--name',
'-b': '--batch',
'-o': '--output'
});
process.on("beforeExit", (code) => {
if (code === 0 && args["--batch"] && !args["--output"] && global.finalResults) log(JSON.stringify(global.finalResults));
if (code === 0 && args["--output"] && global.finalResults) require("fs").writeFileSync(require("path").join(process.cwd(), args["--output"]), JSON.stringify(global.finalResults));
});
if (args["--version"]) {
log("Sherlock.js v1.0.0");
process.exit(0);
}
if (args["--help"]) {
log(`
Available command line switches:
--help: Display this message
--version or -v: Print version
--name user or -n user: Specify a username to search for (remove interactive prompt)
--batch or -b: Output results in minified JSON
--output res.json or -o res.json: Print minified JSON results in a file
Additional info available at https://github.com/GitSquared/sherlock-js
`);
process.exit(0);
}
if (args["--name"]) {
scan(args["--name"]);
} else {
prompt().then(scan);
}
async function prompt() {
log(chalk.bold(`
."""-.
/ \\
____ _ _ _ | _..--'-.
/ ___|| |__ ___ _ __| | ___ ___| |__ >.\`__.-""\\;"\`
\\___ \\| '_ \\ / _ \\ '__| |/ _ \\ / __| |/ / _ / /( ^\\
___) | | | | __/ | | | (_) | (__| < _ |_|___ '-\`) =|-.
|____/|_| |_|\\___|_| |_|\\___/ \\___|_|\\_\\ |_| | |_ -| /\`--.'--' \\ .-.
_| |___| .'\`-._ \`.\\ | J /
|___| / \`--.| \\__/
`));
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let name = await new Promise((resolve, reject) => {
try {
rl.question(chalk.green.bold("[>] Input username: "), answer => {
rl.close();
log("");
resolve(answer);
});
} catch(e) { reject(e); }
});
name = name.trim();
if (name.match(/^[^ /&?]+$/g)) {
return name;
} else {
throw new Error("Name contains unauthorised characters. Cannot proceed.");
}
}
async function scan(name) {
global.finalResults = {};
let results = new Proxy(global.finalResults, {
set: (target, prop, value) => {
switch(value) {
case "Checking...":
// log(chalk.bold("[")+chalk.bold.yellow("*")+chalk.bold("]")+" "+chalk.bold.green(prop+": ")+chalk.dim(value));
break;
case "Not Found!":
if (!args["--batch"]) log(chalk.bold("[")+chalk.bold.red("-")+chalk.bold("]")+" "+chalk.bold.green(prop+": ")+chalk.bold.yellow(value));
break;
case "Error":
if (!args["--batch"]) log(chalk.bold("[")+chalk.bold.red("X")+chalk.bold("]")+" "+chalk.bold.red(prop+": ")+chalk.bold.red(value));
break;
default:
if (!args["--batch"]) log(chalk.bold("[")+chalk.bold.green("+")+chalk.bold("]")+" "+chalk.bold.green(prop+": ")+value);
}
target[prop] = value;
},
get: (target, prop) => {
return target[prop];
}
});
Object.keys(services).forEach(key => {
let url = services[key].replace("{}", name);
results[key] = "Checking...";
let worker = fork(path.join(__dirname, "httpsWorker.js"));
worker.on("message", r => {
if (typeof r === "boolean") {
results[key] = r ? url : "Not Found!";
} else {
results[key] = "Error";
}
});
worker.send(url+" "+name);
});
}
})();