# -*- 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 [Fixnum] # @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,Fixnum,Bignum] # @return [Fixnum] 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?(Fixnum) or value.kind_of?(Bignum)) pattern.index([ value ].pack('V'), start) else raise ::ArgumentError, "Invalid class for value: #{value.class}" end end end end