Merge branch '4.3-schema'
commit
dbd00efefe
|
@ -0,0 +1,13 @@
|
|||
class InetColumns < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
change_column :hosts, :address, 'INET using address::INET'
|
||||
remove_column :hosts, :address6
|
||||
end
|
||||
|
||||
def self.down
|
||||
change_column :hosts, :address, :text
|
||||
add_column :hosts, :address6, :text
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
class MoreInetColumns < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
change_column :wmap_requests, :address, 'INET using address::INET'
|
||||
remove_column :wmap_requests, :address6
|
||||
change_column :wmap_targets, :address, 'INET using address::INET'
|
||||
remove_column :wmap_targets, :address6
|
||||
end
|
||||
|
||||
def self.down
|
||||
change_column :wmap_requests, :address, :string, :limit => 16
|
||||
add_column :wmap_requests, :address6, :string, :limit => 255
|
||||
change_column :wmap_targets, :address, :string, :limit => 16
|
||||
add_column :wmap_targets, :address6, :string, :limit => 255
|
||||
end
|
||||
|
||||
end
|
|
@ -51,7 +51,7 @@ module Auxiliary::JohnTheRipper
|
|||
end
|
||||
|
||||
when /x86_64-linux/
|
||||
::FileUtils.chmod(755, "#{cpuinfo_base}/cpuinfo.ia64.bin") rescue nil
|
||||
::FileUtils.chmod(0755, "#{cpuinfo_base}/cpuinfo.ia64.bin") rescue nil
|
||||
data = `#{cpuinfo_base}/cpuinfo.ia64.bin` rescue nil
|
||||
case data
|
||||
when /mmx/
|
||||
|
@ -61,7 +61,7 @@ module Auxiliary::JohnTheRipper
|
|||
end
|
||||
|
||||
when /i[\d]86-linux/
|
||||
::FileUtils.chmod(755, "#{cpuinfo_base}/cpuinfo.ia32.bin") rescue nil
|
||||
::FileUtils.chmod(0755, "#{cpuinfo_base}/cpuinfo.ia32.bin") rescue nil
|
||||
data = `#{cpuinfo_base}/cpuinfo.ia32.bin` rescue nil
|
||||
case data
|
||||
when /sse2/
|
||||
|
|
|
@ -130,7 +130,7 @@ class DBManager
|
|||
ip_x = ip.to_x
|
||||
ip_i = ip.to_i
|
||||
when "String"
|
||||
if ipv4_validator(ip)
|
||||
if ipv46_validator(ip)
|
||||
ip_x = ip
|
||||
ip_i = Rex::Socket.addr_atoi(ip)
|
||||
else
|
||||
|
@ -154,9 +154,17 @@ class DBManager
|
|||
return false
|
||||
end
|
||||
|
||||
def ipv46_validator(addr)
|
||||
ipv4_validator(addr) or ipv6_validator(addr)
|
||||
end
|
||||
|
||||
def ipv4_validator(addr)
|
||||
return false unless addr.kind_of? String
|
||||
addr =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
|
||||
Rex::Socket.is_ipv4?(addr)
|
||||
end
|
||||
|
||||
def ipv6_validator(addr)
|
||||
Rex::Socket.is_ipv6?(addr)
|
||||
end
|
||||
|
||||
# Takes a space-delimited set of ips and ranges, and subjects
|
||||
|
@ -164,7 +172,7 @@ class DBManager
|
|||
def validate_ips(ips)
|
||||
ret = true
|
||||
begin
|
||||
ips.split(' ').each {|ip|
|
||||
ips.split(/\s+/).each {|ip|
|
||||
unless Rex::Socket::RangeWalker.new(ip).ranges
|
||||
ret = false
|
||||
break
|
||||
|
@ -267,7 +275,7 @@ class DBManager
|
|||
|
||||
if not addr.kind_of? Host
|
||||
addr = normalize_host(addr)
|
||||
unless ipv4_validator(addr)
|
||||
unless ipv46_validator(addr)
|
||||
raise ::ArgumentError, "Invalid IP address in report_host(): #{addr}"
|
||||
end
|
||||
|
||||
|
@ -2215,7 +2223,7 @@ class DBManager
|
|||
# then it's an amap log
|
||||
@import_filedata[:type] = "Amap Log"
|
||||
return :amap_log
|
||||
elsif (firstline =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)
|
||||
elsif ipv46_validator(firstline)
|
||||
# then its an IP list
|
||||
@import_filedata[:type] = "IP Address List"
|
||||
return :ip_list
|
||||
|
@ -2539,7 +2547,7 @@ class DBManager
|
|||
end
|
||||
|
||||
next unless [addr,port,user,pass].compact.size == 4
|
||||
next unless ipv4_validator(addr) # Skip Malformed addrs
|
||||
next unless ipv46_validator(addr) # Skip Malformed addrs
|
||||
next unless port[/^[0-9]+$/] # Skip malformed ports
|
||||
if bl.include? addr
|
||||
next
|
||||
|
@ -4302,7 +4310,7 @@ class DBManager
|
|||
data = r[6]
|
||||
|
||||
# If there's no resolution, or if it's malformed, skip it.
|
||||
next unless ipv4_validator(addr)
|
||||
next unless ipv46_validator(addr)
|
||||
|
||||
if bl.include? addr
|
||||
next
|
||||
|
@ -4407,7 +4415,7 @@ class DBManager
|
|||
hname = host.elements['HostName'].text
|
||||
end
|
||||
addr ||= host.elements['HostName'].text
|
||||
next unless ipv4_validator(addr) # Skip resolved names and SCAN-ERROR.
|
||||
next unless ipv46_validator(addr) # Skip resolved names and SCAN-ERROR.
|
||||
if bl.include? addr
|
||||
next
|
||||
else
|
||||
|
@ -4477,7 +4485,7 @@ class DBManager
|
|||
hobj = nil
|
||||
addr = host['addr'] || host['hname']
|
||||
|
||||
next unless ipv4_validator(addr) # Catches SCAN-ERROR, among others.
|
||||
next unless ipv46_validator(addr) # Catches SCAN-ERROR, among others.
|
||||
|
||||
if bl.include? addr
|
||||
next
|
||||
|
@ -4791,7 +4799,7 @@ class DBManager
|
|||
hobj = nil
|
||||
addr = host['addr'] || host['hname']
|
||||
|
||||
next unless ipv4_validator(addr) # Catches SCAN-ERROR, among others.
|
||||
next unless ipv46_validator(addr) # Catches SCAN-ERROR, among others.
|
||||
|
||||
if bl.include? addr
|
||||
next
|
||||
|
|
|
@ -602,6 +602,14 @@ class Module
|
|||
(datastore['DEBUG'] || '') =~ /^(1|t|y)/i
|
||||
end
|
||||
|
||||
#
|
||||
# Indicates whether the module supports IPv6. This is true by default,
|
||||
# but certain modules require additional work to be compatible or are
|
||||
# hardcoded in terms of application support and should be skipped.
|
||||
#
|
||||
def support_ipv6?
|
||||
true
|
||||
end
|
||||
|
||||
#
|
||||
# This provides a standard set of search filters for every module.
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
module Msf
|
||||
module RPC
|
||||
class Auth < Base
|
||||
|
||||
def login(user,pass)
|
||||
|
||||
# handle authentication here
|
||||
fail = true
|
||||
@users.each do |u|
|
||||
if(u[0] == user and u[1] == pass)
|
||||
fail = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if fail
|
||||
# Introduce a random delay in the response to annoy brute forcers
|
||||
delay = [ ( rand(3000) / 1000.0 ), 0.50 ].max
|
||||
::IO.select(nil, nil, nil, delay)
|
||||
|
||||
# Send back a 401 denied error
|
||||
raise ::XMLRPC::FaultException.new(401, "authentication error")
|
||||
end
|
||||
|
||||
token = Rex::Text.rand_text_alphanumeric(32)
|
||||
@tokens[token] = [user, Time.now.to_i, Time.now.to_i]
|
||||
{ "result" => "success", "token" => token }
|
||||
end
|
||||
|
||||
def logout(token)
|
||||
@tokens.delete(token)
|
||||
{ "result" => "success" }
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,38 +0,0 @@
|
|||
module Msf
|
||||
module RPC
|
||||
class Base
|
||||
|
||||
def initialize(framework,tokens,users)
|
||||
@framework = framework
|
||||
@tokens = tokens
|
||||
@users = users
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def authenticate(token)
|
||||
stale = []
|
||||
|
||||
# Force the encoding to ASCII-8BIT
|
||||
token = token.unpack("C*").pack("C*")
|
||||
|
||||
@tokens.each_key do |t|
|
||||
user,ctime,mtime,perm = @tokens[t]
|
||||
if ! perm and mtime + 300 < Time.now.to_i
|
||||
stale << t
|
||||
end
|
||||
end
|
||||
|
||||
stale.each { |t| @tokens.delete(t) }
|
||||
|
||||
if not @tokens[token]
|
||||
raise ::XMLRPC::FaultException.new(401, "authentication error")
|
||||
end
|
||||
|
||||
@tokens[token][2] = Time.now.to_i
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
require "xmlrpc/client"
|
||||
require "rex"
|
||||
|
||||
module Msf
|
||||
module RPC
|
||||
|
||||
# Loosely based on the XMLRPC::ClientS class
|
||||
# Reimplemented for Metasploit
|
||||
|
||||
class Client < ::XMLRPC::Client
|
||||
|
||||
attr_accessor :sock, :token
|
||||
|
||||
# Use a TCP socket to do RPC
|
||||
def initialize(info={})
|
||||
|
||||
@buff = ""
|
||||
self.sock = Rex::Socket::Tcp.create(
|
||||
'PeerHost' => info[:host],
|
||||
'PeerPort' => info[:port],
|
||||
'SSL' => info[:ssl]
|
||||
)
|
||||
end
|
||||
|
||||
# This override hooks into the RPCXML library
|
||||
def do_rpc(request,async)
|
||||
|
||||
begin
|
||||
self.sock.put(request + "\x00")
|
||||
|
||||
while(not @buff.index("\x00"))
|
||||
if ::IO.select([self.sock], nil, nil, 30)
|
||||
resp = self.sock.sysread(32768)
|
||||
@buff << resp if resp
|
||||
end
|
||||
end
|
||||
rescue ::Exception => e
|
||||
self.close
|
||||
raise EOFError, "XMLRPC connection closed"
|
||||
end
|
||||
|
||||
mesg,left = @buff.split("\x00", 2)
|
||||
@buff = left.to_s
|
||||
mesg
|
||||
end
|
||||
|
||||
def login(user,pass)
|
||||
res = self.call("auth.login", user, pass)
|
||||
if(not (res and res['result'] == "success"))
|
||||
raise RuntimeError, "authentication failed"
|
||||
end
|
||||
self.token = res['token']
|
||||
true
|
||||
end
|
||||
|
||||
# Prepend the authentication token as the first parameter
|
||||
# of every call except auth.login. Requires the
|
||||
def call(meth, *args)
|
||||
if(meth != "auth.login")
|
||||
if(not self.token)
|
||||
raise RuntimeError, "client not authenticated"
|
||||
end
|
||||
args.unshift(self.token)
|
||||
end
|
||||
super(meth, *args)
|
||||
end
|
||||
|
||||
def close
|
||||
self.sock.close rescue nil
|
||||
self.sock = nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
require 'pp'
|
||||
require 'rex'
|
||||
require 'msf/ui/web/driver'
|
||||
|
||||
module Msf
|
||||
module RPC
|
||||
class Console < Base
|
||||
|
||||
def initialize(framework,tokens,users)
|
||||
super(framework, tokens, users)
|
||||
@console_driver = Msf::Ui::Web::Driver.new(:framework => framework)
|
||||
end
|
||||
|
||||
def create(token)
|
||||
authenticate(token)
|
||||
cid = @console_driver.create_console
|
||||
{
|
||||
'id' => cid,
|
||||
'prompt' => Rex::Text.encode_base64(@console_driver.consoles[cid].prompt || ''),
|
||||
'busy' => @console_driver.consoles[cid].busy || false,
|
||||
'encoding' => "base64"
|
||||
}
|
||||
end
|
||||
|
||||
def list(token)
|
||||
authenticate(token)
|
||||
ret = []
|
||||
@console_driver.consoles.each_key do |cid|
|
||||
ret << {
|
||||
'id' => cid,
|
||||
'prompt' => Rex::Text.encode_base64(@console_driver.consoles[cid].prompt || ''),
|
||||
'busy' => @console_driver.consoles[cid].busy || false,
|
||||
'encoding' => "base64"
|
||||
}
|
||||
end
|
||||
{'consoles' => ret}
|
||||
end
|
||||
|
||||
def destroy(token, cid)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
res = @console_driver.destroy_console(cid)
|
||||
{ 'result' => res ? 'success' : 'failure' }
|
||||
end
|
||||
|
||||
def read(token, cid)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
{
|
||||
"data" => Rex::Text.encode_base64(@console_driver.read_console(cid) || ''),
|
||||
"prompt" => Rex::Text.encode_base64(@console_driver.consoles[cid].prompt || ''),
|
||||
"busy" => @console_driver.consoles[cid].busy || false,
|
||||
"encoding" => "base64"
|
||||
}
|
||||
end
|
||||
|
||||
def write(token, cid, data)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
{ "wrote" => @console_driver.write_console(cid, Rex::Text.decode_base64(data || '')) }
|
||||
end
|
||||
|
||||
def tabs(token, cid, line)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
{ "tabs" => @console_driver.consoles[cid].tab_complete(line) }
|
||||
end
|
||||
|
||||
def session_kill(token, cid)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
@console_driver.consoles[cid].session_kill
|
||||
{ 'result' => 'success' }
|
||||
end
|
||||
|
||||
def session_detach(token, cid)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
@console_driver.consoles[cid].session_detach
|
||||
{ 'result' => 'success' }
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
module Msf
|
||||
module RPC
|
||||
class Core < Base
|
||||
|
||||
def initialize(framework, tokens, users, server=nil)
|
||||
@server = server
|
||||
super(framework, tokens, users)
|
||||
end
|
||||
|
||||
def version(token)
|
||||
authenticate(token)
|
||||
{ "version" => ::Msf::Framework::Version, "ruby" => "#{RUBY_VERSION} #{RUBY_PLATFORM} #{RUBY_RELEASE_DATE}" }
|
||||
end
|
||||
|
||||
#
|
||||
# Stop the RPC server. This method will never return a value to the client
|
||||
# because the socket for communicating with it will be closed.
|
||||
#
|
||||
def stop(token)
|
||||
authenticate(token)
|
||||
@server.stop_rpc if @server
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
File diff suppressed because it is too large
Load Diff
|
@ -1,49 +0,0 @@
|
|||
module Msf
|
||||
module RPC
|
||||
class Job < Base
|
||||
|
||||
def list(token)
|
||||
authenticate(token)
|
||||
res = {}
|
||||
res['jobs'] = {}
|
||||
@framework.jobs.each do |j|
|
||||
res['jobs'][j[0]] = j[1].name
|
||||
end
|
||||
res
|
||||
end
|
||||
|
||||
def stop(token,jid)
|
||||
authenticate(token)
|
||||
obj = @framework.jobs[jid.to_s]
|
||||
if(not obj)
|
||||
raise ::XMLRPC::FaultException.new(404, "no such job")
|
||||
else
|
||||
obj.stop
|
||||
{ "result" => "success" }
|
||||
end
|
||||
end
|
||||
def info(token,jid)
|
||||
authenticate(token)
|
||||
obj = @framework.jobs[jid.to_s]
|
||||
if(not obj)
|
||||
raise ::XMLRPC::FaultException.new(404, "no such job")
|
||||
else
|
||||
info = {
|
||||
"jid" => obj.jid,
|
||||
"name" => obj.name,
|
||||
"start_time" => obj.start_time.to_i
|
||||
}
|
||||
if obj.ctx && obj.ctx[0]
|
||||
if obj.ctx[0].respond_to?(:get_resource)
|
||||
info['uripath'] = obj.ctx[0].get_resource
|
||||
end
|
||||
if obj.ctx[0].respond_to?(:datastore)
|
||||
info['datastore'] = obj.ctx[0].datastore
|
||||
end
|
||||
end
|
||||
{ "result" => "success" , "info" => info}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,333 +0,0 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
module Msf
|
||||
module RPC
|
||||
class Module < Base
|
||||
|
||||
def exploits(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.exploits.keys }
|
||||
end
|
||||
|
||||
def auxiliary(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.auxiliary.keys }
|
||||
end
|
||||
|
||||
def payloads(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.payloads.keys }
|
||||
end
|
||||
|
||||
def encoders(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.encoders.keys }
|
||||
end
|
||||
|
||||
def nops(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.nops.keys }
|
||||
end
|
||||
|
||||
def post(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.post.keys }
|
||||
end
|
||||
|
||||
|
||||
def info(token, mtype, mname)
|
||||
authenticate(token)
|
||||
|
||||
m = _find_module(mtype,mname)
|
||||
res = {}
|
||||
|
||||
res['name'] = m.name
|
||||
res['description'] = m.description
|
||||
res['license'] = m.license
|
||||
res['filepath'] = m.file_path
|
||||
res['version'] = m.version
|
||||
res['rank'] = m.rank.to_i
|
||||
|
||||
res['references'] = []
|
||||
m.references.each do |r|
|
||||
res['references'] << [r.ctx_id, r.ctx_val]
|
||||
end
|
||||
|
||||
res['authors'] = []
|
||||
m.each_author do |a|
|
||||
res['authors'] << a.to_s
|
||||
end
|
||||
|
||||
if(m.type == "exploit")
|
||||
res['targets'] = {}
|
||||
m.targets.each_index do |i|
|
||||
res['targets'][i] = m.targets[i].name
|
||||
end
|
||||
|
||||
if (m.default_target)
|
||||
res['default_target'] = m.default_target
|
||||
end
|
||||
end
|
||||
|
||||
if(m.type == "auxiliary")
|
||||
res['actions'] = {}
|
||||
m.actions.each_index do |i|
|
||||
res['actions'][i] = m.actions[i].name
|
||||
end
|
||||
|
||||
if (m.default_action)
|
||||
res['default_action'] = m.default_action
|
||||
end
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
|
||||
def compatible_payloads(token, mname)
|
||||
authenticate(token)
|
||||
m = _find_module('exploit',mname)
|
||||
if(not m)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown module")
|
||||
end
|
||||
|
||||
res = {}
|
||||
res['payloads'] = []
|
||||
m.compatible_payloads.each do |k|
|
||||
res['payloads'] << k[0]
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def compatible_sessions(token, mname)
|
||||
authenticate(token)
|
||||
m = _find_module('post',mname)
|
||||
if(not m)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown module")
|
||||
end
|
||||
|
||||
res = {}
|
||||
res['sessions'] = m.compatible_sessions
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def target_compatible_payloads(token, mname, target)
|
||||
authenticate(token)
|
||||
m = _find_module('exploit',mname)
|
||||
if(not m)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown module")
|
||||
end
|
||||
|
||||
res = {}
|
||||
res['payloads'] = []
|
||||
m.datastore['TARGET'] = target.to_i
|
||||
m.compatible_payloads.each do |k|
|
||||
res['payloads'] << k[0]
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def options(token, mtype, mname)
|
||||
authenticate(token)
|
||||
|
||||
m = _find_module(mtype,mname)
|
||||
|
||||
res = {}
|
||||
|
||||
m.options.each_key do |k|
|
||||
o = m.options[k]
|
||||
res[k] = {
|
||||
'type' => o.type,
|
||||
'required' => o.required,
|
||||
'advanced' => o.advanced,
|
||||
'evasion' => o.evasion,
|
||||
'desc' => o.desc
|
||||
}
|
||||
|
||||
if(not o.default.nil?)
|
||||
res[k]['default'] = o.default
|
||||
end
|
||||
|
||||
if(o.enums.length > 1)
|
||||
res[k]['enums'] = o.enums
|
||||
end
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def execute(token, mtype, mname, opts)
|
||||
authenticate(token)
|
||||
|
||||
mod = _find_module(mtype,mname)
|
||||
case mtype
|
||||
when 'exploit'
|
||||
_run_exploit(mod, opts)
|
||||
when 'auxiliary'
|
||||
_run_auxiliary(mod, opts)
|
||||
when 'payload'
|
||||
_run_payload(mod, opts)
|
||||
when 'post'
|
||||
_run_post(mod, opts)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def encode(token, data, encoder, options)
|
||||
authenticate(token)
|
||||
buf = Rex::Text.decode_base64(data)
|
||||
|
||||
# Load supported formats
|
||||
supported_formats = Msf::Simple::Buffer.transform_formats + Msf::Util::EXE.to_executable_fmt_formats
|
||||
|
||||
if (fmt = options['format'])
|
||||
if not supported_formats.include?(fmt)
|
||||
raise ::XMLRPC::FaultException.new(500, "failed to generate: invalid format: #{fmt}")
|
||||
end
|
||||
end
|
||||
|
||||
badchars = ''
|
||||
if options['badchars']
|
||||
badchars = Rex::Text.hex_to_raw(options['badchars'])
|
||||
end
|
||||
|
||||
plat = nil
|
||||
if options['plat']
|
||||
plat = Msf::Module::PlatformList.transform(val)
|
||||
end
|
||||
arch = nil
|
||||
if options['arch']
|
||||
arch = options['arch']
|
||||
end
|
||||
|
||||
ecount = 1
|
||||
if options['ecount']
|
||||
ecount = options['ecount'].to_i
|
||||
end
|
||||
|
||||
exeopts = {
|
||||
:inject => options['inject'],
|
||||
:template => options['altexe'],
|
||||
:template_path => options['exedir']
|
||||
}
|
||||
|
||||
# If we were given addshellcode for a win32 payload,
|
||||
# create a double-payload; one running in one thread, one running in the other
|
||||
if options['addshellcode']
|
||||
buf = Msf::Util::EXE.win32_rwx_exec_thread(buf,0,'end')
|
||||
file = ::File.new(options['addshellcode'])
|
||||
file.binmode
|
||||
buf << file.read
|
||||
file.close
|
||||
end
|
||||
|
||||
enc = @framework.encoders.create(encoder)
|
||||
|
||||
begin
|
||||
# Imports options
|
||||
enc.datastore.update(options)
|
||||
|
||||
raw = buf.dup
|
||||
|
||||
1.upto(ecount) do |iteration|
|
||||
# Encode it up
|
||||
raw = enc.encode(raw, badchars, nil, plat)
|
||||
end
|
||||
|
||||
output = Msf::Util::EXE.to_executable_fmt(@framework, arch, plat, raw, fmt, exeopts)
|
||||
|
||||
if not output
|
||||
fmt ||= "ruby"
|
||||
output = Msf::Simple::Buffer.transform(raw, fmt)
|
||||
end
|
||||
|
||||
# How to warn?
|
||||
#if exeopts[:fellback]
|
||||
# $stderr.puts(OutError + "Warning: Falling back to default template: #{exeopts[:fellback]}")
|
||||
#end
|
||||
|
||||
{"encoded" => Rex::Text.encode_base64(output.to_s)}
|
||||
rescue => e
|
||||
raise ::XMLRPC::FaultException.new(500, "#{enc.refname} failed: #{e} #{e.backtrace}")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _find_module(mtype,mname)
|
||||
mod = @framework.modules.create(mname)
|
||||
|
||||
if(not mod)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown module")
|
||||
end
|
||||
|
||||
mod
|
||||
end
|
||||
|
||||
def _run_exploit(mod, opts)
|
||||
s = Msf::Simple::Exploit.exploit_simple(mod, {
|
||||
'Payload' => opts['PAYLOAD'],
|
||||
'Target' => opts['TARGET'],
|
||||
'RunAsJob' => true,
|
||||
'Options' => opts
|
||||
})
|
||||
{"result" => "success"}
|
||||
end
|
||||
|
||||
def _run_auxiliary(mod, opts)
|
||||
Msf::Simple::Auxiliary.run_simple(mod, {
|
||||
'Action' => opts['ACTION'],
|
||||
'RunAsJob' => true,
|
||||
'Options' => opts
|
||||
})
|
||||
{"result" => "success"}
|
||||
end
|
||||
|
||||
def _run_payload(mod, opts)
|
||||
badchars = [opts['BadChars'] || ''].pack("H*")
|
||||
fmt = opts['Format'] || 'raw'
|
||||
force = opts['ForceEncode'] || false
|
||||
template = opts['Template'] || nil
|
||||
plat = opts['Platform'] || nil
|
||||
keep = opts['KeepTemplateWorking'] || false
|
||||
force = opts['ForceEncode'] || false
|
||||
sled_size = opts['NopSledSize'].to_i || 0
|
||||
iter = opts['Iterations'].to_i || 0
|
||||
|
||||
begin
|
||||
res = Msf::Simple::Payload.generate_simple(mod, {
|
||||
'BadChars' => badchars,
|
||||
'Encoder' => opts['Encoder'],
|
||||
'Format' => fmt,
|
||||
'NoComment' => true,
|
||||
'NopSledSize' => sled_size,
|
||||
'Options' => opts,
|
||||
'ForceEncode' => force,
|
||||
'Template' => template,
|
||||
'Platform' => plat,
|
||||
'KeepTemplateWorking' => keep,
|
||||
'Iterations' => iter
|
||||
})
|
||||
|
||||
{"result" => "success", "payload" => res.unpack("H*")[0]}
|
||||
rescue ::Exception => e
|
||||
raise ::XMLRPC::FaultException.new(500, "failed to generate: #{e.message}")
|
||||
end
|
||||
end
|
||||
|
||||
def _run_post(mod, opts)
|
||||
Msf::Simple::Post.run_simple(mod, {
|
||||
'RunAsJob' => true,
|
||||
'Options' => opts
|
||||
})
|
||||
{"result" => "success"}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
module Msf
|
||||
module RPC
|
||||
class Plugin < Base
|
||||
|
||||
def load(token,path,xopts = {})
|
||||
|
||||
authenticate(token)
|
||||
opts = {}
|
||||
|
||||
xopts.each do |k,v|
|
||||
if k.class == String
|
||||
opts[k.to_sym] = v
|
||||
end
|
||||
end
|
||||
|
||||
if (path !~ /#{File::SEPARATOR}/)
|
||||
plugin_file_name = path
|
||||
|
||||
# If the plugin isn't in the user direcotry (~/.msf3/plugins/), use the base
|
||||
path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name
|
||||
if not File.exists?( path + ".rb" )
|
||||
# If the following "path" doesn't exist it will be caught when we attempt to load
|
||||
path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
if (inst = @framework.plugins.load(path, opts))
|
||||
return { "result" => "success" }
|
||||
end
|
||||
rescue ::Exception => e
|
||||
elog("Error loading plugin #{path}: #{e}\n\n#{e.backtrace.join("\n")}", src = 'core', level = 0, from = caller)
|
||||
return { "result" => "failure" }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def unload(token,name)
|
||||
authenticate(token)
|
||||
@framework.plugins.each { |plugin|
|
||||
# Unload the plugin if it matches the name we're searching for
|
||||
if (plugin.name == name)
|
||||
@framework.plugins.unload(plugin)
|
||||
return { "result" => "success" }
|
||||
end
|
||||
}
|
||||
return { "result" => "failure" }
|
||||
|
||||
end
|
||||
|
||||
def loaded(token)
|
||||
authenticate(token)
|
||||
ret = {}
|
||||
ret[:plugins] = []
|
||||
@framework.plugins.each do |plugin|
|
||||
ret[:plugins] << plugin.name
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,210 +0,0 @@
|
|||
require "xmlrpc/server"
|
||||
require 'rex/service_manager'
|
||||
require "rex"
|
||||
|
||||
|
||||
module Msf
|
||||
module RPC
|
||||
|
||||
|
||||
module MonkeyPatcher
|
||||
def initialize(*args)
|
||||
|
||||
# Enable Bigint processing (required for big file sizes,etc)
|
||||
if XMLRPC::Config.const_defined?(:ENABLE_BIGINT)
|
||||
XMLRPC::Config.send(:remove_const, :ENABLE_BIGINT)
|
||||
XMLRPC::Config.const_set(:ENABLE_BIGINT, true)
|
||||
end
|
||||
|
||||
# Enable nils in requests
|
||||
if XMLRPC::Config.const_defined?(:ENABLE_NIL_CREATE)
|
||||
XMLRPC::Config.send(:remove_const, :ENABLE_NIL_CREATE)
|
||||
XMLRPC::Config.const_set(:ENABLE_NIL_CREATE, true)
|
||||
end
|
||||
|
||||
# Enable nils in replies
|
||||
if XMLRPC::Config.const_defined?(:ENABLE_NIL_PARSER)
|
||||
XMLRPC::Config.send(:remove_const, :ENABLE_NIL_PARSER)
|
||||
XMLRPC::Config.const_set(:ENABLE_NIL_PARSER, true)
|
||||
end
|
||||
|
||||
super(*args)
|
||||
end
|
||||
end
|
||||
|
||||
class Service < ::XMLRPC::BasicServer
|
||||
|
||||
include MonkeyPatcher
|
||||
|
||||
attr_accessor :service, :state, :on_input, :on_output, :on_error
|
||||
attr_accessor :dispatcher_timeout
|
||||
|
||||
def initialize(srvhost, srvport, ssl=false, cert=nil, ckey=nil)
|
||||
|
||||
self.dispatcher_timeout = 0
|
||||
|
||||
self.service = Rex::Socket::TcpServer.create(
|
||||
'LocalHost' => srvhost,
|
||||
'LocalPort' => srvport,
|
||||
'SSL' => ssl
|
||||
)
|
||||
|
||||
self.service.on_client_connect_proc = Proc.new { |client|
|
||||
on_client_connect(client)
|
||||
}
|
||||
self.service.on_client_data_proc = Proc.new { |client|
|
||||
begin
|
||||
Timeout.timeout(self.dispatcher_timeout) do
|
||||
on_client_data(client)
|
||||
end
|
||||
rescue ::EOFError => e
|
||||
raise e
|
||||
rescue ::Exception => e
|
||||
wlog("XMLRPC Server Error: #{client.inspect} #{e.class} #{e} #{e.backtrace}")
|
||||
raise e
|
||||
end
|
||||
}
|
||||
self.service.on_client_close_proc = Proc.new { |client|
|
||||
on_client_close(client)
|
||||
}
|
||||
|
||||
self.state = {}
|
||||
super()
|
||||
end
|
||||
|
||||
def start
|
||||
self.state = {}
|
||||
self.service.start
|
||||
end
|
||||
|
||||
def stop
|
||||
self.state = {}
|
||||
self.service.stop
|
||||
self.service.close
|
||||
end
|
||||
|
||||
def wait
|
||||
self.service.wait
|
||||
end
|
||||
|
||||
def on_client_close(c)
|
||||
self.state.delete(c)
|
||||
end
|
||||
|
||||
def on_client_connect(c)
|
||||
self.state[c] = ""
|
||||
self.clean_state_table
|
||||
end
|
||||
|
||||
def on_client_data(c)
|
||||
data = c.get_once(-1)
|
||||
if(not data)
|
||||
c.close
|
||||
return
|
||||
end
|
||||
|
||||
if not self.state[c]
|
||||
c.close
|
||||
return
|
||||
end
|
||||
|
||||
self.state[c] << data
|
||||
procxml(c)
|
||||
end
|
||||
|
||||
def clean_state_table
|
||||
self.state.keys.each do |s|
|
||||
self.state.delete(s) if s.closed?
|
||||
end
|
||||
end
|
||||
|
||||
def procxml(c)
|
||||
while(self.state[c].index("\x00"))
|
||||
mesg,left = self.state[c].split("\x00", 2)
|
||||
self.state[c] = left
|
||||
begin
|
||||
self.on_input.call(mesg) if self.on_input
|
||||
|
||||
res = process(mesg)
|
||||
|
||||
self.on_output.call(res) if self.on_output
|
||||
|
||||
c.put(res+"\x00")
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Exception => e
|
||||
self.on_error.call(e) if self.on_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class WebService < ::XMLRPC::BasicServer
|
||||
|
||||
include MonkeyPatcher
|
||||
|
||||
attr_accessor :service, :state, :srvhost, :srvport, :uri
|
||||
|
||||
|
||||
def initialize(port, host, uri = "/RPC2")
|
||||
self.srvhost = host
|
||||
self.srvport = port
|
||||
self.uri = uri
|
||||
self.service = nil
|
||||
super()
|
||||
end
|
||||
|
||||
def start
|
||||
self.state = {}
|
||||
self.service = Rex::ServiceManager.start(
|
||||
Rex::Proto::Http::Server,
|
||||
self.srvport,
|
||||
self.srvhost,
|
||||
{}
|
||||
)
|
||||
|
||||
uopts = {
|
||||
'Proc' => Proc.new { |cli, req|
|
||||
on_request_uri(cli, req)
|
||||
},
|
||||
'Path' => self.uri
|
||||
}
|
||||
|
||||
self.service.add_resource(self.uri,uopts)
|
||||
end
|
||||
|
||||
def stop
|
||||
self.state = {}
|
||||
self.service.stop
|
||||
end
|
||||
|
||||
def wait
|
||||
self.service.wait
|
||||
end
|
||||
|
||||
def on_client_close(c)
|
||||
self.state.delete(c)
|
||||
end
|
||||
|
||||
def on_client_connect(c)
|
||||
self.state[c] = ""
|
||||
end
|
||||
def on_request_uri(cli, req)
|
||||
begin
|
||||
res = Rex::Proto::Http::Response.new()
|
||||
res["Content-Type"] = "text/xml"
|
||||
res.body = process(req.body)
|
||||
rescue XMLRPC::FaultException => e
|
||||
res = Rex::Proto::Http::Response.new(e.faultCode,e.faultString)
|
||||
rescue
|
||||
res = Rex::Proto::Http::Response.new(404,"An Error Occured")
|
||||
end
|
||||
cli.send_response(res)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -1,242 +0,0 @@
|
|||
require 'rex'
|
||||
require 'rex/ui/text/output/buffer'
|
||||
|
||||
module Msf
|
||||
module RPC
|
||||
class Session < Base
|
||||
|
||||
|
||||
def list(token)
|
||||
authenticate(token)
|
||||
res = {}
|
||||
@framework.sessions.each do |sess|
|
||||
i,s = sess
|
||||
res[s.sid] = {
|
||||
'type' => s.type.to_s,
|
||||
'tunnel_local'=> s.tunnel_local.to_s,
|
||||
'tunnel_peer' => s.tunnel_peer.to_s,
|
||||
'via_exploit' => s.via_exploit.to_s,
|
||||
'via_payload' => s.via_payload.to_s,
|
||||
'desc' => s.desc.to_s,
|
||||
'info' => s.info.to_s,
|
||||
'workspace' => s.workspace.to_s,
|
||||
'target_host' => s.target_host.to_s,
|
||||
'username' => s.username.to_s,
|
||||
'uuid' => s.uuid.to_s,
|
||||
'exploit_uuid' => s.exploit_uuid.to_s,
|
||||
'routes' => s.routes.join(",")
|
||||
}
|
||||
if(s.type.to_s == "meterpreter")
|
||||
res[s.sid]['platform'] = s.platform.to_s
|
||||
end
|
||||
end
|
||||
res
|
||||
end
|
||||
|
||||
def stop(token, sid)
|
||||
authenticate(token)
|
||||
s = @framework.sessions[sid.to_i]
|
||||
if(not s)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown session while stopping")
|
||||
end
|
||||
s.kill
|
||||
{ "result" => "success" }
|
||||
end
|
||||
|
||||
# Shell read is now a positon-aware reader of the shell's associated
|
||||
# ring buffer. For more direct control of the pointer into a ring
|
||||
# buffer, a client can instead use ring_read, and note the returned
|
||||
# sequence number on their own (making multiple views into the same
|
||||
# session possible, regardless of position in the stream)
|
||||
def shell_read(token, sid, ptr=nil)
|
||||
_valid_session(token,sid,"shell")
|
||||
# @session_sequence tracks the pointer into the ring buffer
|
||||
# data of sessions (by sid) in order to emulate the old behavior
|
||||
# of shell_read
|
||||
@session_sequence ||= {}
|
||||
@session_sequence[sid] ||= 0
|
||||
ring_buffer = ring_read(token,sid,(ptr || @session_sequence[sid]))
|
||||
if not (ring_buffer["seq"].nil? || ring_buffer["seq"].empty?)
|
||||
@session_sequence[sid] = ring_buffer["seq"].to_i
|
||||
end
|
||||
return ring_buffer
|
||||
end
|
||||
|
||||
# shell_write is pretty much totally identical to ring_put
|
||||
def shell_write(token, sid, data)
|
||||
_valid_session(token,sid,"shell")
|
||||
ring_put(token,sid,data)
|
||||
end
|
||||
|
||||
def shell_upgrade(token, sid, lhost, lport)
|
||||
s = _valid_session(token,sid,"shell")
|
||||
s.exploit_datastore['LHOST'] = lhost
|
||||
s.exploit_datastore['LPORT'] = lport
|
||||
s.execute_script('spawn_meterpreter', nil)
|
||||
{ "result" => "success" }
|
||||
end
|
||||
|
||||
def meterpreter_read(token, sid)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
|
||||
if not s.user_output.respond_to? :dump_buffer
|
||||
s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
|
||||
end
|
||||
|
||||
data = s.user_output.dump_buffer
|
||||
{ "data" => Rex::Text.encode_base64(data), "encoding" => "base64" }
|
||||
end
|
||||
|
||||
def ring_read(token, sid, ptr=nil)
|
||||
authenticate(token)
|
||||
s = _valid_session(token,sid,"ring")
|
||||
begin
|
||||
res = s.ring.read_data(ptr)
|
||||
{ "seq" => res[0].to_s, "data" =>(Rex::Text.encode_base64(res[1].to_s)), "encoding" => "base64"}
|
||||
rescue ::Exception => e
|
||||
raise ::XMLRPC::FaultException.new(500, "session disconnected: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
def ring_put(token, sid, data)
|
||||
authenticate(token)
|
||||
s = _valid_session(token,sid,"ring")
|
||||
buff = Rex::Text.decode_base64(data)
|
||||
begin
|
||||
res = s.shell_write(buff)
|
||||
{ "write_count" => res.to_s}
|
||||
rescue ::Exception => e
|
||||
raise ::XMLRPC::FaultException.new(500, "session disconnected: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
def ring_last(token, sid)
|
||||
authenticate(token)
|
||||
s = _valid_session(token,sid,"ring")
|
||||
{ "seq" => s.ring.last_sequence.to_s }
|
||||
end
|
||||
|
||||
def ring_clear(token, sid)
|
||||
authenticate(token)
|
||||
s = _valid_session(token,sid,"ring")
|
||||
res = s.ring.clear_data
|
||||
if res.compact.empty?
|
||||
{ "result" => "success"}
|
||||
else # Doesn't seem like this can fail. Maybe a race?
|
||||
{ "result" => "failure"}
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Run a single meterpreter console command
|
||||
#
|
||||
def meterpreter_write(token, sid, data)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
|
||||
if not s.user_output.respond_to? :dump_buffer
|
||||
s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
|
||||
end
|
||||
|
||||
buff = Rex::Text.decode_base64(data)
|
||||
|
||||
interacting = false
|
||||
s.channels.each_value do |ch|
|
||||
interacting ||= ch.respond_to?('interacting') && ch.interacting
|
||||
end
|
||||
if interacting
|
||||
s.user_input.put(buff+"\n")
|
||||
else
|
||||
@framework.threads.spawn("MeterpreterRunSingle", false, s) { |sess| sess.console.run_single(buff) }
|
||||
end
|
||||
{}
|
||||
end
|
||||
|
||||
def meterpreter_session_detach(token,sid)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
s.channels.each_value do |ch|
|
||||
if(ch.respond_to?('interacting') && ch.interacting)
|
||||
ch.detach()
|
||||
return { "result" => "success" }
|
||||
end
|
||||
end
|
||||
{ "result" => "failure" }
|
||||
end
|
||||
|
||||
def meterpreter_session_kill(token,sid)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
s.channels.each_value do |ch|
|
||||
if(ch.respond_to?('interacting') && ch.interacting)
|
||||
ch._close
|
||||
return { "result" => "success" }
|
||||
end
|
||||
end
|
||||
{ "result" => "failure" }
|
||||
end
|
||||
|
||||
def meterpreter_tabs(token,sid, line)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
{ "tabs" => s.console.tab_complete(line) }
|
||||
end
|
||||
|
||||
# runs a meterpreter command even if interacting with a shell or other channel
|
||||
def meterpreter_run_single(token, sid, data)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
|
||||
if not s.user_output.respond_to? :dump_buffer
|
||||
s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
|
||||
end
|
||||
|
||||
@framework.threads.spawn("MeterpreterRunSingle", false, s) { |sess| sess.console.run_single(data) }
|
||||
{}
|
||||
end
|
||||
|
||||
def meterpreter_script(token, sid, data)
|
||||
meterpreter_run_single(token, sid, "run #{data}")
|
||||
end
|
||||
|
||||
def compatible_modules(token, sid)
|
||||
authenticate(token)
|
||||
ret = []
|
||||
|
||||
mtype = "post"
|
||||
names = @framework.post.keys.map{ |x| "post/#{x}" }
|
||||
names.each do |mname|
|
||||
m = _find_module(mtype, mname)
|
||||
next if not m.session_compatible?(sid)
|
||||
ret << m.fullname
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _find_module(mtype,mname)
|
||||
mod = @framework.modules.create(mname)
|
||||
|
||||
if(not mod)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown module")
|
||||
end
|
||||
|
||||
mod
|
||||
end
|
||||
|
||||
def _valid_session(token,sid,type)
|
||||
authenticate(token)
|
||||
s = @framework.sessions[sid.to_i]
|
||||
if(not s)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown session while validating")
|
||||
end
|
||||
if type == "ring"
|
||||
if not s.respond_to?(:ring)
|
||||
raise ::XMLRPC::FaultException.new(403, "session #{s.type} does not support ring operations")
|
||||
end
|
||||
elsif(s.type != type)
|
||||
raise ::XMLRPC::FaultException.new(403, "session is not "+type)
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -100,7 +100,6 @@ public
|
|||
host = {}
|
||||
host[:created_at] = h.created_at.to_i
|
||||
host[:address] = h.address.to_s
|
||||
host[:address6] = h.address6.to_s
|
||||
host[:mac] = h.mac.to_s
|
||||
host[:name] = h.name.to_s
|
||||
host[:state] = h.state.to_s
|
||||
|
@ -135,7 +134,7 @@ public
|
|||
:limit => limit, :offset => offset).each do |s|
|
||||
service = {}
|
||||
host = s.host
|
||||
service[:host] = host.address || host.address6 || "unknown"
|
||||
service[:host] = host.address || "unknown"
|
||||
service[:created_at] = s[:created_at].to_i
|
||||
service[:updated_at] = s[:updated_at].to_i
|
||||
service[:port] = s[:port]
|
||||
|
@ -172,7 +171,7 @@ public
|
|||
vuln[:proto] = nil
|
||||
end
|
||||
vuln[:time] = v.created_at.to_i
|
||||
vuln[:host] = v.host.address || v.host.address6 || nil
|
||||
vuln[:host] = v.host.address || nil
|
||||
vuln[:name] = v.name
|
||||
vuln[:refs] = reflist.join(',')
|
||||
ret[:vulns] << vuln
|
||||
|
@ -261,7 +260,6 @@ public
|
|||
host = {}
|
||||
host[:created_at] = h.created_at.to_i
|
||||
host[:address] = h.address.to_s
|
||||
host[:address6] = h.address6.to_s
|
||||
host[:mac] = h.mac.to_s
|
||||
host[:name] = h.name.to_s
|
||||
host[:state] = h.state.to_s
|
||||
|
@ -324,7 +322,7 @@ public
|
|||
services.each do |s|
|
||||
service = {}
|
||||
host = s.host
|
||||
service[:host] = host.address || host.address6 || "unknown"
|
||||
service[:host] = host.address || "unknown"
|
||||
service[:created_at] = s[:created_at].to_i
|
||||
service[:updated_at] = s[:updated_at].to_i
|
||||
service[:port] = s[:port]
|
||||
|
@ -371,7 +369,7 @@ public
|
|||
notes.each do |n|
|
||||
note = {}
|
||||
host = n.host
|
||||
note[:host] = host.address || host.address6 || "unknown"
|
||||
note[:host] = host.address || "unknown"
|
||||
if n.service
|
||||
note[:port] = n.service.port
|
||||
note[:proto] = n.service.proto
|
||||
|
@ -449,7 +447,7 @@ public
|
|||
note[:time] = n.created_at.to_i
|
||||
note[:host] = ""
|
||||
note[:service] = ""
|
||||
note[:host] = n.host.address || n.host.address6 if(n.host)
|
||||
note[:host] = n.host.address if(n.host)
|
||||
note[:service] = n.service.name || n.service.port if(n.service)
|
||||
note[:type ] = n.ntype.to_s
|
||||
note[:data] = n.data.inspect
|
||||
|
@ -718,7 +716,7 @@ public
|
|||
|
||||
wspace.events.all(:limit => limit, :offset => offset).each do |e|
|
||||
event = {}
|
||||
event[:host] = e.host.address || e.host.address6 if(e.host)
|
||||
event[:host] = e.host.address if(e.host)
|
||||
event[:created_at] = e.created_at.to_i
|
||||
event[:updated_at] = e.updated_at.to_i
|
||||
event[:name] = e.name
|
||||
|
@ -757,7 +755,7 @@ public
|
|||
ret[:loots] = []
|
||||
wspace.loots.all(:limit => limit, :offset => offset).each do |l|
|
||||
loot = {}
|
||||
loot[:host] = l.host.address || l.host.address6 if(l.host)
|
||||
loot[:host] = l.host.address if(l.host)
|
||||
loot[:service] = l.service.name || n.service.port if(n.service)
|
||||
loot[:ltype] = l.ltype
|
||||
loot[:ctype] = l.ctype
|
||||
|
@ -790,7 +788,7 @@ public
|
|||
DBManager::Cred.find(:all, :include => {:service => :host}, :conditions => ["hosts.workspace_id = ?",
|
||||
framework.db.workspace.id ], :limit => limit, :offset => offset).each do |c|
|
||||
cred = {}
|
||||
cred[:host] = c.service.host.address || c.service.host.address6 if(c.service.host)
|
||||
cred[:host] = c.service.host.address if(c.service.host)
|
||||
cred[:updated_at] = c.updated_at.to_i
|
||||
cred[:port] = c.service.port
|
||||
cred[:proto] = c.service.proto
|
||||
|
@ -840,7 +838,7 @@ public
|
|||
vulns.each do |v|
|
||||
vuln= {}
|
||||
host= v.host
|
||||
vuln[:host] = host.address || host.address6 || "unknown"
|
||||
vuln[:host] = host.address || "unknown"
|
||||
if v.service
|
||||
vuln[:port] = v.service.port
|
||||
vuln[:proto] = v.service.proto
|
||||
|
|
|
@ -169,7 +169,7 @@ module Socket
|
|||
#
|
||||
def self.getaddress(addr, accept_ipv6 = true)
|
||||
begin
|
||||
if dotted_ip?(addr)
|
||||
if addr =~ MATCH_IPV4 or (accept_ipv6 and addr =~ MATCH_IPV6)
|
||||
return addr
|
||||
end
|
||||
|
||||
|
@ -205,12 +205,12 @@ module Socket
|
|||
#
|
||||
def self.getaddresses(addr, accept_ipv6 = true)
|
||||
begin
|
||||
if dotted_ip?(addr)
|
||||
return addr
|
||||
if addr =~ MATCH_IPV4 or (accept_ipv6 and addr =~ MATCH_IPV6)
|
||||
return [addr]
|
||||
end
|
||||
|
||||
res = ::Socket.gethostbyname(addr)
|
||||
return nil if not res
|
||||
return [] if not res
|
||||
|
||||
# Shift the first three elements out
|
||||
rname = res.shift
|
||||
|
@ -223,12 +223,12 @@ module Socket
|
|||
end
|
||||
|
||||
# Make sure we have at least one name
|
||||
return nil if res.length == 0
|
||||
return [] if res.length == 0
|
||||
|
||||
# Return an array of all addresses
|
||||
res.map{ |addr| self.addr_ntoa(addr) }
|
||||
rescue ::ArgumentError # Win32 bug
|
||||
nil
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -357,10 +357,10 @@ module Socket
|
|||
|
||||
# IPv4
|
||||
if (addr < 0x100000000 and not v6)
|
||||
nboa.unpack('C4').join('.')
|
||||
addr_ntoa(nboa)
|
||||
# IPv6
|
||||
else
|
||||
nboa.unpack('n8').map{ |c| "%.4x" % c }.join(":")
|
||||
addr_ntoa(nboa)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -383,12 +383,33 @@ module Socket
|
|||
|
||||
# IPv6
|
||||
if (addr.length == 16)
|
||||
return addr.unpack('n8').map{ |c| "%.4x" % c }.join(":")
|
||||
return compress_address(addr.unpack('n8').map{ |c| "%x" % c }.join(":"))
|
||||
end
|
||||
|
||||
raise RuntimeError, "Invalid address format"
|
||||
end
|
||||
|
||||
#
|
||||
# Implement zero compression for IPv6 addresses.
|
||||
# Uses the compression method from Marco Ceresa's IPAddress GEM
|
||||
# https://github.com/bluemonk/ipaddress/blob/master/lib/ipaddress/ipv6.rb
|
||||
#
|
||||
def self.compress_address(addr)
|
||||
return addr unless is_ipv6?(addr)
|
||||
addr = addr.dup
|
||||
while true
|
||||
break if addr.sub!(/\A0:0:0:0:0:0:0:0\Z/, '::')
|
||||
break if addr.sub!(/\b0:0:0:0:0:0:0\b/, ':')
|
||||
break if addr.sub!(/\b0:0:0:0:0:0\b/, ':')
|
||||
break if addr.sub!(/\b0:0:0:0:0\b/, ':')
|
||||
break if addr.sub!(/\b0:0:0:0\b/, ':')
|
||||
break if addr.sub!(/\b0:0:0\b/, ':')
|
||||
break if addr.sub!(/\b0:0\b/, ':')
|
||||
break
|
||||
end
|
||||
addr.sub(/:{3,}/, '::')
|
||||
end
|
||||
|
||||
#
|
||||
# Converts a network byte order address to an integer
|
||||
#
|
||||
|
@ -656,6 +677,7 @@ module Socket
|
|||
return [lsock, rsock]
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
#
|
||||
# Class initialization
|
||||
|
|
|
@ -73,16 +73,19 @@ class RangeWalker
|
|||
else
|
||||
return false
|
||||
end
|
||||
|
||||
elsif arg.include?(":")
|
||||
# Then it's IPv6
|
||||
# Can't really do much with IPv6 right now, just return it and
|
||||
# hope for the best
|
||||
# IPv6 ranges are not yet supported (or useful)
|
||||
return false unless Rex::Socket.is_ipv6?(arg)
|
||||
|
||||
addr = Rex::Socket.addr_atoi(arg)
|
||||
ranges.push [addr, addr, true]
|
||||
|
||||
elsif arg =~ /[^-0-9,.*]/
|
||||
# Then it's a domain name and we should send it on to addr_atoi
|
||||
# unmolested to force a DNS lookup.
|
||||
Rex::Socket.addr_atoi_list(arg).each { |addr| ranges.push [addr, addr] }
|
||||
|
||||
elsif arg =~ /^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})-([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$/
|
||||
# Then it's in the format of 1.2.3.4-5.6.7.8
|
||||
# Note, this will /not/ deal with DNS names, or the fancy/obscure 10...1-10...2
|
||||
|
|
|
@ -49,6 +49,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
# Not compatible today
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
def setup
|
||||
super
|
||||
|
|
|
@ -40,6 +40,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
# Not compatible today
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def resolve(ip)
|
||||
results = ''
|
||||
|
|
|
@ -40,6 +40,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
deregister_options('FILTER','PCAPFILE')
|
||||
end
|
||||
|
||||
# No IPv6 support yet
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def run_batch_size
|
||||
datastore['BATCHSIZE'] || 256
|
||||
end
|
||||
|
|
|
@ -41,6 +41,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
deregister_options('RHOST', 'RPORT')
|
||||
end
|
||||
|
||||
# No IPv6 support yet
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
ports = Rex::Socket.portspec_crack(datastore['PORTS'])
|
||||
|
||||
|
|
|
@ -38,6 +38,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
deregister_options('FILTER','PCAPFILE')
|
||||
end
|
||||
|
||||
# No IPv6 support yet
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def run_batch_size
|
||||
datastore['BATCHSIZE'] || 256
|
||||
end
|
||||
|
|
|
@ -40,6 +40,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
deregister_options('FILTER','PCAPFILE')
|
||||
end
|
||||
|
||||
# No IPv6 support yet
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def run_batch_size
|
||||
datastore['BATCHSIZE'] || 256
|
||||
end
|
||||
|
|
|
@ -61,6 +61,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
# Not compatible today
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def run
|
||||
@formsdir = datastore['FORMSDIR']
|
||||
@template = datastore['TEMPLATE']
|
||||
|
|
8
msfrpc
8
msfrpc
|
@ -37,7 +37,7 @@ opts = {
|
|||
'User' => 'msf',
|
||||
'SSL' => true,
|
||||
'ServerPort' => 55553,
|
||||
'Type' => 'Xml'
|
||||
'Type' => 'Msg'
|
||||
}
|
||||
|
||||
# Parse command line arguments.
|
||||
|
@ -53,8 +53,6 @@ arguments.parse(ARGV) { |opt, idx, val|
|
|||
opts['User'] = val
|
||||
when '-P'
|
||||
opts['Pass'] = val
|
||||
when '-t'
|
||||
opts['Type'] = (val =~ /xml/i) ? 'XML' : 'Msg'
|
||||
when "-h"
|
||||
print("\nUsage: #{File.basename(__FILE__)} <options>\n" + arguments.usage)
|
||||
exit
|
||||
|
@ -76,11 +74,7 @@ end
|
|||
|
||||
$0 = "msfrpc"
|
||||
|
||||
if opts['Type'] == 'Msg'
|
||||
require 'msf/core/rpc/v10/client'
|
||||
else
|
||||
require 'msf/core/rpc/client'
|
||||
end
|
||||
require 'rex/ui'
|
||||
|
||||
rpc = Msf::RPC::Client.new(
|
||||
|
|
8
msfrpcd
8
msfrpcd
|
@ -28,7 +28,6 @@ arguments = Rex::Parser::Arguments.new(
|
|||
"-p" => [ true, "Bind to this port instead of 55553" ],
|
||||
"-U" => [ true, "Specify the username to access msfrpcd" ],
|
||||
"-P" => [ true, "Specify the password to access msfrpcd" ],
|
||||
"-t" => [ true, "Server type, [Basic|Web|Msg]" ],
|
||||
"-u" => [ true, "URI for Web server" ],
|
||||
"-S" => [ false, "Disable SSL on the RPC socket" ],
|
||||
"-f" => [ false, "Run the daemon in the foreground" ],
|
||||
|
@ -40,7 +39,7 @@ opts = {
|
|||
'SSL' => true,
|
||||
'ServerHost' => '0.0.0.0',
|
||||
'ServerPort' => 55553,
|
||||
'ServerType' => 'Basic'
|
||||
'ServerType' => 'Msg'
|
||||
}
|
||||
|
||||
foreground = false
|
||||
|
@ -62,8 +61,6 @@ arguments.parse(ARGV) { |opt, idx, val|
|
|||
opts['Pass'] = val
|
||||
when "-f"
|
||||
foreground = true
|
||||
when "-t"
|
||||
opts['ServerType'] = val
|
||||
when "-u"
|
||||
opts['URI'] = val
|
||||
when "-n"
|
||||
|
@ -81,8 +78,7 @@ end
|
|||
|
||||
$0 = "msfrpcd"
|
||||
|
||||
rpctype = 'XML'
|
||||
rpctype = 'MSG' if opts['ServerType'].downcase == 'msg'
|
||||
rpctype = 'MSG'
|
||||
|
||||
$stderr.puts "[*] #{rpctype}RPC starting on #{opts['ServerHost']}:#{opts['ServerPort']} (#{opts['SSL'] ? "SSL" : "NO SSL"}):#{opts['ServerType']}..."
|
||||
|
||||
|
|
|
@ -1,188 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# This plugin provides an msf daemon interface that spawns a listener on a
|
||||
# defined port (default 55553) and gives each connecting client its own
|
||||
# console interface. These consoles all share the same framework instance.
|
||||
# Be aware that the console instance that spawns on the port is entirely
|
||||
# unauthenticated, so realize that you have been warned.
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
require "msf/core/rpc"
|
||||
require "fileutils"
|
||||
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This class implements the msfd plugin interface.
|
||||
#
|
||||
###
|
||||
class Plugin::XMLRPC < Msf::Plugin
|
||||
|
||||
#
|
||||
# The default local hostname that the server listens on.
|
||||
#
|
||||
DefaultHost = "127.0.0.1"
|
||||
|
||||
#
|
||||
# The default local port that the server listens on.
|
||||
#
|
||||
DefaultPort = 55553
|
||||
|
||||
#
|
||||
# ServerPort
|
||||
#
|
||||
# The local port to listen on for connections. The default is 55553
|
||||
#
|
||||
def initialize(framework, opts)
|
||||
super
|
||||
|
||||
host = opts['ServerHost'] || DefaultHost
|
||||
port = opts['ServerPort'] || DefaultPort
|
||||
ssl = (opts['SSL'] and opts['SSL'].to_s =~ /^[ty]/i) ? true : false
|
||||
cert = opts['SSLCert']
|
||||
ckey = opts['SSLKey']
|
||||
|
||||
user = opts['User'] || "msf"
|
||||
pass = opts['Pass'] || ::Rex::Text.rand_text_alphanumeric(8)
|
||||
type = opts['ServerType'] || "Basic"
|
||||
uri = opts['URI'] || "/RPC2"
|
||||
|
||||
print_status("XMLRPC Service: #{host}:#{port} #{ssl ? " (SSL)" : ""}")
|
||||
print_status("XMLRPC Username: #{user}")
|
||||
print_status("XMLRPC Password: #{pass}")
|
||||
print_status("XMLRPC Server Type: #{type}")
|
||||
|
||||
@users = [ [user,pass] ]
|
||||
if(type =~ /Web/i)
|
||||
print_status("XMLRPC Web URI: #{uri}")
|
||||
self.server = ::Msf::RPC::WebService.new(port,host,uri)
|
||||
elsif(type =~ /Basic/i)
|
||||
self.server = ::Msf::RPC::Service.new(host,port,ssl,cert,ckey)
|
||||
else
|
||||
print_status("Invalid server type #{type}, please choose Web or Basic")
|
||||
end
|
||||
|
||||
# If the run in foreground flag is not specified, then go ahead and fire
|
||||
# it off in a worker thread.
|
||||
if (opts['RunInForeground'] != true)
|
||||
# Store a handle to the thread so we can kill it during
|
||||
# cleanup when we get unloaded.
|
||||
self.thread = Thread.new {
|
||||
run
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Returns 'xmlrpc'
|
||||
#
|
||||
def name
|
||||
"xmlrpc"
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the plugin description.
|
||||
#
|
||||
def desc
|
||||
"Provides a XMLRPC interface over a listening TCP port."
|
||||
end
|
||||
|
||||
#
|
||||
# The meat of the plugin, sets up handlers for requests
|
||||
#
|
||||
def run
|
||||
|
||||
# Initialize the list of authenticated sessions
|
||||
@tokens = {}
|
||||
|
||||
args = [framework,@tokens,@users]
|
||||
|
||||
# Add handlers for every class
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("auth"),
|
||||
::Msf::RPC::Auth.new(*args)
|
||||
)
|
||||
|
||||
# Note the extra argument for core as compared to the other
|
||||
# handlers. This allows rpc clients access to the plugin so
|
||||
# they can shutdown the server.
|
||||
core_args = args + [self]
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("core"),
|
||||
::Msf::RPC::Core.new(*core_args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("session"),
|
||||
::Msf::RPC::Session.new(*args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("job"),
|
||||
::Msf::RPC::Job.new(*args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("module"),
|
||||
::Msf::RPC::Module.new(*args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("console"),
|
||||
::Msf::RPC::Console.new(*args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("db"),
|
||||
::Msf::RPC::Db.new(*args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("plugin"),
|
||||
::Msf::RPC::Plugin.new(*args)
|
||||
)
|
||||
|
||||
# Set the default/catch-all handler
|
||||
self.server.set_default_handler do |name, *args|
|
||||
raise ::XMLRPC::FaultException.new(-99, "Method #{name} missing or wrong number of parameters!")
|
||||
end
|
||||
|
||||
# Start the actual service
|
||||
self.server.start
|
||||
|
||||
# Wait for the service to complete
|
||||
self.server.wait
|
||||
end
|
||||
|
||||
#
|
||||
# Closes the listener service.
|
||||
#
|
||||
def cleanup
|
||||
self.server.stop if self.server
|
||||
self.thread.kill if self.thread
|
||||
self.server = nil
|
||||
super
|
||||
end
|
||||
|
||||
def stop_rpc
|
||||
print_line
|
||||
print_status("XMLRPC Client requested server stop")
|
||||
# Plugins aren't really meant to be able to unload themselves, so this
|
||||
# is a bit of a corner case. Unloading ourselves ends up killing the
|
||||
# thread that's doing the unloading so we need to fire off the unload
|
||||
# in a seperate one.
|
||||
Thread.new {
|
||||
framework.plugins.unload(self)
|
||||
}
|
||||
nil
|
||||
end
|
||||
|
||||
#
|
||||
# The XMLRPC instance.
|
||||
#
|
||||
attr_accessor :server
|
||||
attr_accessor :thread
|
||||
attr_accessor :users
|
||||
attr_accessor :tokens
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
Loading…
Reference in New Issue