diff --git a/core/main/command.rb b/core/main/command.rb index 90a1dd2e3..2856f23fe 100644 --- a/core/main/command.rb +++ b/core/main/command.rb @@ -13,42 +13,38 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core - - # - # This module contains a list of utils functions to use - # when writing commands. - # + # @note This module contains a list of utils functions to use when writing commands module CommandUtils # Format a string to support multiline in javascript. + # @param [String] text String to convert + # @return [String] Formatted string 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. - # + # @note 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::Core::CommandUtils + # Constructor + # @param [Hash] hash 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. - # + # @note 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 :datastore, :path, :default_command_url, :beefjs_components, :friendlyname @@ -59,6 +55,7 @@ module Core include BeEF::Core::Constants::CommandModule # Super class controller + # @param [String] key command module key def initialize(key) get_extensions config = BeEF::Core::Configuration.instance @@ -75,42 +72,32 @@ module Core @beefjs_components = {} end - # - # Uses the API to include all the code from extensions that need to add - # methods, constants etc to that class. - # - # See BeEF::API::Command for examples. - # + # Uses the API to include all the code from extensions that need to add methods, constants etc to that class. + # @todo Determine if this method is deprecated def get_extensions BeEF::API::Command.extended_in_modules.each do |mod| self.class.send(:include, mod) end 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. - # + # This function is called just before the instructions are sent to hooked browser. 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. - # + # @param [] head + # @param [Hash] params Hash of parameters + # @todo Determine argument "head" type def process_zombie_response(head, params); end - # # Returns true if the command needs configurations to work. False if not. - # + # @deprecated This command should not be used since the implementation of the new configuration system def needs_configuration?; !@datastore.nil?; end - # # Returns information about the command in a JSON format. - # + # @return [String] JSON formatted string def to_json { 'Name' => @friendlyname, @@ -120,18 +107,16 @@ module Core }.to_json end - # # Builds the 'datastore' attribute of the command which is used to generate javascript code. - # + # @param [Hash] data Data to be inserted into the datastore + # @todo Confirm argument "data" type 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) - # + # @param [Hash] http_params HTTP parameters + # @param [Hash] http_header HTTP headers def build_callback_datastore(http_params, http_header) @datastore = {'http_headers' => {}} # init the datastore @@ -152,9 +137,8 @@ module Core } end - # # Returns the output of the command. These are the actual instructions sent to the browser. - # + # @return [String] The command output def output f = @path+'command.js' raise WEBrick::HTTPStatus::BadRequest, "#{f} file does not exist" if not File.exists? f @@ -178,28 +162,25 @@ module Core @output end - # - # Saves the results received from the zombie. - # + # Saves the results received from the hooked browser + # @param [Hash] results Results from hooked browser def save(results); @results = results; end - # If nothing else than the file is specified, the function will map the file to a random path - # without any extension. + # If nothing else than the file is specified, the function will map the file to a random path without any extension. + # @param [String] file File to be mounted + # @param [String] path URL path to mounted file + # @param [String] extension URL extension + # @param [Integer] count The amount of times this file can be accessed before being automatically unmounted + # @deprecated This function is possibly deprecated in place of the API def map_file_to_url(file, path=nil, extension=nil, count=1) return BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind(file, path, extension, count) end - # - # Tells the framework to load a specific module of the BeEFJS library that - # the command will be using. - # - # Example: - # - # use 'beef.net.local' - # use 'beef.encode.base64' - # + # Tells the framework to load a specific module of the BeEFJS library that the command will be using. + # @param [String] component String of BeEFJS component to load + # @note Example: use 'beef.net.local' def use(component) return if @beefjs_components.include? component @@ -213,12 +194,14 @@ module Core @beefjs_components[component] = component_path end + # @todo Document def oc_value(name) option = BeEF::Core::Models::OptionCache.first(:name => name) return nil if not option return option.value end + # @todo Document def apply_defaults() @datastore.each { |opt| opt["value"] = oc_value(opt["name"]) || opt["value"] diff --git a/core/main/configuration.rb b/core/main/configuration.rb index be6b4c317..e4ae5e3b3 100644 --- a/core/main/configuration.rb +++ b/core/main/configuration.rb @@ -13,23 +13,16 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core - # - # Parses the user configuration file for beef. - # - # Example: - # - # configuration = BeEF::Core::Configuration.instance - # p configuration.get('beef.http.host) # => "0.0.0.0" - # + class Configuration include Singleton - # - # Constructor - # + # Loads the default configuration system + # @param [String] configuration_file Configuration file to be loaded, by default loads $root_dir/config.yaml def initialize(configuration_file="#{$root_dir}/config.yaml") # argument type checking raise Exception::TypeError, '"configuration_file" needs to be a string' if not configuration_file.string? @@ -41,18 +34,18 @@ module Core @config.default = nil end - # # Loads yaml file - # + # @param [String] file YAML file to be loaded + # @return [Hash] YAML formatted hash def load(file) return nil if not File.exists?(file) raw = File.read(file) return YAML.load(raw) end - # # Returns the value of a selected key in the configuration file. - # + # @param [String] key Key of configuration item + # @return [Hash|String] The resulting value stored against the 'key' def get(key) subkeys = key.split('.') lastkey = subkeys.pop @@ -62,9 +55,10 @@ module Core return (subhash != nil and subhash.has_key?(lastkey)) ? subhash[lastkey] : nil end - # # Sets the give key value pair to the config instance - # + # @param [String] key The configuration key + # @param value The value to be stored against the 'key' + # @return [Boolean] If the store procedure was successful def set(key, value) subkeys = key.split('.').reverse return false if subkeys.length == 0 @@ -76,9 +70,9 @@ module Core return true end - # # Clears the given key hash - # + # @param [String] key Configuration key to be cleared + # @return [Boolean] If the configuration key was cleared def clear(key) subkeys = key.split('.') return false if subkeys.length == 0 @@ -90,9 +84,7 @@ module Core return (hash.delete(lastkey) == nil) ? false : true end - # - # load extensions configurations - # + # Load extensions configurations def load_extensions_config self.set('beef.extension', {}) Dir.glob("#{$root_dir}/extensions/*/config.yaml") do | cf | @@ -104,9 +96,7 @@ module Core end end - # # Load module configurations - # def load_modules_config self.set('beef.module', {}) Dir.glob("#{$root_dir}/modules/**/*/config.yaml") do | cf | diff --git a/core/main/constants/browsers.rb b/core/main/constants/browsers.rb index 4b1a29411..4325e1a36 100644 --- a/core/main/constants/browsers.rb +++ b/core/main/constants/browsers.rb @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core module Constants @@ -38,6 +39,9 @@ module Constants FRIENDLY_O_NAME = 'Opera' FRIENDLY_UN_NAME = "UNKNOWN" + # Attempt to retrieve a browsers friendly name + # @param [String] browser_name Short browser name + # @return [String] Friendly browser name def self.friendly_name(browser_name) case browser_name @@ -53,6 +57,10 @@ module Constants end + # Attempt to match the browserstring to a browser constant + # @param [String] browserstring Browser UA string + # @return [Array] An array of matching browser constants + # @todo Confirm this function returns an array if multiple constants are matched def self.match_browser(browserstring) matches = [] browserstring.split(" ").each do |chunk| @@ -80,4 +88,4 @@ module Constants end end -end \ No newline at end of file +end diff --git a/core/main/constants/commandmodule.rb b/core/main/constants/commandmodule.rb index 4aeed9791..e5c7e42bf 100644 --- a/core/main/constants/commandmodule.rb +++ b/core/main/constants/commandmodule.rb @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core module Constants @@ -20,6 +21,7 @@ module Constants module CommandModule + # @note Constants to define the execution probability of a command module (this is browser dependant) VERIFIED_WORKING = 0 VERIFIED_UNKNOWN = 1 VERIFIED_USER_NOTIFY = 2 @@ -30,4 +32,4 @@ module Constants end end -end \ No newline at end of file +end diff --git a/core/main/constants/distributedengine.rb b/core/main/constants/distributedengine.rb index 6faa4ea08..8a06f56a0 100644 --- a/core/main/constants/distributedengine.rb +++ b/core/main/constants/distributedengine.rb @@ -13,11 +13,12 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core module Constants - # The distributed engine codes + # @note The distributed engine codes module DistributedEngine REQUESTER = 1 @@ -27,4 +28,4 @@ module Constants end end -end \ No newline at end of file +end diff --git a/core/main/constants/os.rb b/core/main/constants/os.rb index 367f10d61..e3ad74c32 100644 --- a/core/main/constants/os.rb +++ b/core/main/constants/os.rb @@ -13,11 +13,12 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core module Constants - # The OS'es strings for os detection. + # @note The OS'es strings for os detection. module Os OS_UNKNOWN_IMG = 'unknown.png' @@ -47,6 +48,9 @@ module Constants OS_ANDROID_IMG = 'android.png' OS_ALL_UA_STR = 'All' + # Attempt to match operating system string to constant + # @param [String] name Name of operating system + # @return [String] Constant name of matched operating system, returns 'ALL' if nothing are matched def self.match_os(name) case name.downcase when /win/ diff --git a/core/main/crypto.rb b/core/main/crypto.rb index f6bf6b5de..e4c6840d7 100644 --- a/core/main/crypto.rb +++ b/core/main/crypto.rb @@ -13,21 +13,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core - # - # This module provides crypto functionality - # + module Crypto - # the minimum length of the security token + # @note the minimum length of the security token TOKEN_MINIMUM_LENGTH = 15 - # # Generate a secure random token - # - # @param: {Integer} the length of the secure token - # + # @param [Integer] len The length of the secure token + # @return [String] Security token def self.secure_token(len = nil) # get default length from config config = BeEF::Core::Configuration.instance diff --git a/core/main/distributed_engine/models/rules.rb b/core/main/distributed_engine/models/rules.rb index 8884a1cbb..986a91ae7 100644 --- a/core/main/distributed_engine/models/rules.rb +++ b/core/main/distributed_engine/models/rules.rb @@ -13,13 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core module DistributedEngine module Models - # - # Table stores the rules for the Distributed Engine. - # + + # @note Table stores the rules for the Distributed Engine. class Rules include DataMapper::Resource @@ -35,4 +35,4 @@ module Models end end end -end \ No newline at end of file +end diff --git a/core/main/handlers/commands.rb b/core/main/handlers/commands.rb index 42a97a33a..1ebbd62d2 100644 --- a/core/main/handlers/commands.rb +++ b/core/main/handlers/commands.rb @@ -25,6 +25,10 @@ module Handlers attr_reader :guard @data = {} + # Handles command data + # @param [Hash] data Data from command execution + # @param [Class] kclass Class of command + # @todo Confirm argument data variable type. def initialize(data, kclass) @guard = Mutex.new @kclass = BeEF::Core::Command.const_get(kclass.capitalize) @@ -32,40 +36,45 @@ module Handlers setup() end + # Initial setup function, creates the command module and saves details to datastore 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 + @http_params = @data['request'].query + @http_header = @data['request'].header + @http_header['referer'] ||= '' - # get and check command id from the request + # @note 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 + # @todo 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::Filters.is_valid_command_id?(command_id.to_s()) - # get and check session id from the request + # @note get and check session id from the request beefhook = get_param(@data, 'beefhook') raise WEBrick::HTTPStatus::BadRequest, "beefhook is invalid" if not BeEF::Filters.is_valid_hook_session_id?(beefhook) - # create the command module to handle the response - command = @kclass.new(BeEF::Module.get_key_by_class(@kclass)) # create the commamd module - command.build_callback_datastore(@http_params, @http_header) # build datastore from the response + # @note create the command module to handle the response + command = @kclass.new(BeEF::Module.get_key_by_class(@kclass)) + command.build_callback_datastore(@http_params, @http_header) command.session_id = beefhook if command.respond_to?(:post_execute) command.post_execute end - # get/set details for datastore and log entry + # @note 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 + # @note save the command module results to the datastore and create a log entry command_results = {'data' => command_results} BeEF::Core::Models::Command.save_result(beefhook, command_id, command_friendly_name, command_results) end + # Returns parameter from hash + # @param [Hash] query Hash of data to return data from + # @param [String] key Key to search for and return inside `query` + # @return Value referenced in hash at the supplied key def get_param(query, key) return (query.class == Hash and query.has_key?(key)) ? query[key] : nil end diff --git a/core/main/handlers/hookedbrowsers.rb b/core/main/handlers/hookedbrowsers.rb index 155525e6c..57f2e7b1d 100644 --- a/core/main/handlers/hookedbrowsers.rb +++ b/core/main/handlers/hookedbrowsers.rb @@ -17,9 +17,7 @@ module BeEF module Core module Handlers - # - # This class handles connections from zombies to the framework. - # + # @note This class handles connections from hooked browsers to the framework. class HookedBrowsers < WEBrick::HTTPServlet::AbstractServlet include BeEF::Core::Handlers::Modules::BeEFJS @@ -31,11 +29,10 @@ module Handlers @guard = Mutex.new 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. - # + # This method processes the http requests sent by a hooked browser to the framework. It will update the database to add or update the current zombie and deploy some command modules or plugins. + # @param [Hash] request HTTP request object + # @param [Hash] response HTTP response object + # @todo Confirm return type of this function def do_GET(request, response) @body = '' @params = request.query @@ -43,7 +40,7 @@ module Handlers @response = response config = BeEF::Core::Configuration.instance - # check source ip address of browser + # @note check source ip address of browser permitted_hooking_subnet = config.get('beef.restrictions.permitted_hooking_subnet') target_network = IPAddr.new(permitted_hooking_subnet) if not target_network.include?(request.peeraddr[3].to_s) @@ -52,23 +49,24 @@ module Handlers return end - # get zombie if already hooked the framework + # @note get zombie if already hooked the framework hook_session_id = request.get_hook_session_id() hooked_browser = BeEF::Core::Models::HookedBrowser.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 + + # @note is a new browser so return instructions to set up the hook + if not hooked_browser - # generate the instructions to hook the browser - host_name = @request.host # get the host from the HOST attribute in the HTTP header + # @note generate the instructions to hook the browser + host_name = @request.host raise WEBrick::HTTPStatus::BadRequest, "Invalid host name" if not BeEF::Filters.is_valid_hostname?(host_name) build_beefjs!(host_name) - - else # is a known browseer so send instructions - - # record the last poll from the browser + + # @note is a known browser so send instructions + else + # @note record the last poll from the browser hooked_browser.lastseen = Time.new.to_i - # Check for a change in zombie IP and log an event + # @note Check for a change in zombie IP and log an event if hooked_browser.ip != @request.peeraddr[3].to_s BeEF::Core::Logger.instance.register('Zombie',"IP address has changed from #{hooked_browser.ip} to #{@request.peeraddr[3].to_s}","#{hooked_browser.id}") hooked_browser.ip = @request.peeraddr[3].to_s @@ -77,17 +75,15 @@ module Handlers hooked_browser.count! hooked_browser.save - # add all availible command module instructions to the response + # @note add all available command module instructions to the response 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)} - # - # We dynamically get the list of all browser hook handler using the API and register them - # + # @note We dynamically get the list of all browser hook handler using the API and register them BeEF::API::Registrar.instance.fire(BeEF::API::Server::Hook, 'pre_hook_send', hooked_browser, @body, @params, @request, @response) end - # set response headers and body + # @note set response headers and body response.set_no_cache response.header['Content-Type'] = 'text/javascript' response.header['Access-Control-Allow-Origin'] = '*' @@ -96,17 +92,19 @@ module Handlers end + # @note alias do_POST function to do_GET alias do_POST do_GET private - # Object representing the HTTP request + # @note Object representing the HTTP request @request - # Object representing the HTTP response + # @note Object representing the HTTP response @response - # A string containing the list of BeEF components active in the hooked browser + # @note A string containing the list of BeEF components active in the hooked browser + # @todo Confirm this variable is still used @beef_js_cmps end diff --git a/core/main/handlers/modules/beefjs.rb b/core/main/handlers/modules/beefjs.rb index a1b78f1dd..8eb8607f2 100644 --- a/core/main/handlers/modules/beefjs.rb +++ b/core/main/handlers/modules/beefjs.rb @@ -18,50 +18,45 @@ module Core module Handlers module Modules - # - # Purpose: avoid rewriting several times the same code. - # + # @note Purpose: avoid rewriting several times the same code. module BeEFJS - # # 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 - # + # @param [Object] req_host The request object 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}/core/main/client/" # location of sub files + # @note set up values required to construct beefjs + beefjs = '' + # @note location of sub files + beefjs_path = "#{$root_dir}/core/main/client/" js_sub_files = %w(lib/jquery-1.5.2.min.js lib/evercookie.js lib/json2.js beef.js browser.js browser/cookie.js 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) + # @note construct the beefjs string from file(s) js_sub_files.each {|js_sub_file_name| - js_sub_file_abs_path = beefjs_path + js_sub_file_name # construct absolute path - beefjs << (File.read(js_sub_file_abs_path) + "\n\n") # concat each js sub file + js_sub_file_abs_path = beefjs_path + js_sub_file_name + beefjs << (File.read(js_sub_file_abs_path) + "\n\n") } - # create the config for the hooked browser session + # @note create the config for the hooked browser session config = BeEF::Core::Configuration.instance hook_session_name = config.get('beef.http.hook_session_name') hook_session_config = BeEF::Core::Server.instance.to_h - # if http_host="0.0.0.0" in config ini, use the host requested by client + # @note if http_host="0.0.0.0" in config ini, use the host requested by client if hook_session_config['beef_host'].eql? "0.0.0.0" hook_session_config['beef_host'] = req_host hook_session_config['beef_url'].sub!(/0\.0\.0\.0/, req_host) end - # populate place holders in the beefjs string and set the response body + # @note 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 - # + # @param [String] component Name of component + # @return [String|Boolean] Returns false if path was not found, otherwise returns component path def find_beefjs_component_path(component) component_path = component component_path.gsub!(/beef./, '') @@ -73,13 +68,10 @@ module Modules component_path end - # # Builds missing beefjs components. - # - # Ex: build_missing_beefjs_components(['beef.net.local', 'beef.net.requester']) - # + # @param [Array] beefjs_components An array of component names def build_missing_beefjs_components(beefjs_components) - # verifies that @beef_js_cmps is not nil to avoid bugs + # @note verifies that @beef_js_cmps is not nil to avoid bugs @beef_js_cmps = '' if @beef_js_cmps.nil? if beefjs_components.is_a? String @@ -91,14 +83,13 @@ module Modules beefjs_components.keys.each {|k| next if @beef_js_cmps.include? beefjs_components[k] - # path to the component + # @note path to the component component_path = beefjs_components[k] - # we output the component to the hooked browser + # @note 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. + # @note finally we add the component to the list of components already generated so it does not get generated numerous times. if @beef_js_cmps.eql? '' @beef_js_cmps = component_path else diff --git a/core/main/handlers/modules/command.rb b/core/main/handlers/modules/command.rb index 11979e071..78a78e251 100644 --- a/core/main/handlers/modules/command.rb +++ b/core/main/handlers/modules/command.rb @@ -20,9 +20,9 @@ module Modules module Command - # # Adds the command module instructions to a hooked browser's http response. - # + # @param [Object] command Command object + # @param [Object] hooked_browser Hooked Browser object def add_command_instructions(command, hooked_browser) raise WEBrick::HTTPStatus::BadRequest, "hooked_browser is nil" if hooked_browser.nil? @@ -30,7 +30,7 @@ module Modules raise WEBrick::HTTPStatus::BadRequest, "hooked_browser is nil" if command.nil? raise WEBrick::HTTPStatus::BadRequest, "hooked_browser.command_module_id is nil" if command.command_module_id.nil? - # get the command module + # @note get the command module command_module = BeEF::Core::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? @@ -51,13 +51,13 @@ module Modules @body << command_module.output + "\n\n" - # prints the event to the console + # @note prints the event to the console if BeEF::Settings.console? name = command_module.friendlyname || kclass print_info "Hooked browser #{hooked_browser.ip} has been sent instructions from command module '#{name}'" end - # flag that the command has been sent to the hooked browser + # @note flag that the command has been sent to the hooked browser command.instructions_sent = true command.save end diff --git a/core/main/logger.rb b/core/main/logger.rb index 604d3428c..bb3d92cbf 100644 --- a/core/main/logger.rb +++ b/core/main/logger.rb @@ -13,48 +13,35 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core - # - # This class takes care of logging events in the db. - # - # Example: - # - # logger = BeEF::Core::Logger.instance - # logger.register('Authentication', 'User with ip 127.0.0.1 has successfully authenticated into the application') # => true - # - # zombie_id = 1 - # logger.register('Zombie', '123.456.789.123 just joined the horde', zombie_id) # => true - # + class Logger include Singleton - # # Constructor - # def initialize @logs = BeEF::Core::Models::Log end - # # Registers a new event in the logs - # - # @param: {String} the origine of the event (i.e. Authentication, Zombie) - # @param: {String} the event description - # @param: {Integer} the id of the hooked browser affected (default = 0 if no HB) - # - def register(from, event, zombie = 0) + # @param [String] from The origin of the event (i.e. Authentication, Hooked Browser) + # @param [String] event The event description + # @param [Integer] hb The id of the hooked browser affected (default = 0 if no HB) + # @return [Boolean] True if the register was successful + def register(from, event, hb = 0) # type conversion to enforce standards - zombie = zombie.to_i + hb = hb.to_i # arguments type checking raise Exception::TypeError, '"from" needs to be a string' if not from.string? raise Exception::TypeError, '"event" needs to be a string' if not event.string? - raise Exception::TypeError, '"zombie" needs to be an integer' if not zombie.integer? + raise Exception::TypeError, '"Hooked Browser ID" needs to be an integer' if not hb.integer? # logging the new event into the database - @logs.new(:type => "#{from}", :event => "#{event}", :date => Time.now, :hooked_browser_id => zombie).save + @logs.new(:type => "#{from}", :event => "#{event}", :date => Time.now, :hooked_browser_id => hb).save # return true diff --git a/core/main/migration.rb b/core/main/migration.rb index e48c7e75f..bafc94720 100644 --- a/core/main/migration.rb +++ b/core/main/migration.rb @@ -13,27 +13,23 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core - # - # 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. - # + + # @note 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! end - # # Checks for new command modules and updates the database. - # def update_commands! config = BeEF::Core::Configuration.instance diff --git a/core/main/models/command.rb b/core/main/models/command.rb index 1acd63871..069f51d61 100644 --- a/core/main/models/command.rb +++ b/core/main/models/command.rb @@ -13,22 +13,12 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core module Models - # - # Table stores the commands that have been sent to the Hooked Browsers. - # - # Attributes: - # - # - id - # - data - # - creationdate - # - label - # - instructions_sent - # - command_module_id - # - hooked_browser_id - # + + # @note Table stores the commands that have been sent to the Hooked Browsers. class Command include DataMapper::Resource @@ -43,25 +33,22 @@ module Models has n, :results - # # Save results and flag that the command has been run on the hooked browser - # - # @param: {String} the session_id. - # @param: {String} the command_id. - # @param: {String} the command friendly name. - # @param: {String} the result of the command module. - # + # @param [String] hook_session_id The session_id. + # @param [String] command_id The command_id. + # @param [String] command_friendly_name The command friendly name. + # @param [String] result The result of the command module. def self.save_result(hook_session_id, command_id, command_friendly_name, result) - # enforcing arguments types + # @note enforcing arguments types command_id = command_id.to_i - # argument type checking + # @note argument type checking raise Exception::TypeError, '"hook_session_id" needs to be a string' if not hook_session_id.string? raise Exception::TypeError, '"command_id" needs to be an integer' if not command_id.integer? raise Exception::TypeError, '"command_friendly_name" needs to be a string' if not command_friendly_name.string? raise Exception::TypeError, '"result" needs to be a hash' if not result.hash? - # get the hooked browser structure and id from the database + # @note get the hooked browser structure and id from the database hooked_browser = BeEF::Core::Models::HookedBrowser.first(:session => hook_session_id) || nil raise Exception::TypeError, "hooked_browser is nil" if hooked_browser.nil? raise Exception::TypeError, "hooked_browser.id is nil" if hooked_browser.id.nil? @@ -69,18 +56,18 @@ module Models raise Exception::TypeError, "hooked_browser.ip is nil" if hooked_browser.ip.nil? hooked_browser_ip = hooked_browser.ip - # get the command module data structure from the database + # @note get the command module data structure from the database command = first(:id => command_id.to_i, :hooked_browser_id => hooked_browser_id) || nil raise Exception::TypeError, "command is nil" if command.nil? - # create the entry for the results + # @note create the entry for the results command.results.new(:hooked_browser_id => hooked_browser_id, :data => result.to_json, :date => Time.now.to_i) command.save - # log that the result was returned + # @note log that the result was returned BeEF::Core::Logger.instance.register('Command', "Hooked browser #{hooked_browser.ip} has executed instructions from command module '#{command_friendly_name}'", hooked_browser_id) - # prints the event into the console + # @note prints the event into the console if BeEF::Settings.console? print_info "Hooked browser #{hooked_browser.ip} has executed instructions from command module '#{command_friendly_name}'" end @@ -90,4 +77,4 @@ module Models end end -end \ No newline at end of file +end diff --git a/core/main/models/hookedbrowser.rb b/core/main/models/hookedbrowser.rb index 7539d382d..96519f340 100644 --- a/core/main/models/hookedbrowser.rb +++ b/core/main/models/hookedbrowser.rb @@ -31,27 +31,25 @@ module Models 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 + # @note the domain originating the hook request + property :domain, Text, :lazy => false property :count, Integer, :lazy => false property :has_init, Boolean, :default => false - property :is_proxy, Boolean, :default => false # if true the HB is used as a tunneling proxy - + property :is_proxy, Boolean, :default => false + # @note if true the HB is used as a tunneling proxy + 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) - # + # Returns the icon representing the browser type the hooked browser is using (i.e. Firefox, Internet Explorer) + # @return [String] String constant containing browser icon path def browser_icon agent = JSON.parse(self.httpheaders)['user-agent'].to_s || nil @@ -67,10 +65,8 @@ module Models BeEF::Extension::AdminUI::Constants::Agents::AGENT_UNKNOWN_IMG end - # - # Returns the icon representing the os type the - # hooked browser is running (i.e. Windows, Linux) - # + # Returns the icon representing the os type the hooked browser is running (i.e. Windows, Linux) + # @return [String] String constant containing operating system icon path def os_icon agent = JSON.parse(self.httpheaders)['user-agent'].to_s || nil @@ -86,4 +82,4 @@ module Models end end -end \ No newline at end of file +end diff --git a/core/main/models/log.rb b/core/main/models/log.rb index d2674c0db..7bd992fce 100644 --- a/core/main/models/log.rb +++ b/core/main/models/log.rb @@ -16,11 +16,7 @@ module BeEF module Core module Models - # - # This table stores the logs from the framework. - # - # See BeEF::Core::Logger for how to log events. - # + class Log include DataMapper::Resource @@ -36,4 +32,4 @@ module Models end end end -end \ No newline at end of file +end diff --git a/core/main/models/result.rb b/core/main/models/result.rb index 70d86ffd0..9cc40653b 100644 --- a/core/main/models/result.rb +++ b/core/main/models/result.rb @@ -16,9 +16,7 @@ module BeEF module Core module Models - # - # Table stores the results from commands. - # + class Result include DataMapper::Resource @@ -33,4 +31,4 @@ module Models end end -end \ No newline at end of file +end diff --git a/core/main/models/user.rb b/core/main/models/user.rb index 551f684a5..b7cd05762 100644 --- a/core/main/models/user.rb +++ b/core/main/models/user.rb @@ -16,11 +16,8 @@ module BeEF module Core module Models - # - # Table stores the list of users that have authenticated into beef. - # - # TODO: move this table into the AdminUI extension folder. - # + + # @todo move this table into the AdminUI extension folder. class User include DataMapper::Resource @@ -31,9 +28,8 @@ module Models property :session_id, String, :length => 255 property :ip, Text - # # Checks if the user has been authenticated - # + # @return [Boolean] If the user is authenticated def authenticated? true || false if not @ip.nil? end @@ -42,4 +38,4 @@ module Models end end -end \ No newline at end of file +end diff --git a/core/main/network_stack/api.rb b/core/main/network_stack/api.rb index a6c023dbd..0f8a25392 100644 --- a/core/main/network_stack/api.rb +++ b/core/main/network_stack/api.rb @@ -18,17 +18,16 @@ module Core module NetworkStack module RegisterHttpHandler - # + # Register the http handler for the network stack - # + # @param [Object] server HTTP server instance def self.mount_handler(server) - #dynamic handler + # @note this mounts the dynamic handler server.mount('/dh', true, BeEF::Core::NetworkStack::Handlers::DynamicReconstruction) end end - # Register core API calls BeEF::API::Registrar.instance.register(BeEF::Core::NetworkStack::RegisterHttpHandler, BeEF::API::Server, 'mount_handler') end diff --git a/core/main/network_stack/assethandler.rb b/core/main/network_stack/assethandler.rb index 89c9beb63..b80624a94 100644 --- a/core/main/network_stack/assethandler.rb +++ b/core/main/network_stack/assethandler.rb @@ -18,25 +18,28 @@ module Core module NetworkStack module Handlers - # - # Class defining BeEF assets - # + # @note Class defining BeEF assets class AssetHandler - # call BeEF::Core::NetworkStack::Handlers::AssetHandler.instance + # @note call BeEF::Core::NetworkStack::Handlers::AssetHandler.instance include Singleton attr_reader :allocations, :root_dir + # Starts the AssetHandler instance def initialize @allocations = {} @http_server = BeEF::Core::Server.instance @root_dir = File.expand_path('../../../../', __FILE__) end - # # Binds a file to a mount point - # + # @param [String] file File path to asset + # @param [String] path URL path to mount the asset to (can be nil for random path) + # @param [String] extension Extension to append to the URL path (can be nil for none) + # @param [Integer] count The amount of times the asset can be accessed before being automatically unbinded (-1 = unlimited) + # @return [String] URL Path of mounted asset + # @todo This function should accept a hooked browser session to limit the mounted file to a certain session 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} @@ -45,26 +48,27 @@ module Handlers return url end - # # Unbinds a file from a mount point - # + # @param [String] url URL path of asset to be unbinded 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 - # + # Builds a URL based on the path and extension, if neither are passed a random URL will be generated + # @param [String] path URL Path defined by bind() + # @param [String] extension Extension defined by bind() + # @param [Integer] length The amount of characters to be used when generating a random URL + # @return [String] Generated URL 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. - # + # @param [String] url URL Path of mounted file + # @return [Boolean] Returns true if the file is mounted def check(url) if @allocations.has_key?(url) count = @allocations[url]['count'] diff --git a/core/main/network_stack/handlers/dynamicreconstruction.rb b/core/main/network_stack/handlers/dynamicreconstruction.rb index 955345e05..051e91c82 100644 --- a/core/main/network_stack/handlers/dynamicreconstruction.rb +++ b/core/main/network_stack/handlers/dynamicreconstruction.rb @@ -18,19 +18,20 @@ module Core module NetworkStack module Handlers - #DynamicHanlder is used reconstruct segmented traffic from the zombies - + # @note DynamicHanlder is used reconstruct segmented traffic from the hooked browser class DynamicReconstruction < WEBrick::HTTPServlet::AbstractServlet attr_reader :guard - #holds packet queue + # @note holds packet queue PQ = Array.new() - #obtain dynamic mount points from HttpHookServer + # @note obtain dynamic mount points from HttpHookServer MOUNTS = BeEF::Core::Server.instance.mounts - #Combines packet information and pushes to PQ, then checks packets + # Combines packet information and pushes to PQ, then checks packets + # @param [Object] request Request object + # @param [Object] response Response object def do_POST(request, response) @request = request response.set_no_cache @@ -48,9 +49,10 @@ module Handlers check_packets() end + # @note Alias do_GET function to do_POST alias do_GET do_POST - #check packets goes through the PQ array and attempts to reconstruct the stream from multiple packets + # 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| @@ -88,14 +90,17 @@ module Handlers end end - #delete packets that have been reconstructed, return deleted packets + # Delete packets that have been reconstructed, return deleted packets + # @param [String] beefhook Beefhook of hooked browser + # @param [Integer] stream_id The stream ID def expunge(beefhook, stream_id) packets = PQ.select{ |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id } PQ.delete_if { |p| p[:beefhook] == beefhook and p[:stream_id] == stream_id } return packets.sort_by { |p| p[:packet_id] } end - #execute is called once a stream has been rebuilt. it searches the mounts and passes the data to the correct handler + # Execute is called once a stream has been rebuilt. it searches the mounts and passes the data to the correct handler + # @param [Hash] data Hash of data that has been rebuilt by the dynamic reconstruction def execute(data) handler = get_param(data, 'handler') if (MOUNTS.has_key?(handler)) @@ -107,7 +112,10 @@ module Handlers end end - #assist function for getting parameter from hash + # Assist function for getting parameter from hash + # @param [Hash] query Hash to pull key from + # @param [String] key The key association to return from `query` + # @return Value associated with `key` def get_param(query, key) return nil if query[key].nil? query[key] diff --git a/core/main/server.rb b/core/main/server.rb index 4d26f05fc..3be3fae16 100644 --- a/core/main/server.rb +++ b/core/main/server.rb @@ -13,30 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. # + module BeEF module Core - # - # Class defining the BeEF http server. - # - # Example: - # - # server = BeEF::Core::Server.instance - # server.prepare - # server.start - # ... - # server.stop - # + class Server include Singleton - # Grabs the version of beef the framework is deployed on + # @note Grabs the version of beef the framework is deployed on VERSION = BeEF::Core::Configuration.instance.get('beef.version') attr_reader :root_dir, :url, :configuration, :command_urls, :mounts - # - # Constructor - # + + # Constructor starts the BeEF server including the configuration system def initialize @configuration = BeEF::Core::Configuration.instance beef_host = @configuration.get("beef.http.public") || @configuration.get("beef.http.host") @@ -46,10 +36,8 @@ module Core @mounts = {} end - # - # Returns all server variables in a hash. Useful for Erubis when - # generating the javascript for the command modules and hooking. - # + # Returns all server variables in a hash. Useful for Erubis when generating the javascript for the command modules and hooking. + # @return [Hash] BeEF info hash def to_h { 'beef_version' => VERSION, @@ -62,9 +50,11 @@ module Core } end - # - # - # + # Returns command URL + # @param [String] command_path Command path + # @return [String] URL of command + # @todo Unsure how @command_urls is populated, this command is possibly deprecated + # @deprecated See note def get_command_url(command_path) # argument type checking raise Exception::TypeError, '"command_path" needs to be a string' if not command_path.string? @@ -76,9 +66,7 @@ module Core end end - # # Starts the BeEF http server. - # def prepare if not @http_server config = {} @@ -93,16 +81,12 @@ module Core # Create http handler for the javascript hook file mount("#{@configuration.get("beef.http.hook_file")}", true, BeEF::Core::Handlers::HookedBrowsers) - # # We dynamically get the list of all http handler using the API and register them - # BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'mount_handler', self) end end - # # Starts the BeEF http server - # def start # we trap CTRL+C in the console and kill the server trap("INT") { BeEF::Core::Server.instance.stop } @@ -111,9 +95,7 @@ module Core @http_server.start end - # # Stops the BeEF http server. - # def stop if @http_server # shuts down the server @@ -125,19 +107,14 @@ module Core end end - # # Restarts the BeEF http server. - # def restart; stop; start; end - # # Mounts a handler, can either be a hard or soft mount - # - # @param: {String} the url to mount - # @param: {Boolean} set to true for a hard mount, false for a soft mount. - # @param: {Class} class to call once mount is triggered - # @param: {Various} arguments to pass to the http handler class - # + # @param [String] url The url to mount + # @param [Boolean] hard Set to true for a hard mount, false for a soft mount. + # @param [Class] http_handler_class Class to call once mount is triggered + # @param args Arguments to pass to the http handler class def mount(url, hard, http_handler_class, args = nil) # argument type checking raise Exception::TypeError, '"url" needs to be a string' if not url.string? @@ -161,12 +138,9 @@ module Core end end - # # Unmounts handler - # - # @param: {String} url to mount. - # @param: {Boolean} set to true for a hard mount, false for a soft mount. - # + # @param [String] url URL to unmount. + # @param [Boolean] hard Set to true for a hard mount, false for a soft mount. def unmount(url, hard) # argument type checking raise Exception::TypeError, '"url" needs to be a string' if not url.string?