2008-10-10 04:22:20 +02:00
|
|
|
#!/usr/bin/env ruby
|
2010-05-03 19:13:09 +02:00
|
|
|
#
|
|
|
|
# $Id$
|
|
|
|
# $Revision$
|
|
|
|
#
|
2008-10-10 04:22:20 +02:00
|
|
|
|
2009-01-30 07:27:10 +01:00
|
|
|
msfbase = __FILE__
|
|
|
|
while File.symlink?(msfbase)
|
|
|
|
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
|
|
|
|
end
|
|
|
|
|
2008-10-10 04:22:20 +02:00
|
|
|
$:.unshift(File.join(File.dirname(msfbase), 'lib'))
|
2009-01-10 14:55:03 +01:00
|
|
|
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
|
2008-10-10 04:22:20 +02:00
|
|
|
|
|
|
|
require 'rex/machparsey'
|
|
|
|
require 'rex/machscan'
|
|
|
|
require 'rex/arch/x86'
|
|
|
|
require 'optparse'
|
|
|
|
|
|
|
|
|
|
|
|
def opt2i(o)
|
|
|
|
o.index("0x")==0 ? o.hex : o.to_i
|
|
|
|
end
|
|
|
|
|
|
|
|
opt = OptionParser.new
|
|
|
|
|
|
|
|
opt.banner = "Usage: #{$PROGRAM_NAME} [mode] <options> [targets]"
|
|
|
|
opt.separator('')
|
|
|
|
opt.separator('Modes:')
|
|
|
|
|
|
|
|
worker = nil
|
|
|
|
param = {}
|
|
|
|
|
|
|
|
opt.on('-j', '--jump [regA,regB,regC]', 'Search for jump equivalent instructions') do |t|
|
|
|
|
# take csv of register names (like eax,ebx) and convert
|
|
|
|
# them to an array of register numbers
|
2010-04-16 01:21:23 +02:00
|
|
|
regnums = t.split(',').collect { |o|
|
|
|
|
begin
|
|
|
|
Rex::Arch::X86.reg_number(o)
|
|
|
|
rescue
|
|
|
|
puts "Invalid register \"#{o}\""
|
|
|
|
exit(1)
|
|
|
|
end
|
|
|
|
}
|
2008-10-10 04:22:20 +02:00
|
|
|
worker = Rex::MachScan::Scanner::JmpRegScanner
|
|
|
|
param['args'] = regnums
|
|
|
|
end
|
|
|
|
|
|
|
|
opt.on('-p', '--poppopret', 'Search for pop+pop+ret combinations') do |t|
|
|
|
|
worker = Rex::MachScan::Scanner::PopPopRetScanner
|
|
|
|
param['args'] = t
|
|
|
|
end
|
|
|
|
|
|
|
|
opt.on('-r', '--regex [regex]', 'Search for regex match') do |t|
|
|
|
|
worker = Rex::MachScan::Scanner::RegexScanner
|
|
|
|
param['args'] = t
|
|
|
|
end
|
|
|
|
|
|
|
|
opt.separator('')
|
|
|
|
opt.separator('Options:')
|
|
|
|
|
|
|
|
opt.on('-A', '--after [bytes]', 'Number of bytes to show after match (-a/-b)') do |t|
|
|
|
|
param['after'] = opt2i(t)
|
|
|
|
end
|
|
|
|
|
|
|
|
opt.on('-B', '--before [bytes]', 'Number of bytes to show before match (-a/-b)') do |t|
|
|
|
|
param['before'] = opt2i(t)
|
|
|
|
end
|
|
|
|
|
|
|
|
opt.on('-I', '--image-base [address]', 'Specify an alternate ImageBase') do |t|
|
|
|
|
param['imagebase'] = opt2i(t)
|
|
|
|
end
|
|
|
|
|
|
|
|
opt.on_tail("-h", "--help", "Show this message") do
|
|
|
|
puts opt
|
2010-04-16 01:21:23 +02:00
|
|
|
exit(1)
|
2008-10-10 04:22:20 +02:00
|
|
|
end
|
|
|
|
|
2009-11-30 00:47:03 +01:00
|
|
|
begin
|
|
|
|
opt.parse!
|
|
|
|
rescue OptionParser::InvalidOption
|
|
|
|
puts "Invalid option, try -h for usage"
|
2010-04-16 01:21:23 +02:00
|
|
|
exit(1)
|
2009-11-30 00:47:03 +01:00
|
|
|
end
|
2008-10-10 04:22:20 +02:00
|
|
|
|
|
|
|
if (! worker)
|
|
|
|
puts opt
|
2010-04-16 01:21:23 +02:00
|
|
|
exit(1)
|
2008-10-10 04:22:20 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
ARGV.each do |file|
|
|
|
|
|
|
|
|
param['file'] = file
|
|
|
|
|
|
|
|
begin
|
|
|
|
mach = Rex::MachParsey::Mach.new_from_file(file, true)
|
|
|
|
o = worker.new(mach)
|
|
|
|
o.scan(param)
|
|
|
|
mach.close
|
|
|
|
rescue Rex::MachParsey::MachHeaderError
|
|
|
|
$stderr.puts("File is not a Mach-O binary, trying Fat..\n")
|
|
|
|
fat = Rex::MachParsey::Fat.new_from_file(file, true)
|
|
|
|
o = worker.new(fat)
|
|
|
|
o.scan(param)
|
|
|
|
fat.close
|
|
|
|
rescue Errno::ENOENT
|
|
|
|
$stderr.puts("File does not exist: #{file}")
|
|
|
|
next
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|