class PEdump::Packer

Constants

BIN_SIGS_FILE
BLOCK_SIZE
DATA_ROOT

Public Class Methods

all() click to toggle source
# File lib/pedump/packer.rb, line 23
def all
  @@all ||=
    begin
      r = unmarshal
      unless r
        msg = "[?] #{self}: unmarshal failed, using slow text parsing instead"
        if PEdump.respond_to?(:logger) && PEdump.logger
          PEdump.logger.warn msg
        else
          STDERR.puts msg
        end
        r = SigParser.parse
      end
      r
    end
end
Also aliased as: load
default_deep() click to toggle source
# File lib/pedump/packer.rb, line 44
def default_deep
  @@deep
end
default_deep=(value) click to toggle source
# File lib/pedump/packer.rb, line 48
def default_deep= value
  @@deep = value
end
load()
Alias for: all
max_size() click to toggle source
# File lib/pedump/packer.rb, line 52
def max_size
  @@max_size ||= all.map(&:size).max
end
method_missing(*args, &block) click to toggle source
Calls superclass method
# File lib/pedump/packer.rb, line 159
def method_missing *args, &block
  all.respond_to?(args.first) ? all.send(*args,&block) : super
end
of(data, h = {}) click to toggle source
# File lib/pedump/packer.rb, line 56
def of data, h = {}
  if data.respond_to?(:read) && data.respond_to?(:seek) && h[:pedump]
    of_pedump data, h
  elsif data.respond_to?(:read) && data.respond_to?(:seek) && h[:ep_offset]
    of_pe_file data, h
  else
    of_data data
  end
end
of_data(data) click to toggle source
# File lib/pedump/packer.rb, line 148
def of_data data
  r = []
  return r unless data
  each do |packer|
    if (idx=data.index(packer.re)) == 0
      r << Match.new(idx, packer)
    end
  end
  r.any? ? r.sort_by{ |x| -x.packer.size } : nil
end
of_pe_file(f, h) click to toggle source

try to determine packer of FILE f, ep_offset - offset to entrypoint from start of file

# File lib/pedump/packer.rb, line 97
def of_pe_file f, h
  h[:deep] = @@deep unless h.key?(:deep)
  h[:deep] = 1 if h[:deep] == true
  h[:deep] = 0 if h[:deep] == false

  begin
    f.seek(h[:ep_offset])             # offset of PE EntryPoint from start of file
  rescue
    if h[:pedump] && h[:pedump].logger
      h[:pedump].logger.warn "[?] failed to seek to EP at #{h[:ep_offset]}, skipping packer detect"
    end
    return
  end

  r = Array(of_data(f.read(max_size)))
  return r if r && r.any? && h[:deep] < 2
  r += scan_whole_file(f,
                       :limit => (h[:deep] > 0 ? nil : 1048576),
                       :deep  => h[:deep]
                      ) # scan only 1st mb unless :deep
end
of_pedump(f, h) click to toggle source

try to determine packer of FILE f, h is a PEdump instance

# File lib/pedump/packer.rb, line 67
def of_pedump f, h
  pedump = h[:pedump]
  pe = pedump.pe
  if !(va=pe.ioh.AddressOfEntryPoint)
    pedump.logger.error "[?] can't find EntryPoint RVA"
    nil
  elsif va == 0 && pe.dll?
    pedump.logger.debug "[.] it's a DLL with no EntryPoint"
    nil
  elsif !(ofs = pedump.va2file(va))
    pedump.logger.error "[?] can't find EntryPoint RVA (0x#{va.to_s(16)}) file offset"
    nil
  else
    r = of_pe_file(f, h.merge({:ep_offset => ofs}))
    return r if r && r.any?

    # nothing found, try to guess by pe section names
    if pedump.sections
      if pedump.sections.any?{ |s| s.Name.to_s =~ /upx/i }
        return [Guess.new('UPX?')]
      end
      if pedump.sections.any?{ |s| s.Name.to_s =~ /aspack/i }
        return [Guess.new('ASPack?')]
      end
    end
    nil
  end
end
scan_whole_file(f, h = {}) click to toggle source
# File lib/pedump/packer.rb, line 121
def scan_whole_file f, h = {}
  h[:limit] ||= f.size
  f.seek( pos = 0 )
  buf = ''.force_encoding('binary')
  sigs =
    if h[:deep].is_a?(Numeric) && h[:deep] > 1
      self.all
    else
      self.find_all{ |sig| !sig.ep_only }
    end
  r = []
  while true
    f.read BLOCK_SIZE, buf
    pos += buf.size
    sigs.each do |sig|
      if idx = buf.index(sig.re)
        r << Match.new(f.tell-buf.size+idx, sig)
      end
    end
    break if f.eof? || pos >= h[:limit]
    # overlap the read for the case when read buffer boundary breaks signature
    f.seek -max_size-2, IO::SEEK_CUR
    pos -= (max_size+2)
  end
  r
end
unmarshal() click to toggle source
# File lib/pedump/packer.rb, line 163
def unmarshal
  File.open(BIN_SIGS_FILE,"rb") do |f|
    Marshal.load(f)
  end
rescue
  nil
end