module Rex::Payloads::Meterpreter::UriChecksum
Constants
- URI_CHECKSUM_CONN
- 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
- URI_CHECKSUM_INITJ
- URI_CHECKSUM_INITN
- URI_CHECKSUM_INITP
- URI_CHECKSUM_INITW
Define 8-bit checksums for matching URLs These are based on charset frequency
- URI_CHECKSUM_INIT_CONN
- URI_CHECKSUM_MIN_LEN
- URI_CHECKSUM_MODES
Mapping between checksums and modes
- URI_CHECKSUM_UUID_MIN_LEN
Public Instance Methods
Create an arbitrary length URI that matches a given checksum
@param sum [Fixnum] The checksum value that the generated URI should match @param len [Fixnum] The length of the URI to generate @param prefix [String] The optional prefix to use to build the URI @return [String] The URI string that checksums to the given value
# File lib/rex/payloads/meterpreter/uri_checksum.rb, line 90 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
Create a URI that matches the specified checksum and payload uuid
@param sum [Fixnum] A checksum mode value to use for the generated url @param uuid [Msf::Payload::UUID] A valid UUID object @param len [Fixnum] An optional URI length value, including the leading slash @return [String] The URI string for connections
# File lib/rex/payloads/meterpreter/uri_checksum.rb, line 67 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
Map “random” URIs to static strings, allowing us to randomize the URI sent in the first request.
@param uri [String] The URI string from the HTTP request @return [Hash] The attributes extracted from the URI
# File lib/rex/payloads/meterpreter/uri_checksum.rb, line 41 def process_uri_resource(uri) # Ignore non-base64url characters in the URL uri_bare = uri.gsub(/[^a-zA-Z0-9_\-]/, '') # Figure out the mode based on the checksum uri_csum = Rex::Text.checksum8(uri_bare) # Extract the UUID if the URI is long enough uri_uuid = nil if uri_bare.length >= URI_CHECKSUM_UUID_MIN_LEN uri_uuid = Msf::Payload::UUID.new(uri: uri_bare) end uri_mode = URI_CHECKSUM_MODES[uri_csum] # Return a hash of URI attributes { uri: uri_bare, sum: uri_csum, uuid: uri_uuid, mode: uri_mode } end
Return the numerical checksum for a given mode symbol
@param mode [Symbol] The mode symbol to lookup (:connect, :init_native, :init_python, :init_java) @return [Fixnum] The URI checksum value corresponding with the mode
# File lib/rex/payloads/meterpreter/uri_checksum.rb, line 125 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