Added new metasploit extension. Needs more work but the majority of the extension is there
git-svn-id: https://beef.googlecode.com/svn/trunk@1259 b87d56ec-f9c0-11de-8c8a-61c5e9addfc9
This commit is contained in:
128
extensions/metasploit/api.rb
Normal file
128
extensions/metasploit/api.rb
Normal file
@@ -0,0 +1,128 @@
|
||||
#
|
||||
# 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 Metasploit
|
||||
module API
|
||||
|
||||
module MetasploitHooks
|
||||
|
||||
BeEF::API::Registra.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Modules, 'post_soft_load')
|
||||
|
||||
# Load modules from metasploit just after all other module config is loaded
|
||||
def self.post_soft_load
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
if msf.login
|
||||
msf_module_config = {}
|
||||
path = BeEF::Core::Configuration.instance.get('beef.extension.metasploit.path')
|
||||
if not BeEF::Extension::Console.resetdb? and File.exists?("#{path}msf-exploits.cache")
|
||||
print_debug "Attempting to use Metasploit exploits cache file"
|
||||
raw = File.read("#{path}msf-exploits.cache")
|
||||
begin
|
||||
msf_module_config = YAML.load(raw)
|
||||
rescue => e
|
||||
puts e
|
||||
end
|
||||
count = 1
|
||||
msf_module_config.each{|k,v|
|
||||
BeEF::API::Registra.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_options', [k])
|
||||
BeEF::API::Registra.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'override_execute', [k, nil])
|
||||
print_over "Loaded #{count} Metasploit exploits."
|
||||
count += 1
|
||||
}
|
||||
print "\r\n"
|
||||
else
|
||||
msf_modules = msf.call('module.exploits')
|
||||
count = 1
|
||||
msf_modules['modules'].each{|m|
|
||||
m_details = msf.call('module.info', 'exploits', m)
|
||||
if m_details
|
||||
key = 'msf_'+m.split('/').last
|
||||
# system currently doesn't support multilevel categories
|
||||
#categories = ['Metasploit']
|
||||
#m.split('/')[0...-1].each{|c|
|
||||
# categories.push(c.capitalize)
|
||||
#}
|
||||
msf_module_config[key] = {
|
||||
'enable'=> true,
|
||||
'msf'=> true,
|
||||
'msf_key' => m,
|
||||
'name'=> m_details['name'],
|
||||
'category' => 'Metasploit',
|
||||
'description'=> m_details['description'],
|
||||
'authors'=> m_details['references'],
|
||||
'path'=> path,
|
||||
'class'=> 'Msf_module'
|
||||
}
|
||||
BeEF::API::Registra.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'get_options', [key])
|
||||
BeEF::API::Registra.instance.register(BeEF::Extension::Metasploit::API::MetasploitHooks, BeEF::API::Module, 'override_execute', [key, nil])
|
||||
print_over "Loaded #{count} Metasploit exploits."
|
||||
count += 1
|
||||
end
|
||||
}
|
||||
print "\r\n"
|
||||
File.open("#{path}msf-exploits.cache", "w") do |f|
|
||||
f.write(msf_module_config.to_yaml)
|
||||
print_debug "Wrote Metasploit exploits to cache file"
|
||||
end
|
||||
end
|
||||
BeEF::Core::Configuration.instance.set('beef.module', msf_module_config)
|
||||
end
|
||||
end
|
||||
|
||||
# Get module options + payloads when the beef framework requests this information
|
||||
def self.get_options(mod)
|
||||
msf_key = BeEF::Core::Configuration.instance.get("beef.module.#{mod}.msf_key")
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
if msf_key != nil and msf.login
|
||||
msf_module_options = msf.call('module.options', 'exploit', msf_key)
|
||||
if msf_module_options
|
||||
options = BeEF::Extension::Metasploit.translate_options(msf_module_options)
|
||||
msf_payload_options = msf.call('module.compatible_payloads', msf_key)
|
||||
if msf_payload_options
|
||||
options << BeEF::Extension::Metasploit.translate_payload(msf_payload_options)
|
||||
return options
|
||||
else
|
||||
print_error "Unable to retrieve metasploit payloads for exploit: #{msf_key}"
|
||||
end
|
||||
else
|
||||
print_error "Unable to retrieve metasploit options for exploit: #{msf_key}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Execute function for all metasploit exploits
|
||||
def self.override_execute(mod, opts)
|
||||
msf = BeEF::Extension::Metasploit::RpcClient.instance
|
||||
msf_key = BeEF::Core::Configuration.instance.get("beef.module.#{mod}.msf_key")
|
||||
if msf_key != nil and msf.login
|
||||
# Are the options correctly formatted for msf?
|
||||
# This call has not been tested
|
||||
msf.call('module.execute', 'exploit', msf_key, opts)
|
||||
end
|
||||
# Still need to create command object to store a string saying "Exploit launched @ [time]", to ensure BeEF can keep track of
|
||||
# which exploits where executed against which hooked browsers
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
33
extensions/metasploit/config.yaml
Normal file
33
extensions/metasploit/config.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Enable MSF by changing extension:metasploit:enable to true
|
||||
# Then set msf_callback_host to be the public IP of your MSF server
|
||||
#
|
||||
# Ensure you load the xmlrpc interface in Metasploit
|
||||
# msf > load xmlrpc ServerHost=10.211.55.2 Pass=abc123 ServerType=Web
|
||||
# Please note that the ServerHost parameter must have the same value of host and callback_host variables here below.
|
||||
beef:
|
||||
extension:
|
||||
metasploit:
|
||||
name: 'Metasploit'
|
||||
enable: true
|
||||
host: "127.0.0.1"
|
||||
url-path: "/RPC2"
|
||||
port: 55553
|
||||
user: "msf"
|
||||
pass: "abc123"
|
||||
callback_host: "192.168.84.1"
|
||||
autopwn_url: "autopwn"
|
||||
85
extensions/metasploit/extension.rb
Normal file
85
extensions/metasploit/extension.rb
Normal file
@@ -0,0 +1,85 @@
|
||||
#
|
||||
# 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 Metasploit
|
||||
|
||||
extend BeEF::API::Extension
|
||||
|
||||
# Translates msf exploit options to beef options array
|
||||
def self.translate_options(msf_options)
|
||||
options = []
|
||||
msf_options.each{|k,v|
|
||||
case v['type']
|
||||
when "string", "address", "port", "integer"
|
||||
v['type'] = 'text'
|
||||
when "bool"
|
||||
v['type'] = 'checkbox'
|
||||
when "enum"
|
||||
v['type'] = 'combobox'
|
||||
v['store_type'] = 'arraystore',
|
||||
v['store_fields'] = ['enum'],
|
||||
v['store_data'] = self.translate_enums(v['enums']),
|
||||
v['valueField'] = 'enum',
|
||||
v['displayField'] = 'enum',
|
||||
v['autoWidth'] = true,
|
||||
v['mode'] = 'local'
|
||||
end
|
||||
v['name'] = k
|
||||
v['label'] = k
|
||||
options << v
|
||||
}
|
||||
return options
|
||||
end
|
||||
|
||||
# Translates msf payloads to a beef compatible drop down
|
||||
def self.translate_payload(payloads)
|
||||
if payloads.has_key?('payloads')
|
||||
values = self.translate_enums(payloads['payloads'])
|
||||
if values.length > 0
|
||||
return {
|
||||
'name' => 'payload',
|
||||
'type' => 'combobox',
|
||||
'ui_label' => 'Payload',
|
||||
'store_type' => 'arraystore',
|
||||
'store_fields' => ['payload'],
|
||||
'store_data' => values,
|
||||
'valueField' => 'payload',
|
||||
'displayField' => 'payload',
|
||||
'mode' => 'local',
|
||||
'autoWidth' => true
|
||||
}
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
# Translates metasploit enums to ExtJS combobox store_data
|
||||
def self.translate_enums(enums)
|
||||
values = []
|
||||
enums.each{|e|
|
||||
values << [e]
|
||||
}
|
||||
return values
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'extensions/metasploit/rpcclient'
|
||||
require 'extensions/metasploit/api'
|
||||
20
extensions/metasploit/module.rb
Normal file
20
extensions/metasploit/module.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# This is a dummy module to fool BeEF's loading system
|
||||
class Msf_module < BeEF::Core::Command
|
||||
|
||||
end
|
||||
16119
extensions/metasploit/msf-exploits.cache
Normal file
16119
extensions/metasploit/msf-exploits.cache
Normal file
File diff suppressed because it is too large
Load Diff
209
extensions/metasploit/rpcclient.rb
Normal file
209
extensions/metasploit/rpcclient.rb
Normal file
@@ -0,0 +1,209 @@
|
||||
#
|
||||
# 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 Metasploit
|
||||
|
||||
class RpcClient < ::XMLRPC::Client
|
||||
|
||||
include Singleton
|
||||
|
||||
def initialize
|
||||
@config = BeEF::Core::Configuration.instance.get('beef.extension.metasploit')
|
||||
|
||||
if not (@config.key?('host') or @config.key?('url-path') or @config.key?('port') or @config.key?('user') or @config.key?('pass'))
|
||||
print_error 'There is not enough information to initalize Metasploit connectivity at this time'
|
||||
print_error 'Please check your options in config.yaml to verify that all information is present'
|
||||
BeEF::Core::Configuration.instance.set('beef.extension.metasploit.enabled', false)
|
||||
BeEF::Core::Configuration.instance.set('beef.extension.metasploit.loaded', false)
|
||||
return nil
|
||||
end
|
||||
|
||||
@lock = false
|
||||
@token = nil
|
||||
@lastauth = nil
|
||||
|
||||
super(@config['host'],@config['url-path'],@config['port'])
|
||||
end
|
||||
|
||||
def get_lock()
|
||||
sleep 0.2 while @lock
|
||||
@lock = true
|
||||
end
|
||||
|
||||
def release_lock()
|
||||
@lock = false
|
||||
end
|
||||
|
||||
# login into metasploit
|
||||
def login
|
||||
get_lock()
|
||||
res = self.call("auth.login", @config['user'] , @config['pass'])
|
||||
|
||||
if(not (res and res['result'] == "success"))
|
||||
release_lock()
|
||||
print_error 'Could not authenticate to Metasploit xmlrpc.'
|
||||
return false
|
||||
end
|
||||
|
||||
print_info 'Successful connection with Metasploit.' if not @lastauth
|
||||
|
||||
@token = res['token']
|
||||
@lastauth = Time.now
|
||||
|
||||
release_lock()
|
||||
true
|
||||
end
|
||||
|
||||
# sends commands to the metasploit xml rpc server
|
||||
def call(meth, *args)
|
||||
if(meth != "auth.login")
|
||||
self.login() if not @token
|
||||
args.unshift(@token)
|
||||
end
|
||||
|
||||
begin
|
||||
super(meth, *args)
|
||||
rescue Errno::ECONNREFUSED
|
||||
print_error "Connection to Metasploit backend failed."
|
||||
return false
|
||||
rescue XMLRPC::FaultException => e
|
||||
if e.faultCode == 401 and meth == "auth.login"
|
||||
print_error "Your username and password combination was rejected by the Metasploit backend server"
|
||||
elsif e.faultCode == 401
|
||||
res = self.login()
|
||||
else
|
||||
print_error "An unknown exception has occured while talking to the Metasploit backend."
|
||||
print_error "The Exception text is (#{e.faultCode} : #{e.faultString}."
|
||||
print_error "Please check the Metasploit logs for more details."
|
||||
end
|
||||
return false
|
||||
rescue Exception => e
|
||||
print_error "An unknown exception (#{e}) has occured while talking to the Metasploit backend."
|
||||
print_error "Please check the Metasploit logs for more details."
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def browser_exploits()
|
||||
|
||||
get_lock()
|
||||
res = self.call('module.exploits')
|
||||
return [] if not res or not res['modules']
|
||||
|
||||
mods = res['modules']
|
||||
ret = []
|
||||
|
||||
mods.each do |m|
|
||||
ret << m if(m.include? '/browser/')
|
||||
end
|
||||
|
||||
release_lock()
|
||||
ret.sort
|
||||
end
|
||||
|
||||
def get_exploit_info(name)
|
||||
return if not @enabled
|
||||
get_lock()
|
||||
res = self.call('module.info','exploit',name)
|
||||
release_lock()
|
||||
res || {}
|
||||
end
|
||||
|
||||
def get_payloads(name)
|
||||
return if not @enabled
|
||||
get_lock()
|
||||
res = self.call('module.compatible_payloads',name)
|
||||
release_lock()
|
||||
res || {}
|
||||
end
|
||||
|
||||
def get_options(name)
|
||||
return if not @enabled
|
||||
get_lock()
|
||||
res = self.call('module.options','exploit',name)
|
||||
release_lock()
|
||||
res || {}
|
||||
end
|
||||
|
||||
def payloads()
|
||||
return if not @enabled
|
||||
get_lock()
|
||||
res = self.call('module.payloads')
|
||||
release_lock()
|
||||
return {} if not res or not res['modules']
|
||||
res['modules']
|
||||
end
|
||||
|
||||
def payload_options(name)
|
||||
return if not @enabled
|
||||
get_lock()
|
||||
res = self.call('module.options','payload',name)
|
||||
release_lock
|
||||
return {} if not res
|
||||
res
|
||||
end
|
||||
|
||||
def launch_exploit(exploit,opts)
|
||||
return if not @enabled
|
||||
get_lock()
|
||||
begin
|
||||
res = self.call('module.execute','exploit',exploit,opts)
|
||||
rescue Exception => e
|
||||
print_error "Exploit failed for #{exploit} \n"
|
||||
release_lock()
|
||||
return false
|
||||
end
|
||||
|
||||
release_lock()
|
||||
|
||||
uri = ""
|
||||
if opts['SSL']
|
||||
uri += "https://"
|
||||
else
|
||||
uri += "http://"
|
||||
end
|
||||
|
||||
uri += @config.get('beef.extension.metasploit.callback_host') + ":" + opts['SRVPORT'] + "/" + opts['URIPATH']
|
||||
|
||||
res['uri'] = uri
|
||||
res
|
||||
end
|
||||
|
||||
def launch_autopwn
|
||||
return if not @enabled
|
||||
opts = {
|
||||
'LHOST' => @config.get('beef.extension.metasploit.callback_host') ,
|
||||
'URIPATH' => @apurl
|
||||
}
|
||||
get_lock()
|
||||
begin
|
||||
res = self.call('module.execute','auxiliary','server/browser_autopwn',opts)
|
||||
rescue Exception => e
|
||||
print_error "Failed to launch autopwn\n"
|
||||
release_lock()
|
||||
return false
|
||||
end
|
||||
release_lock()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user