class PEdump::PE
Attributes
ioh_offset[RW]
Public Class Methods
logger()
click to toggle source
# File lib/pedump/pe.rb, line 112 def self.logger; PEdump.logger; end
read(f, args = {})
click to toggle source
# File lib/pedump/pe.rb, line 59 def self.read f, args = {} pe_offset = f.tell pe_sig = f.read 4 #logger.error "[!] 'NE' format is not supported!" if pe_sig == "NE\x00\x00" if pe_sig != "PE\x00\x00" if args[:force] logger.warn "[?] no PE signature (want: 'PE\\x00\\x00', got: #{pe_sig.inspect})" else logger.debug "[?] no PE signature (want: 'PE\\x00\\x00', got: #{pe_sig.inspect}). (not forced)" return nil end end pe = PE.new(pe_sig) pe.image_file_header = IMAGE_FILE_HEADER.read(f) pe.ioh_offset = f.tell # offset to IMAGE_OPTIONAL_HEADER if pe.ifh.SizeOfOptionalHeader.to_i > 0 if pe.x64? pe.image_optional_header = IMAGE_OPTIONAL_HEADER64.read(f, pe.ifh.SizeOfOptionalHeader) else pe.image_optional_header = IMAGE_OPTIONAL_HEADER32.read(f, pe.ifh.SizeOfOptionalHeader) end end nToRead=pe.ifh.NumberOfSections.to_i # The Windows loader expects to find the PE section headers after the optional header. It calculates the address of the first section header by adding SizeOfOptionalHeader to the beginning of the optional header. # // http://www.phreedom.org/research/tinype/ f.seek( pe.ioh_offset + pe.ifh.SizeOfOptionalHeader.to_i ) pe.sections = read_sections(f, nToRead, args) pe_end = f.tell if s=pe.sections.find{ |s| (pe_offset...pe_end).include?(s.va) } if args[:pass2] # already called with CompositeIO ? PEdump.logger.error "[!] section with va=0x#{s.va.to_s(16)} overwrites PE header! 2nd time?!" elsif pe_end-pe_offset < 0x100_000 PEdump.logger.warn "[!] section with va=0x#{s.va.to_s(16)} overwrites PE header! trying to rebuild..." f.seek pe_offset data = f.read(s.va-pe_offset) f.seek s.PointerToRawData io = CompositeIO.new(StringIO.new(data), f) args1 = args.dup args1[:pass2] = true return PE.read(io, args1) else PEdump.logger.error "[!] section with va=0x#{s.va.to_s(16)} overwrites PE header! too big to rebuild!" end end pe end
read_sections(f, nToRead, args = {})
click to toggle source
# File lib/pedump/pe.rb, line 29 def self.read_sections f, nToRead, args = {} force = args[:force] if nToRead > 0xffff if force.is_a?(Numeric) && force > 1 PEdump.logger.warn "[!] too many sections (#{nToRead}). forced. reading all" else PEdump.logger.warn "[!] too many sections (#{nToRead}). not forced, reading first 65535" nToRead = 65535 end end sections = [] nToRead.times do break if f.eof? sections << IMAGE_SECTION_HEADER.read(f) end if sections.any? # zero all missing values of last section sections.last.tap do |last_section| last_section.each_pair do |k,v| last_section[k] = 0 if v.nil? end end end sections end
Public Instance Methods
dll?()
click to toggle source
# File lib/pedump/pe.rb, line 21 def dll? ifh && ifh.flags.include?('DLL') end
pack()
click to toggle source
# File lib/pedump/pe.rb, line 25 def pack signature + ifh.pack + ioh.pack end
x64?()
click to toggle source
# File lib/pedump/pe.rb, line 18 def x64? ifh && ifh.Machine == 0x8664 end