This repository has been archived by the owner on Nov 15, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 224
/
app.js
141 lines (126 loc) · 3.7 KB
/
app.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
const path = require('path')
const http = require('http')
const { Z_SYNC_FLUSH } = require('zlib')
require('colors')
const frida = require('frida')
const FRIDA_VERSION = require('frida/package.json').version
const Koa = require('koa')
const logger = require('koa-logger')
const json = require('koa-json')
const compress = require('koa-compress')
const bodyParser = require('koa-bodyparser')
const send = require('koa-send')
const Router = require('koa-router')
const { FridaUtil, serializeDevice, serializeApp } = require('./lib/utils')
const channels = require('./lib/channels.js')
const { KnownError, InvalidDeviceError, VersionMismatchError } = require('./lib/error')
const app = new Koa()
const router = new Router({ prefix: '/api' })
router
.get('/devices', async (ctx) => {
const mgr = await frida.getDeviceManager()
const list = await mgr.enumerateDevices()
ctx.body = {
version: FRIDA_VERSION,
list: list.map(serializeDevice),
}
})
.get('/device/:device/apps', async (ctx) => {
const id = ctx.params.device
// todo: refactor me
try {
const dev = await FridaUtil.getDevice(id)
const apps = await dev.enumerateApplications()
ctx.body = apps.map(serializeApp)
} catch (ex) {
if (ex.message.startsWith('Unable to connect to remote frida-server'))
throw new InvalidDeviceError(id)
if (ex.message.startsWith('Unable to communicate with remote frida-server'))
throw new VersionMismatchError(ex.message)
else
throw ex
}
})
.post('/url/start', async (ctx) => {
const { device, bundle, url } = ctx.request.body
const dev = await FridaUtil.getDevice(device)
const pid = await dev.spawn([bundle], { url })
await dev.resume(pid)
ctx.body = { status: 'ok', pid }
})
.put('/device/add', async (ctx) => {
const ip = ctx.request.rawBody
const mgr = await frida.getDeviceManager()
try {
mgr.addRemoteDevice(ip)
} catch(e) {
ctx.status = 400
ctx.body = { status: 'failed', error: e.message }
return
}
ctx.body = { status: 'ok' }
})
.delete('/device/:device', async (ctx) => {
const mgr = await frida.getDeviceManager()
try {
await mgr.removeRemoteDevice(ctx.params.device)
} catch(e) {
ctx.status = 404
ctx.body = { status: 'failed', error: e.message }
return
}
ctx.body = { status: 'ok' }
})
app
.use(compress({
filter(contentType) {
return /text|json/i.test(contentType)
},
threshold: 2048,
flush: Z_SYNC_FLUSH,
}))
.use(bodyParser())
.use(async(ctx, next) => {
try {
await next()
} catch (e) {
if (e instanceof KnownError) ctx.throw(404, e.message)
if (process.env.NODE_ENV === 'development') throw e
else ctx.throw(500, e.message)
}
})
.use(router.routes())
.use(router.allowedMethods())
if (process.env.NODE_ENV === 'development') {
app.use(json({
pretty: false,
param: 'pretty',
}))
} else {
app.use(async (ctx, next) => {
const opt = { root: path.join(__dirname, 'gui') }
if (ctx.path.startsWith('/static/')) await send(ctx, ctx.path, opt)
else await send(ctx, '/index.html', opt)
next()
})
app.use(logger())
}
function start({ host, port }) {
console.info(`listening on http://${host}:${port}`.green)
const server = http.createServer(app.callback())
channels.attach(server)
server.listen(port, host)
process.on('unhandledRejection', (err) => {
console.error('An unhandledRejection occurred: '.red)
console.error(`Rejection: ${err}`.red)
console.error(err.stack)
channels.broadcast('unhandledRejection', {
err: err.toString(),
stack: err.stack,
})
})
}
module.exports = {
app,
start,
}