85 lines
2.9 KiB
Ruby
85 lines
2.9 KiB
Ruby
# -*- coding: binary -*-
|
|
module Rex
|
|
module Text
|
|
# We are re-opening the module to add these module methods.
|
|
# Breaking them up this way allows us to maintain a little higher
|
|
# degree of organisation and make it easier to find what you're looking for
|
|
# without hanging the underlying calls that we historically rely upon.
|
|
|
|
#
|
|
# Creates a pattern that can be used for offset calculation purposes. This
|
|
# routine is capable of generating patterns using a supplied set and a
|
|
# supplied number of identifiable characters (slots). The supplied sets
|
|
# should not contain any duplicate characters or the logic will fail.
|
|
#
|
|
# @param length [Integer]
|
|
# @param sets [Array<(String,String,String)>] The character sets to choose
|
|
# from. Should have 3 elements, each of which must be a string containing
|
|
# no characters contained in the other sets.
|
|
# @return [String] A pattern of +length+ bytes, in which any 4-byte chunk is
|
|
# unique
|
|
# @see pattern_offset
|
|
def self.pattern_create(length, sets = nil)
|
|
buf = ''
|
|
offsets = []
|
|
|
|
# Make sure there's something in sets even if we were given an explicit nil
|
|
sets ||= [ UpperAlpha, LowerAlpha, Numerals ]
|
|
|
|
# Return stupid uses
|
|
return "" if length.to_i < 1
|
|
return sets[0][0].chr * length if sets.size == 1 and sets[0].size == 1
|
|
|
|
sets.length.times { offsets << 0 }
|
|
|
|
until buf.length >= length
|
|
buf << converge_sets(sets, 0, offsets, length)
|
|
end
|
|
|
|
buf[0,length]
|
|
end
|
|
|
|
# Step through an arbitrary number of sets of bytes to build up a findable pattern.
|
|
# This is mostly useful for experimentially determining offset lengths into memory
|
|
# structures. Note that the supplied sets should never contain duplicate bytes, or
|
|
# else it can become impossible to measure the offset accurately.
|
|
def self.patt2(len, sets = nil)
|
|
buf = ""
|
|
counter = []
|
|
sets ||= [ UpperAlpha, LowerAlpha, Numerals ]
|
|
len ||= len.to_i
|
|
return "" if len.zero?
|
|
|
|
sets = sets.map {|a| a.split(//)}
|
|
sets.size.times { counter << 0}
|
|
0.upto(len-1) do |i|
|
|
setnum = i % sets.size
|
|
|
|
#puts counter.inspect
|
|
end
|
|
|
|
return buf
|
|
end
|
|
|
|
#
|
|
# Calculate the offset to a pattern
|
|
#
|
|
# @param pattern [String] The pattern to search. Usually the return value
|
|
# from {.pattern_create}
|
|
# @param value [String,Integer]
|
|
# @return [Integer] Index of the given +value+ within +pattern+, if it exists
|
|
# @return [nil] if +pattern+ does not contain +value+
|
|
# @see pattern_create
|
|
def self.pattern_offset(pattern, value, start=0)
|
|
if value.kind_of?(String)
|
|
pattern.index(value, start)
|
|
elsif value.kind_of?(Integer)
|
|
pattern.index([ value ].pack('V'), start)
|
|
else
|
|
raise ::ArgumentError, "Invalid class for value: #{value.class}"
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|