Module: Rex::Payloads::Meterpreter::UriChecksum
- Included in:
- Msf::Handler::ReverseHttp, Msf::Payload::UUID::Options, Config, Rex::Post::Meterpreter::ClientCore
- Defined in:
- lib/rex/payloads/meterpreter/uri_checksum.rb
Constant Summary collapse
- URI_CHECKSUM_INITW =
Define 8-bit checksums for matching URLs These are based on charset frequency
92- URI_CHECKSUM_INITN =
Windows
92- URI_CHECKSUM_INITP =
Native (same as Windows)
80- URI_CHECKSUM_INITJ =
Python
88- URI_CHECKSUM_INITPH =
Java
84- URI_CHECKSUM_CONN =
PHP
98- URI_CHECKSUM_INIT_CONN =
Existing session
95- URI_CHECKSUM_MODES =
Mapping between checksums and modes
Hash[ URI_CHECKSUM_INITN, :init_native, URI_CHECKSUM_INITP, :init_python, URI_CHECKSUM_INITJ, :init_java, URI_CHECKSUM_INITPH, :init_php, URI_CHECKSUM_INIT_CONN, :init_connect, URI_CHECKSUM_CONN, :connect ]
- URI_CHECKSUM_MIN_LEN =
5- URI_CHECKSUM_CONN_MAX_LEN =
Limit how long :connect URLs are to stay within 256 bytes when including the hostname, colon, port, and leading slash
128- URI_CHECKSUM_UUID_MIN_LEN =
URI_CHECKSUM_MIN_LEN + Msf::Payload::UUID::UriLength
Instance Method Summary collapse
-
#generate_uri_checksum(sum, len = 5, prefix = "") ⇒ String
Create an arbitrary length URI that matches a given checksum.
-
#generate_uri_uuid(sum, uuid, len = nil) ⇒ String
Create a URI that matches the specified checksum and payload uuid.
-
#process_cookie_resource(cookie) ⇒ Hash
Map “random” cookies to static strings.
-
#process_query_string_resource(query_string) ⇒ Hash
Map “random” get params to static strings.
-
#process_uri_resource(uri) ⇒ Hash
Map “random” URIs to static strings, allowing us to randomize the URI sent in the first request.
- #process_uuid_string(uri_bare) ⇒ Object
-
#uri_checksum_lookup(mode) ⇒ Integer
Return the numerical checksum for a given mode symbol.
Instance Method Details
#generate_uri_checksum(sum, len = 5, prefix = "") ⇒ String
Create an arbitrary length URI that matches a given checksum
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/rex/payloads/meterpreter/uri_checksum.rb', line 117 def generate_uri_checksum(sum, len=5, prefix="") # Lengths shorter than 4 bytes are unable to match all possible checksums # Lengths of exactly 4 are relatively slow to find for high checksum values # Lengths of 5 or more bytes find a matching checksum fairly quickly (~80ms) if len < URI_CHECKSUM_MIN_LEN raise ArgumentError, "Length must be #{URI_CHECKSUM_MIN_LEN} bytes or greater" end gen_len = len-prefix.length if gen_len < URI_CHECKSUM_MIN_LEN raise ArgumentError, "Prefix must be at least {URI_CHECKSUM_MIN_LEN} bytes smaller than total length" end # Brute force a matching checksum for shorter URIs if gen_len < 40 loop do uri = prefix + Rex::Text.rand_text_base64url(gen_len) return uri if Rex::Text.checksum8(uri) == sum end end # The rand_text_base64url() method becomes a bottleneck at around 40 bytes # Calculating a static prefix flattens out the average runtime for longer URIs prefix << Rex::Text.rand_text_base64url(gen_len-20) loop do uri = prefix + Rex::Text.rand_text_base64url(20) return uri if Rex::Text.checksum8(uri) == sum end end |
#generate_uri_uuid(sum, uuid, len = nil) ⇒ String
Create a URI that matches the specified checksum and payload uuid
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/rex/payloads/meterpreter/uri_checksum.rb', line 94 def generate_uri_uuid(sum, uuid, len=nil) curl_uri_len = URI_CHECKSUM_UUID_MIN_LEN + rand(URI_CHECKSUM_CONN_MAX_LEN - URI_CHECKSUM_UUID_MIN_LEN) curl_prefix = uuid.to_uri if len # Subtract a byte to take into account the leading / curl_uri_len = len - 1 end if curl_uri_len < URI_CHECKSUM_UUID_MIN_LEN raise ArgumentError, "Length must be #{URI_CHECKSUM_UUID_MIN_LEN+1} bytes or greater" end # Pad out the URI and make the checksum match the specified sum "/" + generate_uri_checksum(sum, curl_uri_len, curl_prefix) end |
#process_cookie_resource(cookie) ⇒ Hash
Map “random” cookies to static strings.
85 86 |
# File 'lib/rex/payloads/meterpreter/uri_checksum.rb', line 85 def () end |
#process_query_string_resource(query_string) ⇒ Hash
Map “random” get params to static strings.
78 79 |
# File 'lib/rex/payloads/meterpreter/uri_checksum.rb', line 78 def process_query_string_resource(query_string) end |
#process_uri_resource(uri) ⇒ Hash
Map “random” URIs to static strings, allowing us to randomize the URI sent in the first request.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/rex/payloads/meterpreter/uri_checksum.rb', line 59 def process_uri_resource(uri) # look for the UUID anywhere in the given URI, excluding the query string uri.split('?')[0].split('/').each {|u| # Ignore non-base64url characters in the URL = u.gsub(/[^a-zA-Z0-9_\-]/, '') h = process_uuid_string() return h if h[:uuid] } # No embedded UUID was found in any URI segment; fall back to a # checksum-based mode lookup against the whole URI, e.g. for the # INITW/INITJ/CONN handshake requests which don't carry a UUID yet. process_uuid_string(uri.gsub(/[^a-zA-Z0-9_\-]/, '')) end |
#process_uuid_string(uri_bare) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/rex/payloads/meterpreter/uri_checksum.rb', line 38 def process_uuid_string() # Figure out the mode based on the checksum uri_csum = Rex::Text.checksum8() # Extract the UUID if the URI is long enough uri_uuid = nil if .length >= URI_CHECKSUM_UUID_MIN_LEN uri_uuid = Msf::Payload::UUID.new(uri: ) end uri_mode = URI_CHECKSUM_MODES[uri_csum] # Return a hash of URI attributes { uri: , sum: uri_csum, uuid: uri_uuid, mode: uri_mode } end |
#uri_checksum_lookup(mode) ⇒ Integer
Return the numerical checksum for a given mode symbol
152 153 154 155 156 157 158 |
# File 'lib/rex/payloads/meterpreter/uri_checksum.rb', line 152 def uri_checksum_lookup(mode) sum = URI_CHECKSUM_MODES.keys.select{|ksum| URI_CHECKSUM_MODES[ksum] == mode}.first unless sum raise ArgumentError, "Unknown checksum mode: #{mode}" end sum end |