diff --git a/tools/exploit/pattern_offset.rb b/tools/exploit/pattern_offset.rb index 8a25f8d41d..7887c02ad9 100755 --- a/tools/exploit/pattern_offset.rb +++ b/tools/exploit/pattern_offset.rb @@ -5,8 +5,8 @@ while File.symlink?(msfbase) msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) end -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] +$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) +$LOAD_PATH.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] require 'msfenv' require 'msf/core' @@ -22,16 +22,17 @@ module PatternOffset opt.banner = "Usage: #{__FILE__} [options]\nExample: #{__FILE__} -q Aa3A|0x39634138|0xFFFF4138\n[*] Exact match at offset 9" opt.separator '' opt.separator 'Options:' - opt.on('-q', '--query Aa0A', String, "Query to Locate") do |query| - options[:query] = query + + opt.on('-q', '--query Aa0A', String, "Query to Locate") do |query| + options[:query] = query end opt.on('-l', '--length ', Integer, "The length of the pattern") do |len| options[:length] = len - end + end opt.on('-s', '--sets ', Array, "Custom Pattern Sets") do |sets| - options[:sets] = sets + options[:sets] = sets end opt.on_tail('-h', '--help', 'Show this message') do @@ -57,7 +58,7 @@ module PatternOffset end end -class Driver + class Driver def initialize begin @opts = OptsConsole.parse(ARGV) @@ -69,69 +70,66 @@ class Driver def run query = (@opts[:query]) - pattern = Rex::Text.pattern_create(@opts[:length], @opts[:sets]) - - if (query.length >= 8 and query.hex > 0) + if query.length >= 8 && query.hex > 0 query = query.hex # However, you can also specify a four-byte string - elsif (query.length == 4) + elsif query.length == 4 query = query.unpack("V").first else - # Or even a hex query that isn't 8 bytes long + # Or even a hex query that isn't 8 bytes long query = query.to_i(16) end buffer = Rex::Text.pattern_create(@opts[:length], @opts[:sets]) offset = Rex::Text.pattern_offset(buffer, query) - # Handle cases where there is no match by looking for "close" matches - unless offset - found = false - $stderr.puts "[*] No exact matches, looking for likely candidates..." + # Handle cases where there is no match by looking for "close" matches + unless offset + found = false + $stderr.puts "[*] No exact matches, looking for likely candidates..." - # Look for shifts by a single byte - 0.upto(3) do |idx| - 0.upto(255) do |c| - nvb = [query].pack("V") - nvb[idx, 1] = [c].pack("C") - nvi = nvb.unpack("V").first + # Look for shifts by a single byte + 0.upto(3) do |idx| + 0.upto(255) do |c| + nvb = [query].pack("V") + nvb[idx, 1] = [c].pack("C") + nvi = nvb.unpack("V").first - off = Rex::Text.pattern_offset(buffer, nvi) - if off - mle = query - buffer[off,4].unpack("V").first - mbe = query - buffer[off,4].unpack("N").first - puts "[+] Possible match at offset #{off} (adjusted [ little-endian: #{mle} | big-endian: #{mbe} ] ) byte offset #{idx}" - found = true - end - end - end + off = Rex::Text.pattern_offset(buffer, nvi) + if off + mle = query - buffer[off, 4].unpack("V").first + mbe = query - buffer[off, 4].unpack("N").first + puts "[+] Possible match at offset #{off} (adjusted [ little-endian: #{mle} | big-endian: #{mbe} ] ) byte offset #{idx}" + found = true + end + end + end - exit! if found + exit! if found - # Look for 16-bit offsets - [0, 2].each do |idx| - 0.upto(65535) do |c| - nvb = [query].pack("V") - nvb[idx, 2] = [c].pack("v") - nvi = nvb.unpack("V").first + # Look for 16-bit offsets + [0, 2].each do |idx| + 0.upto(65535) do |c| + nvb = [query].pack("V") + nvb[idx, 2] = [c].pack("v") + nvi = nvb.unpack("V").first - off = Rex::Text.pattern_offset(buffer, nvi) - if off - mle = query - buffer[off,4].unpack("V").first - mbe = query - buffer[off,4].unpack("N").first - puts "[+] Possible match at offset #{off} (adjusted [ little-endian: #{mle} | big-endian: #{mbe} ] )" - found = true - end - end - end - end - - while offset - puts "[*] Exact match at offset #{offset}" - offset = Rex::Text.pattern_offset(buffer, query, offset + 1) + off = Rex::Text.pattern_offset(buffer, nvi) + if off + mle = query - buffer[off, 4].unpack("V").first + mbe = query - buffer[off, 4].unpack("N").first + puts "[+] Possible match at offset #{off} (adjusted [ little-endian: #{mle} | big-endian: #{mbe} ] )" + found = true + end + end + end end + while offset + puts "[*] Exact match at offset #{offset}" + offset = Rex::Text.pattern_offset(buffer, query, offset + 1) + end end end end @@ -140,7 +138,7 @@ if __FILE__ == $PROGRAM_NAME driver = PatternOffset::Driver.new begin driver.run - rescue ::Exception => e + rescue ::StandardError => e elog("#{e.class}: #{e.message}\n#{e.backtrace * "\n"}") $stderr.puts "[x] #{e.class}: #{e.message}" $stderr.puts "[*] If necessary, please refer to framework.log for more details."