Extensions: Remove console extension (#2802)
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2023 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
beef:
|
||||
extension:
|
||||
console:
|
||||
# The console extension is no longer supported. Please do not use. It will break BeEF.
|
||||
# See issue: https://github.com/beefproject/beef/issues/1090
|
||||
enable: false
|
||||
name: 'Console'
|
||||
shell:
|
||||
enable: false
|
||||
historyfolder: '~/.beef/'
|
||||
historyfile: 'history'
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2023 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
|
||||
extend BeEF::API::Extension
|
||||
|
||||
#
|
||||
# Sets the information for that extension.
|
||||
#
|
||||
@short_name = @full_name = 'console'
|
||||
@description = 'console environment to manage beef'
|
||||
|
||||
module PostLoad
|
||||
BeEF::API::Registrar.instance.register(BeEF::Extension::Console::PostLoad, BeEF::API::Extensions, 'post_load')
|
||||
|
||||
def self.post_load
|
||||
return unless BeEF::Core::Configuration.instance.get('beef.extension.console.enable')
|
||||
|
||||
print_error 'The console extension is currently unsupported.'
|
||||
print_more 'See issue #1090 - https://github.com/beefproject/beef/issues/1090'
|
||||
BeEF::Core::Configuration.instance.set('beef.extension.console.enable', false)
|
||||
BeEF::Core::Configuration.instance.set('beef.extension.console.loaded', false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,26 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2023 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
|
||||
include Rex::Ui::Text::DispatcherShell::CommandDispatcher
|
||||
|
||||
def initialize(driver)
|
||||
super
|
||||
|
||||
self.driver = driver
|
||||
end
|
||||
|
||||
attr_accessor :driver
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'extensions/console/lib/command_dispatcher/core'
|
||||
require 'extensions/console/lib/command_dispatcher/target'
|
||||
require 'extensions/console/lib/command_dispatcher/command'
|
||||
@@ -1,200 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2023 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 Command
|
||||
include BeEF::Extension::Console::CommandDispatcher
|
||||
|
||||
@@params = []
|
||||
|
||||
def initialize(driver)
|
||||
super
|
||||
begin
|
||||
driver.interface.cmd['Data'].each do |data|
|
||||
@@params << data['name']
|
||||
end
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def commands
|
||||
{
|
||||
'execute' => 'Go! Execute the command module',
|
||||
'param' => 'Set parameters for this module',
|
||||
'response' => 'Get previous responses to this command module',
|
||||
'cmdinfo' => 'See information about this particular command module'
|
||||
}
|
||||
end
|
||||
|
||||
def name
|
||||
'Command'
|
||||
end
|
||||
|
||||
@@bare_opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [false, 'Help.']
|
||||
)
|
||||
|
||||
def cmd_cmdinfo(*args)
|
||||
@@bare_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_cmdinfo_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
print_line('Module name: ' + driver.interface.cmd['Name'])
|
||||
print_line('Module category: ' + driver.interface.cmd['Category'].to_s)
|
||||
print_line('Module description: ' + driver.interface.cmd['Description'])
|
||||
print_line('Module parameters:') unless driver.interface.cmd['Data'].length == 0
|
||||
|
||||
unless driver.interface.cmd['Data'].nil?
|
||||
driver.interface.cmd['Data'].each do |data|
|
||||
if data['type'].eql?('combobox')
|
||||
print_line(data['name'] + ' => "' + data['value'].to_s + '" # ' + data['ui_label'] + ' (Options include: ' + data['store_data'].to_s + ')')
|
||||
else
|
||||
print_line(data['name'] + ' => "' + data['value'].to_s + '" # ' + data['ui_label'])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_cmdinfo_help(*_args)
|
||||
print_status('Displays information about the current command module')
|
||||
end
|
||||
|
||||
def cmd_param(*args)
|
||||
@@bare_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_param_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if args[0].nil? || args[1].nil?
|
||||
cmd_param_help
|
||||
nil
|
||||
else
|
||||
p = ''
|
||||
(1..args.length - 1).each do |x|
|
||||
p << args[x] << ' '
|
||||
end
|
||||
p.chop!
|
||||
driver.interface.setparam(args[0], p)
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_param_help(*_args)
|
||||
print_status('Sets parameters for the current modules. Run "cmdinfo" to see the parameter values')
|
||||
print_status(' Usage: param <paramname> <paramvalue>')
|
||||
end
|
||||
|
||||
def cmd_param_tabs(_str, words)
|
||||
return if words.length > 1
|
||||
|
||||
if @@params == ''
|
||||
# nothing prepopulated?
|
||||
else
|
||||
@@params
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_execute(*args)
|
||||
@@bare_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_execute_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if driver.interface.executecommand == true
|
||||
print_status('Command successfully queued')
|
||||
else
|
||||
print_status('Something went wrong')
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_execute_help(*_args)
|
||||
print_status('Execute this module... go on!')
|
||||
end
|
||||
|
||||
def cmd_response(*args)
|
||||
@@bare_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_response_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Columns' =>
|
||||
[
|
||||
'Id',
|
||||
'Executed Time',
|
||||
'Response Time'
|
||||
]
|
||||
)
|
||||
|
||||
if args[0].nil?
|
||||
lastcmdid = nil
|
||||
driver.interface.getcommandresponses.each do |resp|
|
||||
indiresp = driver.interface.getindividualresponse(resp['object_id'])
|
||||
respout = ''
|
||||
if indiresp.nil? or indiresp[0].nil?
|
||||
respout = 'No response yet'
|
||||
else
|
||||
respout = Time.at(indiresp[0]['date'].to_i).to_s
|
||||
lastcmdid = resp['object_id']
|
||||
end
|
||||
tbl << [resp['object_id'].to_s, resp['creationdate'], respout]
|
||||
end
|
||||
|
||||
puts "\n"
|
||||
puts "List of responses for this command module:\n"
|
||||
puts tbl.to_s + "\n"
|
||||
|
||||
unless lastcmdid.nil?
|
||||
resp = driver.interface.getindividualresponse(lastcmdid)
|
||||
puts "\n"
|
||||
print_line('The last response [' + lastcmdid.to_s + '] was retrieved: ' + Time.at(resp[0]['date'].to_i).to_s)
|
||||
print_line('Response:')
|
||||
resp.each do |op|
|
||||
print_line(op['data']['data'].to_s)
|
||||
end
|
||||
end
|
||||
else
|
||||
output = driver.interface.getindividualresponse(args[0])
|
||||
if output.nil?
|
||||
print_line('Invalid response ID')
|
||||
elsif output[0].nil?
|
||||
print_line('No response yet from the hooked browser or perhaps an invalid response ID')
|
||||
else
|
||||
print_line('Results retrieved: ' + Time.at(output[0]['date'].to_i).to_s)
|
||||
print_line('')
|
||||
print_line('Response:')
|
||||
output.each do |op|
|
||||
print_line(op['data']['data'].to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_response_help(*_args)
|
||||
print_status('List and review particular responses to this command')
|
||||
print_status(' Usage: response (id)')
|
||||
print_status(" If you omit id you'll see a list of all responses for the currently active command module")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,518 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2023 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) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-k'
|
||||
if !driver.jobs.has_key?(val)
|
||||
print_error('no such job')
|
||||
elsif driver.jobs[val].name == 'http_hook_server'
|
||||
# This is a special job, that has to be terminated different prior to cleanup
|
||||
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
|
||||
when '-l'
|
||||
cmd_jobs_list
|
||||
when '-h'
|
||||
cmd_jobs_help
|
||||
return false
|
||||
end
|
||||
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 do |k|
|
||||
tbl << [driver.jobs[k].jid.to_s, driver.jobs[k].name]
|
||||
end
|
||||
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) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_online_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Columns' =>
|
||||
[
|
||||
'Id',
|
||||
'IP',
|
||||
'Hook Host',
|
||||
'Browser',
|
||||
'OS',
|
||||
'Hardware'
|
||||
]
|
||||
)
|
||||
|
||||
BeEF::Core::Models::HookedBrowser.where('lastseen >= ?', (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 "\nCurrently hooked browsers within BeEF\n#{tbl}\n"
|
||||
end
|
||||
|
||||
def cmd_online_help(*_args)
|
||||
print_status('Show currently hooked browsers within BeEF')
|
||||
end
|
||||
|
||||
def cmd_offline(*args)
|
||||
@@bare_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_offline_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Columns' =>
|
||||
[
|
||||
'Id',
|
||||
'IP',
|
||||
'Hook Host',
|
||||
'Browser',
|
||||
'OS',
|
||||
'Hardware'
|
||||
]
|
||||
)
|
||||
|
||||
BeEF::Core::Models::HookedBrowser.where('lastseen < ?', (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) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_target_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if args[0].nil?
|
||||
cmd_target_help
|
||||
return
|
||||
end
|
||||
|
||||
onlinezombies = []
|
||||
BeEF::Core::Models::HookedBrowser.where('lastseen > ?', (Time.new.to_i - 30)).each do |zombie|
|
||||
onlinezombies << zombie.id
|
||||
end
|
||||
|
||||
targets = args[0].split(',')
|
||||
targets.each do |t|
|
||||
unless 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.")
|
||||
end
|
||||
|
||||
unless 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 <id>')
|
||||
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) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_rtcgo_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if args[0].nil? or args[1].nil?
|
||||
cmd_rtcgo_help
|
||||
return
|
||||
end
|
||||
|
||||
onlinezombies = []
|
||||
BeEF::Core::Models::HookedBrowser.where('lastseen > ?', (Time.new.to_i - 30)).each do |z|
|
||||
onlinezombies << z.id
|
||||
end
|
||||
|
||||
unless onlinezombies.include?(args[0].to_i)
|
||||
print_status('Browser [id:' + args[0].to_s + '] does not appear to be online.')
|
||||
return false
|
||||
end
|
||||
|
||||
unless 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)
|
||||
elsif 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
|
||||
|
||||
def cmd_rtcgo_help(*_args)
|
||||
print_status('To kick off the WebRTC Peer to Peer between two browsers')
|
||||
print_status(' Usage: rtcgo <caller id> <receiver id> <verbosity - defaults to false>')
|
||||
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) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_rtcmsg_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if args[0].nil? || args[1].nil? || args[2].nil?
|
||||
cmd_rtcmsg_help
|
||||
nil
|
||||
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 <from> <to> <msg>')
|
||||
print_status('There are a few <msg> formats that are available within the beefwebrtc client-side object:')
|
||||
print_status(' !gostealth - will put the <to> browser into a stealth mode')
|
||||
print_status(' !endstealth - will put the <to> browser into normal mode, and it will start talking to BeEF again')
|
||||
print_status(' %<javascript> - will execute JavaScript on <to> sending the results back to <from> - who will relay back to BeEF')
|
||||
print_status(" <text> - will simply send a datachannel message from <from> to <to>. If the <to> is stealthed, it'll bounce the message back. If the <to> 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) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_rtcstatus_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if args[0].nil?
|
||||
cmd_rtcstatus_help
|
||||
nil
|
||||
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 <id>')
|
||||
end
|
||||
|
||||
def cmd_irb(*args)
|
||||
@@bare_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_irb_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
print_status("Starting IRB shell...\n")
|
||||
|
||||
begin
|
||||
Rex::Ui::Text::IrbShell.new(binding).run
|
||||
rescue StandardError
|
||||
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) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_review_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if args[0].nil?
|
||||
cmd_review_help
|
||||
return
|
||||
end
|
||||
|
||||
offlinezombies = []
|
||||
BeEF::Core::Models::HookedBrowser.where('lastseen < ?', (Time.new.to_i - 30)).each do |zombie|
|
||||
offlinezombies << zombie.id
|
||||
end
|
||||
|
||||
targets = args[0].split(',')
|
||||
targets.each do |t|
|
||||
unless 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.")
|
||||
end
|
||||
|
||||
# if not offlinezombies.include?(args[0].to_i)
|
||||
# print_status("Browser does not appear to be offline..")
|
||||
# return false
|
||||
# end
|
||||
|
||||
unless 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 <id>')
|
||||
end
|
||||
|
||||
def cmd_show(*args)
|
||||
args << '-h' if args.length == 0
|
||||
|
||||
args.each do |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 !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
|
||||
end
|
||||
|
||||
def cmd_show_tabs(_str, words)
|
||||
return [] if words.length > 1
|
||||
|
||||
res = %w[zombies browsers online offline]
|
||||
|
||||
res.concat(%w[commands info]) if driver.dispatched_enstacked(Target)
|
||||
|
||||
res.concat(%w[cmdinfo]) if driver.dispatched_enstacked(Command)
|
||||
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,285 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2023 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 Target
|
||||
include BeEF::Extension::Console::CommandDispatcher
|
||||
|
||||
@@commands = []
|
||||
|
||||
def initialize(driver)
|
||||
super
|
||||
begin
|
||||
driver.interface.getcommands.each do |folder|
|
||||
folder['children'].each do |command|
|
||||
@@commands << (folder['text'].gsub(/\s/, '_') + command['text'].gsub(/[-()]/, '').gsub(/\W+/, '_'))
|
||||
end
|
||||
end
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def commands
|
||||
{
|
||||
'commands' => 'List available commands against this particular target',
|
||||
'info' => 'Info about the target',
|
||||
'select' => 'Prepare the command module for execution against this target',
|
||||
'hosts' => 'List identified network hosts',
|
||||
'services' => 'List identified network services'
|
||||
}
|
||||
end
|
||||
|
||||
def name
|
||||
'Target'
|
||||
end
|
||||
|
||||
@@bare_opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [false, 'Help.']
|
||||
)
|
||||
|
||||
@@commands_opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [false, 'Help.'],
|
||||
'-s' => [false, '<search term>'],
|
||||
'-r' => [false, 'List modules which have responses against them only']
|
||||
)
|
||||
|
||||
def cmd_commands(*args)
|
||||
searchstring = nil
|
||||
responly = nil
|
||||
|
||||
@@commands_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_commands_help
|
||||
return false
|
||||
when '-s'
|
||||
searchstring = args[1].downcase unless args[1].nil?
|
||||
when '-r'
|
||||
responly = true
|
||||
end
|
||||
end
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Columns' =>
|
||||
[
|
||||
'Id',
|
||||
'Command',
|
||||
'Status',
|
||||
'Execute Count'
|
||||
]
|
||||
)
|
||||
|
||||
driver.interface.getcommands.each do |folder|
|
||||
folder['children'].each do |command|
|
||||
cmdstring = folder['text'].gsub(/\s/, '_') + command['text'].gsub(/[-()]/, '').gsub(/\W+/, '_')
|
||||
|
||||
if !searchstring.nil?
|
||||
unless cmdstring.downcase.index(searchstring).nil?
|
||||
tbl << [command['id'].to_i,
|
||||
cmdstring,
|
||||
command['status'].gsub(/^Verified /, ''),
|
||||
driver.interface.getcommandresponses(command['id']).length] # TODO
|
||||
end
|
||||
elsif !responly.nil?
|
||||
if driver.interface.getcommandresponses(command['id']).length.to_i > 0
|
||||
tbl << [command['id'].to_i,
|
||||
cmdstring,
|
||||
command['status'].gsub(/^Verified /, ''),
|
||||
driver.interface.getcommandresponses(command['id']).length]
|
||||
end
|
||||
|
||||
else
|
||||
tbl << [command['id'].to_i,
|
||||
cmdstring,
|
||||
command['status'].gsub(/^Verified /, ''),
|
||||
driver.interface.getcommandresponses(command['id']).length] # TODO
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
puts "\n"
|
||||
puts "List command modules for this target\n"
|
||||
puts tbl.to_s + "\n"
|
||||
end
|
||||
|
||||
def cmd_commands_help(*_args)
|
||||
print_status('List command modules for this target')
|
||||
print_line('Usage: commands [options]')
|
||||
print_line
|
||||
print @@commands_opts.usage
|
||||
end
|
||||
|
||||
def cmd_info(*args)
|
||||
@@bare_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_info_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Columns' =>
|
||||
%w[
|
||||
Param
|
||||
Value
|
||||
]
|
||||
)
|
||||
|
||||
driver.interface.select_zombie_summary['results'].each do |x|
|
||||
x['data'].each do |k, v|
|
||||
tbl << [k, v]
|
||||
end
|
||||
end
|
||||
|
||||
puts "\nHooked Browser Info:\n"
|
||||
puts tbl.to_s + "\n"
|
||||
end
|
||||
|
||||
def cmd_info_help(*_args)
|
||||
print_status('Display initialisation information about the hooked browser.')
|
||||
end
|
||||
|
||||
def cmd_hosts(*args)
|
||||
@@bare_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_hosts_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
unless configuration.get('beef.extension.network.enable')
|
||||
print_error('Network extension is disabled')
|
||||
return
|
||||
end
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Columns' =>
|
||||
[
|
||||
'IP',
|
||||
'Hostname',
|
||||
'Type',
|
||||
'Operating System',
|
||||
'MAC Address',
|
||||
'Last Seen'
|
||||
]
|
||||
)
|
||||
|
||||
driver.interface.select_network_hosts['results'].each do |x|
|
||||
tbl << [x['ip'], x['hostname'], x['type'], x['os'], x['mac'], x['lastseen']]
|
||||
end
|
||||
|
||||
puts "\nNetwork Hosts:\n\n"
|
||||
puts tbl.to_s + "\n"
|
||||
end
|
||||
|
||||
def cmd_hosts_help(*_args)
|
||||
print_status("Display information about network hosts on the hooked browser's network.")
|
||||
end
|
||||
|
||||
def cmd_services(*args)
|
||||
@@bare_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_services_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
unless configuration.get('beef.extension.network.enable')
|
||||
print_error('Network extension is disabled')
|
||||
return
|
||||
end
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Columns' =>
|
||||
%w[
|
||||
IP
|
||||
Port
|
||||
Protocol
|
||||
Type
|
||||
]
|
||||
)
|
||||
|
||||
driver.interface.select_network_services['results'].each do |x|
|
||||
tbl << [x['ip'], x['port'], x['proto'], x['type']]
|
||||
end
|
||||
|
||||
puts "\nNetwork Services:\n\n"
|
||||
puts tbl.to_s + "\n"
|
||||
end
|
||||
|
||||
def cmd_services_help(*_args)
|
||||
print_status("Display information about network services on the hooked browser's network.")
|
||||
end
|
||||
|
||||
def cmd_select(*args)
|
||||
@@bare_opts.parse(args) do |opt, _idx, _val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_select_help
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if args[0].nil?
|
||||
cmd_select_help
|
||||
return false
|
||||
end
|
||||
|
||||
modid = nil
|
||||
|
||||
if args[0] =~ /[0-9]+/
|
||||
modid = args[0]
|
||||
else
|
||||
driver.interface.getcommands.each do |x|
|
||||
x['children'].each do |y|
|
||||
modid = y['id'] if args[0].chomp == x['text'].gsub(/\s/, '_') + y['text'].gsub(/[-()]/, '').gsub(/\W+/, '_')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if modid.nil?
|
||||
print_status('Could not find command module')
|
||||
return false
|
||||
end
|
||||
|
||||
driver.interface.setcommand(modid)
|
||||
|
||||
driver.enstack_dispatcher(Command) if driver.dispatched_enstacked(Command) == false
|
||||
|
||||
if driver.interface.targetid.length > 1
|
||||
driver.update_prompt('(%bld%redMultiple%clr) [' + driver.interface.targetid.join(',') + '] / ' + driver.interface.cmd['Name'] + ' ')
|
||||
else
|
||||
driver.update_prompt('(%bld%red' + driver.interface.targetip + '%clr) [' + driver.interface.targetid.first.to_s + '] / ' + driver.interface.cmd['Name'] + ' ')
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_select_help(*_args)
|
||||
print_status('Select a command module to use against the current target')
|
||||
print_status(' Usage: module <id> OR <modulename>')
|
||||
end
|
||||
|
||||
def cmd_select_tabs(_str, words)
|
||||
return if words.length > 1
|
||||
|
||||
if @@commands == ''
|
||||
# nothing prepopulated?
|
||||
else
|
||||
@@commands
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,549 +0,0 @@
|
||||
# readline.rb -- GNU Readline module
|
||||
# Copyright (C) 1997-2001 Shugo Maed
|
||||
#
|
||||
# Ruby translation by Park Heesob phasis@gmail.com
|
||||
|
||||
=begin
|
||||
Copyright (c) 2009, Park Heesob
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of Park Heesob nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
=end
|
||||
|
||||
module Readline
|
||||
|
||||
require 'extensions/console/lib/rbreadline'
|
||||
include RbReadline
|
||||
|
||||
@completion_proc = nil
|
||||
@completion_case_fold = false
|
||||
|
||||
#
|
||||
# A sneaky way to prevent the real Readline from loading after us
|
||||
#
|
||||
$LOADED_FEATURES.unshift("readline.rb")
|
||||
|
||||
# Begins an interactive terminal process using +prompt+ as the command
|
||||
# prompt that users see when they type commands. The method returns the
|
||||
# line entered whenever a carriage return is encountered.
|
||||
#
|
||||
# If an +add_history+ argument is provided, commands entered by users are
|
||||
# stored in a history buffer that can be recalled for later use.
|
||||
#
|
||||
# Note that this method depends on $stdin and $stdout both being open.
|
||||
# Because this is meant as an interactive console interface, they should
|
||||
# generally not be redirected.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# loop{ Readline.readline('> ') }
|
||||
#
|
||||
def readline(prompt, add_history=nil)
|
||||
if $stdin.closed?
|
||||
raise IOError, "stdin closed"
|
||||
end
|
||||
|
||||
status = 0
|
||||
|
||||
begin
|
||||
RbReadline.rl_instream = $stdin
|
||||
RbReadline.rl_outstream = $stdout
|
||||
buff = RbReadline.readline(prompt)
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue => e
|
||||
buff = nil
|
||||
RbReadline.rl_cleanup_after_signal()
|
||||
RbReadline.rl_deprep_terminal()
|
||||
$stderr.puts "[-] RbReadline Error: #{e.class} #{e} #{e.backtrace}"
|
||||
retry
|
||||
end
|
||||
|
||||
if add_history && buff
|
||||
RbReadline.add_history(buff)
|
||||
end
|
||||
|
||||
return buff ? buff.dup : nil
|
||||
end
|
||||
|
||||
# Sets the input stream (an IO object) for readline interaction. The
|
||||
# default is <tt>$stdin</tt>.
|
||||
#
|
||||
def self.input=(input)
|
||||
RbReadline.rl_instream = input
|
||||
end
|
||||
|
||||
# Sets the output stream (an IO object) for readline interaction. The
|
||||
# default is <tt>$stdout</tt>.
|
||||
#
|
||||
def self.output=(output)
|
||||
RbReadline.rl_outstream = output
|
||||
end
|
||||
|
||||
# Sets the auto-completion procedure (i.e. tab auto-complete).
|
||||
#
|
||||
# The +proc+ argument is typically a Proc object. It must respond to
|
||||
# <tt>.call</tt>, take a single String argument and return an Array of
|
||||
# candidates for completion.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# list = ['search', 'next', 'clear']
|
||||
# Readline.completion_proc = proc{ |s| list.grep( /^#{Regexp.escape(s)}/) }
|
||||
#
|
||||
def self.completion_proc=(proc)
|
||||
unless defined? proc.call
|
||||
raise ArgumentError,"argument must respond to `call'"
|
||||
end
|
||||
@completion_proc = proc
|
||||
end
|
||||
|
||||
# Returns the current auto-completion procedure.
|
||||
#
|
||||
def self.completion_proc()
|
||||
@completion_proc
|
||||
end
|
||||
|
||||
# Sets whether or not the completion proc should ignore case sensitivity.
|
||||
# The default is false, i.e. completion procs are case sensitive.
|
||||
#
|
||||
def self.completion_case_fold=(bool)
|
||||
@completion_case_fold = bool
|
||||
end
|
||||
|
||||
# Returns whether or not the completion proc is case sensitive. The
|
||||
# default is false, i.e. completion procs are case sensitive.
|
||||
#
|
||||
def self.completion_case_fold()
|
||||
@completion_case_fold
|
||||
end
|
||||
|
||||
def self.readline_attempted_completion_function(text,start,_end)
|
||||
proc = @completion_proc
|
||||
return nil if proc.nil?
|
||||
|
||||
RbReadline.rl_attempted_completion_over = true
|
||||
|
||||
# Remove leading spaces
|
||||
text.gsub!(/^\s+/, '')
|
||||
|
||||
case_fold = @completion_case_fold
|
||||
ary = proc.call(text)
|
||||
if ary.class != Array
|
||||
ary = Array(ary)
|
||||
else
|
||||
ary.compact!
|
||||
ary.uniq!
|
||||
end
|
||||
|
||||
ary.delete('')
|
||||
|
||||
matches = ary.length
|
||||
return nil if (matches == 0)
|
||||
|
||||
if(matches == 1)
|
||||
ary[0] = ary[0].strip + " "
|
||||
end
|
||||
|
||||
result = Array.new(matches+2)
|
||||
for i in 0 ... matches
|
||||
result[i+1] = ary[i].dup
|
||||
end
|
||||
result[matches+1] = nil
|
||||
|
||||
if(matches==1)
|
||||
result[0] = result[1].dup
|
||||
else
|
||||
i = 1
|
||||
low = 100000
|
||||
|
||||
while (i < matches)
|
||||
if (case_fold)
|
||||
si = 0
|
||||
while ((c1 = result[i][si,1].downcase) &&
|
||||
(c2 = result[i + 1][si,1].downcase))
|
||||
break if (c1 != c2)
|
||||
si += 1
|
||||
end
|
||||
else
|
||||
si = 0
|
||||
while ((c1 = result[i][si,1]) &&
|
||||
(c2 = result[i + 1][si,1]))
|
||||
break if (c1 != c2)
|
||||
si += 1
|
||||
end
|
||||
end
|
||||
if (low > si)
|
||||
low = si
|
||||
end
|
||||
i+=1
|
||||
end
|
||||
result[0] = result[1][0,low]
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
# Sets vi editing mode.
|
||||
#
|
||||
def self.vi_editing_mode()
|
||||
RbReadline.rl_vi_editing_mode(1,0)
|
||||
nil
|
||||
end
|
||||
|
||||
# Sets emacs editing mode
|
||||
#
|
||||
def self.emacs_editing_mode()
|
||||
RbReadline.rl_emacs_editing_mode(1,0)
|
||||
nil
|
||||
end
|
||||
|
||||
# Sets the character that is automatically appended after the
|
||||
# Readline.completion_proc method is called.
|
||||
#
|
||||
# If +char+ is nil or empty, then a null character is used.
|
||||
#
|
||||
def self.completion_append_character=(char)
|
||||
if char.nil?
|
||||
RbReadline.rl_completion_append_character = ?\0
|
||||
elsif char.length==0
|
||||
RbReadline.rl_completion_append_character = ?\0
|
||||
else
|
||||
RbReadline.rl_completion_append_character = char[0]
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the character that is automatically appended after the
|
||||
# Readline.completion_proc method is called.
|
||||
#
|
||||
def self.completion_append_character()
|
||||
if RbReadline.rl_completion_append_character == ?\0
|
||||
nil
|
||||
end
|
||||
return RbReadline.rl_completion_append_character
|
||||
end
|
||||
|
||||
# Sets the character string that signal a break between words for the
|
||||
# completion proc.
|
||||
#
|
||||
def self.basic_word_break_characters=(str)
|
||||
RbReadline.rl_basic_word_break_characters = str.dup
|
||||
end
|
||||
|
||||
# Returns the character string that signal a break between words for the
|
||||
# completion proc. The default is " \t\n\"\\'`@$><=|&{(".
|
||||
#
|
||||
def self.basic_word_break_characters()
|
||||
if RbReadline.rl_basic_word_break_characters.nil?
|
||||
nil
|
||||
else
|
||||
RbReadline.rl_basic_word_break_characters.dup
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the character string that signal the start or end of a word for
|
||||
# the completion proc.
|
||||
#
|
||||
def self.completer_word_break_characters=(str)
|
||||
RbReadline.rl_completer_word_break_characters = str.dup
|
||||
end
|
||||
|
||||
# Returns the character string that signal the start or end of a word for
|
||||
# the completion proc.
|
||||
#
|
||||
def self.completer_word_break_characters()
|
||||
if RbReadline.rl_completer_word_break_characters.nil?
|
||||
nil
|
||||
else
|
||||
RbReadline.rl_completer_word_break_characters.dup
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the list of quote characters that can cause a word break.
|
||||
#
|
||||
def self.basic_quote_characters=(str)
|
||||
RbReadline.rl_basic_quote_characters = str.dup
|
||||
end
|
||||
|
||||
# Returns the list of quote characters that can cause a word break.
|
||||
# The default is "'\"" (single and double quote characters).
|
||||
#
|
||||
def self.basic_quote_characters()
|
||||
if RbReadline.rl_basic_quote_characters.nil?
|
||||
nil
|
||||
else
|
||||
RbReadline.rl_basic_quote_characters.dup
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the list of characters that can be used to quote a substring of
|
||||
# the line, i.e. a group of characters within quotes.
|
||||
#
|
||||
def self.completer_quote_characters=(str)
|
||||
RbReadline.rl_completer_quote_characters = str.dup
|
||||
end
|
||||
|
||||
# Returns the list of characters that can be used to quote a substring
|
||||
# of the line, i.e. a group of characters inside quotes.
|
||||
#
|
||||
def self.completer_quote_characters()
|
||||
if RbReadline.rl_completer_quote_characters.nil?
|
||||
nil
|
||||
else
|
||||
RbReadline.rl_completer_quote_characters.dup
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the character string of one or more characters that indicate quotes
|
||||
# for the filename completion of user input.
|
||||
#
|
||||
def self.filename_quote_characters=(str)
|
||||
RbReadline.rl_filename_quote_characters = str.dup
|
||||
end
|
||||
|
||||
# Returns the character string used to indicate quotes for the filename
|
||||
# completion of user input.
|
||||
#
|
||||
def self.filename_quote_characters()
|
||||
if RbReadline.rl_filename_quote_characters.nil?
|
||||
nil
|
||||
else
|
||||
RbReadline.rl_filename_quote_characters.dup
|
||||
end
|
||||
end
|
||||
|
||||
# The History class encapsulates a history of all commands entered by
|
||||
# users at the prompt, providing an interface for inspection and retrieval
|
||||
# of all commands.
|
||||
class History
|
||||
extend Enumerable
|
||||
|
||||
# The History class, stringified in all caps.
|
||||
#--
|
||||
# Why?
|
||||
#
|
||||
def self.to_s
|
||||
"HISTORY"
|
||||
end
|
||||
|
||||
# Returns the command that was entered at the specified +index+
|
||||
# in the history buffer.
|
||||
#
|
||||
# Raises an IndexError if the entry is nil.
|
||||
#
|
||||
def self.[](index)
|
||||
if index < 0
|
||||
index += RbReadline.history_length
|
||||
end
|
||||
entry = RbReadline.history_get(RbReadline.history_base+index)
|
||||
if entry.nil?
|
||||
raise IndexError,"invalid index"
|
||||
end
|
||||
entry.line.dup
|
||||
end
|
||||
|
||||
# Sets the command +str+ at the given index in the history buffer.
|
||||
#
|
||||
# You can only replace an existing entry. Attempting to create a new
|
||||
# entry will result in an IndexError.
|
||||
#
|
||||
def self.[]=(index,str)
|
||||
if index<0
|
||||
index += RbReadline.history_length
|
||||
end
|
||||
entry = RbReadline.replace_history_entry(index,str,nil)
|
||||
if entry.nil?
|
||||
raise IndexError,"invalid index"
|
||||
end
|
||||
str
|
||||
end
|
||||
|
||||
# Synonym for Readline.add_history.
|
||||
#
|
||||
def self.<<(str)
|
||||
RbReadline.add_history(str)
|
||||
end
|
||||
|
||||
# Pushes a list of +args+ onto the history buffer.
|
||||
#
|
||||
def self.push(*args)
|
||||
args.each do |str|
|
||||
RbReadline.add_history(str)
|
||||
end
|
||||
end
|
||||
|
||||
# Internal function that removes the item at +index+ from the history
|
||||
# buffer, performing necessary duplication in the process.
|
||||
#--
|
||||
# TODO: mark private?
|
||||
#
|
||||
def self.rb_remove_history(index)
|
||||
entry = RbReadline.remove_history(index)
|
||||
if (entry)
|
||||
val = entry.line.dup
|
||||
entry = nil
|
||||
return val
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
# Removes and returns the last element from the history buffer.
|
||||
#
|
||||
def self.pop()
|
||||
if RbReadline.history_length>0
|
||||
rb_remove_history(RbReadline.history_length-1)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Removes and returns the first element from the history buffer.
|
||||
#
|
||||
def self.shift()
|
||||
if RbReadline.history_length>0
|
||||
rb_remove_history(0)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Iterates over each entry in the history buffer.
|
||||
#
|
||||
def self.each()
|
||||
for i in 0 ... RbReadline.history_length
|
||||
entry = RbReadline.history_get(RbReadline.history_base + i)
|
||||
break if entry.nil?
|
||||
yield entry.line.dup
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
# Returns the length of the history buffer.
|
||||
#
|
||||
def self.length()
|
||||
RbReadline.history_length
|
||||
end
|
||||
|
||||
# Synonym for Readline.length.
|
||||
#
|
||||
def self.size()
|
||||
RbReadline.history_length
|
||||
end
|
||||
|
||||
# Returns a bolean value indicating whether or not the history buffer
|
||||
# is empty.
|
||||
#
|
||||
def self.empty?()
|
||||
RbReadline.history_length == 0
|
||||
end
|
||||
|
||||
# Deletes an entry from the histoyr buffer at the specified +index+.
|
||||
#
|
||||
def self.delete_at(index)
|
||||
if index < 0
|
||||
i += RbReadline.history_length
|
||||
end
|
||||
if index < 0 || index > RbReadline.history_length - 1
|
||||
raise IndexError, "invalid index"
|
||||
end
|
||||
rb_remove_history(index)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
HISTORY = History
|
||||
|
||||
# The Fcomp class provided to encapsulate typical filename completion
|
||||
# procedure. You will not typically use this directly, but will instead
|
||||
# use the Readline::FILENAME_COMPLETION_PROC.
|
||||
#
|
||||
class Fcomp
|
||||
def self.call(str)
|
||||
matches = RbReadline.rl_completion_matches(str,
|
||||
:rl_filename_completion_function)
|
||||
if (matches)
|
||||
result = []
|
||||
i = 0
|
||||
while(matches[i])
|
||||
result << matches[i].dup
|
||||
matches[i] = nil
|
||||
i += 1
|
||||
end
|
||||
matches = nil
|
||||
if (result.length >= 2)
|
||||
result.shift
|
||||
end
|
||||
else
|
||||
result = nil
|
||||
end
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
FILENAME_COMPLETION_PROC = Fcomp
|
||||
|
||||
# The Ucomp class provided to encapsulate typical filename completion
|
||||
# procedure. You will not typically use this directly, but will instead
|
||||
# use the Readline::USERNAME_COMPLETION_PROC.
|
||||
#
|
||||
# Note that this feature currently only works on Unix systems since it
|
||||
# ultimately uses the Etc module to iterate over a list of users.
|
||||
#
|
||||
class Ucomp
|
||||
def self.call(str)
|
||||
matches = RbReadline.rl_completion_matches(str,
|
||||
:rl_username_completion_function)
|
||||
if (matches)
|
||||
result = []
|
||||
i = 0
|
||||
while(matches[i])
|
||||
result << matches[i].dup
|
||||
matches[i] = nil
|
||||
i += 1
|
||||
end
|
||||
matches = nil
|
||||
if (result.length >= 2)
|
||||
result.shift
|
||||
end
|
||||
else
|
||||
result = nil
|
||||
end
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
USERNAME_COMPLETION_PROC = Ucomp
|
||||
|
||||
RbReadline.rl_readline_name = "Ruby"
|
||||
|
||||
RbReadline.using_history()
|
||||
|
||||
VERSION = RbReadline.rl_library_version
|
||||
|
||||
module_function :readline
|
||||
|
||||
RbReadline.rl_attempted_completion_function = :readline_attempted_completion_function
|
||||
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,432 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2023 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
|
||||
class ShellInterface
|
||||
BD = BeEF::Core::Models::BrowserDetails
|
||||
|
||||
def initialize(config)
|
||||
self.config = config
|
||||
self.cmd = {}
|
||||
end
|
||||
|
||||
def settarget(id)
|
||||
self.targetsession = BeEF::Core::Models::HookedBrowser.find(id).session
|
||||
self.targetip = BeEF::Core::Models::HookedBrowser.find(id).ip
|
||||
self.targetid = id
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
|
||||
def setofflinetarget(id)
|
||||
self.targetsession = BeEF::Core::Models::HookedBrowser.find(id).session
|
||||
self.targetip = '(OFFLINE) ' + BeEF::Core::Models::HookedBrowser.find(id).ip
|
||||
self.targetid = id
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
|
||||
def cleartarget
|
||||
self.targetsession = nil
|
||||
self.targetip = nil
|
||||
self.targetid = nil
|
||||
self.cmd = {}
|
||||
end
|
||||
|
||||
# @note Get commands. This is a *modified* replica of select_command_modules_tree from extensions/admin_ui/controllers/modules/modules.rb
|
||||
def getcommands
|
||||
return if targetid.nil?
|
||||
|
||||
tree = []
|
||||
BeEF::Modules.get_categories.each do |c|
|
||||
c.concat('/') if c[-1, 1] != '/'
|
||||
tree.push({
|
||||
'text' => c,
|
||||
'cls' => 'folder',
|
||||
'children' => []
|
||||
})
|
||||
end
|
||||
|
||||
BeEF::Modules.get_enabled.each do |k, mod|
|
||||
flatcategory = ''
|
||||
if mod['category'].is_a?(Array)
|
||||
# Therefore this module has nested categories (sub-folders), munge them together into a string with '/' characters, like a folder.
|
||||
mod['category'].each do |cat|
|
||||
flatcategory << (cat + '/')
|
||||
end
|
||||
else
|
||||
flatcategory = mod['category']
|
||||
flatcategory.concat('/') if flatcategory[-1, 1] != '/'
|
||||
end
|
||||
|
||||
update_command_module_tree(tree, flatcategory, get_command_module_status(k), mod['name'], mod['db']['id'])
|
||||
end
|
||||
|
||||
# if dynamic modules are found in the DB, then we don't have yaml config for them
|
||||
# and loading must proceed in a different way.
|
||||
dynamic_modules = BeEF::Core::Models::CommandModule.where('path LIKE ?', 'Dynamic/')
|
||||
|
||||
unless dynamic_modules.nil?
|
||||
all_modules = BeEF::Core::Models::CommandModule.all.order(:id)
|
||||
all_modules.each do |dyn_mod|
|
||||
next unless dyn_mod.path.split('/').first.match(/^Dynamic/)
|
||||
|
||||
dyn_mod_name = dyn_mod.path.split('/').last
|
||||
dyn_mod_category = nil
|
||||
if dyn_mod_name == 'Msf'
|
||||
dyn_mod_category = 'Metasploit'
|
||||
else
|
||||
# future dynamic modules...
|
||||
end
|
||||
|
||||
# print_debug ("Loading Dynamic command module: category [#{dyn_mod_category}] - name [#{dyn_mod.name.to_s}]")
|
||||
command_mod = BeEF::Modules::Commands.const_get(dyn_mod_name.capitalize).new
|
||||
command_mod.session_id = hook_session_id
|
||||
command_mod.update_info(dyn_mod.id)
|
||||
command_mod_name = command_mod.info['Name'].downcase
|
||||
|
||||
update_command_module_tree(tree, dyn_mod_category, 'Verified Unknown', command_mod_name, dyn_mod.id)
|
||||
end
|
||||
end
|
||||
|
||||
# sort the parent array nodes
|
||||
tree.sort! { |a, b| a['text'] <=> b['text'] }
|
||||
|
||||
# sort the children nodes by status
|
||||
tree.each do |x|
|
||||
x['children'] =
|
||||
x['children'].sort_by { |a| a['status'] }
|
||||
end
|
||||
|
||||
# append the number of command modules so the branch name results in: "<category name> (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
|
||||
tree
|
||||
end
|
||||
|
||||
def setcommand(id)
|
||||
key = BeEF::Module.get_key_by_database_id(id.to_i)
|
||||
|
||||
cmd['id'] = id
|
||||
cmd['Name'] = config.get("beef.module.#{key}.name")
|
||||
cmd['Description'] = config.get("beef.module.#{key}.description")
|
||||
cmd['Category'] = config.get("beef.module.#{key}.category")
|
||||
cmd['Data'] = BeEF::Module.get_options(key)
|
||||
end
|
||||
|
||||
def clearcommand
|
||||
self.cmd = {}
|
||||
end
|
||||
|
||||
def setparam(param, value)
|
||||
cmd['Data'].each do |data|
|
||||
if data['name'] == param
|
||||
data['value'] = value
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def getcommandresponses(cmdid = cmd['id'])
|
||||
commands = []
|
||||
i = 0
|
||||
|
||||
BeEF::Core::Models::Command.where(command_module_id: cmdid, hooked_browser_id: targetid).each do |command|
|
||||
commands.push({
|
||||
'id' => i,
|
||||
'object_id' => command.id,
|
||||
'creationdate' => Time.at(command.creationdate.to_i).strftime('%Y-%m-%d %H:%M').to_s,
|
||||
'label' => command.label
|
||||
})
|
||||
i += 1
|
||||
end
|
||||
|
||||
commands
|
||||
end
|
||||
|
||||
def getindividualresponse(cmdid)
|
||||
results = []
|
||||
begin
|
||||
BeEF::Core::Models::Result.where(command_id: cmdid).each do |result|
|
||||
results.push({ 'date' => result.date, 'data' => JSON.parse(result.data) })
|
||||
end
|
||||
rescue StandardError
|
||||
return nil
|
||||
end
|
||||
results
|
||||
end
|
||||
|
||||
def executecommand
|
||||
definition = {}
|
||||
options = {}
|
||||
options.store('zombie_session', targetsession.to_s)
|
||||
options.store('command_module_id', cmd['id'])
|
||||
|
||||
unless cmd['Data'].nil?
|
||||
cmd['Data'].each do |key|
|
||||
options.store('txt_' + key['name'].to_s, key['value'])
|
||||
end
|
||||
end
|
||||
|
||||
options.keys.each do |param|
|
||||
definition[param[4..-1]] = options[param]
|
||||
oc = BeEF::Core::Models::OptionCache.first_or_create(name: param[4..-1])
|
||||
oc.value = options[param]
|
||||
oc.save
|
||||
end
|
||||
|
||||
mod_key = BeEF::Module.get_key_by_database_id(cmd['id'])
|
||||
# Hack to rework the old option system into the new option system
|
||||
def2 = []
|
||||
definition.each do |k, v|
|
||||
def2.push({ 'name' => k, 'value' => v })
|
||||
end
|
||||
# End hack
|
||||
if BeEF::Module.execute(mod_key, targetsession.to_s, def2).nil?
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
|
||||
# Old method
|
||||
# begin
|
||||
# BeEF::Core::Models::Command.new( :data => definition.to_json,
|
||||
# :hooked_browser_id => self.targetid,
|
||||
# :command_module_id => self.cmd['id'],
|
||||
# :creationdate => Time.new.to_i
|
||||
# ).save
|
||||
# rescue
|
||||
# return false
|
||||
# end
|
||||
|
||||
# return true
|
||||
end
|
||||
|
||||
def update_command_module_tree(tree, cmd_category, cmd_status, cmd_name, cmd_id)
|
||||
# construct leaf node for the command module tree
|
||||
leaf_node = {
|
||||
'text' => cmd_name,
|
||||
'leaf' => true,
|
||||
'status' => cmd_status,
|
||||
'id' => cmd_id
|
||||
}
|
||||
|
||||
# add the node to the branch in the command module tree
|
||||
tree.each do |x|
|
||||
if x['text'].eql? cmd_category
|
||||
x['children'].push(leaf_node)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_command_module_status(mod)
|
||||
hook_session_id = targetsession
|
||||
return 'Verified Unknown' if hook_session_id.nil?
|
||||
|
||||
case 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')]
|
||||
}
|
||||
)
|
||||
|
||||
when BeEF::Core::Constants::CommandModule::VERIFIED_NOT_WORKING
|
||||
'Verified Not Working'
|
||||
when BeEF::Core::Constants::CommandModule::VERIFIED_USER_NOTIFY
|
||||
'Verified User Notify'
|
||||
when BeEF::Core::Constants::CommandModule::VERIFIED_WORKING
|
||||
'Verified Working'
|
||||
when BeEF::Core::Constants::CommandModule::VERIFIED_UNKNOWN
|
||||
'Verified Unknown'
|
||||
else
|
||||
'Verified Unknown'
|
||||
end
|
||||
end
|
||||
|
||||
# @note Returns a JSON array containing the summary for a selected zombie.
|
||||
# Yoinked from the UI panel -
|
||||
# we really need to centralise all this stuff and encapsulate it away.
|
||||
def select_zombie_summary
|
||||
return if targetsession.nil?
|
||||
|
||||
# init the summary grid
|
||||
summary_grid_hash = {
|
||||
'success' => 'true',
|
||||
'results' => []
|
||||
}
|
||||
|
||||
# zombie properties
|
||||
# in the form of: category, UI label, value
|
||||
zombie_properties = [
|
||||
|
||||
# Browser
|
||||
['Browser', 'Browser Name', 'BrowserName'],
|
||||
['Browser', 'Browser Version', 'BrowserVersion'],
|
||||
['Browser', 'Browser UA String', 'BrowserReportedName'],
|
||||
['Browser', 'Browser Language', 'BrowserLanguage'],
|
||||
['Browser', 'Browser Platform', 'BrowserPlatform'],
|
||||
['Browser', 'Browser Plugins', 'BrowserPlugins'],
|
||||
['Browser', 'Window Size', 'WindowSize'],
|
||||
|
||||
# Browser Components
|
||||
['Browser Components', 'Flash', 'HasFlash'],
|
||||
['Browser Components', 'Java', 'JavaEnabled'],
|
||||
['Browser Components', 'VBScript', 'VBScriptEnabled'],
|
||||
['Browser Components', 'PhoneGap', 'HasPhonegap'],
|
||||
['Browser Components', 'Google Gears', 'HasGoogleGears'],
|
||||
['Browser Components', 'Web Sockets', 'HasWebSocket'],
|
||||
['Browser Components', 'QuickTime', 'HasQuickTime'],
|
||||
['Browser Components', 'RealPlayer', 'HasRealPlayer'],
|
||||
['Browser Components', 'Windows Media Player', 'HasWMP'],
|
||||
['Browser Components', 'VLC', 'HasVLC'],
|
||||
['Browser Components', 'WebRTC', 'HasWebRTC'],
|
||||
['Browser Components', 'ActiveX', 'HasActiveX'],
|
||||
['Browser Components', 'Session Cookies', 'hasSessionCookies'],
|
||||
['Browser Components', 'Persistent Cookies', 'hasPersistentCookies'],
|
||||
|
||||
# Hooked Page
|
||||
['Hooked Page', 'Page Title', 'PageTitle'],
|
||||
['Hooked Page', 'Page URI', 'PageURI'],
|
||||
['Hooked Page', 'Page Referrer', 'PageReferrer'],
|
||||
['Hooked Page', 'Hook Host', 'HostName'],
|
||||
['Hooked Page', 'Cookies', 'Cookies'],
|
||||
|
||||
# Host
|
||||
%w[Host Date DateStamp],
|
||||
['Host', 'Operating System', 'OsName'],
|
||||
%w[Host Hardware Hardware],
|
||||
%w[Host CPU CPU],
|
||||
['Host', 'Default Browser', 'DefaultBrowser'],
|
||||
['Host', 'Screen Size', 'ScreenSize'],
|
||||
['Host', 'Touch Screen', 'TouchEnabled']
|
||||
]
|
||||
|
||||
# set and add the return values for each browser property
|
||||
# in the form of: category, UI label, value
|
||||
zombie_properties.each do |p|
|
||||
case p[2]
|
||||
when 'BrowserName'
|
||||
data = BeEF::Core::Constants::Browsers.friendly_name(BD.get(targetsession.to_s, p[2])).to_s
|
||||
|
||||
when 'ScreenSize'
|
||||
screen_size_hash = JSON.parse(BD.get(targetsession.to_s, p[2]).gsub(/"=>/, '":')) # tidy up the string for JSON
|
||||
width = screen_size_hash['width']
|
||||
height = screen_size_hash['height']
|
||||
cdepth = screen_size_hash['colordepth']
|
||||
data = "Width: #{width}, Height: #{height}, Colour Depth: #{cdepth}"
|
||||
|
||||
when 'WindowSize'
|
||||
window_size_hash = JSON.parse(BD.get(targetsession.to_s, p[2]).gsub(/"=>/, '":')) # tidy up the string for JSON
|
||||
width = window_size_hash['width']
|
||||
height = window_size_hash['height']
|
||||
data = "Width: #{width}, Height: #{height}"
|
||||
else
|
||||
data = BD.get(targetsession, p[2])
|
||||
end
|
||||
|
||||
# add property to summary hash
|
||||
next if data.nil?
|
||||
|
||||
summary_grid_hash['results'].push({
|
||||
'category' => p[0],
|
||||
'data' => { p[1] => CGI.escapeHTML(data.to_s) },
|
||||
'from' => 'Initialization'
|
||||
})
|
||||
end
|
||||
|
||||
summary_grid_hash
|
||||
end
|
||||
|
||||
def select_network_hosts
|
||||
return if targetsession.nil?
|
||||
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
unless configuration.get('beef.extension.network.enable')
|
||||
print_error('Network extension is disabled')
|
||||
return {
|
||||
'success' => 'false',
|
||||
'results' => []
|
||||
}
|
||||
end
|
||||
|
||||
# init the summary grid
|
||||
summary_grid_hash = {
|
||||
'success' => 'true',
|
||||
'results' => []
|
||||
}
|
||||
@nh = BeEF::Core::Models::NetworkHost
|
||||
hosts = @nh.where(hooked_browser_id: targetsession)
|
||||
|
||||
# add property to summary hash
|
||||
unless hosts.empty?
|
||||
hosts.each do |x|
|
||||
summary_grid_hash['results'].push({
|
||||
'ip' => x['ip'].to_s,
|
||||
'hostname' => x['hostname'].to_s,
|
||||
'type' => x['type'].to_s,
|
||||
'os' => x['os'].to_s,
|
||||
'mac' => x['mac'].to_s,
|
||||
'lastseen' => x['lastseen'].to_s
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
summary_grid_hash
|
||||
end
|
||||
|
||||
def select_network_services
|
||||
return if targetsession.nil?
|
||||
|
||||
configuration = BeEF::Core::Configuration.instance
|
||||
unless configuration.get('beef.extension.network.enable')
|
||||
print_error('Network extension is disabled')
|
||||
return {
|
||||
'success' => 'false',
|
||||
'results' => []
|
||||
}
|
||||
end
|
||||
|
||||
# init the summary grid
|
||||
summary_grid_hash = {
|
||||
'success' => 'true',
|
||||
'results' => []
|
||||
}
|
||||
@ns = BeEF::Core::Models::NetworkService
|
||||
services = @ns.where(hooked_browser_id: targetsession)
|
||||
|
||||
# add property to summary hash
|
||||
unless services.empty?
|
||||
services.each do |x|
|
||||
summary_grid_hash['results'].push({
|
||||
'proto' => x['proto'].to_s,
|
||||
'ip' => x['ip'].to_s,
|
||||
'port' => x['port'].to_s,
|
||||
'type' => x['type'].to_s
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
summary_grid_hash
|
||||
end
|
||||
|
||||
attr_reader :targetsession, :targetid, :targetip, :cmd
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :targetsession, :targetid, :targetip, :cmd
|
||||
attr_accessor :config
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,63 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2023 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
require 'rex'
|
||||
require 'rex/ui'
|
||||
|
||||
module BeEF
|
||||
module Extension
|
||||
module Console
|
||||
class Shell
|
||||
DefaultPrompt = '%undBeEF%clr'
|
||||
DefaultPromptChar = '%clr>'
|
||||
|
||||
include Rex::Ui::Text::DispatcherShell
|
||||
|
||||
def initialize(prompt = DefaultPrompt, prompt_char = DefaultPromptChar, opts = {})
|
||||
require 'extensions/console/lib/readline_compatible'
|
||||
require 'extensions/console/lib/command_dispatcher'
|
||||
require 'extensions/console/lib/shellinterface'
|
||||
|
||||
self.http_hook_server = opts['http_hook_server']
|
||||
self.config = opts['config']
|
||||
self.jobs = Rex::JobContainer.new
|
||||
self.interface = BeEF::Extension::Console::ShellInterface.new(config)
|
||||
|
||||
super(prompt, prompt_char, File.expand_path(config.get('beef.extension.console.shell.historyfolder').to_s + config.get('beef.extension.console.shell.historyfile').to_s))
|
||||
|
||||
input = Rex::Ui::Text::Input::Stdio.new
|
||||
output = Rex::Ui::Text::Output::Stdio.new
|
||||
|
||||
init_ui(input, output)
|
||||
|
||||
enstack_dispatcher(CommandDispatcher::Core)
|
||||
|
||||
# To prevent http_hook_server from blocking, we kick it off as a background job here.
|
||||
jobs.start_bg_job(
|
||||
'http_hook_server',
|
||||
self,
|
||||
proc { |_ctx_| http_hook_server.start }
|
||||
)
|
||||
end
|
||||
|
||||
def stop
|
||||
super
|
||||
end
|
||||
|
||||
# New method to determine if a particular command dispatcher it already .. enstacked .. gooood
|
||||
def dispatched_enstacked(dispatcher)
|
||||
inst = dispatcher.new(self)
|
||||
dispatcher_stack.each do |disp|
|
||||
return true if disp.name == inst.name
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
attr_accessor :http_hook_server, :config, :jobs, :interface
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,15 +0,0 @@
|
||||
RSpec.describe 'BeEF Extension Console' do
|
||||
|
||||
before(:all) do
|
||||
@config = BeEF::Core::Configuration.instance
|
||||
@config.load_extensions_config
|
||||
end
|
||||
|
||||
it 'loads configuration' do
|
||||
expect(@config.get('beef.extension.console')).to have_key('enable')
|
||||
console_shell = @config.get('beef.extension.console.shell')
|
||||
expect(console_shell).to have_key('historyfolder')
|
||||
expect(console_shell).to have_key('historyfile')
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user