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

Returns a new instance of Pe.



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
148
149
# File 'lib/rex/peparsey/pe.rb', line 15

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…



156
157
158
# File 'lib/rex/peparsey/pe.rb', line 156

def all_sections
	[ header_section ] + sections
end

#file_offset_to_va(offset) ⇒ Object

Converts a file offset into a virtual address



190
191
192
# File 'lib/rex/peparsey/pe.rb', line 190

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

#lengthObject



208
209
210
# File 'lib/rex/peparsey/pe.rb', line 208

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.

Returns:

  • (Boolean)


175
176
177
# File 'lib/rex/peparsey/pe.rb', line 175

def ptr_32?
	ptr_64? == false
end

#ptr_64?Boolean

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

Returns:

  • (Boolean)


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

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.



183
184
185
# File 'lib/rex/peparsey/pe.rb', line 183

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.



201
202
203
# File 'lib/rex/peparsey/pe.rb', line 201

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

#sizeObject



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

def size
	_isource.size
end