From e9a6049e58c7bd3cd60e69f774da213337ea9913 Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Sun, 4 Mar 2012 14:55:03 +0100 Subject: [PATCH] Fixes issue 621: Added 2 new command line options. Now it's psosible to specify a different config.yaml file. Also changed the core load order, adding a new bootstrap module. --- .gitignore | 1 + beef | 30 ++++++++----- core/bootstrap.rb | 42 +++++++++++++++++++ core/core.rb | 18 ++------ core/loader.rb | 9 +--- core/main/configuration.rb | 21 ++++++---- {extensions => core/main}/console/banners.rb | 6 +-- {extensions => core/main}/console/beef.ascii | 0 .../main}/console/commandline.rb | 34 +++++++++------ core/ruby/print.rb | 3 +- extensions/console/extension.rb | 33 +-------------- test/common/test_constants.rb | 4 +- test/thirdparty/msf/unit/tc_metasploit.rb | 1 + 13 files changed, 111 insertions(+), 91 deletions(-) create mode 100644 core/bootstrap.rb rename {extensions => core/main}/console/banners.rb (96%) rename {extensions => core/main}/console/beef.ascii (100%) rename {extensions => core/main}/console/commandline.rb (61%) diff --git a/.gitignore b/.gitignore index 88f0bf558..c02e0a406 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ beef.db test/msf-test +custom-config.yaml \ No newline at end of file diff --git a/beef b/beef index f55a3a8c4..f6cbb0840 100755 --- a/beef +++ b/beef @@ -41,15 +41,26 @@ end # @note Require core loader's require 'core/loader' -# @note Starts configuration system -config = BeEF::Core::Configuration.instance +# @note Initialize the Configuration object. Eventually loads a different config.yaml if -c flag was passed. +if BeEF::Core::Console::CommandLine.parse[:ext_config].empty? + config = BeEF::Core::Configuration.new("#{$root_dir}/config.yaml") +else + config = BeEF::Core::Configuration.new("#{$root_dir}/#{BeEF::Core::Console::CommandLine.parse[:ext_config]}") +end + +# @note After the BeEF core is loaded, bootstrap the rest of the framework internals +require 'core/bootstrap' # @note Loads enabled extensions BeEF::Extensions.load +# @note Prints the BeEF ascii art if the -a flag was passed +if BeEF::Core::Console::CommandLine.parse[:ascii_art] == true + BeEF::Core::Console::Banners.print_ascii_art +end + # @note Prints BeEF welcome message -#BeEF::Extension::Console::Banners.print_ascii_art -BeEF::Extension::Console::Banners.print_welcome_msg +BeEF::Core::Console::Banners.print_welcome_msg # @note Loads enabled modules BeEF::Modules.load @@ -75,8 +86,7 @@ case config.get("beef.database.driver") end # @note Resets the database if the -x flag was passed -# @todo Change reference from Extension::Console to Core::Console once the console extension is merged with the core -if BeEF::Extension::Console.resetdb? +if BeEF::Core::Console::CommandLine.parse[:resetdb] print_info 'Resetting the database for BeEF.' DataMapper.auto_migrate! else @@ -94,10 +104,10 @@ http_hook_server = BeEF::Core::Server.instance http_hook_server.prepare # @note Prints information back to the user before running the server -BeEF::Extension::Console::Banners.print_loaded_extensions -BeEF::Extension::Console::Banners.print_loaded_modules -BeEF::Extension::Console::Banners.print_network_interfaces_count -BeEF::Extension::Console::Banners.print_network_interfaces_routes +BeEF::Core::Console::Banners.print_loaded_extensions +BeEF::Core::Console::Banners.print_loaded_modules +BeEF::Core::Console::Banners.print_network_interfaces_count +BeEF::Core::Console::Banners.print_network_interfaces_routes # @note Call the API method 'pre_http_start' BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server) diff --git a/core/bootstrap.rb b/core/bootstrap.rb new file mode 100644 index 000000000..68c6df8dd --- /dev/null +++ b/core/bootstrap.rb @@ -0,0 +1,42 @@ +# +# Copyright 2012 Wade Alcorn wade@bindshell.net +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +module BeEF + module Core + + end +end + +## @note Include http server functions for beef +require 'core/main/server' +require 'core/main/handlers/modules/beefjs' +require 'core/main/handlers/modules/command' +require 'core/main/handlers/commands' +require 'core/main/handlers/hookedbrowsers' + +# @note Include the network stack +require 'core/main/network_stack/handlers/dynamicreconstruction' +require 'core/main/network_stack/assethandler' +require 'core/main/network_stack/api' + +# @note Include the distributed engine +require 'core/main/distributed_engine/models/rules' + +## @note Include helpers +require 'core/module' +require 'core/modules' +require 'core/extension' +require 'core/extensions' +require 'core/hbmanager' \ No newline at end of file diff --git a/core/core.rb b/core/core.rb index 1abd7adc5..49139feea 100644 --- a/core/core.rb +++ b/core/core.rb @@ -44,20 +44,8 @@ require 'core/main/crypto' require 'core/main/logger' require 'core/main/migration' -# @note Include http server functions for beef -require 'core/main/server' +# @note Include the command line parser and the banner printer +require 'core/main/console/commandline' +require 'core/main/console/banners' -require 'core/main/handlers/modules/beefjs' -require 'core/main/handlers/modules/command' - -require 'core/main/handlers/commands' -require 'core/main/handlers/hookedbrowsers' - -# @note Include the network stack -require 'core/main/network_stack/handlers/dynamicreconstruction' -require 'core/main/network_stack/assethandler' -require 'core/main/network_stack/api' - -# @note Include the distributed engine -require 'core/main/distributed_engine/models/rules' diff --git a/core/loader.rb b/core/loader.rb index 6e3bd192d..3ba04c62f 100644 --- a/core/loader.rb +++ b/core/loader.rb @@ -38,11 +38,4 @@ require 'core/api' require 'core/settings' # @note Include the core of BeEF -require 'core/core' - -# @note Include helpers -require 'core/module' -require 'core/modules' -require 'core/extension' -require 'core/extensions' -require 'core/hbmanager' +require 'core/core' \ No newline at end of file diff --git a/core/main/configuration.rb b/core/main/configuration.rb index 6db3b9f0d..c6d7de06f 100644 --- a/core/main/configuration.rb +++ b/core/main/configuration.rb @@ -19,24 +19,31 @@ module BeEF class Configuration - include Singleton + attr_accessor :config + + # antisnatchor: still a singleton, but implemented by hand because we want to have only one instance + # of the Configuration object while having the possibility to specify a parameter to the constructor. + # This is why we don't use anymore the default Ruby implementation -> include Singleton + def self.instance() + return @@instance + end # 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? - # test to make sure file exists - raise Exception::TypeError, 'Configuration yaml cannot be found' if not File.exist?(configuration_file) + def initialize(config) + raise Exception::TypeError, '"config" needs to be a string' if not config.string? + raise Exception::TypeError, 'Configuration yaml cannot be found' if not File.exist?(config) begin #open base config - @config = self.load(configuration_file) + @config = self.load(config) # set default value if key? does not exist @config.default = nil + @@config = config rescue Exception => e print_error "Fatal Error: cannot load configuration file" print_debug e end + @@instance = self end # Loads yaml file diff --git a/extensions/console/banners.rb b/core/main/console/banners.rb similarity index 96% rename from extensions/console/banners.rb rename to core/main/console/banners.rb index 038eb7b52..40d52b825 100644 --- a/extensions/console/banners.rb +++ b/core/main/console/banners.rb @@ -14,7 +14,7 @@ # limitations under the License. # module BeEF -module Extension +module Core module Console module Banners @@ -25,8 +25,8 @@ module Banners # Prints BeEF's ascii art # def print_ascii_art - if File.exists?('extensions/console/beef.ascii') - File.open('extensions/console/beef.ascii', 'r') do |f| + if File.exists?('core/main/console/beef.ascii') + File.open('core/main/console/beef.ascii', 'r') do |f| while line = f.gets puts line end diff --git a/extensions/console/beef.ascii b/core/main/console/beef.ascii similarity index 100% rename from extensions/console/beef.ascii rename to core/main/console/beef.ascii diff --git a/extensions/console/commandline.rb b/core/main/console/commandline.rb similarity index 61% rename from extensions/console/commandline.rb rename to core/main/console/commandline.rb index 3c27e814c..340e79135 100644 --- a/extensions/console/commandline.rb +++ b/core/main/console/commandline.rb @@ -14,7 +14,7 @@ # limitations under the License. # module BeEF - module Extension + module Core module Console # # This module parses the command line argument when running beef. @@ -24,6 +24,8 @@ module BeEF @options = Hash.new @options[:verbose] = false @options[:resetdb] = false + @options[:ascii_art] = false + @options[:ext_config] = "" @already_parsed = false @@ -35,19 +37,27 @@ module BeEF return @options if @already_parsed begin - optparse = OptionParser.new do |opts| - opts.on('-x', '--reset', 'Reset the database') do - @options[:resetdb] = true + optparse = OptionParser.new do |opts| + opts.on('-x', '--reset', 'Reset the database') do + @options[:resetdb] = true + end + + opts.on('-v', '--verbose', 'Display debug information') do + @options[:verbose] = true + end + + opts.on('-a', '--ascii_art', 'Prints BeEF ascii art') do + @options[:ascii_art] = true + end + + opts.on('-c', '--config FILE', 'Load a different configuration file: if it\'s called custom-config.yaml, git automatically ignores it.') do |f| + @options[:ext_config] = f + end end - opts.on('-v', '--verbose', 'Display debug information') do - @options[:verbose] = true - end - end - - optparse.parse! - @already_parsed = true - @options + optparse.parse! + @already_parsed = true + @options rescue OptionParser::InvalidOption => e puts "Invalid command line option provided. Please run beef --help" exit 1 diff --git a/core/ruby/print.rb b/core/ruby/print.rb index ae066a5db..138809b0c 100644 --- a/core/ruby/print.rb +++ b/core/ruby/print.rb @@ -29,10 +29,9 @@ end # Function used to print debug information # @param [String] s String to be printed # @note This function will only print messages if the debug flag is set to true -# @todo Once the console extension has been merged into the core, remove the extension checks. def print_debug(s) config = BeEF::Core::Configuration.instance - if config.get('beef.debug') || (BeEF::Extension.is_loaded('console') && BeEF::Extension::Console.verbose?) + if config.get('beef.debug') || BeEF::Core::Console::CommandLine.parse[:verbose] puts Time.now.localtime.strftime("[%k:%M:%S]")+'[>]'.yellow+' '+s.to_s end end diff --git a/extensions/console/extension.rb b/extensions/console/extension.rb index f602fc098..8574e46cc 100644 --- a/extensions/console/extension.rb +++ b/extensions/console/extension.rb @@ -24,39 +24,8 @@ module Console # @short_name = @full_name = 'console' @description = 'console environment to manage beef' - - # - # Returns true of the verbose option has been enabled for the console. - # False if not. - # - # Example: - # - # $ ruby console.rb -v - # BeEF::Extension::Console.verbose? # => true - # - # $ ruby console.rb - # BeEF::Extension::Console.verbose? # => false - # - def self.verbose? - CommandLine.parse[:verbose] - end - - # - # Returns true if we should reset the database. False if not. - # - # $ ruby console.rb -x - # BeEF::Extension::Console.resetdb? # => true - # - # $ ruby console.rb - # BeEF::Extension::Console.resetdb? # => false - # - def self.resetdb? - CommandLine.parse[:resetdb] - end - + end end end -require 'extensions/console/banners' -require 'extensions/console/commandline' diff --git a/test/common/test_constants.rb b/test/common/test_constants.rb index c0d00d9e8..bb25aed5b 100644 --- a/test/common/test_constants.rb +++ b/test/common/test_constants.rb @@ -1,6 +1,6 @@ BEEF_TEST_DIR = "/tmp/beef-test/" -ATTACK_DOMAIN = "attacker.beefproject.com" -VICTIM_DOMAIN = "victim.beefproject.com" +ATTACK_DOMAIN = "127.0.0.1" +VICTIM_DOMAIN = "127.0.0.1" ATTACK_URL = "http://" + ATTACK_DOMAIN + ":3000/ui/panel" VICTIM_URL = "http://" + VICTIM_DOMAIN + ":3000/demos/basic.html" diff --git a/test/thirdparty/msf/unit/tc_metasploit.rb b/test/thirdparty/msf/unit/tc_metasploit.rb index 3f625ca9b..84e7b3a1f 100644 --- a/test/thirdparty/msf/unit/tc_metasploit.rb +++ b/test/thirdparty/msf/unit/tc_metasploit.rb @@ -41,6 +41,7 @@ class TC_Metasploit < Test::Unit::TestCase # Load the config for testing # def load_config + BeEF::Core::Configuration.new("#{$root_dir}/config.yaml") BeEF::Core::Configuration.instance.load_extensions_config @config = BeEF::Core::Configuration.instance.get('beef.extension.metasploit') end