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
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