Class: PEdump::Packer
Defined Under Namespace
Constant Summary collapse
- DATA_ROOT =
File.dirname(File.dirname(File.dirname(__FILE__)))
- BIN_SIGS_FILE =
File.join(DATA_ROOT, "data", "sig.bin")
- BLOCK_SIZE =
0x10000- @@deep =
default deep-scan flag
false
Instance Attribute Summary collapse
-
#ep_only ⇒ Object
Returns the value of attribute ep_only.
-
#name ⇒ Object
Returns the value of attribute name.
-
#re ⇒ Object
Returns the value of attribute re.
-
#size ⇒ Object
Returns the value of attribute size.
Class Method Summary collapse
- .all ⇒ Object (also: load)
- .default_deep ⇒ Object
- .default_deep=(value) ⇒ Object
- .max_size ⇒ Object
- .method_missing(*args, &block) ⇒ Object
- .of(data, h = {}) ⇒ Object
- .of_data(data) ⇒ Object
-
.of_pe_file(f, h) ⇒ Object
try to determine packer of FILE f, ep_offset - offset to entrypoint from start of file.
-
.of_pedump(f, h) ⇒ Object
try to determine packer of FILE f, h is a PEdump instance.
- .scan_whole_file(f, h = {}) ⇒ Object
- .unmarshal ⇒ Object
Instance Attribute Details
#ep_only ⇒ Object
Returns the value of attribute ep_only
4 5 6 |
# File 'lib/pedump/packer.rb', line 4 def ep_only @ep_only end |
#name ⇒ Object
Returns the value of attribute name
4 5 6 |
# File 'lib/pedump/packer.rb', line 4 def name @name end |
#re ⇒ Object
Returns the value of attribute re
4 5 6 |
# File 'lib/pedump/packer.rb', line 4 def re @re end |
#size ⇒ Object
Returns the value of attribute size
4 5 6 |
# File 'lib/pedump/packer.rb', line 4 def size @size end |
Class Method Details
.all ⇒ Object Also known as: load
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# 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 |
.default_deep ⇒ Object
44 45 46 |
# File 'lib/pedump/packer.rb', line 44 def default_deep @@deep end |
.default_deep=(value) ⇒ Object
48 49 50 |
# File 'lib/pedump/packer.rb', line 48 def default_deep= value @@deep = value end |
.max_size ⇒ Object
52 53 54 |
# File 'lib/pedump/packer.rb', line 52 def max_size @@max_size ||= all.map(&:size).max end |
.method_missing(*args, &block) ⇒ Object
151 152 153 |
# File 'lib/pedump/packer.rb', line 151 def method_missing *args, &block all.respond_to?(args.first) ? all.send(*args,&block) : super end |
.of(data, h = {}) ⇒ Object
56 57 58 59 60 61 62 63 64 |
# 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) ⇒ Object
140 141 142 143 144 145 146 147 148 149 |
# File 'lib/pedump/packer.rb', line 140 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) ⇒ Object
try to determine packer of FILE f, ep_offset - offset to entrypoint from start of file
97 98 99 100 101 102 103 104 105 106 107 108 109 |
# 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 f.seek(h[:ep_offset]) # offset of PE EntryPoint from start of file 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) ⇒ Object
try to determine packer of FILE f, h is a PEdump instance
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# 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 = {}) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/pedump/packer.rb', line 113 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 ⇒ Object
155 156 157 158 159 160 161 |
# File 'lib/pedump/packer.rb', line 155 def unmarshal File.open(BIN_SIGS_FILE,"rb") do |f| Marshal.load(f) end rescue nil end |