Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/tools/exploit/find_badchars.rb
Views: 11766
#!/usr/bin/env ruby12##3# This module requires Metasploit: https://metasploit.com/download4# Current source: https://github.com/rapid7/metasploit-framework5##67#8# This script is intended to assist an exploit developer in deducing what9# "bad characters" exist for a given input path to a program.10#11begin12msfbase = __FILE__13while File.symlink?(msfbase)14msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))15end1617gem 'rex-text'1819$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib')))20require 'msfenv'2122$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']23require 'rex'2425OutStatus = "[*] "26OutError = "[-] "2728$args = Rex::Parser::Arguments.new(29"-b" => [ true, "The list of characters to avoid: '\\x00\\xff'" ],30"-h" => [ false, "Help banner" ],31"-i" => [ true, "Read memory contents from the supplied file path" ],32"-t" => [ true, "The format that the memory contents are in (empty to list)" ])3334def usage35$stderr.puts("\n" + " Usage: #{File.basename($0)} <options>\n" + $args.usage)36exit37end3839def show_format_list40$stderr.puts("Supported formats:\n")41$stderr.puts(" raw raw binary data\n")42$stderr.puts(" windbg output from windbg's \"db\" command\n")43$stderr.puts(" gdb output from gdb's \"x/bx\" command\n")44$stderr.puts(" hex hex bytes like \"\\xFF\\x41\" or \"eb fe\"\n")45end4647def debug_buffer(name, buf)48str = "\n#{buf.length} bytes of "49str << name50str += ":" if buf.length > 051str += "\n\n"52$stderr.puts str53if buf.length > 054$stderr.puts Rex::Text.to_hex_dump(buf)55end56end575859# Input defaults60badchars = ''61fmt = 'raw'62input = $stdin6364# Output65new_badchars = ''6667# Parse the argument and rock it68$args.parse(ARGV) { |opt, idx, val|69case opt70when "-i"71begin72input = File.new(val)73rescue74$stderr.puts(OutError + "Failed to open file #{val}: #{$!}")75exit76end77when "-b"78badchars = Rex::Text.dehex(val)79when "-t"80if (val =~ /^(raw|windbg|gdb|hex)$/)81fmt = val82else83if val.nil? or val.length < 184show_format_list85else86$stderr.puts(OutError + "Invalid format: #{val}")87end88exit89end90when "-h"91usage92end93}9495if input == $stdin96$stderr.puts(OutStatus + "Please paste the memory contents in \"" + fmt + "\" format below (end with EOF):\n")97end9899100101# Working data set102from_msf = Rex::Text.charset_exclude(badchars)103from_dbg = ''104105106# Process the input107from_dbg = input.read108case fmt109when "raw"110# this should already be in the correct format :)111112when "windbg"113translated = ''114from_dbg.each_line do |ln|115translated << ln.chomp[10,47].gsub!(/(-| )/, '')116end117from_dbg = Rex::Text.hex_to_raw(translated)118119when "gdb"120translated = ''121from_dbg.each_line do |ln|122translated << ln.chomp.split(':')[1].gsub!(/0x/, '\x').gsub!(/ /, '')123end124from_dbg = Rex::Text.hex_to_raw(translated)125126when "hex"127translated = ''128from_dbg.each_line do |ln|129translated << ln.chomp.gsub!(/ /,'')130end131from_dbg = Rex::Text.hex_to_raw(translated)132end133134135136=begin137# Uncomment these to debug stuff ..138debug_buffer("BadChars", badchars)139debug_buffer("memory contents", from_dbg)140debug_buffer("Rex::Text.charset_exclude() output", from_msf)141=end142143144# Find differences between the two data sets145from_msf = from_msf.unpack('C*')146from_dbg = from_dbg.unpack('C*')147minlen = from_msf.length148minlen = from_dbg.length if from_dbg.length < minlen149(0..(minlen-1)).each do |idx|150ch1 = from_msf[idx]151ch2 = from_dbg[idx]152if ch1 != ch2153str = "Byte at index 0x%04x differs (0x%02x became 0x%02x)" % [idx, ch1, ch2]154$stderr.puts OutStatus + str155new_badchars << ch1156end157end158159160# show the results161if new_badchars.length < 1162$stderr.puts(OutStatus + "All characters matched, no new bad characters discovered.")163else164$stderr.puts(OutStatus + "Proposed BadChars: \"" + Rex::Text.to_hex(new_badchars) + "\"")165end166rescue SignalException => e167puts("Aborted! #{e}")168end169170171