#!/usr/bin/env ruby # # Copyright (c) 2006-2024 Wade Alcorn - wade@bindshell.net # Browser Exploitation Framework (BeEF) - http://beefproject.com # See the file 'doc/COPYING' for copying permission # # # @note stop Fixnum deprecation warning from being displayed # $VERBOSE = nil # # @note Version check to ensure BeEF is running Ruby 3.0+ # min_ruby_version = '3.0' if RUBY_VERSION < min_ruby_version puts puts "Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to Ruby version #{min_ruby_version} or later." puts exit 1 end # # @note Platform check to ensure BeEF is not running on Windows # if RUBY_PLATFORM.downcase.include?('mswin') || RUBY_PLATFORM.downcase.include?('mingw') puts puts "Ruby platform #{RUBY_PLATFORM} is not supported." puts exit 1 end # # @note set load path, application root directory and user preferences directory # $root_dir = File.join(File.expand_path(File.dirname(File.realpath(__FILE__))), '.') $:.unshift($root_dir) $home_dir = File.expand_path("#{Dir.home}/.beef/", __FILE__).freeze # # @note Require core loader # require 'core/loader' require 'timeout' # # @note Ask user if they would like to update beef # if File.exist?("#{$root_dir}git") && BeEF::Core::Console::CommandLine.parse[:update_disabled] == false if BeEF::Core::Console::CommandLine.parse[:update_auto] == true print 'Checking latest BeEF repository and updating' `git pull && bundle` elsif `git rev-parse master` != `git rev-parse origin/master` begin Timeout.timeout(5) do puts '-- BeEF Update Available --' print 'Would you like to update to lastest version? y/n: ' response = gets `git pull && bundle` if response&.strip == 'y' end rescue Timeout::Error puts "\nUpdate Skipped with input timeout" end end end # # @note Create ~/.beef/ # begin FileUtils.mkdir_p($home_dir) unless File.directory?($home_dir) rescue => e print_error "Could not create '#{$home_dir}': #{e.message}" exit 1 end # # @note Initialize the Configuration object. 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("#{BeEF::Core::Console::CommandLine.parse[:ext_config]}") end # # @note set log level # BeEF.logger.level = config.get('beef.debug') ? Logger::DEBUG : Logger::WARN # # @note Check the system language settings for UTF-8 compatibility # env_lang = ENV['LANG'] if env_lang !~ /(utf8|utf-8)/i print_warning "Warning: System language $LANG '#{env_lang}' does not appear to be UTF-8 compatible." if env_lang =~ /\A([a-z]+_[a-z]+)\./i country = $1 print_more "Try: export LANG=#{country}.utf8" end end # # @note Check if port and WebSocket port need to be updated from command line parameters # unless BeEF::Core::Console::CommandLine.parse[:port].empty? config.set('beef.http.port', BeEF::Core::Console::CommandLine.parse[:port]) end unless BeEF::Core::Console::CommandLine.parse[:ws_port].empty? config.set('beef.http.websocket.port', BeEF::Core::Console::CommandLine.parse[:ws_port]) end # # @note Validate configuration file # unless BeEF::Core::Configuration.instance.validate exit 1 end # # @note Exit on default credentials # if config.get("beef.credentials.user").eql?('beef') && config.get("beef.credentials.passwd").eql?('beef') print_error "ERROR: Default username and password in use!" print_more "Change the beef.credentials.passwd in config.yaml" exit 1 end # # @note Validate beef.http.public and beef.http.public_port # unless config.get('beef.http.public.host').to_s.eql?('') || BeEF::Filters.is_valid_hostname?(config.get('beef.http.public.host')) print_error "ERROR: Invalid public hostname: #{config.get('beef.http.public.host')}" exit 1 end unless config.get('beef.http.public.port').to_s.eql?('') || BeEF::Filters.is_valid_port?(config.get('beef.http.public.port')) print_error "ERROR: Invalid public port: #{config.get('beef.http.public.port')}" exit 1 end # # @note After the BeEF core is loaded, bootstrap the rest of the framework internals # require 'core/bootstrap' # # @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::Core::Console::Banners.print_welcome_msg # # @note Loads enabled extensions # BeEF::Extensions.load # # @note Loads enabled modules # BeEF::Modules.load # # @note Disable reverse DNS # Socket.do_not_reverse_lookup = true # # @note Database setup # # # @note Load the database # db_file = config.get('beef.database.file') # @note Resets the database if the -x flag was passed if BeEF::Core::Console::CommandLine.parse[:resetdb] print_info 'Resetting the database for BeEF.' begin File.delete(db_file) if File.exist?(db_file) rescue => e print_error("Could not remove '#{db_file}' database file: #{e.message}") exit(1) end end # Connect to DB ActiveRecord::Base.logger = nil OTR::ActiveRecord.migrations_paths = [File.join('core', 'main', 'ar-migrations')] OTR::ActiveRecord.configure_from_hash!(adapter:'sqlite3', database:db_file) # otr-activerecord require you to manually establish the connection with the following line #Also a check to confirm that the correct Gem version is installed to require it, likely easier for old systems. if Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2') OTR::ActiveRecord.establish_connection! end # Migrate (if required) context = ActiveRecord::Migration.new.migration_context if context.needs_migration? ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration).migrate end # # @note Extensions may take a moment to load, thus we print out a please wait message # print_info 'BeEF is loading. Wait a few seconds...' # # @note Execute migration procedure, checks for new modules # begin BeEF::Core::Migration.instance.update_db! rescue => e print_error("Could not update '#{db_file}' database file: #{e.message}") exit(1) end # # @note Create HTTP Server and prepare it to run # http_hook_server = BeEF::Core::Server.instance http_hook_server.prepare begin BeEF::Core::Logger.instance.register('System', 'BeEF server started') rescue => e print_error("Database connection failed: #{e.message}") exit(1) end # # @note Prints information back to the user before running the server # 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 Prints the API key needed to use the RESTful API # print_info "RESTful API key: #{BeEF::Core::Crypto::api_token}" # # @note Load the GeoIP database # BeEF::Core::GeoIp.instance # # @note Call the API method 'pre_http_start' # BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server) # # @note Load any ARE (Autorun Rule Engine) rules scanning the /arerules/enabled directory # BeEF::Core::AutorunEngine::RuleLoader.instance.load_directory # # @note Start the WebSocket server # if config.get("beef.http.websocket.enable") BeEF::Core::Websocket::Websocket.instance BeEF::Core::Console::Banners.print_websocket_servers end # # @note Start HTTP server # print_info 'BeEF server started (press control+c to stop)' http_hook_server.start