Class: Rex::PeParsey::Pe

Inherits:
PeBase
  • Object
show all
Defined in:
lib/rex/peparsey/pe.rb

Direct Known Subclasses

PeMemDump

Constant Summary

Constants inherited from PeBase

Rex::PeParsey::PeBase::IMAGE_BASE_RELOCATION, Rex::PeParsey::PeBase::IMAGE_BASE_RELOCATION_TYPE_OFFSET, Rex::PeParsey::PeBase::IMAGE_DATA_DIRECTORY, Rex::PeParsey::PeBase::IMAGE_DATA_DIRECTORY_SIZE, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_ARCHITECTURE, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_BASERELOC, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_COPYRIGHT, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_DEBUG, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_EXCEPTION, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_EXPORT, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_GLOBALPTR, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_IAT, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_IMPORT, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_RESOURCE, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_SECURITY, Rex::PeParsey::PeBase::IMAGE_DIRECTORY_ENTRY_TLS, Rex::PeParsey::PeBase::IMAGE_DOS_HEADER, Rex::PeParsey::PeBase::IMAGE_DOS_HEADER_SIZE, Rex::PeParsey::PeBase::IMAGE_DOS_SIGNATURE, Rex::PeParsey::PeBase::IMAGE_EXPORT_DESCRIPTOR, Rex::PeParsey::PeBase::IMAGE_EXPORT_DESCRIPTOR_SIZE, Rex::PeParsey::PeBase::IMAGE_FILE_HEADER, Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE, Rex::PeParsey::PeBase::IMAGE_FILE_MACHINE_ALPHA64, Rex::PeParsey::PeBase::IMAGE_FILE_MACHINE_AMD64, Rex::PeParsey::PeBase::IMAGE_FILE_MACHINE_I386, Rex::PeParsey::PeBase::IMAGE_FILE_MACHINE_IA64, Rex::PeParsey::PeBase::IMAGE_IMPORT_DESCRIPTOR, Rex::PeParsey::PeBase::IMAGE_IMPORT_DESCRIPTOR_SIZE, Rex::PeParsey::PeBase::IMAGE_LOAD_CONFIG_DIRECTORY32, Rex::PeParsey::PeBase::IMAGE_LOAD_CONFIG_DIRECTORY64, Rex::PeParsey::PeBase::IMAGE_LOAD_TLS_DIRECTORY32, Rex::PeParsey::PeBase::IMAGE_LOAD_TLS_DIRECTORY64, Rex::PeParsey::PeBase::IMAGE_NT_OPTIONAL_HDR32_MAGIC, Rex::PeParsey::PeBase::IMAGE_NT_OPTIONAL_HDR64_MAGIC, Rex::PeParsey::PeBase::IMAGE_NT_SIGNATURE, Rex::PeParsey::PeBase::IMAGE_NUMBEROF_DIRECTORY_ENTRIES, Rex::PeParsey::PeBase::IMAGE_OPTIONAL_HEADER32, Rex::PeParsey::PeBase::IMAGE_OPTIONAL_HEADER64, Rex::PeParsey::PeBase::IMAGE_ORDINAL_FLAG32, Rex::PeParsey::PeBase::IMAGE_RUNTIME_FUNCTION_ENTRY, Rex::PeParsey::PeBase::IMAGE_RUNTIME_FUNCTION_ENTRY_SZ, Rex::PeParsey::PeBase::IMAGE_SECTION_HEADER, Rex::PeParsey::PeBase::IMAGE_SIZEOF_BASE_RELOCATION, Rex::PeParsey::PeBase::IMAGE_SIZEOF_NT_OPTIONAL32_HEADER, Rex::PeParsey::PeBase::IMAGE_SIZEOF_NT_OPTIONAL64_HEADER, Rex::PeParsey::PeBase::IMAGE_SIZEOF_SECTION_HEADER, Rex::PeParsey::PeBase::SUPPORTED_MACHINES, Rex::PeParsey::PeBase::UNWIND_INFO_HEADER, Rex::PeParsey::PeBase::UNWIND_INFO_HEADER_SZ, Rex::PeParsey::PeBase::UNW_FLAG_CHAININFO, Rex::PeParsey::PeBase::UNW_FLAG_EHANDLER, Rex::PeParsey::PeBase::UNW_FLAG_UHANDLER, Rex::PeParsey::PeBase::UWOP_ALLOC_LARGE, Rex::PeParsey::PeBase::UWOP_ALLOC_SMALL, Rex::PeParsey::PeBase::UWOP_PUSH_MACHFRAME, Rex::PeParsey::PeBase::UWOP_PUSH_NONVOL, Rex::PeParsey::PeBase::UWOP_SAVE_NONVOL, Rex::PeParsey::PeBase::UWOP_SAVE_NONVOL_FAR, Rex::PeParsey::PeBase::UWOP_SAVE_XMM128, Rex::PeParsey::PeBase::UWOP_SAVE_XMM128_FAR, Rex::PeParsey::PeBase::UWOP_SET_FPREG

Instance Attribute Summary

Attributes inherited from PeBase

#_config_header, #_dos_header, #_exception_header, #_exports_cache, #_exports_cached, #_file_header, #_imports_cache, #_imports_cached, #_isource, #_optional_header, #_relocations_cache, #_relocations_cached, #_resources_cache, #_resources_cached, #_section_headers, #_tls_header, #hdr, #header_section, #image_base, #sections

Instance Method Summary collapse

Methods inherited from PeBase

_align_offset, #_find_section_by_rva, #_load_exception_directory, #_load_exports, #_load_imports, #_load_relocations, #_load_resources, #_parse_config_header, _parse_dos_header, _parse_file_header, _parse_optional_header, #_parse_resource_directory, #_parse_resource_entry, #_parse_resource_name, _parse_section_headers, #_parse_tls_header, #_resource_lookup, #close, #config, #exception, #exports, #file_offset_to_rva, #file_offset_to_vma, #find_section_by_rva, #find_section_by_vma, #imports, new_from_file, new_from_string, #read_asciiz_rva, #read_asciiz_vma, #read_rva, #read_vma, #relocations, #resources, #rva_to_file_offset, #rva_to_vma, #tls, #update_checksum, #valid_rva?, #valid_vma?, #vma_to_file_offset, #vma_to_rva

Constructor Details

#initialize(isource) ⇒ Pe


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
58
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
111
112
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
139
140
141
142
143
144
145
146
147
# File 'lib/rex/peparsey/pe.rb', line 13

def initialize(isource)

  #
  # DOS Header
  #
  # Parse the initial dos header, starting at the file beginning
  #
  offset = 0
  dos_header = self.class._parse_dos_header(isource.read(offset, IMAGE_DOS_HEADER_SIZE))

  #
  # File Header
  #
  # If there is going to be a PE, the dos header tells us where to find it
  # So now we try to parse the file (pe) header
  #
  offset += dos_header.e_lfanew

  # most likely an invalid e_lfanew...
  if offset > isource.size
    raise FileHeaderError, "e_lfanew looks invalid", caller
  end

  file_header = self.class._parse_file_header(isource.read(offset, IMAGE_FILE_HEADER_SIZE))

  #
  # Optional Header
  #
  # After the file header, we find the optional header.  Right now
  # we require a optional header.  Despite it's name, all binaries
  # that we are interested in should have one.  We need this
  # header for a lot of stuff, so we die without it...
  #
  offset += IMAGE_FILE_HEADER_SIZE
  optional_header = self.class._parse_optional_header(
    isource.read(offset, file_header.SizeOfOptionalHeader)
  )

  if !optional_header
    raise OptionalHeaderError, "No optional header!", caller
  end

  base = optional_header.ImageBase

  #
  # Section Headers
  #
  # After the optional header should be the section headers.
  # We know how many there should be from the file header...
  #
  offset += file_header.SizeOfOptionalHeader

  num_sections = file_header.NumberOfSections
  section_headers = self.class._parse_section_headers(
    isource.read(offset, IMAGE_SIZEOF_SECTION_HEADER * num_sections)
  )

  #
  # End of Headers
  #
  # After the section headers (which are padded to FileAlignment)
  # we should find the section data, described by the section
  # headers...
  #
  # So this is the end of our header data, lets store this
  # in an image source for possible access later...
  #
  offset += IMAGE_SIZEOF_SECTION_HEADER * num_sections
  offset = self.class._align_offset(offset, optional_header.FileAlignment)

  header_section = Section.new(isource.subsource(0, offset), 0, nil)

  #
  # Sections
  #
  # So from here on out should be section data, and then any
  # trailing data (like authenticode and stuff I think)
  #

  sections = [ ]

  section_headers.each do |section_header|

    rva         = section_header.VirtualAddress
    size        = section_header.SizeOfRawData
    file_offset = section_header.PointerToRawData

    sections << Section.new(
      isource.subsource(file_offset, size),
      rva,
      section_header
    )
  end



  #
  # Save the stuffs!
  #
  # We have parsed enough to load the file up here, now we just
  # save off all of the structures and data... We will
  # save our fake header section, the real sections, etc.
  #

  #
  # These should not be accessed directly
  #

  self._isource          = isource

  self._dos_header       = dos_header
  self._file_header      = file_header
  self._optional_header  = optional_header
  self._section_headers  = section_headers

  self.image_base        = base
  self.sections          = sections
  self.header_section    = header_section

  self._config_header    = _parse_config_header()
  self._tls_header       = _parse_tls_header()

  # These can be accessed directly
  self.hdr               = HeaderAccessor.new
  self.hdr.dos           = self._dos_header
  self.hdr.file          = self._file_header
  self.hdr.opt           = self._optional_header
  self.hdr.sections      = self._section_headers
  self.hdr.config        = self._config_header
  self.hdr.tls           = self._tls_header
  self.hdr.exceptions    = self._exception_header

  # We load the exception directory last as it relies on hdr.file to be created above.
  self._exception_header = _load_exception_directory()
end

Instance Method Details

#all_sectionsObject

Return everything that's going to be mapped in the process and accessable. This should include all of the sections and our “fake” section for the header data…


154
155
156
# File 'lib/rex/peparsey/pe.rb', line 154

def all_sections
  [ header_section ] + sections
end

#file_offset_to_va(offset) ⇒ Object

Converts a file offset into a virtual address


188
189
190
# File 'lib/rex/peparsey/pe.rb', line 188

def file_offset_to_va(offset)
  image_base + file_offset_to_rva(offset)
end

#lengthObject


206
207
208
# File 'lib/rex/peparsey/pe.rb', line 206

def length
  _isource.size
end

#ptr_32?Boolean

Returns true if this binary is for a 32-bit architecture. This check does not take into account 16-bit binaries at the moment.


173
174
175
# File 'lib/rex/peparsey/pe.rb', line 173

def ptr_32?
  ptr_64? == false
end

#ptr_64?Boolean

Returns true if this binary is for a 64-bit architecture.


161
162
163
164
165
166
167
# File 'lib/rex/peparsey/pe.rb', line 161

def ptr_64?
  [
    IMAGE_FILE_MACHINE_IA64,
    IMAGE_FILE_MACHINE_ALPHA64,
    IMAGE_FILE_MACHINE_AMD64
  ].include?(self._file_header.Machine)
end

#ptr_s(va) ⇒ Object

Converts a virtual address to a string representation based on the underlying architecture.


181
182
183
# File 'lib/rex/peparsey/pe.rb', line 181

def ptr_s(va)
  (ptr_32?) ? ("0x%.8x" % va) : ("0x%.16x" % va)
end

#read(offset, len) ⇒ Object

Read raw bytes from the specified offset in the underlying file

NOTE: You should pass raw file offsets into this, not offsets from the beginning of the section. If you need to read from within a section, add section.file_offset prior to passing the offset in.


199
200
201
# File 'lib/rex/peparsey/pe.rb', line 199

def read(offset, len)
  _isource.read(offset, len)
end

#sizeObject


203
204
205
# File 'lib/rex/peparsey/pe.rb', line 203

def size
  _isource.size
end