Introduce Rex::Text.(en|de)code_base64url and use it for uri_checksum

bug/bundler_fix
HD Moore 2015-03-20 16:29:07 -05:00
parent c0bf51e0f5
commit 858d9b1e7a
2 changed files with 34 additions and 32 deletions

View File

@ -54,7 +54,6 @@ module Msf
# This allows 'random' strings to be used as markers for
# the INIT and CONN request types, based on a checksum
uri_strip, uri_conn = uri_match.split('_', 2)
uri_strip.sub!(/^\//, '')
uri_check = Rex::Text.checksum8(uri_strip)
@ -67,57 +66,46 @@ module Msf
when URI_CHECKSUM_INITJ
uri_match = "/INITJM"
when URI_CHECKSUM_CONN
uri_match = "/CONN_" + ( uri_conn || Rex::Text.rand_text_alphanumeric(16) )
uri_match = "/CONN_" + ( uri_conn || Rex::Text.rand_text_base64url(16) )
end
uri_match
end
# Create a URI that matches a given checksum
#
# @param sum [Fixnum] The checksum value you are trying to create a URI for
# @param len [Fixnum] An optional length value for the created URI
# @return [String] The URI string that checksums to the given value
def generate_uri_checksum(sum,len=nil)
return generate_uri_checksum_with_length(sum, len) if len
chk = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
32.times do
uri = Rex::Text.rand_text_alphanumeric(3)
chk.sort_by {rand}.each do |x|
return(uri + x) if Rex::Text.checksum8(uri + x) == sum
end
end
# Otherwise return one of the pre-calculated strings
return URI_CHECKSUM_PRECALC[sum]
end
# Create an arbitrary length URI that matches a given checksum
#
# @param sum [Fixnum] The checksum value you are trying to create a URI for
# @param len [Fixnum] The length of the created URI
# @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
def generate_uri_checksum_with_length(sum, len)
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)
raise ArgumentError, "Length must be 5 bytes or greater" if len < 5
if len < 5
raise ArgumentError, "Length must be 5 bytes or greater"
end
# Funny enough, this was more efficient than calculating checksum offsets
if len < 40
gen_len = len-prefix.length
if gen_len < 5
raise ArgumentError, "Prefix must be at least 5 bytes smaller than total length"
end
# Brute force a matching checksum for shorter URIs
if gen_len < 40
loop do
uri = Rex::Text.rand_text_alphanumeric(len)
uri = prefix + Rex::Text.rand_text_base64url(gen_len)
return uri if Rex::Text.checksum8(uri) == sum
end
end
# The rand_text_alphanumeric() method becomes a bottleneck at around 40 bytes
# 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_alphanumeric(len-20)
prefix << Rex::Text.rand_text_base64url(gen_len-20)
loop do
uri = prefix + Rex::Text.rand_text_alphanumeric(20)
uri = prefix + Rex::Text.rand_text_base64url(20)
return uri if Rex::Text.checksum8(uri) == sum
end
end

View File

@ -43,6 +43,8 @@ module Text
LowerAlpha = "abcdefghijklmnopqrstuvwxyz"
Numerals = "0123456789"
Base32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
Base64 = UpperAlpha + LowerAlpha + Numerals + '+/'
Base64Url = UpperAlpha + LowerAlpha + Numerals + '-_'
Alpha = UpperAlpha + LowerAlpha
AlphaNumeric = Alpha + Numerals
HighAscii = [*(0x80 .. 0xff)].pack("C*")
@ -1288,6 +1290,18 @@ module Text
rand_base(len, bad, *foo )
end
# Generate random bytes of base64 data
def self.rand_text_base64(len, bad='')
foo = Base64.unpack('C*').map{ |c| c.chr }
rand_base(len, bad, *foo )
end
# Generate random bytes of base64url data
def self.rand_text_base64url(len, bad='')
foo = Base64Url.unpack('C*').map{ |c| c.chr }
rand_base(len, bad, *foo )
end
# Generate a random GUID
#
# @example