Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 302 lines (253 sloc) 7.115 kb
#!/usr/bin/env ruby
# -*- coding: binary -*-
#
# $Id$
# $Revision$
#
msfbase = __FILE__
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')))
require 'fastlib'
require 'msfenv'
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
require 'metasm'
require 'rex/elfparsey'
require 'rex/elfscan'
require 'rex/machparsey'
require 'rex/machscan'
require 'rex/peparsey'
require 'rex/pescan'
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 = {}
files = []
mode = ""
opt.on('-j', '--jump [regA,regB,regC]', 'Search for jump equivalent instructions [PE|ELF|MACHO]') do |t|
# take csv of register names (like eax,ebx) and convert
# them to an array of register numbers
mode = "jump"
regnums = t.split(',').collect { |o|
begin
Rex::Arch::X86.reg_number(o)
rescue
puts "Invalid register \"#{o}\""
exit(1)
end
}
param['args'] = regnums
end
opt.on('-p', '--poppopret', 'Search for pop+pop+ret combinations [PE|ELF|MACHO]') do |t|
mode = "pop"
param['args'] = t
end
opt.on('-r', '--regex [regex]', 'Search for regex match [PE|ELF|MACHO]') do |t|
mode = "regex"
param['args'] = t
end
opt.on('-a', '--analyze-address [address]', 'Display the code at the specified address [PE|ELF]') do |t|
mode = "analyze-address"
param['args'] = opt2i(t)
end
opt.on('-b', '--analyze-offset [offset]', 'Display the code at the specified offset [PE|ELF]') do |t|
mode = "analyze-offset"
param['args'] = opt2i(t)
end
opt.on('-f', '--fingerprint', 'Attempt to identify the packer/compiler [PE]') do |t|
mode = "fingerprint"
param['database'] = File.join(File.dirname(msfbase), 'data', 'msfpescan', 'identify.txt')
end
opt.on('-i', '--info', 'Display detailed information about the image [PE]') do |t|
mode = "info"
end
opt.on('-R', '--ripper [directory]', 'Rip all module resources to disk [PE]') do |t|
mode = "ripper"
param['dir'] = t
end
opt.on('--context-map [directory]', 'Generate context-map files [PE]') do |t|
mode = "context"
param['dir'] = t
end
opt.separator('')
opt.separator('Options:')
opt.on('-A', '--after [bytes]', 'Number of bytes to show after match (-a/-b) [PE|ELF|MACHO]') do |t|
param['after'] = opt2i(t)
end
opt.on('-B', '--before [bytes]', 'Number of bytes to show before match (-a/-b) [PE|ELF|MACHO]') do |t|
param['before'] = opt2i(t)
end
opt.on('-I', '--image-base [address]', 'Specify an alternate ImageBase [PE|ELF|MACHO]') do |t|
param['imagebase'] = opt2i(t)
end
opt.on('-D', '--disasm', 'Disassemble the bytes at this address [PE]') do |t|
param['disasm'] = true
end
opt.on('-F', '--filter-addresses [regex]', 'Filter addresses based on a regular expression [PE]') do |t|
param['filteraddr'] = t
end
opt.on_tail("-h", "--help", "Show this message") do
$stderr.puts opt
exit(1)
end
begin
opt.parse!
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
$stderr.puts "Invalid option, try -h for usage"
exit(1)
end
if mode.empty?
$stderr.puts "A mode must be selected"
$stderr.puts opt
exit(1)
end
# check if the file is a directory if it is collect all the entries
ARGV.each do |file|
if(File.directory?(file))
dir = Dir.open(file)
dir.entries.each do |ent|
path = File.join(file, ent)
next if not File.file?(path)
files << File.join(path)
end
else
files << file
end
end
# we need to do some work to figure out the file format
files.each do |file|
param['file'] = file
bin = Metasm::AutoExe.decode_file(file) if not file.empty?
if bin.kind_of?(Metasm::PE)
case mode
when "jump"
worker = Rex::PeScan::Scanner::JmpRegScanner
when "pop"
worker = Rex::PeScan::Scanner::PopPopRetScanner
when "regex"
worker = Rex::PeScan::Scanner::RegexScanner
when "analyze-address"
worker = Rex::PeScan::Search::DumpRVA
when "analyze-offset"
worker = Rex::PeScan::Search::DumpOffset
when "fingerprint"
worker = Rex::PeScan::Analyze::Fingerprint
when "info"
worker = Rex::PeScan::Analyze::Information
when "ripper"
worker = Rex::PeScan::Analyze::Ripper
when "context"
worker = Rex::PeScan::Analyze::ContextMapDumper
else
$stderr.puts("Mode unsupported by file format")
end
pe_klass = Rex::PeParsey::Pe
begin
pe = pe_klass.new_from_file(file, true)
rescue ::Interrupt
raise $!
rescue Rex::PeParsey::FileHeaderError
next if $!.message == "Couldn't find the PE magic!"
raise $!
rescue Errno::ENOENT
$stdout.puts("File does not exist: #{file}")
next
rescue ::Rex::PeParsey::SkipError
next
rescue ::Exception => e
$stdout.puts "[#{file}] #{e.class}: #{e}"
next
end
if (param['imagebase'])
pe.image_base = param['imagebase'];
end
if not worker
$stderr.puts("A mode could not be set for this file.")
next
end
o = worker.new(pe)
o.scan(param)
pe.close
elsif bin.kind_of?(Metasm::ELF)
case mode
when "jump"
worker = Rex::ElfScan::Scanner::JmpRegScanner
when "pop"
worker = Rex::Elfscan::Scanner::PopPopRetScanner
when "regex"
worker = Rex::ElfScan::Scanner::RegexScanner
when "analyze-address"
worker = Rex::ElfScan::Search::DumpRVA
when "analyze-offset"
worker = Rex::ElfScan::Search::DumpOffset
else
$stderr.puts("Mode unsupported by file format")
end
begin
elf = Rex::ElfParsey::Elf.new_from_file(file, true)
rescue Rex::ElfParsey::ElfHeaderError
if $!.message == 'Invalid magic number'
$stderr.puts("Skipping #{file}: #{$!}")
next
end
raise $!
rescue Errno::ENOENT
$stderr.puts("File does not exist: #{file}")
next
end
if (param['imagebase'])
elf.base_addr = param['imagebase'];
end
if not worker
$stderr.puts("A mode could not be set for this file.")
next
end
o = worker.new(elf)
o.scan(param)
elf.close
elsif bin.kind_of?(Metasm::MachO)
case mode
when "jump"
worker = Rex::MachScan::Scanner::JmpRegScanner
when "pop"
worker = Rex::MachScan::Scanner::PopPopRetScanner
when "regex"
worker = Rex::MachScan::Scanner::RegexScanner
else
$stderr.puts("Mode unsupported by file format")
end
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")
begin
fat = Rex::MachParsey::Fat.new_from_file(file, true)
o = worker.new(fat)
o.scan(param)
fat.close
rescue
$stderr.puts("Error: " + $!.to_s)
$stderr.puts("Skipping #{file}")
end
rescue Errno::ENOENT
$stderr.puts("File does not exist: #{file}")
next
end
end
if not worker
$stderr.puts("Unsupported file format")
$stderr.puts("Skipping #{file}")
next
end
end
Jump to Line
Something went wrong with that request. Please try again.