Class: PEdump::PE

Inherits:
Struct show all
Defined in:
lib/pedump/pe.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#image_file_headerObject Also known as: ifh

Returns the value of attribute image_file_header

Returns:

  • (Object)

    the current value of image_file_header



4
5
6
# File 'lib/pedump/pe.rb', line 4

def image_file_header
  @image_file_header
end

#image_optional_headerObject Also known as: ioh

Returns the value of attribute image_optional_header

Returns:

  • (Object)

    the current value of image_optional_header



4
5
6
# File 'lib/pedump/pe.rb', line 4

def image_optional_header
  @image_optional_header
end

#ioh_offsetObject

Returns the value of attribute ioh_offset.



10
11
12
# File 'lib/pedump/pe.rb', line 10

def ioh_offset
  @ioh_offset
end

#section_tableObject Also known as: sections

Returns the value of attribute section_table

Returns:

  • (Object)

    the current value of section_table



4
5
6
# File 'lib/pedump/pe.rb', line 4

def section_table
  @section_table
end

#signatureObject

Returns the value of attribute signature

Returns:

  • (Object)

    the current value of signature



4
5
6
# File 'lib/pedump/pe.rb', line 4

def signature
  @signature
end

Class Method Details

.loggerObject



112
# File 'lib/pedump/pe.rb', line 112

def self.logger; PEdump.logger; end

.read(f, args = {}) ⇒ Object



59
60
61
62
63
64
65
66
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# 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 = {}) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 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

Instance Method Details

#dll?Boolean

Returns:

  • (Boolean)


21
22
23
# File 'lib/pedump/pe.rb', line 21

def dll?
  ifh && ifh.flags.include?('DLL')
end

#packObject



25
26
27
# File 'lib/pedump/pe.rb', line 25

def pack
  signature + ifh.pack + ioh.pack
end

#x64?Boolean

Returns:

  • (Boolean)


18
19
20
# File 'lib/pedump/pe.rb', line 18

def x64?
  ifh && ifh.Machine == 0x8664
end