# # Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net # Browser Exploitation Framework (BeEF) - http://beefproject.com # See the file 'doc/COPYING' for copying permission # module BeEF module Extension module Console module CommandDispatcher class Core include BeEF::Extension::Console::CommandDispatcher def initialize(driver) super end def commands { "?" => "Help menu", "back" => "Move back from the current context", "exit" => "Exit the console", "help" => "Help menu", "irb" => "Drops into an interactive Ruby environment", "jobs" => "Print jobs", "online" => "List online hooked browsers", "offline" => "List previously hooked browsers", "quit" => "Exit the console", "review" => "Target a particular previously hooked (offline) hooked browser", "show" => "Displays 'zombies' or 'browsers' or 'commands'. (For those who prefer the MSF way)", "target" => "Target a particular online hooked browser", "rtcgo" => "Initiate the WebRTC connectivity between two browsers", "rtcmsg" => "Send a message from a browser to its peers", "rtcstatus" => "Check a browsers WebRTC status" } end def name "Core" end def cmd_back(*args) if (driver.current_dispatcher.name == 'Command') driver.remove_dispatcher('Command') driver.interface.clearcommand #TODO: TIDY THIS UP if driver.interface.targetid.length > 1 driver.update_prompt("(%bld%redMultiple%clr) ["+driver.interface.targetid.join(",")+"] ") else driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.first.to_s+"] ") end elsif (driver.current_dispatcher.name == 'Target') driver.remove_dispatcher('Target') driver.interface.cleartarget driver.update_prompt('') elsif (driver.dispatcher_stack.size > 1 and driver.current_dispatcher.name != 'Core') driver.destack_dispatcher driver.update_prompt('') end end def cmd_back_help(*args) print_status("Move back one step") end def cmd_exit(* args) driver.stop end alias cmd_quit cmd_exit @@jobs_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help." ], "-l" => [ false, "List jobs." ], "-k" => [ true, "Terminate the job." ]) def cmd_jobs(*args) if (args[0] == nil) cmd_jobs_list print_line "Try: jobs -h" return end @@jobs_opts.parse(args) {|opt, idx, val| case opt when "-k" if (not driver.jobs.has_key?(val)) print_error("no such job") else #This is a special job, that has to be terminated different prior to cleanup if driver.jobs[val].name == "http_hook_server" print_line("Nah uh uh - can't stop this job ya BeEF head!") else print_line("Stopping job: #{val}...") driver.jobs.stop_job(val) end end when "-l" cmd_jobs_list when "-h" cmd_jobs_help return false end } end def cmd_jobs_help(*args) print_line "Usage: jobs [options]" print_line print @@jobs_opts.usage() end def cmd_jobs_list tbl = Rex::Ui::Text::Table.new( 'Columns' => [ 'Id', 'Job Name' ]) driver.jobs.keys.each{|k| tbl << [driver.jobs[k].jid.to_s, driver.jobs[k].name] } puts "\n" puts tbl.to_s + "\n" end @@bare_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help." ]) def cmd_online(*args) @@bare_opts.parse(args) {|opt, idx, val| case opt when "-h" cmd_online_help return false end } tbl = Rex::Ui::Text::Table.new( 'Columns' => [ 'Id', 'IP', 'Hook Host', 'Browser', 'OS', 'Hardware' ]) BeEF::Core::Models::HookedBrowser.all(:lastseen.gte => (Time.new.to_i - 30)).each do |zombie| tbl << [zombie.id,zombie.ip,BeEF::Core::Models::BrowserDetails.get(zombie.session,"HostName").to_s,BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserName').to_s+"-"+BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserVersion').to_s,BeEF::Core::Models::BrowserDetails.get(zombie.session, 'OsName'),BeEF::Core::Models::BrowserDetails.get(zombie.session, 'Hardware')] end puts "\n" puts "Currently hooked browsers within BeEF" puts "\n" puts tbl.to_s + "\n" end def cmd_online_help(*args) print_status("Show currently hooked browsers within BeEF") end def cmd_offline(*args) @@bare_opts.parse(args) {|opt, idx, val| case opt when "-h" cmd_offline_help return false end } tbl = Rex::Ui::Text::Table.new( 'Columns' => [ 'Id', 'IP', 'Hook Host', 'Browser', 'OS', 'Hardware' ]) BeEF::Core::Models::HookedBrowser.all(:lastseen.lt => (Time.new.to_i - 30)).each do |zombie| tbl << [zombie.id,zombie.ip,BeEF::Core::Models::BrowserDetails.get(zombie.session,"HostName").to_s,BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserName').to_s+"-"+BeEF::Core::Models::BrowserDetails.get(zombie.session, 'BrowserVersion').to_s,BeEF::Core::Models::BrowserDetails.get(zombie.session, 'OsName'),BeEF::Core::Models::BrowserDetails.get(zombie.session, 'Hardware')] end puts "\n" puts "Previously hooked browsers within BeEF" puts "\n" puts tbl.to_s + "\n" end def cmd_offline_help(*args) print_status("Show previously hooked browsers") end def cmd_target(*args) @@bare_opts.parse(args) {|opt, idx, val| case opt when "-h" cmd_target_help return false end } if args[0] == nil cmd_target_help return end onlinezombies = [] BeEF::Core::Models::HookedBrowser.all(:lastseen.gt => (Time.new.to_i - 30)).each do |zombie| onlinezombies << zombie.id end targets = args[0].split(',') targets.each {|t| if not onlinezombies.include?(t.to_i) print_status("Browser [id:"+t.to_s+"] does not appear to be online.") return false end #print_status("Adding browser [id:"+t.to_s+"] to target list.") } if not driver.interface.settarget(targets).nil? if (driver.dispatcher_stack.size > 1 and driver.current_dispatcher.name != 'Core') driver.destack_dispatcher driver.update_prompt('') end driver.enstack_dispatcher(Target) if driver.interface.targetid.length > 1 driver.update_prompt("(%bld%redMultiple%clr) ["+driver.interface.targetid.join(",")+"] ") else driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.first.to_s+"] ") end end end def cmd_target_help(*args) print_status("Target a particular online, hooked browser") print_status(" Usage: target ") end def cmd_rtcgo(*args) if BeEF::Core::Configuration.instance.get("beef.extension.webrtc.enable") != true print_status("WebRTC Extension is not enabled..") return false end @@bare_opts.parse(args) {|opt,idx,val| case opt when "-h" cmd_rtcgo_help return false end } if args[0] == nil or args[1] == nil cmd_rtcgo_help return end onlinezombies = [] BeEF::Core::Models::HookedBrowser.all(:lastseen.gt => (Time.new.to_i - 30)).each do |z| onlinezombies << z.id end if not onlinezombies.include?(args[0].to_i) print_status("Browser [id:"+args[0].to_s+"] does not appear to be online.") return false end if not onlinezombies.include?(args[1].to_i) print_status("Browser [id:"+args[1].to_s+"] does not appear to be online.") return false end if args[2] == nil BeEF::Core::Models::Rtcmanage.initiate(args[0].to_i,args[1].to_i) else if args[2] =~ (/^(true|t|yes|y|1)$/i) BeEF::Core::Models::Rtcmanage.initiate(args[0].to_i,args[1].to_i,true) else BeEF::Core::Models::Rtcmanage.initiate(args[0].to_i,args[1].to_i) end end end def cmd_rtcgo_help(*args) print_status("To kick off the WebRTC Peer to Peer between two browsers") print_status(" Usage: rtcgo ") end def cmd_rtcmsg(*args) if BeEF::Core::Configuration.instance.get("beef.extension.webrtc.enable") != true print_status("WebRTC Extension is not enabled..") return false end @@bare_opts.parse(args) {|opt,idx,val| case opt when "-h" cmd_rtcmsg_help return false end } if (args[0] == nil || args[1] == nil || args[2] == nil) cmd_rtcmsg_help return else p = "" (2..args.length-1).each do |x| p << args[x] << " " end p.chop! BeEF::Core::Models::Rtcmanage.sendmsg(args[0].to_i,args[1].to_i,p) end end def cmd_rtcmsg_help(*args) print_status("Sends a message from this browser to its peers") print_status(" Usage: rtcmsg ") print_status("There are a few formats that are available within the beefwebrtc client-side object:") print_status(" !gostealth - will put the browser into a stealth mode") print_status(" !endstealth - will put the browser into normal mode, and it will start talking to BeEF again") print_status(" % - will execute JavaScript on sending the results back to - who will relay back to BeEF") print_status(" - will simply send a datachannel message from to . If the is stealthed, it'll bounce the message back. If the is NOT stealthed, it'll send the message back to BeEF via the /rtcmessage handler") end def cmd_rtcstatus(*args) if BeEF::Core::Configuration.instance.get("beef.extension.webrtc.enable") != true print_status("WebRTC Extension is not enabled..") return false end @@bare_opts.parse(args) {|opt,idx,val| case opt when "-h" cmd_rtcstatus_help return false end } if (args[0] == nil) cmd_rtcstatus_help return else BeEF::Core::Models::Rtcmanage.status(args[0].to_i) end end def cmd_rtcstatus_help(*args) print_status("Sends a message to this browser - checking the WebRTC Status of all its peers") print_status(" Usage: rtcstatus ") end def cmd_irb(*args) @@bare_opts.parse(args) {|opt, idx, val| case opt when "-h" cmd_irb_help return false end } print_status("Starting IRB shell...\n") begin Rex::Ui::Text::IrbShell.new(binding).run rescue print_error("Error during IRB: #{$!}\n\n#{$@.join("\n")}") end end def cmd_irb_help(*args) print_status("Load the IRB, Interative Ruby Shell") end def cmd_review(*args) @@bare_opts.parse(args) {|opt, idx, val| case opt when "-h" cmd_review_help return false end } if args[0] == nil cmd_review_help return end offlinezombies = [] BeEF::Core::Models::HookedBrowser.all(:lastseen.lt => (Time.new.to_i - 30)).each do |zombie| offlinezombies << zombie.id end targets = args[0].split(',') targets.each {|t| if not offlinezombies.include?(t.to_i) print_status("Browser [id:"+t.to_s+"] does not appear to be offline.") return false end #print_status("Adding browser [id:"+t.to_s+"] to target list.") } # if not offlinezombies.include?(args[0].to_i) # print_status("Browser does not appear to be offline..") # return false # end if not driver.interface.setofflinetarget(targets).nil? if (driver.dispatcher_stack.size > 1 and driver.current_dispatcher.name != 'Core') driver.destack_dispatcher driver.update_prompt('') end driver.enstack_dispatcher(Target) if driver.interface.targetid.length > 1 driver.update_prompt("(%bld%redMultiple%clr) ["+driver.interface.targetid.join(",")+"] ") else driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.first.to_s+"] ") end end end def cmd_review_help(*args) print_status("Review an offline, previously hooked browser") print_status(" Usage: review ") end def cmd_show(*args) args << "-h" if (args.length == 0) args.each { |type| case type when '-h' cmd_show_help when 'zombies' driver.run_single("online") when 'browsers' driver.run_single("online") when 'online' driver.run_single("online") when 'offline' driver.run_single("offline") when 'commands' if driver.dispatched_enstacked(Target) if args[1] == "-s" and not args[2].nil? driver.run_single("commands #{args[1]} #{args[2]}") return else driver.run_single("commands") end else print_error("You aren't targeting a zombie yet") end when 'info' if driver.dispatched_enstacked(Target) driver.run_single("info") else print_error("You aren't targeting a zombie yet") end when 'cmdinfo' if driver.dispatched_enstacked(Command) driver.run_single("cmdinfo") else print_error("You haven't selected a command module yet") end else print_error("Invalid parameter, try show -h for more information.") end } end def cmd_show_tabs(str, words) return [] if words.length > 1 res = %w{zombies browsers online offline} if driver.dispatched_enstacked(Target) res.concat(%w{commands info}) end if driver.dispatched_enstacked(Command) res.concat(%w{cmdinfo}) end return res end def cmd_show_help global_opts = %w{zombies browsers} print_status("Valid parameters for the \"show\" command are: #{global_opts.join(", ")}") target_opts = %w{commands} print_status("If you're targeting a module, you can also specify: #{target_opts.join(", ")}") end def beef_logo_to_os(logo) case logo when "mac.png" hbos = "Mac OS X" when "linux.png" hbos = "Linux" when "win.png" hbos = "Microsoft Windows" when "unknown.png" hbos = "Unknown" end end end end end end end