class Rex::PeParsey::PeBase
Constants
- IMAGE_BASE_RELOCATION
Struct
typedef struct _IMAGE_BASE_RELOCATION { DWORD VirtualAddress; DWORD SizeOfBlock; // WORD TypeOffset[1]; } IMAGE_BASE_RELOCATION; typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
- IMAGE_BASE_RELOCATION_TYPE_OFFSET
- IMAGE_DATA_DIRECTORY
Struct
typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
- IMAGE_DATA_DIRECTORY_SIZE
- IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
- IMAGE_DIRECTORY_ENTRY_BASERELOC
- IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
- IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
- IMAGE_DIRECTORY_ENTRY_COPYRIGHT
- IMAGE_DIRECTORY_ENTRY_DEBUG
- IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
- IMAGE_DIRECTORY_ENTRY_EXCEPTION
- IMAGE_DIRECTORY_ENTRY_EXPORT
- IMAGE_DIRECTORY_ENTRY_GLOBALPTR
- IMAGE_DIRECTORY_ENTRY_IAT
- IMAGE_DIRECTORY_ENTRY_IMPORT
- IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
- IMAGE_DIRECTORY_ENTRY_RESOURCE
- IMAGE_DIRECTORY_ENTRY_SECURITY
- IMAGE_DIRECTORY_ENTRY_TLS
- IMAGE_DOS_HEADER
Struct
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header WORD e_magic; // Magic number WORD e_cblp; // Bytes on last page of file WORD e_cp; // Pages in file WORD e_crlc; // Relocations WORD e_cparhdr; // Size of header in paragraphs WORD e_minalloc; // Minimum extra paragraphs needed WORD e_maxalloc; // Maximum extra paragraphs needed WORD e_ss; // Initial (relative) SS value WORD e_sp; // Initial SP value WORD e_csum; // Checksum WORD e_ip; // Initial IP value WORD e_cs; // Initial (relative) CS value WORD e_lfarlc; // File address of relocation table WORD e_ovno; // Overlay number WORD e_res[4]; // Reserved words WORD e_oemid; // OEM identifier (for e_oeminfo) WORD e_oeminfo; // OEM information; e_oemid specific WORD e_res2[10]; // Reserved words LONG e_lfanew; // File address of new exe header } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
- IMAGE_DOS_HEADER_SIZE
- IMAGE_DOS_SIGNATURE
define
IMAGE_DOS_SIGNATURE
0x5A4D // MZ- IMAGE_EXPORT_DESCRIPTOR
Struct defining the export table
typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; // RVA from base of image DWORD AddressOfNames; // RVA from base of image DWORD AddressOfNameOrdinals; // RVA from base of image } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
- IMAGE_EXPORT_DESCRIPTOR_SIZE
sizeof(struct _IMAGE_EXPORT_DESCRIPTOR)
- IMAGE_FILE_HEADER
C struct defining the PE file header
typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
- IMAGE_FILE_HEADER_SIZE
define IMAGE_SIZEOF_FILE_HEADER 20
- IMAGE_FILE_MACHINE_ALPHA64
define
IMAGE_FILE_MACHINE_ALPHA64
0x0284 // ALPHA64- IMAGE_FILE_MACHINE_AMD64
define
IMAGE_FILE_MACHINE_AMD64
0x8664 // AMD64 (K8)- IMAGE_FILE_MACHINE_I386
define
IMAGE_FILE_MACHINE_I386
0x014c // Intel 386.- IMAGE_FILE_MACHINE_IA64
define
IMAGE_FILE_MACHINE_IA64
0x0200 // Intel 64- IMAGE_IMPORT_DESCRIPTOR
Struct
typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; // 0 for terminating null import descriptor DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) }; DWORD TimeDateStamp; // 0 if not bound, // -1 if bound, and real date\time stamp // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) // O.W. date/time stamp of DLL bound to (Old BIND) DWORD ForwarderChain; // -1 if no forwarders DWORD Name; DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) } IMAGE_IMPORT_DESCRIPTOR;
- IMAGE_IMPORT_DESCRIPTOR_SIZE
- IMAGE_LOAD_CONFIG_DIRECTORY32
Struct
typedef struct { DWORD Size; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD GlobalFlagsClear; DWORD GlobalFlagsSet; DWORD CriticalSectionDefaultTimeout; DWORD DeCommitFreeBlockThreshold; DWORD DeCommitTotalFreeThreshold; DWORD LockPrefixTable; // VA DWORD MaximumAllocationSize; DWORD VirtualMemoryThreshold; DWORD ProcessHeapFlags; DWORD ProcessAffinityMask; WORD CSDVersion; WORD Reserved1; DWORD EditList; // VA DWORD SecurityCookie; // VA DWORD SEHandlerTable; // VA DWORD SEHandlerCount; } IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;
- IMAGE_LOAD_CONFIG_DIRECTORY64
Struct
typedef struct { ULONG Size; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; ULONG GlobalFlagsClear; ULONG GlobalFlagsSet; ULONG CriticalSectionDefaultTimeout; ULONGLONG DeCommitFreeBlockThreshold; ULONGLONG DeCommitTotalFreeThreshold; ULONGLONG LockPrefixTable; // VA ULONGLONG MaximumAllocationSize; ULONGLONG VirtualMemoryThreshold; ULONGLONG ProcessAffinityMask; ULONG ProcessHeapFlags; USHORT CSDVersion; USHORT Reserved1; ULONGLONG EditList; // VA ULONGLONG SecurityCookie; // VA ULONGLONG SEHandlerTable; // VA ULONGLONG SEHandlerCount; } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64;
- IMAGE_LOAD_TLS_DIRECTORY32
Struct
typedef struct { DWORD Size; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD GlobalFlagsClear; DWORD GlobalFlagsSet; DWORD CriticalSectionDefaultTimeout; DWORD DeCommitFreeBlockThreshold; DWORD DeCommitTotalFreeThreshold; DWORD LockPrefixTable; // VA DWORD MaximumAllocationSize; DWORD VirtualMemoryThreshold; DWORD ProcessHeapFlags; DWORD ProcessAffinityMask; WORD CSDVersion; WORD Reserved1; DWORD EditList; // VA DWORD SecurityCookie; // VA DWORD SEHandlerTable; // VA DWORD SEHandlerCount; } IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;
- IMAGE_LOAD_TLS_DIRECTORY64
Struct
typedef struct { ULONG Size; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; ULONG GlobalFlagsClear; ULONG GlobalFlagsSet; ULONG CriticalSectionDefaultTimeout; ULONGLONG DeCommitFreeBlockThreshold; ULONGLONG DeCommitTotalFreeThreshold; ULONGLONG LockPrefixTable; // VA ULONGLONG MaximumAllocationSize; ULONGLONG VirtualMemoryThreshold; ULONGLONG ProcessAffinityMask; ULONG ProcessHeapFlags; USHORT CSDVersion; USHORT Reserved1; ULONGLONG EditList; // VA ULONGLONG SecurityCookie; // VA ULONGLONG SEHandlerTable; // VA ULONGLONG SEHandlerCount; } IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64;
- IMAGE_NT_OPTIONAL_HDR32_MAGIC
Struct
typedef struct _IMAGE_OPTIONAL_HEADER { // // Standard fields. // WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; // // NT additional fields. // DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b #define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224
- IMAGE_NT_OPTIONAL_HDR64_MAGIC
define
IMAGE_SIZEOF_NT_OPTIONAL64_HEADER
240- IMAGE_NT_SIGNATURE
define
IMAGE_NT_SIGNATURE
0x00004550 // PE00- IMAGE_NUMBEROF_DIRECTORY_ENTRIES
- IMAGE_OPTIONAL_HEADER32
- IMAGE_OPTIONAL_HEADER64
Struct
typedef struct _IMAGE_OPTIONAL_HEADER64 { USHORT Magic; UCHAR MajorLinkerVersion; UCHAR MinorLinkerVersion; ULONG SizeOfCode; ULONG SizeOfInitializedData; ULONG SizeOfUninitializedData; ULONG AddressOfEntryPoint; ULONG BaseOfCode; ULONGLONG ImageBase; ULONG SectionAlignment; ULONG FileAlignment; USHORT MajorOperatingSystemVersion; USHORT MinorOperatingSystemVersion; USHORT MajorImageVersion; USHORT MinorImageVersion; USHORT MajorSubsystemVersion; USHORT MinorSubsystemVersion; ULONG Win32VersionValue; ULONG SizeOfImage; ULONG SizeOfHeaders; ULONG CheckSum; USHORT Subsystem; USHORT DllCharacteristics; ULONGLONG SizeOfStackReserve; ULONGLONG SizeOfStackCommit; ULONGLONG SizeOfHeapReserve; ULONGLONG SizeOfHeapCommit; ULONG LoaderFlags; ULONG NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
- IMAGE_ORDINAL_FLAG32
- IMAGE_RUNTIME_FUNCTION_ENTRY
Struct
typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY { DWORD BeginAddress; DWORD EndAddress; DWORD UnwindInfoAddress; } _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY;
- IMAGE_RUNTIME_FUNCTION_ENTRY_SZ
Exception
directory- IMAGE_SECTION_HEADER
Struct
typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
- IMAGE_SIZEOF_BASE_RELOCATION
define
IMAGE_SIZEOF_BASE_RELOCATION
8- IMAGE_SIZEOF_NT_OPTIONAL32_HEADER
- IMAGE_SIZEOF_NT_OPTIONAL64_HEADER
define
IMAGE_NT_OPTIONAL_HDR64_MAGIC
0x20b- IMAGE_SIZEOF_SECTION_HEADER
define
IMAGE_SIZEOF_SECTION_HEADER
40- SUPPORTED_MACHINES
- UNWIND_INFO_HEADER
- UNWIND_INFO_HEADER_SZ
- UNW_FLAG_CHAININFO
- UNW_FLAG_EHANDLER
- UNW_FLAG_UHANDLER
- UWOP_ALLOC_LARGE
- UWOP_ALLOC_SMALL
- UWOP_PUSH_MACHFRAME
- UWOP_PUSH_NONVOL
- UWOP_SAVE_NONVOL
- UWOP_SAVE_NONVOL_FAR
- UWOP_SAVE_XMM128
- UWOP_SAVE_XMM128_FAR
- UWOP_SET_FPREG
Attributes
instance stuff
Public Class Methods
Just a stupid routine to round an offset up to it’s alignment.
For example, you’re going to want this for FileAlignment and SectionAlignment, etc…
# File lib/rex/peparsey/pebase.rb, line 1133 def self._align_offset(offset, alignment) offset += alignment - 1 offset -= offset % alignment return offset end
# File lib/rex/peparsey/pebase.rb, line 134 def self._parse_dos_header(rawdata) return DosHeader.new(rawdata) end
# File lib/rex/peparsey/pebase.rb, line 212 def self._parse_file_header(rawdata) return FileHeader.new(rawdata) end
# File lib/rex/peparsey/pebase.rb, line 570 def self._parse_optional_header(rawdata) case rawdata.length # no optional header when 0 return nil # good, good when IMAGE_SIZEOF_NT_OPTIONAL32_HEADER return OptionalHeader32.new(rawdata) when IMAGE_SIZEOF_NT_OPTIONAL64_HEADER return OptionalHeader64.new(rawdata) # bad, bad else raise OptionalHeaderError, "I don't know this header size, #{rawdata.length}", caller end end
# File lib/rex/peparsey/pebase.rb, line 642 def self._parse_section_headers(rawdata) section_headers = [ ] size = IMAGE_SIZEOF_SECTION_HEADER numsections = rawdata.length / size numsections.times do |i| data = rawdata[i * size, size] section_headers << SectionHeader.new(data) end return section_headers end
# File lib/rex/peparsey/pebase.rb, line 1156 def self.new_from_file(filename, disk_backed = false) file = ::File.new(filename) file.binmode # windows... :\ if disk_backed return self.new(ImageSource::Disk.new(file)) else obj = new_from_string(file.read) file.close return obj end end
# File lib/rex/peparsey/pebase.rb, line 1170 def self.new_from_string(data) return self.new(ImageSource::Memory.new(data)) end
Public Instance Methods
Find
a section by an RVA
# File lib/rex/peparsey/pebase.rb, line 1234 def _find_section_by_rva(rva) all_sections.each do |section| if section.contains_rva?(rva) return section end end return nil end
# File lib/rex/peparsey/pebase.rb, line 1096 def _load_exception_directory @exception = [] exception_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_EXCEPTION] rva = exception_entry.v['VirtualAddress'] size = exception_entry.v['Size'] return if (rva == 0) data = _isource.read(rva_to_file_offset(rva), size) case hdr.file.Machine when IMAGE_FILE_MACHINE_AMD64 count = data.length / IMAGE_RUNTIME_FUNCTION_ENTRY_SZ count.times { |current| @exception << RuntimeFunctionEntry.new(self, data.slice!(0, IMAGE_RUNTIME_FUNCTION_ENTRY_SZ)) } else end return @exception end
# File lib/rex/peparsey/pebase.rb, line 1378 def _load_exports # # Get the data directory entry, size, etc # exports_entry = _optional_header['DataDirectory'][0] rva = exports_entry.v['VirtualAddress'] size = exports_entry.v['Size'] return nil if size == 0 # # Ok, so we have the data directory, now lets parse it # directory = IMAGE_EXPORT_DESCRIPTOR.make_struct directory.from_s(_isource.read(rva_to_file_offset(rva), IMAGE_EXPORT_DESCRIPTOR_SIZE)) # # We can have nameless exports, so we need to do the whole # NumberOfFunctions NumberOfNames foo # num_functions = directory.v['NumberOfFunctions'] num_names = directory.v['NumberOfNames'] dllname_rva = directory.v['Name'] dllname = _isource.read_asciiz(rva_to_file_offset(dllname_rva)) # FIXME Base, etc fun_off = rva_to_file_offset(directory.v['AddressOfFunctions']) name_off = rva_to_file_offset(directory.v['AddressOfNames']) ord_off = rva_to_file_offset(directory.v['AddressOfNameOrdinals']) base = directory.v['Base'] # Allocate the list of names names = Array.new(num_functions) # # Iterate the names and name/ordinal list, getting the names # and storing them in the name list... # num_names.times do |i| name_rva = _isource.read(name_off + (i * 4), 4).unpack('V')[0] ordinal = _isource.read(ord_off + (i * 2), 2).unpack('v')[0] name = _isource.read_asciiz(rva_to_file_offset(name_rva)) # store the exported name in the name list names[ordinal] = name end exports = ExportDirectory.new(dllname, [ ], base) # # Now just iterate the functions (rvas) list.. # num_functions.times do |i| rva = _isource.read(fun_off + (i * 4), 4).unpack('V')[0] # ExportEntry.new(name, ordinal, rva) exports.entries << ExportEntry.new(names[i], i + base, rva) end return exports end
# File lib/rex/peparsey/pebase.rb, line 1307 def _load_imports # # Get the data directory entry, size, etc # imports_entry = _optional_header['DataDirectory'][1] rva = imports_entry.v['VirtualAddress'] size = imports_entry.v['Size'] return nil if size == 0 # # Ok, so we have the data directory, now lets parse it # imports = [ ] descriptors_data = _isource.read(rva_to_file_offset(rva), size) while descriptors_data.length >= IMAGE_IMPORT_DESCRIPTOR_SIZE descriptor = IMAGE_IMPORT_DESCRIPTOR.make_struct descriptor.from_s(descriptors_data) descriptors_data = descriptor.leftover othunk = descriptor.v['OriginalFirstThunk'] fthunk = descriptor.v['FirstThunk'] break if fthunk == 0 dllname = _isource.read_asciiz(rva_to_file_offset(descriptor.v['Name'])) import = ImportDescriptor.new(dllname, [ ]) # we prefer the Characteristics/OriginalFirstThunk... thunk_off = rva_to_file_offset(othunk == 0 ? fthunk : othunk) while (orgrva = _isource.read(thunk_off, 4).unpack('V')[0]) != 0 hint = nil name = nil if (orgrva & IMAGE_ORDINAL_FLAG32) != 0 hint = orgrva & 0xffff else foff = rva_to_file_offset(orgrva) hint = _isource.read(foff, 2).unpack('v')[0] name = _isource.read_asciiz(foff + 2) end import.entries << ImportEntry.new(name, hint) thunk_off += 4 end imports << import end return imports end
# File lib/rex/peparsey/pebase.rb, line 1454 def _load_relocations # # Get the data directory entry, size, etc # exports_entry = _optional_header['DataDirectory'][5] rva = exports_entry.v['VirtualAddress'] size = exports_entry.v['Size'] return nil if size == 0 # # Ok, so we have the data directory, now lets parse it # dirdata = _isource.read(rva_to_file_offset(rva), size) relocdirs = [ ] while dirdata.length >= IMAGE_SIZEOF_BASE_RELOCATION header = IMAGE_BASE_RELOCATION.make_struct header.from_s(dirdata) dirdata = header.leftover numrelocs = (header.v['SizeOfBlock'] - IMAGE_SIZEOF_BASE_RELOCATION) / 2 relocbase = header.v['VirtualAddress'] relocdir = RelocationDirectory.new(relocbase, [ ]) numrelocs.times do reloc = IMAGE_BASE_RELOCATION_TYPE_OFFSET.make_struct reloc.from_s(dirdata) dirdata = reloc.leftover typeoffset = reloc.v['TypeOffset'] relocrva = relocbase + (typeoffset & 0xfff) reloctype = (typeoffset >> 12) & 0xf relocdir.entries << RelocationEntry.new(relocrva, reloctype) end relocdirs << relocdir end return relocdirs end
# File lib/rex/peparsey/pebase.rb, line 1516 def _load_resources # # Get the data directory entry, size, etc # rsrc_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_RESOURCE] rva = rsrc_entry.v['VirtualAddress'] size = rsrc_entry.v['Size'] return nil if size == 0 # # Ok, so we have the data directory, now lets parse it # data = _isource.read(rva_to_file_offset(rva), size) self._resources_cache = {} _parse_resource_directory(data) end
# File lib/rex/peparsey/pebase.rb, line 831 def _parse_config_header # # Get the data directory entry, size, etc # exports_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG] rva = exports_entry.v['VirtualAddress'] size = exports_entry.v['Size'] return nil if size == 0 # # Ok, so we have the data directory, now lets parse it # dirdata = _isource.read(rva_to_file_offset(rva), size) klass = (ptr_64?) ? IMAGE_LOAD_CONFIG_DIRECTORY64 : IMAGE_LOAD_CONFIG_DIRECTORY32 header = klass.make_struct header.from_s(dirdata) @config = ConfigHeader.new(header) end
# File lib/rex/peparsey/pebase.rb, line 1535 def _parse_resource_directory(data, rname=0, rvalue=0x80000000, path='0', pname=nil) pname = _parse_resource_name(data, rname) if (path.scan('/').length == 1) if (pname !~ /^\d+/) path = "/" + pname else path = "/" + _resource_lookup( (rname & ~0x80000000).to_s) end end rvalue &= ~0x80000000 vals = data[rvalue, 16].unpack('VVvvvv') chars = vals[0] tdate = vals[1] vers = "#{vals[2]}#{vals[3]}" count = vals[4] + vals[5] 0.upto(count-1) do |i| ename, evalue = data[rvalue + 16 + ( i * 8), 8].unpack('VV') epath = path + '/' + i.to_s if (ename & 0x80000000 != 0) pname = _parse_resource_name(data, ename) end if (evalue & 0x80000000 != 0) # This is a subdirectory _parse_resource_directory(data, ename, evalue, epath, pname) else # This is an entry _parse_resource_entry(data, ename, evalue, epath, pname) end end end
# File lib/rex/peparsey/pebase.rb, line 1607 def _parse_resource_entry(data, rname, rvalue, path, pname) rva, size, code = data[rvalue, 12].unpack('VVV') lang = _parse_resource_name(data, rname) ent = ResourceEntry.new( self, path, lang, code, rva, size, pname ) self._resources_cache[path] = ent end
# File lib/rex/peparsey/pebase.rb, line 1624 def _parse_resource_name(data, rname) if (rname & 0x80000000 != 0) rname &= ~0x80000000 unistr = data[rname+2, 2 * data[rname,2].unpack('v')[0] ] unistr, trash = unistr.split(/\x00\x00/n, 2) return unistr ? unistr.gsub(/\x00/n, '') : nil end rname.to_s end
# File lib/rex/peparsey/pebase.rb, line 962 def _parse_tls_header # # Get the data directory entry, size, etc # exports_entry = _optional_header['DataDirectory'][IMAGE_DIRECTORY_ENTRY_TLS] rva = exports_entry.v['VirtualAddress'] size = exports_entry.v['Size'] return nil if size == 0 # # Ok, so we have the data directory, now lets parse it # dirdata = _isource.read(rva_to_file_offset(rva), size) klass = (ptr_64?) ? IMAGE_LOAD_TLS_DIRECTORY64 : IMAGE_LOAD_TLS_DIRECTORY32 header = klass.make_struct header.from_s(dirdata) @tls = TLSHeader.new(header) end
# File lib/rex/peparsey/pebase.rb, line 1575 def _resource_lookup(i) tbl = { '1' => 'RT_CURSOR', '2' => 'RT_BITMAP', '3' => 'RT_ICON', '4' => 'RT_MENU', '5' => 'RT_DIALOG', '6' => 'RT_STRING', '7' => 'RT_FONTDIR', '8' => 'RT_FONT', '9' => 'RT_ACCELERATORS', '10' => 'RT_RCDATA', '11' => 'RT_MESSAGETABLE', '12' => 'RT_GROUP_CURSOR', '14' => 'RT_GROUP_ICON', '16' => 'RT_VERSION', '17' => 'RT_DLGINCLUDE', '19' => 'RT_PLUGPLAY', '20' => 'RT_VXD', '21' => 'RT_ANICURSOR', '22' => 'RT_ANIICON', '23' => 'RT_HTML', '24' => 'RT_MANIFEST', '32767' => 'RT_ERROR', '8192' => 'RT_NEWRESOURCE', '8194' => 'RT_NEWBITMAP', '8196' => 'RT_NEWMENU', '8197' => 'RT_NEWDIALOG' } tbl[i] || i end
# File lib/rex/peparsey/pebase.rb, line 1174 def close _isource.close end
# File lib/rex/peparsey/pebase.rb, line 856 def config _parse_config_header if @config.nil? @config end
# File lib/rex/peparsey/pebase.rb, line 1122 def exception _load_exception_directory if @exception.nil? @exception end
We lazily parse the exports, and then cache it
# File lib/rex/peparsey/pebase.rb, line 1370 def exports if !_exports_cached self._exports_cache = _load_exports self._exports_cached = true end return _exports_cache end
# File lib/rex/peparsey/pebase.rb, line 1205 def file_offset_to_rva(foffset) if foffset < 0 raise WtfError, "lame", caller end all_sections.each do |section| if section.contains_file_offset?(foffset) return section.file_offset_to_rva(foffset) end end raise WtfError, "wtf! #{foffset}", caller end
# File lib/rex/peparsey/pebase.rb, line 1219 def file_offset_to_vma(foffset) return rva_to_vma(file_offset_to_rva(foffset)) end
# File lib/rex/peparsey/pebase.rb, line 1243 def find_section_by_rva(rva) section = _find_section_by_rva(rva) if !section raise WtfError, "Cannot find rva! #{rva}", caller end return section end
Find
a section by a VMA
# File lib/rex/peparsey/pebase.rb, line 1256 def find_section_by_vma(vma) return find_section_by_rva(vma_to_rva(vma)) end
We lazily parse the imports, and then cache it
# File lib/rex/peparsey/pebase.rb, line 1299 def imports if !_imports_cached self._imports_cache = _load_imports self._imports_cached = true end return _imports_cache end
# File lib/rex/peparsey/pebase.rb, line 1282 def read_asciiz_rva(rva) return find_section_by_rva(rva).read_asciiz_rva(rva) end
# File lib/rex/peparsey/pebase.rb, line 1286 def read_asciiz_vma(vma) return read_asciiz_rva(vma_to_rva(vma)) end
Some convenient methods to read a vma/rva without having the section… (inefficent though I suppose…)
# File lib/rex/peparsey/pebase.rb, line 1274 def read_rva(rva, length) return find_section_by_rva(rva).read_rva(rva, length) end
# File lib/rex/peparsey/pebase.rb, line 1278 def read_vma(vma, length) return read_rva(vma_to_rva(vma), length) end
Base relocations in the hizzy
# File lib/rex/peparsey/pebase.rb, line 1446 def relocations if !_relocations_cached self._relocations_cache = _load_relocations self._relocations_cached = true end return _relocations_cache end
We lazily parse the resources, and then cache them
# File lib/rex/peparsey/pebase.rb, line 1507 def resources if !_resources_cached _load_resources self._resources_cached = true end return self._resources_cache end
# File lib/rex/peparsey/pebase.rb, line 1192 def rva_to_file_offset(rva) all_sections.each do |section| if section.contains_rva?(rva) return section.rva_to_file_offset(rva) end end raise WtfError, "wtf!", caller end
Random rva, vma, file offset, section offset, etc conversion routines…
# File lib/rex/peparsey/pebase.rb, line 1184 def rva_to_vma(rva) return rva + image_base end
# File lib/rex/peparsey/pebase.rb, line 987 def tls _parse_config_header if @tls.nil? @tls end
# File lib/rex/peparsey/pebase.rb, line 1635 def update_checksum off = _dos_header.e_lfanew + IMAGE_FILE_HEADER_SIZE + 0x40 _isource.rawdata[off, 4] = [0].pack('V') rem = _isource.size % 4 sum_me = '' sum_me << _isource.rawdata sum_me << "\x00" * (4 - rem) if rem > 0 cksum = 0 sum_me.unpack('V*').each { |el| cksum = (cksum & 0xffffffff) + (cksum >> 32) + el if cksum > 2**32 cksum = (cksum & 0xffffffff) + (cksum >> 32) end } cksum = (cksum & 0xffff) + (cksum >> 16) cksum += (cksum >> 16) cksum &= 0xffff cksum += _isource.size _isource.rawdata[off, 4] = [cksum].pack('V') end
# File lib/rex/peparsey/pebase.rb, line 1260 def valid_rva?(rva) _find_section_by_rva(rva) != nil end
# File lib/rex/peparsey/pebase.rb, line 1263 def valid_vma?(vma) _find_section_by_rva(vma_to_rva(vma)) != nil end
# File lib/rex/peparsey/pebase.rb, line 1201 def vma_to_file_offset(vma) return rva_to_file_offset(vma_to_rva(vma)) end
# File lib/rex/peparsey/pebase.rb, line 1188 def vma_to_rva(vma) return vma - image_base end