(Fixes issue 386) Updated 'console' extension to incorporate MSFs Rex Library for an interactive shell
git-svn-id: https://beef.googlecode.com/svn/trunk@1221 b87d56ec-f9c0-11de-8c8a-61c5e9addfc9
This commit is contained in:
15
beef
15
beef
@@ -101,5 +101,16 @@ BeEF::Extension::Console::Banners.print_network_interfaces_routes
|
||||
# We dynamically get the list of all browser hook handler using the API and register them
|
||||
BeEF::API.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)
|
||||
|
||||
# starts the web server
|
||||
http_hook_server.start
|
||||
# We check now for whether we load the Console Shell or not
|
||||
if config.get("beef.extension.console.shell.enable") == true
|
||||
puts ""
|
||||
begin
|
||||
FileUtils.mkdir_p(File.expand_path(config.get("beef.extension.console.shell.historyfolder")))
|
||||
BeEF::Extension::Console::Shell.new(BeEF::Extension::Console::Shell::DefaultPrompt,
|
||||
BeEF::Extension::Console::Shell::DefaultPromptChar,{'config' => config, 'http_hook_server' => http_hook_server}).run
|
||||
rescue Interrupt
|
||||
end
|
||||
else
|
||||
# starts the web server
|
||||
http_hook_server.start
|
||||
end
|
||||
|
||||
@@ -64,3 +64,6 @@ beef:
|
||||
enable: true
|
||||
metasploit:
|
||||
enable: false
|
||||
console:
|
||||
shell:
|
||||
enable: false
|
||||
|
||||
@@ -33,6 +33,8 @@ require 'xmlrpc/client'
|
||||
require 'erubis'
|
||||
require 'openssl'
|
||||
require 'term/ansicolor'
|
||||
require 'rex'
|
||||
require 'rex/ui'
|
||||
|
||||
# Include the filters
|
||||
require 'core/filters'
|
||||
|
||||
@@ -18,4 +18,8 @@ beef:
|
||||
console:
|
||||
enable: true
|
||||
name: 'Console'
|
||||
shell:
|
||||
enable: true
|
||||
historyfolder: '~/.beef/'
|
||||
historyfile: 'history'
|
||||
|
||||
|
||||
@@ -60,3 +60,4 @@ end
|
||||
|
||||
require 'extensions/console/banners'
|
||||
require 'extensions/console/commandline'
|
||||
require 'extensions/console/shell'
|
||||
|
||||
37
extensions/console/lib/command_dispatcher.rb
Normal file
37
extensions/console/lib/command_dispatcher.rb
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# Copyright 2011 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 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'
|
||||
169
extensions/console/lib/command_dispatcher/command.rb
Normal file
169
extensions/console/lib/command_dispatcher/command.rb
Normal file
@@ -0,0 +1,169 @@
|
||||
#
|
||||
# Copyright 2011 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 Extension
|
||||
module Console
|
||||
module CommandDispatcher
|
||||
|
||||
class Command
|
||||
include BeEF::Extension::Console::CommandDispatcher
|
||||
|
||||
def initialize(driver)
|
||||
super
|
||||
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) {|opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
cmd_cmdinfo_help
|
||||
return false
|
||||
end
|
||||
}
|
||||
|
||||
print_line("Module name: " + driver.interface.cmd['Name'])
|
||||
print_line("Module category: " + driver.interface.cmd['Category'])
|
||||
print_line("Module description: " + driver.interface.cmd['Description'])
|
||||
print_line("Module parameters:")
|
||||
|
||||
driver.interface.cmd['Data'].each{|data|
|
||||
print_line(data['name'] + " => \"" + data['value'] + "\" # this is the " + data['ui_label'] + " parameter")
|
||||
} if not driver.interface.cmd['Data'].nil?
|
||||
end
|
||||
|
||||
def cmd_cmdinfo_help(*args)
|
||||
print_status("Displays information about the current command module")
|
||||
end
|
||||
|
||||
def cmd_param(*args)
|
||||
@@bare_opts.parse(args) {|opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
cmd_param_help
|
||||
return false
|
||||
end
|
||||
}
|
||||
|
||||
if (args[0] == nil || args[1] == nil)
|
||||
cmd_param_help
|
||||
return
|
||||
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_execute(*args)
|
||||
@@bare_opts.parse(args) {|opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
cmd_execute_help
|
||||
return false
|
||||
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) {|opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
cmd_response_help
|
||||
return false
|
||||
end
|
||||
}
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Columns' =>
|
||||
[
|
||||
'Id',
|
||||
'Executed Time',
|
||||
'Response Time'
|
||||
])
|
||||
|
||||
if args[0] == 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
|
||||
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"
|
||||
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:")
|
||||
print_line(output[0]['data']['data'].to_s)
|
||||
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
|
||||
339
extensions/console/lib/command_dispatcher/core.rb
Normal file
339
extensions/console/lib/command_dispatcher/core.rb
Normal file
@@ -0,0 +1,339 @@
|
||||
#
|
||||
# Copyright 2011 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 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",
|
||||
"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",
|
||||
}
|
||||
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
|
||||
driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.to_s+"] ")
|
||||
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
|
||||
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
|
||||
driver.http_hook_server.stop if driver.jobs[val].name == "http_hook_server"
|
||||
|
||||
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
|
||||
|
||||
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',
|
||||
'OS'
|
||||
])
|
||||
|
||||
BeEF::Core::Models::HookedBrowser.all(:lastseen.gte => (Time.new.to_i - 30)).each do |zombie|
|
||||
tbl << [zombie.id,zombie.ip,beef_logo_to_os(BeEF::Extension::Initialization::Models::BrowserDetails.os_icon(zombie.session))]
|
||||
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',
|
||||
'OS'
|
||||
])
|
||||
|
||||
BeEF::Core::Models::HookedBrowser.all(:lastseen.lt => (Time.new.to_i - 30)).each do |zombie|
|
||||
tbl << [zombie.id,zombie.ip,beef_logo_to_os(BeEF::Extension::Initialization::Models::BrowserDetails.os_icon(zombie.session))]
|
||||
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
|
||||
|
||||
if not driver.interface.settarget(args[0]).nil?
|
||||
|
||||
if (driver.dispatcher_stack.size > 1 and
|
||||
driver.current_dispatcher.name != 'Core')
|
||||
|
||||
driver.destack_dispatcher
|
||||
driver.update_prompt('')
|
||||
end
|
||||
|
||||
driver.enstack_dispatcher(Target)
|
||||
driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.to_s+"] ")
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_target_help(*args)
|
||||
print_status("Target a particular online, hooked browser")
|
||||
print_status(" Usage: target <id>")
|
||||
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
|
||||
|
||||
if not driver.interface.setofflinetarget(args[0]).nil?
|
||||
if (driver.dispatcher_stack.size > 1 and
|
||||
driver.current_dispatcher.name != 'Core')
|
||||
|
||||
driver.destack_dispatcher
|
||||
driver.update_prompt('')
|
||||
end
|
||||
|
||||
driver.enstack_dispatcher(Target)
|
||||
driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.to_s+"] ")
|
||||
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 { |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)
|
||||
driver.run_single("commands")
|
||||
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
|
||||
182
extensions/console/lib/command_dispatcher/target.rb
Normal file
182
extensions/console/lib/command_dispatcher/target.rb
Normal file
@@ -0,0 +1,182 @@
|
||||
#
|
||||
# Copyright 2011 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 Extension
|
||||
module Console
|
||||
module CommandDispatcher
|
||||
|
||||
class Target
|
||||
include BeEF::Extension::Console::CommandDispatcher
|
||||
|
||||
@@commands = []
|
||||
|
||||
def initialize(driver)
|
||||
super
|
||||
begin
|
||||
driver.interface.getcommands.each { |folder|
|
||||
folder['children'].each { |command|
|
||||
@@commands << folder['text'] + "/" + command['text'].gsub(/[-\(\)]/,"").gsub(/\W+/,"_")
|
||||
}
|
||||
}
|
||||
rescue
|
||||
return
|
||||
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"
|
||||
}
|
||||
end
|
||||
|
||||
def name
|
||||
"Target"
|
||||
end
|
||||
|
||||
@@bare_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help." ])
|
||||
|
||||
def cmd_commands(*args)
|
||||
|
||||
@@bare_opts.parse(args) {|opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
cmd_commands_help
|
||||
return false
|
||||
end
|
||||
}
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Columns' =>
|
||||
[
|
||||
'Id',
|
||||
'Command',
|
||||
'Status',
|
||||
'Execute Count'
|
||||
])
|
||||
|
||||
|
||||
driver.interface.getcommands.each { |folder|
|
||||
folder['children'].each { |command|
|
||||
tbl << [command['id'].to_s,
|
||||
folder['text'] + "/" + command['text'].gsub(/[-\(\)]/,"").gsub(/\W+/,"_"),
|
||||
command['status'],
|
||||
driver.interface.getcommandresponses(command['id']).length] #TODO
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
end
|
||||
|
||||
def cmd_info(*args)
|
||||
|
||||
@@bare_opts.parse(args) {|opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
cmd_info_help
|
||||
return false
|
||||
end
|
||||
}
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Columns' =>
|
||||
[
|
||||
'Param',
|
||||
'Value'
|
||||
])
|
||||
|
||||
driver.interface.select_zombie_summary['results'].each { |x|
|
||||
x['data'].each { |k,v|
|
||||
tbl << [k,v]
|
||||
}
|
||||
}
|
||||
|
||||
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_select(*args)
|
||||
@@bare_opts.parse(args) {|opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
cmd_select_help
|
||||
return false
|
||||
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 { |x|
|
||||
x['children'].each { |y|
|
||||
if args[0].chomp == x['text']+"/"+y['text'].gsub(/[-\(\)]/,"").gsub(/\W+/,"_")
|
||||
modid = y['id']
|
||||
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
|
||||
|
||||
driver.update_prompt("(%bld%red"+driver.interface.targetip+"%clr) ["+driver.interface.targetid.to_s+"] / "+driver.interface.cmd['Name']+" ")
|
||||
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
|
||||
return @@commands
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end end end end
|
||||
8738
extensions/console/lib/rbreadline.rb
Normal file
8738
extensions/console/lib/rbreadline.rb
Normal file
File diff suppressed because it is too large
Load Diff
549
extensions/console/lib/readline_compatible.rb
Normal file
549
extensions/console/lib/readline_compatible.rb
Normal file
@@ -0,0 +1,549 @@
|
||||
# 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 Exception => 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
|
||||
|
||||
576
extensions/console/lib/shellinterface.rb
Normal file
576
extensions/console/lib/shellinterface.rb
Normal file
@@ -0,0 +1,576 @@
|
||||
#
|
||||
# Copyright 2011 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 Extension
|
||||
module Console
|
||||
|
||||
class ShellInterface
|
||||
|
||||
BD = BeEF::Extension::Initialization::Models::BrowserDetails
|
||||
|
||||
def initialize(config)
|
||||
self.config = config
|
||||
self.cmd = {}
|
||||
end
|
||||
|
||||
def settarget(id)
|
||||
begin
|
||||
self.targetsession = BeEF::Core::Models::HookedBrowser.first(:id => id).session
|
||||
self.targetip = BeEF::Core::Models::HookedBrowser.first(:id => id).ip
|
||||
self.targetid = id
|
||||
rescue
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def setofflinetarget(id)
|
||||
begin
|
||||
self.targetsession = BeEF::Core::Models::HookedBrowser.first(:id => id).session
|
||||
self.targetip = "(OFFLINE) " + BeEF::Core::Models::HookedBrowser.first(:id => id).ip
|
||||
self.targetid = id
|
||||
rescue
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def cleartarget
|
||||
self.targetsession = nil
|
||||
self.targetip = nil
|
||||
self.targetid = nil
|
||||
self.cmd = {}
|
||||
end
|
||||
|
||||
# This is a *modified* replica of select_command_modules_tree from extensions/admin_ui/controllers/modules/modules.rb
|
||||
def getcommands
|
||||
|
||||
return if self.targetid.nil?
|
||||
|
||||
tree = []
|
||||
BeEF::Modules.get_categories.each { |c|
|
||||
tree.push({
|
||||
'text' => c,
|
||||
'cls' => 'folder',
|
||||
'children' => []
|
||||
})
|
||||
}
|
||||
|
||||
BeEF::Modules.get_enabled.each{|k, mod|
|
||||
update_command_module_tree(tree, mod['category'], get_command_module_status(k), mod['name'],mod['db']['id'])
|
||||
}
|
||||
|
||||
# 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.all(:path.like => "Dynamic/")
|
||||
|
||||
if(dynamic_modules != nil)
|
||||
all_modules = BeEF::Core::Models::CommandModule.all(:order => [:id.asc])
|
||||
all_modules.each{|dyn_mod|
|
||||
next if !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
|
||||
|
||||
# sort the parent array nodes
|
||||
tree.sort! {|a,b| a['text'] <=> b['text']}
|
||||
|
||||
# sort the children nodes by status
|
||||
tree.each {|x| x['children'] =
|
||||
x['children'].sort_by {|a| a['status']}
|
||||
}
|
||||
|
||||
# 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)
|
||||
|
||||
self.cmd['id'] = id
|
||||
self.cmd['Name'] = self.config.get("beef.module.#{key}.name")
|
||||
self.cmd['Description'] = self.config.get("beef.module.#{key}.description")
|
||||
self.cmd['Category'] = self.config.get("beef.module.#{key}.category")
|
||||
self.cmd['Data'] = BeEF::Module.get_options(key)
|
||||
end
|
||||
|
||||
def clearcommand
|
||||
self.cmd = {}
|
||||
end
|
||||
|
||||
def setparam(param,value)
|
||||
self.cmd['Data'].each do |data|
|
||||
if data['name'] == param
|
||||
data['value'] = value
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def getcommandresponses(cmdid = self.cmd['id'])
|
||||
|
||||
commands = []
|
||||
i = 0
|
||||
|
||||
BeEF::Core::Models::Command.all(:command_module_id => cmdid, :hooked_browser_id => self.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.all(:command_id => cmdid).each { |result|
|
||||
results.push({'date' => result.date, 'data' => JSON.parse(result.data)})
|
||||
}
|
||||
rescue
|
||||
return nil
|
||||
end
|
||||
results
|
||||
end
|
||||
|
||||
def executecommand
|
||||
definition = {}
|
||||
options = {}
|
||||
options.store("zombie_session", self.targetsession.to_s)
|
||||
options.store("command_module_id", self.cmd['id'])
|
||||
|
||||
if not self.cmd['Data'].nil?
|
||||
self.cmd['Data'].each do |key|
|
||||
options.store("txt_"+key['name'].to_s,key['value'])
|
||||
end
|
||||
end
|
||||
|
||||
options.keys.each {|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
|
||||
}
|
||||
|
||||
mod_key = BeEF::Module.get_key_by_database_id(self.cmd['id'])
|
||||
# Hack to rework the old option system into the new option system
|
||||
def2 = []
|
||||
definition.each{|k,v|
|
||||
def2.push({'name' => k, 'value' => v})
|
||||
}
|
||||
# End hack
|
||||
if BeEF::Module.execute(mod_key, self.targetsession.to_s, def2) == true
|
||||
return true
|
||||
else
|
||||
return false
|
||||
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 {|x|
|
||||
if x['text'].eql? cmd_category
|
||||
x['children'].push( leaf_node )
|
||||
break
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def get_command_module_status(mod)
|
||||
hook_session_id = self.targetsession
|
||||
if hook_session_id == nil
|
||||
return "Verified Unknown"
|
||||
end
|
||||
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
|
||||
return "Verfied Not Working"
|
||||
when BeEF::Core::Constants::CommandModule::VERIFIED_USER_NOTIFY
|
||||
return "Verified User Notify"
|
||||
when BeEF::Core::Constants::CommandModule::VERIFIED_WORKING
|
||||
return "Verified Working"
|
||||
when BeEF::Core::Constants::CommandModule::VERIFIED_UNKNOWN
|
||||
return "Verified Unknown"
|
||||
else
|
||||
return "Verified Unknown"
|
||||
end
|
||||
end
|
||||
|
||||
#Yoinked from the UI panel - we really need to centralise all this stuff and encapsulate it away??
|
||||
def select_zombie_summary
|
||||
|
||||
return if self.targetsession.nil?
|
||||
|
||||
# init the summary grid
|
||||
summary_grid_hash = {
|
||||
'success' => 'true',
|
||||
'results' => []
|
||||
}
|
||||
|
||||
# set and add the return values for the page title
|
||||
page_title = BD.get(self.targetsession, 'PageTitle')
|
||||
if not page_title.nil?
|
||||
encoded_page_title = CGI.escapeHTML(page_title)
|
||||
encoded_page_hash = { 'Page Title' => encoded_page_title }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_page_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for the host name
|
||||
host_name = BD.get(self.targetsession, 'HostName')
|
||||
if not host_name.nil?
|
||||
encoded_host_name = CGI.escapeHTML(host_name)
|
||||
encoded_host_name_hash = { 'Hostname/IP' => encoded_host_name }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_host_name_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for the os name
|
||||
os_name = BD.get(self.targetsession, 'OsName')
|
||||
if not os_name.nil?
|
||||
encoded_os_name = CGI.escapeHTML(os_name)
|
||||
encoded_os_name_hash = { 'OS Name' => encoded_os_name }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_os_name_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for the browser name
|
||||
browser_name = BD.get(self.targetsession, 'BrowserName')
|
||||
if not browser_name.nil?
|
||||
friendly_browser_name = BeEF::Core::Constants::Browsers.friendly_name(browser_name)
|
||||
browser_name_hash = { 'Browser Name' => friendly_browser_name }
|
||||
|
||||
browser_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => browser_name_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(browser_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for the browser version
|
||||
browser_version = BD.get(self.targetsession, 'BrowserVersion')
|
||||
if not browser_version.nil?
|
||||
encoded_browser_version = CGI.escapeHTML(browser_version)
|
||||
browser_version_hash = { 'Browser Version' => encoded_browser_version }
|
||||
|
||||
browser_version_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => browser_version_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(browser_version_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for the browser ua string
|
||||
browser_uastring = BD.get(self.targetsession, 'BrowserReportedName')
|
||||
if not browser_uastring.nil?
|
||||
browser_uastring_hash = { 'Browser UA String' => browser_uastring }
|
||||
|
||||
browser_uastring_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => browser_uastring_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(browser_uastring_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the list of cookies
|
||||
cookies = BD.get(self.targetsession, 'Cookies')
|
||||
if not cookies.nil? and not cookies.empty?
|
||||
encoded_cookies = CGI.escapeHTML(cookies)
|
||||
encoded_cookies_hash = { 'Cookies' => encoded_cookies }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_cookies_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the list of plugins installed in the browser
|
||||
browser_plugins = BD.get(self.targetsession, 'BrowserPlugins')
|
||||
if not browser_plugins.nil? and not browser_plugins.empty?
|
||||
encoded_browser_plugins = CGI.escapeHTML(browser_plugins)
|
||||
encoded_browser_plugins_hash = { 'Browser Plugins' => encoded_browser_plugins }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_browser_plugins_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the internal ip address
|
||||
internal_ip = BD.get(self.targetsession, 'InternalIP')
|
||||
if not internal_ip.nil?
|
||||
encoded_internal_ip = CGI.escapeHTML(internal_ip)
|
||||
encoded_internal_ip_hash = { 'Internal IP' => encoded_internal_ip }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_internal_ip_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the internal hostname
|
||||
internal_hostname = BD.get(self.targetsession, 'InternalHostname')
|
||||
if not internal_hostname.nil?
|
||||
encoded_internal_hostname = CGI.escapeHTML(internal_hostname)
|
||||
encoded_internal_hostname_hash = { 'Internal Hostname' => encoded_internal_hostname }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_internal_hostname_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the zombie screen size and color depth
|
||||
screen_params = BD.get(self.targetsession, 'ScreenParams')
|
||||
if not screen_params.nil?
|
||||
|
||||
screen_params_hash = JSON.parse(screen_params.gsub(/\"\=\>/, '":')) # tidy up the string for JSON
|
||||
width = screen_params_hash['width']
|
||||
#raise WEBrick::HTTPStatus::BadRequest, "width is wrong type" if not width.is_a?(Fixnum)
|
||||
height = screen_params_hash['height']
|
||||
#raise WEBrick::HTTPStatus::BadRequest, "height is wrong type" if not height.is_a?(Fixnum)
|
||||
colordepth = screen_params_hash['colordepth']
|
||||
#raise WEBrick::HTTPStatus::BadRequest, "colordepth is wrong type" if not colordepth.is_a?(Fixnum)
|
||||
|
||||
# construct the string to be displayed in the details tab
|
||||
encoded_screen_params = CGI.escapeHTML("Width: "+width.to_s + ", Height: " + height.to_s + ", Colour Depth: " + colordepth.to_s)
|
||||
encoded_screen_params_hash = { 'Screen Params' => encoded_screen_params }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_screen_params_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the zombie browser window size
|
||||
window_size = BD.get(self.targetsession, 'WindowSize')
|
||||
if not window_size.nil?
|
||||
|
||||
window_size_hash = JSON.parse(window_size.gsub(/\"\=\>/, '":')) # tidy up the string for JSON
|
||||
width = window_size_hash['width']
|
||||
#raise WEBrick::HTTPStatus::BadRequest, "width is wrong type" if not width.is_a?(Fixnum)
|
||||
height = window_size_hash['height']
|
||||
#raise WEBrick::HTTPStatus::BadRequest, "height is wrong type" if not height.is_a?(Fixnum)
|
||||
|
||||
# construct the string to be displayed in the details tab
|
||||
encoded_window_size = CGI.escapeHTML("Width: "+width.to_s + ", Height: " + height.to_s)
|
||||
encoded_window_size_hash = { 'Window Size' => encoded_window_size }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_window_size_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the yes|no value for JavaEnabled
|
||||
java_enabled = BD.get(self.targetsession, 'JavaEnabled')
|
||||
if not java_enabled.nil?
|
||||
encoded_java_enabled = CGI.escapeHTML(java_enabled)
|
||||
encoded_java_enabled_hash = { 'Java Enabled' => encoded_java_enabled }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_java_enabled_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the yes|no value for VBScriptEnabled
|
||||
vbscript_enabled = BD.get(self.targetsession, 'VBScriptEnabled')
|
||||
if not vbscript_enabled.nil?
|
||||
encoded_vbscript_enabled = CGI.escapeHTML(vbscript_enabled)
|
||||
encoded_vbscript_enabled_hash = { 'VBScript Enabled' => encoded_vbscript_enabled }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_vbscript_enabled_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the yes|no value for HasFlash
|
||||
has_flash = BD.get(self.targetsession, 'HasFlash')
|
||||
if not has_flash.nil?
|
||||
encoded_has_flash = CGI.escapeHTML(has_flash)
|
||||
encoded_has_flash_hash = { 'Has Flash' => encoded_has_flash }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_has_flash_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the yes|no value for HasGoogleGears
|
||||
has_googlegears = BD.get(self.targetsession, 'HasGoogleGears')
|
||||
if not has_googlegears.nil?
|
||||
encoded_has_googlegears = CGI.escapeHTML(has_googlegears)
|
||||
encoded_has_googlegears_hash = { 'Has GoogleGears' => encoded_has_googlegears }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_has_googlegears_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for hasSessionCookies
|
||||
has_session_cookies = BD.get(self.targetsession, 'hasSessionCookies')
|
||||
if not has_session_cookies.nil?
|
||||
encoded_has_session_cookies = CGI.escapeHTML(has_session_cookies)
|
||||
encoded_has_session_cookies_hash = { 'Session Cookies' => encoded_has_session_cookies }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_has_session_cookies_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
# set and add the return values for hasPersistentCookies
|
||||
has_persistent_cookies = BD.get(self.targetsession, 'hasPersistentCookies')
|
||||
if not has_persistent_cookies.nil?
|
||||
encoded_has_persistent_cookies = CGI.escapeHTML(has_persistent_cookies)
|
||||
encoded_has_persistent_cookies_hash = { 'Persistent Cookies' => encoded_has_persistent_cookies }
|
||||
|
||||
page_name_row = {
|
||||
'category' => 'Browser Hook Initialisation',
|
||||
'data' => encoded_has_persistent_cookies_hash,
|
||||
'from' => 'Initialisation'
|
||||
}
|
||||
|
||||
summary_grid_hash['results'].push(page_name_row) # add the row
|
||||
end
|
||||
|
||||
summary_grid_hash
|
||||
end
|
||||
|
||||
attr_reader :targetsession
|
||||
attr_reader :targetid
|
||||
attr_reader :targetip
|
||||
attr_reader :cmd
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :targetsession
|
||||
attr_writer :targetid
|
||||
attr_writer :targetip
|
||||
attr_writer :cmd
|
||||
attr_accessor :config
|
||||
|
||||
end
|
||||
|
||||
end end end
|
||||
78
extensions/console/shell.rb
Normal file
78
extensions/console/shell.rb
Normal file
@@ -0,0 +1,78 @@
|
||||
#
|
||||
# Copyright 2011 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 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(self.config)
|
||||
|
||||
super(prompt, prompt_char, File.expand_path(self.config.get("beef.extension.console.shell.historyfolder").to_s + self.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.
|
||||
self.jobs.start_bg_job(
|
||||
"http_hook_server",
|
||||
self,
|
||||
Proc.new { |ctx_| self.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)
|
||||
self.dispatcher_stack.each { |disp|
|
||||
if (disp.name == inst.name)
|
||||
return true
|
||||
end
|
||||
}
|
||||
return false
|
||||
end
|
||||
|
||||
attr_accessor :http_hook_server
|
||||
attr_accessor :config
|
||||
attr_accessor :jobs
|
||||
attr_accessor :interface
|
||||
|
||||
end
|
||||
|
||||
end end end
|
||||
2
install
2
install
@@ -34,7 +34,7 @@ puts "\nPlease make sure you have installed SQLite before proceeding. For instr
|
||||
|
||||
# array of required gems - add to as needed (specify a version if needed eg "gem_name, =x.x.x")
|
||||
$gems_required = ["ansi", "term-ansicolor", "dm-core", "json", "data_objects", "do_sqlite3", "sqlite3", "dm-sqlite-adapter",
|
||||
"parseconfig", "erubis", "dm-migrations"]
|
||||
"parseconfig", "erubis", "dm-migrations", "librex"]
|
||||
|
||||
# array of missing non-version specific gems installed
|
||||
$gems_missing = Array.new
|
||||
|
||||
Reference in New Issue
Block a user