├── .appveyor.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CMakeLists.txt ├── MIT_LICENSE ├── README.md ├── ZLIB_LICENSE ├── include └── pelib │ ├── BoundImportDirectory.h │ ├── CoffSymbolTable.h │ ├── ComHeaderDirectory.h │ ├── DebugDirectory.h │ ├── DelayImportDirectory.h │ ├── ExportDirectory.h │ ├── IatDirectory.h │ ├── ImportDirectory.h │ ├── InputBuffer.h │ ├── MzHeader.h │ ├── OutputBuffer.h │ ├── PeFile.h │ ├── PeHeader.h │ ├── PeLib.h │ ├── PeLibAux.h │ ├── PeLibInc.h │ ├── RelocationsDirectory.h │ ├── ResourceDirectory.h │ ├── RichHeader.h │ ├── SecurityDirectory.h │ └── TlsDirectory.h └── src ├── CMakeLists.txt └── pelib ├── BoundImportDirectory.cpp ├── CMakeLists.txt ├── CoffSymbolTable.cpp ├── ComHeaderDirectory.cpp ├── DebugDirectory.cpp ├── ExportDirectory.cpp ├── IatDirectory.cpp ├── InputBuffer.cpp ├── MzHeader.cpp ├── OutputBuffer.cpp ├── PeFile.cpp ├── PeHeader.cpp ├── PeLibAux.cpp ├── RelocationsDirectory.cpp ├── ResourceDirectory.cpp ├── RichHeader.cpp └── SecurityDirectory.cpp /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | 3 | environment: 4 | matrix: 5 | - CMAKE_GENERATOR: Visual Studio 15 2017 Win64 6 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 7 | - CMAKE_GENERATOR: Visual Studio 15 2017 8 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 9 | 10 | configuration: 11 | - Debug 12 | - Release 13 | 14 | matrix: 15 | fast_finish: true 16 | 17 | before_build: 18 | - cmd: mkdir build 19 | - cmd: cd build 20 | - cmd: cmake -G"%CMAKE_GENERATOR%" -DCMAKE_BUILD_TYPE=%configuration% -DCMAKE_INSTALL_PREFIX="%APPVEYOR_BUILD_FOLDER%\install" .. 21 | 22 | build_script: 23 | - cmd: cmake --build . --config %configuration% -- /m 24 | 25 | branches: 26 | only: 27 | # Pushes and PRs to the master branch. 28 | - master 29 | # Version tags. 30 | - /^v?\d+\.\d+.*$/ 31 | 32 | skip_commits: 33 | files: 34 | # Exact files. 35 | - .travis.yml 36 | - MIT_LICENSE 37 | - ZLIB_LICENSE 38 | # All .gitignore files within repository. 39 | - '**/.gitignore' 40 | # All *.md files within repository. 41 | - '**/*.md' 42 | # All README files within repository. 43 | - '**/README' 44 | - '**/README.txt' 45 | - '**/readme' 46 | - '**/readme.txt' 47 | 48 | notifications: 49 | - provider: Email 50 | to: 51 | - '{{commitAuthorEmail}}' 52 | on_build_success: false 53 | on_build_failure: true 54 | on_build_status_changed: true 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | /build/ 3 | /.cproject 4 | /.settings/ 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | matrix: 4 | fast_finish: true 5 | include: 6 | - os: linux 7 | dist: xenial 8 | addons: 9 | apt: 10 | packages: 11 | - build-essential 12 | - cmake 13 | env: 14 | - MATRIX_EVAL="NPROC=$(nproc)" 15 | - os: osx 16 | osx_image: xcode11.2 17 | env: 18 | - MATRIX_EVAL="NPROC=$(sysctl -n hw.physicalcpu)" 19 | 20 | before_install: 21 | - eval "${MATRIX_EVAL}" 22 | 23 | script: 24 | - mkdir build && cd build 25 | - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$(pwd)/install" .. 26 | - cmake --build . -- -j $NPROC 27 | 28 | branches: 29 | only: 30 | # Pushes and PRs to the master branch. 31 | - master 32 | # Version tags. 33 | - /^v?\d+\.\d+.*$/ 34 | 35 | notifications: 36 | email: 37 | on_success: never 38 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | # dev 4 | 5 | * Rewrite for C++17. 6 | * Removed functionality concerning re-building of relocations due to its flaws 7 | ([#15](https://github.com/avast/pelib/issues/15), 8 | [#16](https://github.com/avast/pelib/pull/16)). 9 | * Fixed detection of cut import directory 10 | ([#17](https://github.com/avast/pelib/pull/17)). 11 | 12 | # v1.0 (2017-12-12) 13 | 14 | Initial release. 15 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6) 2 | 3 | project(pelib CXX) 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | set(CMAKE_CXX_EXTENSIONS OFF) 7 | 8 | # Set the default build type to 'Release' 9 | if(NOT CMAKE_BUILD_TYPE) 10 | set(default_build_type "Release") 11 | message(STATUS "Setting build type to '${default_build_type}' as none was specified.") 12 | set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE) 13 | endif() 14 | 15 | set(CMAKE_CXX_STANDARD 14) 16 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 17 | set(CMAKE_CXX_EXTENSIONS OFF) 18 | set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") 19 | 20 | add_subdirectory(src) 21 | -------------------------------------------------------------------------------- /MIT_LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Avast Software 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## PeLib 2 | 3 | This repository is no longer alive. Its sources were moved directly to the main RetDec [repository](https://github.com/avast/retdec). It will be removed altogether after some transitional period. 4 | -------------------------------------------------------------------------------- /ZLIB_LICENSE: -------------------------------------------------------------------------------- 1 | The zlib/libpng License 2 | 3 | Copyright (c) 2004 - Sebastian Porst 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | -------------------------------------------------------------------------------- /include/pelib/BoundImportDirectory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BoundImportDirectory.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef BOUNDIMPORTDIRECTORY_H 14 | #define BOUNDIMPORTDIRECTORY_H 15 | 16 | #include "pelib/PeHeader.h" 17 | #include "pelib/PeLibAux.h" 18 | 19 | namespace PeLib 20 | { 21 | /// Class that handles the BoundImport directory. 22 | /** 23 | * This class can read and modify the BoundImport directory table of a PE file. 24 | **/ 25 | class BoundImportDirectory 26 | { 27 | protected: 28 | std::vector m_vIbd; ///< Stores the individual BoundImport fields. 29 | 30 | int read(InputBuffer& inpBuffer, unsigned char* data, unsigned int dwSize); 31 | unsigned int totalModules() const; 32 | public: 33 | virtual ~BoundImportDirectory() = default; 34 | 35 | /// Adds another bound import. 36 | int addBoundImport(const std::string& strModuleName, dword dwTds, word dwOmn, word wWfr); // EXPORT 37 | /// Identifies a module through it's name. 38 | int getModuleIndex(const std::string& strModuleName) const; // EXPORT 39 | /// Returns the number of files in the BoundImport directory. 40 | unsigned int calcNumberOfModules() const; // EXPORT 41 | /// Reads the BoundImport directory table from a PE file. 42 | int read(unsigned char* pcBuffer, unsigned int uiSize); // EXPORT 43 | /// Rebuilds the BoundImport directory. 44 | void rebuild(std::vector& vBuffer, bool fMakeValid = true) const; // EXPORT 45 | /// Empties the BoundImport directory. 46 | void clear(); // EXPORT 47 | /// Removes a bound import. 48 | void removeBoundImport(const std::string& strModuleName); // EXPORT 49 | /// Returns the size of the BoundImport directory. 50 | unsigned int size() const; // EXPORT 51 | /// Writes the current bound import directory to a file. 52 | int write(const std::string& strFilename, dword dwOffset, bool fMakeValid = true) const; // EXPORT 53 | 54 | /// Retrieves the TimeDateStamp value of a bound import. 55 | dword getTimeDateStamp(dword dwBidnr) const; // EXPORT 56 | /// Retrieves the OffsetModuleName value of a bound import. 57 | word getOffsetModuleName(dword dwBidnr) const; // EXPORT 58 | /// Retrieves the NumberOfModuleForwarderRefs value of a bound import. 59 | word getNumberOfModuleForwarderRefs(dword dwBidnr) const; // EXPORT 60 | /// Retrieves the ModuleName value of a bound import. 61 | std::string getModuleName(dword dwBidnr) const; // EXPORT 62 | 63 | /// Updates the TimeDateStamp value of a bound import. 64 | void setTimeDateStamp(dword dwBidnr, dword dwTds); // EXPORT 65 | /// Updates the OffsetModuleName value of a bound import. 66 | void setOffsetModuleName(dword dwBidnr, word wOmn); // EXPORT 67 | /// Updates the NumberOfModuleForwarderRefs value of a bound import. 68 | void setNumberOfModuleForwarderRefs(dword dwBidnr, word wMfr); // EXPORT 69 | /// Updates the ModuleName value of a bound import. 70 | void setModuleName(dword dwBidnr, const std::string& strModuleName); // EXPORT 71 | 72 | dword getTimeDateStamp(dword dwBidnr, dword forwardedModule) const; // EXPORT _module 73 | word getOffsetModuleName(dword dwBidnr, dword forwardedModule) const; // EXPORT _module 74 | word getNumberOfModuleForwarderRefs(dword dwBidnr, dword forwardedModule) const; // EXPORT _module 75 | std::string getModuleName(dword dwBidnr, dword forwardedModule) const; // EXPORT _module 76 | 77 | void setTimeDateStamp(dword dwBidnr, dword forwardedModule, dword dwTds); // EXPORT _module 78 | void setOffsetModuleName(dword dwBidnr, dword forwardedModule, word wOmn); // EXPORT _module 79 | void setNumberOfModuleForwarderRefs(dword dwBidnr, dword forwardedModule, word wMfr); // EXPORT _module 80 | void setModuleName(dword dwBidnr, dword forwardedModule, const std::string& strModuleName); // EXPORT _module 81 | 82 | word calcNumberOfModuleForwarderRefs(dword dwBidnr) const; // EXPORT 83 | void addForwardedModule(dword dwBidnr, const std::string& name, dword timeStamp = 0, word offsetModuleName = 0, word forwardedModules = 0); // EXPORT 84 | void removeForwardedModule(dword dwBidnr, word forwardedModule); // EXPORT 85 | }; 86 | 87 | template 88 | class BoundImportDirectoryT : public BoundImportDirectory 89 | { 90 | public: 91 | /// Reads the BoundImport directory table from a PE file. 92 | int read(std::istream& inStream, const PeHeaderT& peHeader); // EXPORT 93 | }; 94 | 95 | /** 96 | * Reads the BoundImport directory from a PE file. 97 | * @param inStream Input stream. 98 | * @param peHeader A valid PE header which is necessary because some RVA calculations need to be done. 99 | **/ 100 | template 101 | int BoundImportDirectoryT::read( 102 | std::istream& inStream, 103 | const PeHeaderT& peHeader) 104 | { 105 | IStreamWrapper inStream_w(inStream); 106 | 107 | if (!inStream_w) 108 | { 109 | return ERROR_OPENING_FILE; 110 | } 111 | 112 | dword dwOffset = peHeader.rvaToOffset(peHeader.getIddBoundImportRva()); 113 | unsigned int uiSize = peHeader.getIddBoundImportSize(); 114 | 115 | if (fileSize(inStream_w) < dwOffset + uiSize) 116 | { 117 | return ERROR_INVALID_FILE; 118 | } 119 | 120 | std::vector vBimpDir(uiSize); 121 | inStream_w.seekg(dwOffset, std::ios::beg); 122 | inStream_w.read(reinterpret_cast(vBimpDir.data()), uiSize); 123 | 124 | InputBuffer inpBuffer{vBimpDir}; 125 | return BoundImportDirectory::read(inpBuffer, vBimpDir.data(), uiSize); 126 | } 127 | } 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /include/pelib/CoffSymbolTable.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file CoffSymbolTable.h 3 | * @brief Class for COFF symbol table. 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #ifndef COFFSYMBOLTABLE_H 8 | #define COFFSYMBOLTABLE_H 9 | 10 | #include 11 | 12 | namespace PeLib 13 | { 14 | /** 15 | * This class handless the COFF symbol table. 16 | */ 17 | class CoffSymbolTable 18 | { 19 | private: 20 | std::size_t stringTableSize; 21 | dword numberOfStoredSymbols; 22 | std::vector stringTable; 23 | std::vector symbolTableDump; 24 | std::vector symbolTable; 25 | LoaderError m_ldrError; 26 | 27 | void read(InputBuffer& inputbuffer, unsigned int uiSize); 28 | public: 29 | CoffSymbolTable(); 30 | ~CoffSymbolTable(); 31 | 32 | LoaderError loaderError() const; 33 | void setLoaderError(LoaderError ldrError); 34 | 35 | int read( 36 | std::istream& inStream, 37 | unsigned int uiOffset, 38 | unsigned int uiSize); 39 | std::size_t getSizeOfStringTable() const; 40 | std::size_t getNumberOfStoredSymbols() const; 41 | dword getSymbolIndex(std::size_t ulSymbol) const; 42 | std::string getSymbolName(std::size_t ulSymbol) const; 43 | dword getSymbolValue(std::size_t ulSymbol) const; 44 | word getSymbolSectionNumber(std::size_t ulSymbol) const; 45 | byte getSymbolTypeComplex(std::size_t ulSymbol) const; 46 | byte getSymbolTypeSimple(std::size_t ulSymbol) const; 47 | byte getSymbolStorageClass(std::size_t ulSymbol) const; 48 | byte getSymbolNumberOfAuxSymbols(std::size_t ulSymbol) const; 49 | }; 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /include/pelib/ComHeaderDirectory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ComHeaderDirectory.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef COMHEADERDIRECTORY_H 14 | #define COMHEADERDIRECTORY_H 15 | 16 | #include "pelib/PeHeader.h" 17 | 18 | namespace PeLib 19 | { 20 | /// Class that handles the COM+ descriptor directory. 21 | /** 22 | * This class handles the COM+ Descriptor directory which was added to PE files 23 | * which work with the .NET runtime modules. 24 | **/ 25 | class ComHeaderDirectory 26 | { 27 | protected: 28 | PELIB_IMAGE_COR20_HEADER m_ichComHeader; ///< The COM+ descriptor. 29 | 30 | void read(InputBuffer& inputbuffer); 31 | 32 | public: 33 | virtual ~ComHeaderDirectory() = default; 34 | 35 | /// Read a file's COM+ runtime descriptor directory. 36 | int read(unsigned char* buffer, unsigned int buffersize); // EXPORT 37 | /// Rebuild the COM+ descriptor. 38 | void rebuild(std::vector& vBuffer) const; // EXPORT 39 | /// Returns the size of the current COM+ descriptor. 40 | unsigned int size() const; // EXPORT 41 | /// Writes the current COM+ descriptor directory to a file. 42 | int write(const std::string& strFilename, unsigned int dwOffset) const; // EXPORT 43 | 44 | /// Get the COM+ descriptor's SizeOfHeader (cb) value. 45 | dword getSizeOfHeader() const; // EXPORT 46 | /// Get the COM+ descriptor's MajorRuntimeVersion value. 47 | word getMajorRuntimeVersion() const; // EXPORT 48 | /// Get the COM+ descriptor's MinorRuntimeVersion value. 49 | word getMinorRuntimeVersion() const; // EXPORT 50 | /// Get the COM+ descriptor's MetaData (Virtual Address) value. 51 | dword getMetaDataVa() const; // EXPORT 52 | /// Get the COM+ descriptor's MetaData (Size) value. 53 | dword getMetaDataSize() const; // EXPORT 54 | /// Get the COM+ descriptor's Flags value. 55 | dword getFlags() const; // EXPORT 56 | /// Get the COM+ descriptor's EntryPointToken value. 57 | dword getEntryPointToken() const; // EXPORT 58 | /// Get the COM+ descriptor's Resources (Virtual Address) value. 59 | dword getResourcesVa() const; // EXPORT 60 | /// Get the COM+ descriptor's Resources (Size) value. 61 | dword getResourcesSize() const; // EXPORT 62 | /// Get the COM+ descriptor's StrongNameSignature (Virtual Address) value. 63 | dword getStrongNameSignatureVa() const; // EXPORT 64 | /// Get the COM+ descriptor's StrongNameSignature (Size) value. 65 | dword getStrongNameSignatureSize() const; // EXPORT 66 | /// Get the COM+ descriptor's CodeManagerTable (Virtual Address) value. 67 | dword getCodeManagerTableVa() const; // EXPORT 68 | /// Get the COM+ descriptor's CodeManagerTable (Size) value. 69 | dword getCodeManagerTableSize() const; // EXPORT 70 | /// Get the COM+ descriptor's VTableFixup (Virtual Address) value. 71 | dword getVTableFixupsVa() const; // EXPORT 72 | /// Get the COM+ descriptor's VTableFixup (Size) value. 73 | dword getVTableFixupsSize() const; // EXPORT 74 | /// Get the COM+ descriptor's ExportAddressTable (Virtual Address) value. 75 | dword getExportAddressTableJumpsVa() const; // EXPORT 76 | /// Get the COM+ descriptor's ExportAddressTable (Size) value. 77 | dword getExportAddressTableJumpsSize() const; // EXPORT 78 | /// Get the COM+ descriptor's ManagedNativeHeader (Virtual Address) value. 79 | dword getManagedNativeHeaderVa() const; // EXPORT 80 | /// Get the COM+ descriptor's ManagedNativeHeader (Size) value. 81 | dword getManagedNativeHeaderSize() const; // EXPORT 82 | 83 | /// Change the COM+ descriptor's SizeOfHeader (cb) value. 84 | void setSizeOfHeader(dword dwValue); // EXPORT 85 | /// Change the COM+ descriptor's MajorRuntimeVersion value. 86 | void setMajorRuntimeVersion(word wValue); // EXPORT 87 | /// Change the COM+ descriptor's MinorRuntimeVersion value. 88 | void setMinorRuntimeVersion(word wValue); // EXPORT 89 | /// Change the COM+ descriptor's MetaData (VirtualAddress) value. 90 | void setMetaDataVa(dword dwValue); // EXPORT 91 | /// Change the COM+ descriptor's MetaData (Size) value. 92 | void setMetaDataSize(dword dwValue); // EXPORT 93 | /// Change the COM+ descriptor's Flags value. 94 | void setFlags(dword dwValue); // EXPORT 95 | /// Change the COM+ descriptor's EntryPointToken value. 96 | void setEntryPointToken(dword dwValue); // EXPORT 97 | /// Change the COM+ descriptor's Resources (VirtualAddress) value. 98 | void setResourcesVa(dword dwValue); // EXPORT 99 | /// Change the COM+ descriptor's Resources (Size) value. 100 | void setResourcesSize(dword dwValue); // EXPORT 101 | /// Change the COM+ descriptor's StrongNameSignatureVa (VirtualAddress) value. 102 | void setStrongNameSignatureVa(dword dwValue); // EXPORT 103 | /// Change the COM+ descriptor's StrongNameSignatureVa (Size) value. 104 | void setStrongNameSignagureSize(dword dwValue); // EXPORT 105 | /// Change the COM+ descriptor's CodeManagerTable (VirtualAddress) value. 106 | void setCodeManagerTableVa(dword dwValue); // EXPORT 107 | /// Change the COM+ descriptor's CodeManagerTable (Size) value. 108 | void setCodeManagerTableSize(dword dwValue); // EXPORT 109 | /// Change the COM+ descriptor's VTableFixups (VirtualAddress) value. 110 | void setVTableFixupsVa(dword dwValue); // EXPORT 111 | /// Change the COM+ descriptor's VTableFixups (Size) value. 112 | void setVTableFixupsSize(dword dwValue); // EXPORT 113 | /// Change the COM+ descriptor's ExportAddressTableJumps (VirtualAddress) value. 114 | void setExportAddressTableJumpsVa(dword dwValue); // EXPORT 115 | /// Change the COM+ descriptor's ExportAddressTableJumps (Size) value. 116 | void setExportAddressTableJumpsSize(dword dwValue); // EXPORT 117 | /// Change the COM+ descriptor's ManagedNativeHeader (VirtualAddress) value. 118 | void setManagedNativeHeaderVa(dword dwValue); // EXPORT 119 | /// Change the COM+ descriptor's ManagedNativeHeader (Size) value. 120 | void setManagedNativeHeaderSize(dword dwValue); // EXPORT 121 | }; 122 | 123 | template 124 | class ComHeaderDirectoryT : public ComHeaderDirectory 125 | { 126 | public: 127 | /// Read a file's COM+ runtime descriptor directory. 128 | int read(std::istream& inStream, const PeHeaderT& peHeader); // EXPORT 129 | }; 130 | 131 | /** 132 | * Reads a file's COM+ descriptor. 133 | * @param inStream Input stream. 134 | * @param peHeader A valid PE header which is necessary because some RVA calculations need to be done. 135 | **/ 136 | template 137 | int ComHeaderDirectoryT::read(std::istream& inStream, const PeHeaderT& peHeader) 138 | { 139 | IStreamWrapper inStream_w(inStream); 140 | 141 | if (!inStream_w) 142 | { 143 | return ERROR_OPENING_FILE; 144 | } 145 | 146 | std::uint64_t ulFileSize = fileSize(inStream_w); 147 | 148 | unsigned int uiOffset = peHeader.rvaToOffset(peHeader.getIddComHeaderRva()); 149 | unsigned int uiSize = peHeader.getIddComHeaderSize(); 150 | 151 | if (ulFileSize < uiOffset + uiSize) 152 | { 153 | return ERROR_INVALID_FILE; 154 | } 155 | 156 | inStream_w.seekg(uiOffset, std::ios::beg); 157 | 158 | std::vector vComDescDirectory(uiSize); 159 | inStream_w.read(reinterpret_cast(vComDescDirectory.data()), uiSize); 160 | 161 | InputBuffer ibBuffer{vComDescDirectory}; 162 | ComHeaderDirectory::read(ibBuffer); 163 | return ERROR_NONE; 164 | } 165 | } 166 | #endif 167 | -------------------------------------------------------------------------------- /include/pelib/DebugDirectory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * DebugDirectory.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef DEBUGDIRECTORY_H 14 | #define DEBUGDIRECTORY_H 15 | 16 | #include "pelib/PeHeader.h" 17 | 18 | namespace PeLib 19 | { 20 | /// Class that handles the Debug directory. 21 | class DebugDirectory 22 | { 23 | protected: 24 | /// Stores the various DebugDirectory structures. 25 | std::vector m_vDebugInfo; 26 | /// Stores RVAs which are occupied by this debug directory. 27 | std::vector> m_occupiedAddresses; 28 | 29 | std::vector read(InputBuffer& ibBuffer, unsigned int uiRva, unsigned int uiSize); 30 | 31 | public: 32 | virtual ~DebugDirectory() = default; 33 | 34 | void clear(); // EXPORT 35 | /// Reads the Debug directory from a file. 36 | int read(unsigned char* buffer, unsigned int buffersize); 37 | /// Rebuilds the current Debug directory. 38 | void rebuild(std::vector& obBuffer) const; // EXPORT 39 | /// Returns the size the current Debug directory needs after rebuilding. 40 | unsigned int size() const; 41 | /// Writes the current Debug directory back to a file. 42 | int write(const std::string& strFilename, unsigned int uiOffset) const; // EXPORT 43 | 44 | /// Returns the number of DebugDirectory image structures in the current DebugDirectory. 45 | unsigned int calcNumberOfEntries() const; // EXPORT 46 | 47 | /// Adds a new debug structure. 48 | void addEntry(); // EXPORT 49 | /// Removes a debug structure. 50 | void removeEntry(std::size_t uiIndex); // EXPORT 51 | 52 | /// Returns the Characteristics value of a debug structure. 53 | dword getCharacteristics(std::size_t uiIndex) const; // EXPORT 54 | /// Returns the TimeDateStamp value of a debug structure. 55 | dword getTimeDateStamp(std::size_t uiIndex) const; // EXPORT 56 | /// Returns the MajorVersion value of a debug structure. 57 | word getMajorVersion(std::size_t uiIndex) const; // EXPORT 58 | /// Returns the MinorVersion value of a debug structure. 59 | word getMinorVersion(std::size_t uiIndex) const; // EXPORT 60 | /// Returns the Type value of a debug structure. 61 | dword getType(std::size_t uiIndex) const; // EXPORT 62 | /// Returns the SizeOfData value of a debug structure. 63 | dword getSizeOfData(std::size_t uiIndex) const; // EXPORT 64 | /// Returns the AddressOfRawData value of a debug structure. 65 | dword getAddressOfRawData(std::size_t uiIndex) const; // EXPORT 66 | /// Returns the PointerToRawData value of a debug structure. 67 | dword getPointerToRawData(std::size_t uiIndex) const; // EXPORT 68 | std::vector getData(std::size_t index) const; // EXPORT 69 | 70 | /// Sets the Characteristics value of a debug structure. 71 | void setCharacteristics(std::size_t uiIndex, dword dwValue); // EXPORT 72 | /// Sets the TimeDateStamp value of a debug structure. 73 | void setTimeDateStamp(std::size_t uiIndex, dword dwValue); // EXPORT 74 | /// Sets the MajorVersion value of a debug structure. 75 | void setMajorVersion(std::size_t uiIndex, word wValue); // EXPORT 76 | /// Sets the MinorVersion value of a debug structure. 77 | void setMinorVersion(std::size_t uiIndex, word wValue); // EXPORT 78 | /// Sets the Type value of a debug structure. 79 | void setType(std::size_t uiIndex, dword dwValue); // EXPORT 80 | /// Sets the SizeOfData value of a debug structure. 81 | void setSizeOfData(std::size_t uiIndex, dword dwValue); // EXPORT 82 | /// Sets the AddressOfRawData value of a debug structure. 83 | void setAddressOfRawData(std::size_t uiIndex, dword dwValue); // EXPORT 84 | /// Sets the PointerToRawData value of a debug structure. 85 | void setPointerToRawData(std::size_t uiIndex, dword dwValue); // EXPORT 86 | void setData(std::size_t index, const std::vector& data); // EXPORT 87 | 88 | const std::vector>& getOccupiedAddresses() const; 89 | }; 90 | 91 | template 92 | class DebugDirectoryT : public DebugDirectory 93 | { 94 | public: 95 | /// Reads the Debug directory from a file. 96 | int read(std::istream& inStream, const PeHeaderT& peHeader); 97 | }; 98 | 99 | /** 100 | * @param inStream Input stream. 101 | * @param peHeader A valid PE header which is necessary because some RVA calculations need to be done. 102 | **/ 103 | template 104 | int DebugDirectoryT::read(std::istream& inStream, const PeHeaderT& peHeader) 105 | { 106 | IStreamWrapper inStream_w(inStream); 107 | 108 | if (!inStream_w) 109 | { 110 | return ERROR_OPENING_FILE; 111 | } 112 | 113 | std::uint64_t ulFileSize = fileSize(inStream_w); 114 | 115 | unsigned int uiRva = peHeader.getIddDebugRva(); 116 | unsigned int uiOffset = peHeader.rvaToOffset(uiRva); 117 | unsigned int uiSize = peHeader.getIddDebugSize(); 118 | 119 | if (ulFileSize < uiOffset + uiSize) 120 | { 121 | return ERROR_INVALID_FILE; 122 | } 123 | 124 | inStream_w.seekg(uiOffset, std::ios::beg); 125 | 126 | std::vector vDebugDirectory(uiSize); 127 | inStream_w.read(reinterpret_cast(vDebugDirectory.data()), uiSize); 128 | 129 | InputBuffer ibBuffer{vDebugDirectory}; 130 | 131 | std::vector currDebugInfo = DebugDirectory::read(ibBuffer, uiRva, uiSize); 132 | 133 | for (unsigned int i=0;i= ulFileSize) || 136 | (currDebugInfo[i].idd.PointerToRawData + currDebugInfo[i].idd.SizeOfData >= ulFileSize)) 137 | { 138 | return ERROR_INVALID_FILE; 139 | } 140 | 141 | inStream_w.seekg(currDebugInfo[i].idd.PointerToRawData, std::ios::beg); 142 | currDebugInfo[i].data.resize(currDebugInfo[i].idd.SizeOfData); 143 | inStream_w.read(reinterpret_cast(currDebugInfo[i].data.data()), currDebugInfo[i].idd.SizeOfData); 144 | if (!inStream_w) return ERROR_INVALID_FILE; 145 | 146 | if (currDebugInfo[i].idd.SizeOfData > 0) 147 | { 148 | m_occupiedAddresses.push_back( 149 | std::make_pair( 150 | currDebugInfo[i].idd.AddressOfRawData, 151 | currDebugInfo[i].idd.AddressOfRawData + currDebugInfo[i].idd.SizeOfData - 1 152 | )); 153 | } 154 | } 155 | 156 | std::swap(currDebugInfo, m_vDebugInfo); 157 | 158 | return ERROR_NONE; 159 | } 160 | } 161 | #endif 162 | -------------------------------------------------------------------------------- /include/pelib/DelayImportDirectory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file DelayImportDirectory.h 3 | * @brief Class for delay import directory. 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #ifndef DELAY_IMPORT_DIRECTORY_H 8 | #define DELAY_IMPORT_DIRECTORY_H 9 | 10 | #include "pelib/PeLibInc.h" 11 | #include "pelib/PeHeader.h" 12 | 13 | namespace PeLib 14 | { 15 | /** 16 | * This class handless delay import directory. 17 | */ 18 | template 19 | class DelayImportDirectory 20 | { 21 | typedef typename std::vector >::const_iterator DelayImportDirectoryIterator; 22 | typedef typename FieldSizes::VAR4_8 VAR4_8; 23 | 24 | private: 25 | std::vector > records; 26 | 27 | void init() 28 | { 29 | records.clear(); 30 | } 31 | 32 | public: 33 | DelayImportDirectory() 34 | { 35 | init(); 36 | } 37 | 38 | ~DelayImportDirectory() 39 | { 40 | 41 | } 42 | 43 | // Delay-import descriptors made by MS Visual C++ 6.0 has an old format 44 | // of delay import directory, where all entries are VAs (as opposite to RVAs from newer MS compilers). 45 | // We convert the delay-import directory entries to RVAs by checking the lowest bit in the delay-import descriptor's Attributes value 46 | VAR4_8 normalizeDelayImportValue(const PELIB_IMAGE_DELAY_IMPORT_DIRECTORY_RECORD & rec, const PeHeaderT& peHeader, VAR4_8 valueToConvert) 47 | { 48 | // Ignore zero items 49 | if (valueToConvert != 0) 50 | { 51 | // Is this the old format version? 52 | if((rec.Attributes & 0x01) == 0) 53 | { 54 | // Sample: 0fc4cb0620f95bdd624f2c78eea4d2b59594244c6671cf249526adf2f2cb71ec 55 | // Contains artificially created delay import directory with incorrect values: 56 | // 57 | // Attributes 0x00000000 <-- Old MS delay import record, contains VAs 58 | // NameRva 0x004010e6 59 | // ModuleHandleRva 0x00000000 60 | // DelayImportAddressTableRva 0x00001140 <-- WRONG! This is an RVA 61 | // DelayImportNameTableRva 0x004010c0 62 | // BoundDelayImportTableRva 0x00000000 63 | // ... 64 | 65 | if (valueToConvert > peHeader.getImageBase()) 66 | { 67 | valueToConvert = valueToConvert - peHeader.getImageBase(); 68 | } 69 | } 70 | } 71 | 72 | return valueToConvert; 73 | } 74 | 75 | int read(std::istream& inStream, const PeHeaderT& peHeader) 76 | { 77 | init(); 78 | 79 | IStreamWrapper inStream_w(inStream); 80 | if (!inStream_w) 81 | { 82 | return ERROR_OPENING_FILE; 83 | } 84 | 85 | std::uint64_t ulFileSize = fileSize(inStream_w); 86 | std::uint64_t uiOffset = peHeader.rvaToOffset(peHeader.getIddDelayImportRva()); 87 | if (uiOffset >= ulFileSize) 88 | { 89 | return ERROR_INVALID_FILE; 90 | } 91 | 92 | PELIB_IMAGE_DELAY_IMPORT_DIRECTORY_RECORD rec; 93 | std::vector dump; 94 | dump.resize(PELIB_IMAGE_SIZEOF_DELAY_IMPORT_DIRECTORY_RECORD); 95 | 96 | // Keep loading until we encounter an entry filles with zeros 97 | for(std::size_t i = 0;; i += PELIB_IMAGE_SIZEOF_DELAY_IMPORT_DIRECTORY_RECORD) 98 | { 99 | InputBuffer inputbuffer(dump); 100 | 101 | // Read the n-th import sdirectory entry 102 | if (!inStream_w.seekg(uiOffset + i, std::ios::beg)) 103 | break; 104 | if (!inStream_w.read(reinterpret_cast(dump.data()), PELIB_IMAGE_SIZEOF_DELAY_IMPORT_DIRECTORY_RECORD)) 105 | break; 106 | 107 | rec.init(); 108 | inputbuffer >> rec.Attributes; 109 | inputbuffer >> rec.NameRva; 110 | inputbuffer >> rec.ModuleHandleRva; 111 | inputbuffer >> rec.DelayImportAddressTableRva; 112 | inputbuffer >> rec.DelayImportNameTableRva; 113 | inputbuffer >> rec.BoundDelayImportTableRva; 114 | inputbuffer >> rec.UnloadDelayImportTableRva; 115 | inputbuffer >> rec.TimeStamp; 116 | if ( rec.Attributes == 0 && rec.NameRva == 0 && rec.ModuleHandleRva == 0 && rec.DelayImportAddressTableRva == 0 && 117 | rec.DelayImportNameTableRva == 0 && rec.BoundDelayImportTableRva == 0 && rec.UnloadDelayImportTableRva == 0 && 118 | rec.TimeStamp == 0) 119 | { 120 | break; 121 | } 122 | 123 | // Convert older (MS Visual C++ 6.0) delay-import descriptor to newer one. 124 | // These delay-import descriptors are distinguishable by lowest bit in rec.Attributes to be zero. 125 | // Sample: 2775d97f8bdb3311ace960a42eee35dbec84b9d71a6abbacb26c14e83f5897e4 126 | rec.NameRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.NameRva); 127 | rec.ModuleHandleRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.ModuleHandleRva); 128 | rec.DelayImportAddressTableRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.DelayImportAddressTableRva); 129 | rec.DelayImportNameTableRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.DelayImportNameTableRva); 130 | rec.BoundDelayImportTableRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.BoundDelayImportTableRva); 131 | rec.UnloadDelayImportTableRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.UnloadDelayImportTableRva); 132 | 133 | rec.DelayImportAddressTableOffset = (dword)peHeader.rvaToOffset(rec.DelayImportAddressTableRva); 134 | rec.DelayImportNameTableOffset = (dword)peHeader.rvaToOffset(rec.DelayImportNameTableRva); 135 | 136 | // Get name of library 137 | getStringFromFileOffset(inStream_w, rec.Name, (std::size_t)peHeader.rvaToOffset(rec.NameRva), IMPORT_LIBRARY_MAX_LENGTH); 138 | 139 | // 140 | // LOADING NAME ADDRESSES/NAME ORDINALS 141 | // 142 | 143 | // Address table is not guaranteed to be null-terminated and therefore we need to first read name table. 144 | inStream_w.seekg(rec.DelayImportNameTableOffset, std::ios::beg); 145 | if(!inStream_w) 146 | { 147 | return ERROR_INVALID_FILE; 148 | } 149 | 150 | // Read all RVAs (or VAs) of import names 151 | std::vector> nameAddresses; 152 | for(;;) 153 | { 154 | PELIB_VAR_SIZE nameAddr; 155 | std::vector vBuffer(sizeof(nameAddr.Value)); 156 | 157 | // Read the value from the file 158 | inStream_w.read(reinterpret_cast(vBuffer.data()), sizeof(nameAddr.Value)); 159 | if (!inStream_w || inStream_w.gcount() < sizeof(nameAddr.Value)) 160 | break; 161 | 162 | InputBuffer inb(vBuffer); 163 | inb >> nameAddr.Value; 164 | 165 | // Value of zero means that this is the end of the bound import name table 166 | if (nameAddr.Value == 0) 167 | break; 168 | nameAddresses.push_back(nameAddr); 169 | } 170 | 171 | // 172 | // LOADING FUNCTION POINTERS 173 | // 174 | 175 | // Move to the offset of function addresses 176 | inStream_w.seekg(rec.DelayImportAddressTableOffset, std::ios::beg); 177 | if (!inStream_w) 178 | { 179 | return ERROR_INVALID_FILE; 180 | } 181 | 182 | // Read all (VAs) of import names 183 | std::vector> funcAddresses; 184 | for (std::size_t i = 0, e = nameAddresses.size(); i < e; ++i) 185 | { 186 | PELIB_VAR_SIZE funcAddr; 187 | std::vector vBuffer(sizeof(funcAddr.Value)); 188 | 189 | // Read the value from the file 190 | inStream_w.read(reinterpret_cast(vBuffer.data()), sizeof(funcAddr.Value)); 191 | if (!inStream_w || inStream_w.gcount() < sizeof(funcAddr.Value)) 192 | break; 193 | 194 | InputBuffer inb(vBuffer); 195 | inb >> funcAddr.Value; 196 | 197 | // The value of zero means terminator of the function table 198 | if (funcAddr.Value == 0) 199 | break; 200 | funcAddresses.push_back(funcAddr); 201 | } 202 | 203 | // 204 | // MERGE BOTH TOGETHER 205 | // 206 | 207 | std::size_t numberOfFunctions = std::min(nameAddresses.size(), funcAddresses.size()); 208 | for (std::size_t i = 0; i < numberOfFunctions; i++) 209 | { 210 | PELIB_DELAY_IMPORT function; 211 | PELIB_VAR_SIZE nameAddr = nameAddresses[i]; 212 | PELIB_VAR_SIZE funcAddr = funcAddresses[i]; 213 | 214 | // Check name address. It could be ordinal, VA or RVA 215 | if (!(nameAddr.Value & PELIB_IMAGE_ORDINAL_FLAGS::PELIB_IMAGE_ORDINAL_FLAG)) 216 | { 217 | // Convert value to RVA, if needed 218 | nameAddr.Value = normalizeDelayImportValue(rec, peHeader, nameAddr.Value); 219 | 220 | // Read the function hint 221 | inStream_w.seekg(peHeader.rvaToOffset(nameAddr.Value), std::ios::beg); 222 | inStream_w.read(reinterpret_cast(&function.hint), sizeof(function.hint)); 223 | if (!inStream_w || inStream_w.gcount() < sizeof(function.hint)) 224 | break; 225 | 226 | // Read the function name 227 | getStringFromFileOffset(inStream_w, function.fname, inStream_w.tellg(), IMPORT_SYMBOL_MAX_LENGTH); 228 | } 229 | else 230 | { 231 | function.hint = (word)(nameAddr.Value & 0xFFFF); 232 | } 233 | 234 | // Fill-in function address. The table is always in the image itself 235 | if (peHeader.getImageBase() <= funcAddr.Value && funcAddr.Value < peHeader.getImageBase() + peHeader.getSizeOfImage()) 236 | funcAddr.Value -= peHeader.getImageBase(); 237 | function.address.Value = funcAddr.Value; 238 | 239 | // Insert the function to the list 240 | rec.addFunction(function); 241 | } 242 | 243 | records.push_back(rec); 244 | } 245 | 246 | return ERROR_NONE; 247 | } 248 | 249 | std::size_t getNumberOfFiles() const 250 | { 251 | return records.size(); 252 | } 253 | 254 | const PELIB_IMAGE_DELAY_IMPORT_DIRECTORY_RECORD *getFile(std::size_t index) const 255 | { 256 | return index < getNumberOfFiles() ? &records[index] : nullptr; 257 | } 258 | 259 | DelayImportDirectoryIterator begin() const 260 | { 261 | return records.begin(); 262 | } 263 | 264 | DelayImportDirectoryIterator end() const 265 | { 266 | return records.end(); 267 | } 268 | }; 269 | } 270 | 271 | #endif 272 | -------------------------------------------------------------------------------- /include/pelib/ExportDirectory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ExportDirectory.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef EXPORTDIRECTORY_H 14 | #define EXPORTDIRECTORY_H 15 | 16 | #include "pelib/PeHeader.h" 17 | 18 | namespace PeLib 19 | { 20 | /// Class that handles the export directory. 21 | /** 22 | * This class handles the export directory. 23 | * \todo getNameString 24 | **/ 25 | class ExportDirectory 26 | { 27 | protected: 28 | /// Used to store all necessary information about a file's exported functions. 29 | PELIB_IMAGE_EXP_DIRECTORY m_ied; 30 | /// Stores RVAs which are occupied by this export directory. 31 | std::vector> m_occupiedAddresses; 32 | 33 | public: 34 | virtual ~ExportDirectory() = default; 35 | 36 | /// Add another function to be exported. 37 | void addFunction(const std::string& strFuncname, dword dwFuncAddr); // EXPORT 38 | unsigned int calcNumberOfFunctions() const; // EXPORT 39 | void clear(); // EXPORT 40 | /// Identifies a function through it's name. 41 | int getFunctionIndex(const std::string& strFunctionName) const; // EXPORT 42 | /// Rebuild the current export directory. 43 | void rebuild(std::vector& vBuffer, dword dwRva) const; // EXPORT 44 | void removeFunction(unsigned int index); // EXPORT 45 | /// Returns the size of the current export directory. 46 | unsigned int size() const; // EXPORT 47 | /// Writes the current export directory to a file. 48 | int write(const std::string& strFilename, unsigned int uiOffset, unsigned int uiRva) const; // EXPORT 49 | 50 | /// Changes the name of the file (according to the export directory). 51 | void setNameString(const std::string& strFilename); // EXPORT 52 | std::string getNameString() const; // EXPORT 53 | 54 | /// Get the name of an exported function. 55 | std::string getFunctionName(std::size_t index) const; // EXPORT 56 | /// Get the ordinal of an exported function. 57 | word getFunctionOrdinal(std::size_t index) const; // EXPORT 58 | /// Get the address of the name of an exported function. 59 | dword getAddressOfName(std::size_t index) const; // EXPORT 60 | /// Get the address of an exported function. 61 | dword getAddressOfFunction(std::size_t index) const; // EXPORT 62 | 63 | /// Change the name of an exported function. 64 | void setFunctionName(std::size_t index, const std::string& strName); // EXPORT 65 | /// Change the ordinal of an exported function. 66 | void setFunctionOrdinal(std::size_t index, word wValue); // EXPORT 67 | /// Change the address of the name of an exported function. 68 | void setAddressOfName(std::size_t index, dword dwValue); // EXPORT 69 | /// Change the address of an exported function. 70 | void setAddressOfFunction(std::size_t index, dword dwValue); // EXPORT 71 | 72 | /* 73 | word getFunctionOrdinal(std::string strFuncname) const; 74 | dword getAddressOfName(std::string strFuncname) const; 75 | dword getAddressOfFunction(std::string strFuncname) const; 76 | 77 | void setFunctionOrdinal(std::string strFuncname, word wValue); 78 | void setAddressOfName(std::string strFuncname, dword dwValue); 79 | void setAddressOfFunction(std::string strFuncname, dword dwValue); 80 | */ 81 | 82 | /// Return the Base value of the export directory. 83 | dword getBase() const; // EXPORT 84 | /// Return the Characteristics value of the export directory. 85 | dword getCharacteristics() const; // EXPORT 86 | /// Return the TimeDateStamp value of the export directory. 87 | dword getTimeDateStamp() const; // EXPORT 88 | /// Return the MajorVersion value of the export directory. 89 | word getMajorVersion() const; // EXPORT 90 | /// Return the MinorVersion value of the export directory. 91 | word getMinorVersion() const; // EXPORT 92 | /// Return the Name value of the export directory. 93 | dword getName() const; // EXPORT 94 | /// Return the NumberOfFunctions value of the export directory. 95 | dword getNumberOfFunctions() const; // EXPORT 96 | /// Return the NumberOfNames value of the export directory. 97 | dword getNumberOfNames() const; // EXPORT 98 | /// Return the AddressOfFunctions value of the export directory. 99 | dword getAddressOfFunctions() const; // EXPORT 100 | /// Return the AddressOfNames value of the export directory. 101 | dword getAddressOfNames() const; // EXPORT 102 | /// Returns the AddressOfNameOrdinals value. 103 | dword getAddressOfNameOrdinals() const; // EXPORT 104 | 105 | /* /// Returns the number of NameOrdinals. 106 | dword getNumberOfNameOrdinals() const; // EXPORT 107 | /// Returns the number of AddressOfFunctionNames values. 108 | dword getNumberOfAddressOfFunctionNames() const; // EXPORT 109 | /// Returns the number of AddressOfFunction values. 110 | dword getNumberOfAddressOfFunctions() const; // EXPORT 111 | */ 112 | /// Set the Base value of the export directory. 113 | void setBase(dword dwValue); // EXPORT 114 | /// Set the Characteristics value of the export directory. 115 | void setCharacteristics(dword dwValue); // EXPORT 116 | /// Set the TimeDateStamp value of the export directory. 117 | void setTimeDateStamp(dword dwValue); // EXPORT 118 | /// Set the MajorVersion value of the export directory. 119 | void setMajorVersion(word wValue); // EXPORT 120 | /// Set the MinorVersion value of the export directory. 121 | void setMinorVersion(word wValue); // EXPORT 122 | /// Set the Name value of the export directory. 123 | void setName(dword dwValue); // EXPORT 124 | /// Set the NumberOfFunctions value of the export directory. 125 | void setNumberOfFunctions(dword dwValue); // EXPORT 126 | /// Set the NumberOfNames value of the export directory. 127 | void setNumberOfNames(dword dwValue); // EXPORT 128 | /// Set the AddressOfFunctions value of the export directory. 129 | void setAddressOfFunctions(dword dwValue); // EXPORT 130 | /// Set the AddressOfNames value of the export directory. 131 | void setAddressOfNames(dword dwValue); // EXPORT 132 | void setAddressOfNameOrdinals(dword value); // EXPORT 133 | 134 | const std::vector>& getOccupiedAddresses() const; 135 | }; 136 | 137 | template 138 | class ExportDirectoryT : public ExportDirectory 139 | { 140 | public: 141 | /// Read a file's export directory. 142 | int read(std::istream& inStream, const PeHeaderT& peHeader); // EXPORT 143 | }; 144 | 145 | /** 146 | * @param inStream Input stream. 147 | * @param peHeader A valid PE header which is necessary because some RVA calculations need to be done. 148 | * \todo: Proper use of InputBuffer 149 | **/ 150 | template 151 | int ExportDirectoryT::read( 152 | std::istream& inStream, 153 | const PeHeaderT& peHeader) 154 | { 155 | IStreamWrapper inStream_w(inStream); 156 | 157 | if (!inStream_w) 158 | { 159 | return ERROR_OPENING_FILE; 160 | } 161 | 162 | std::uint64_t ulFileSize = fileSize(inStream_w); 163 | unsigned int dirRva = peHeader.getIddExportRva(); 164 | unsigned int dirOffset = peHeader.rvaToOffset(dirRva); 165 | if (ulFileSize < dirOffset + PELIB_IMAGE_EXPORT_DIRECTORY::size()) 166 | { 167 | return ERROR_INVALID_FILE; 168 | } 169 | inStream_w.seekg(dirOffset, std::ios::beg); 170 | 171 | std::vector vExportDirectory(PELIB_IMAGE_EXPORT_DIRECTORY::size()); 172 | inStream_w.read(reinterpret_cast(vExportDirectory.data()), PELIB_IMAGE_EXPORT_DIRECTORY::size()); 173 | 174 | InputBuffer inpBuffer(vExportDirectory); 175 | 176 | PELIB_IMAGE_EXP_DIRECTORY iedCurr; 177 | inpBuffer >> iedCurr.ied.Characteristics; 178 | inpBuffer >> iedCurr.ied.TimeDateStamp; 179 | inpBuffer >> iedCurr.ied.MajorVersion; 180 | inpBuffer >> iedCurr.ied.MinorVersion; 181 | inpBuffer >> iedCurr.ied.Name; 182 | inpBuffer >> iedCurr.ied.Base; 183 | inpBuffer >> iedCurr.ied.NumberOfFunctions; 184 | inpBuffer >> iedCurr.ied.NumberOfNames; 185 | inpBuffer >> iedCurr.ied.AddressOfFunctions; 186 | inpBuffer >> iedCurr.ied.AddressOfNames; 187 | inpBuffer >> iedCurr.ied.AddressOfNameOrdinals; 188 | m_occupiedAddresses.emplace_back(dirRva, dirRva + PELIB_IMAGE_EXPORT_DIRECTORY::size() - 1); 189 | 190 | // Verify the export directory. Do not allow more functions than the limit 191 | // Sample: CCE461B6EB23728BA3B8A97B9BE84C0FB9175DB31B9949E64144198AB3F702CE 192 | if (iedCurr.ied.NumberOfFunctions > PELIB_MAX_EXPORTED_FUNCTIONS || iedCurr.ied.NumberOfNames > PELIB_MAX_EXPORTED_FUNCTIONS) 193 | return ERROR_INVALID_FILE; 194 | 195 | unsigned int offset = peHeader.rvaToOffset(iedCurr.ied.Name); 196 | if (offset >= ulFileSize) 197 | return ERROR_INVALID_FILE; 198 | inStream_w.seekg(offset, std::ios::beg); 199 | 200 | char c = 0; 201 | std::string strFname = ""; 202 | do 203 | { 204 | inStream_w.read(reinterpret_cast(&c), sizeof(c)); 205 | if (!inStream_w) return ERROR_INVALID_FILE; 206 | if (c) strFname += c; 207 | } 208 | while (c != 0); 209 | iedCurr.name = strFname; 210 | m_occupiedAddresses.push_back(std::make_pair(iedCurr.ied.Name, iedCurr.ied.Name + strFname.length() + 1)); 211 | 212 | PELIB_EXP_FUNC_INFORMATION efiCurr; 213 | efiCurr.ordinal = 0; efiCurr.addroffunc = 0; efiCurr.addrofname = 0; 214 | for (unsigned int i=0;i= ulFileSize) 218 | return ERROR_INVALID_FILE; 219 | inStream_w.seekg(offset, std::ios::beg); 220 | inStream_w.read(reinterpret_cast(&efiCurr.addroffunc), sizeof(efiCurr.addroffunc)); 221 | if (!inStream_w) 222 | return ERROR_INVALID_FILE; 223 | 224 | efiCurr.ordinal = iedCurr.ied.Base + i; 225 | iedCurr.functions.push_back(efiCurr); 226 | 227 | m_occupiedAddresses.emplace_back( 228 | iedCurr.ied.AddressOfFunctions + i*sizeof(efiCurr.addroffunc), 229 | iedCurr.ied.AddressOfFunctions + i*sizeof(efiCurr.addroffunc) + sizeof(efiCurr.addroffunc) - 1 230 | ); 231 | } 232 | 233 | for (unsigned int i=0;i= ulFileSize) 237 | return ERROR_INVALID_FILE; 238 | inStream_w.seekg(offset, std::ios::beg); 239 | word ordinal; 240 | inStream_w.read(reinterpret_cast(&ordinal), sizeof(ordinal)); 241 | m_occupiedAddresses.emplace_back( 242 | iedCurr.ied.AddressOfNameOrdinals + i*sizeof(efiCurr.ordinal), 243 | iedCurr.ied.AddressOfNameOrdinals + i*sizeof(efiCurr.ordinal) + sizeof(efiCurr.ordinal) - 1 244 | ); 245 | 246 | if (!inStream_w) 247 | return ERROR_INVALID_FILE; 248 | else if (ordinal >= iedCurr.functions.size()) 249 | continue; 250 | 251 | iedCurr.functions[ordinal].ordinal = iedCurr.ied.Base + ordinal; 252 | 253 | offset = peHeader.rvaToOffset(iedCurr.ied.AddressOfNames) + i*sizeof(efiCurr.addrofname); 254 | if (offset >= ulFileSize) 255 | return ERROR_INVALID_FILE; 256 | inStream_w.seekg(offset, std::ios::beg); 257 | inStream_w.read(reinterpret_cast(&iedCurr.functions[ordinal].addrofname), sizeof(iedCurr.functions[ordinal].addrofname)); 258 | if (!inStream_w) 259 | return ERROR_INVALID_FILE; 260 | m_occupiedAddresses.emplace_back( 261 | iedCurr.ied.AddressOfNames + i*sizeof(efiCurr.addrofname), 262 | iedCurr.ied.AddressOfNames + i*sizeof(efiCurr.addrofname) + sizeof(iedCurr.functions[ordinal].addrofname) - 1 263 | ); 264 | 265 | offset = peHeader.rvaToOffset(iedCurr.functions[ordinal].addrofname); 266 | if (offset >= ulFileSize) 267 | return ERROR_INVALID_FILE; 268 | inStream_w.seekg(offset, std::ios::beg); 269 | 270 | char cc = 0; 271 | std::string strFname2 = ""; 272 | do 273 | { 274 | inStream_w.read(reinterpret_cast(&cc), sizeof(cc)); 275 | 276 | if (!inStream_w) 277 | return ERROR_INVALID_FILE; 278 | 279 | if (cc) strFname2 += cc; 280 | } 281 | while (cc != 0); 282 | 283 | iedCurr.functions[ordinal].funcname = strFname2; 284 | 285 | m_occupiedAddresses.emplace_back( 286 | iedCurr.functions[ordinal].addrofname, 287 | iedCurr.functions[ordinal].addrofname + strFname2.length() + 1 288 | ); 289 | } 290 | 291 | std::swap(m_ied, iedCurr); 292 | 293 | return ERROR_NONE; 294 | } 295 | } 296 | #endif 297 | -------------------------------------------------------------------------------- /include/pelib/IatDirectory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IatDirectory.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef IATDIRECTORY_H 14 | #define IATDIRECTORY_H 15 | 16 | #include "pelib/PeLibInc.h" 17 | #include "pelib/PeHeader.h" 18 | 19 | namespace PeLib 20 | { 21 | /// Class that handles the Import Address Table (IAT) 22 | /** 23 | * This class can read and modify the Import Address Table of a PE file. 24 | **/ 25 | class IatDirectory 26 | { 27 | protected: 28 | std::vector m_vIat; ///< Stores the individual IAT fields. 29 | 30 | int read(InputBuffer& inputBuffer, unsigned int dwOffset, unsigned int dwFileSize); 31 | 32 | public: 33 | virtual ~IatDirectory() = default; 34 | 35 | /// Reads the Import Address Table from a PE file. 36 | int read(unsigned char* buffer, unsigned int buffersize); // EXPORT 37 | /// Returns the number of fields in the IAT. 38 | unsigned int calcNumberOfAddresses() const; // EXPORT 39 | /// Adds another address to the IAT. 40 | void addAddress(dword dwValue); // EXPORT 41 | /// Removes an address from the IAT. 42 | void removeAddress(unsigned int index); // EXPORT 43 | /// Empties the IAT. 44 | void clear(); // EXPORT 45 | // Rebuilds the IAT. 46 | void rebuild(std::vector& vBuffer) const; // EXPORT 47 | /// Returns the size of the current IAT. 48 | unsigned int size() const; // EXPORT 49 | /// Writes the current IAT to a file. 50 | int write(const std::string& strFilename, unsigned int uiOffset) const; // EXPORT 51 | 52 | /// Retrieve the value of a field in the IAT. 53 | dword getAddress(unsigned int index) const; // EXPORT 54 | /// Change the value of a field in the IAT. 55 | void setAddress(dword dwAddrnr, dword dwValue); // EXPORT 56 | }; 57 | 58 | template 59 | class IatDirectoryT : public IatDirectory 60 | { 61 | public: 62 | int read(std::istream& inStream, const PeHeaderT& peHeader); // EXPORT 63 | }; 64 | 65 | /** 66 | * Reads the Import Address table from a file. 67 | * @param inStream Input stream. 68 | * @param peHeader A valid PE header which is necessary because some RVA calculations need to be done. 69 | **/ 70 | template 71 | int IatDirectoryT::read(std::istream& inStream, const PeHeaderT& peHeader) 72 | { 73 | IStreamWrapper inStream_w(inStream); 74 | 75 | if (!inStream_w) 76 | { 77 | return ERROR_OPENING_FILE; 78 | } 79 | 80 | std::uint64_t ulFileSize = fileSize(inStream_w); 81 | std::uint64_t dwOffset = peHeader.rvaToOffset(peHeader.getIddIatRva()); 82 | std::uint64_t dwSize = peHeader.getIddIatSize(); 83 | 84 | if (ulFileSize <= dwOffset) 85 | { 86 | return ERROR_INVALID_FILE; 87 | } 88 | 89 | dwSize = std::min(ulFileSize - dwOffset, dwSize); 90 | inStream_w.seekg(dwOffset, std::ios::beg); 91 | 92 | std::vector vBuffer(dwSize); 93 | inStream_w.read(reinterpret_cast(vBuffer.data()), dwSize); 94 | 95 | InputBuffer inpBuffer{vBuffer}; 96 | return IatDirectory::read(inpBuffer, dwOffset, ulFileSize); 97 | } 98 | 99 | } 100 | 101 | #endif 102 | 103 | -------------------------------------------------------------------------------- /include/pelib/InputBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * InputBuffer.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef INPUTBUFFER_H 14 | #define INPUTBUFFER_H 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | namespace PeLib 21 | { 22 | class InputBuffer 23 | { 24 | private: 25 | std::vector& m_vBuffer; 26 | unsigned long ulIndex; 27 | 28 | public: 29 | InputBuffer(std::vector& vBuffer); 30 | 31 | const unsigned char* data() const; 32 | unsigned long size(); 33 | 34 | template 35 | InputBuffer& operator>>(T& value) 36 | { 37 | //jk: temporarily disabled because of fails on 64bit systems 38 | // assert(ulIndex + sizeof(value) <= m_vBuffer.size()); 39 | 40 | std::vector data(sizeof(T), 0); 41 | std::size_t size = ulIndex + sizeof(T) > m_vBuffer.size() ? m_vBuffer.size() - ulIndex : sizeof(T); 42 | read(data.data(), (unsigned long)size); 43 | value = *reinterpret_cast(data.data()); 44 | return *this; 45 | } 46 | 47 | void read(char* lpBuffer, unsigned long ulSize); 48 | void reset(); 49 | void set(unsigned long ulIndex2); 50 | void move(unsigned long shift); 51 | unsigned long get(); 52 | void setBuffer(std::vector& vBuffer); 53 | // void updateData(unsigned long ulIndex, 54 | }; 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /include/pelib/MzHeader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MzHeader.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef MZHEADER_H 14 | #define MZHEADER_H 15 | 16 | #include "pelib/PeLibInc.h" 17 | 18 | namespace PeLib 19 | { 20 | /// Class that handles the MZ header of files. 21 | /** 22 | * This class can read and modify MZ headers. It provides set- and get functions to access 23 | * all individual members of a MZ header. Furthermore it's possible to validate and rebuild 24 | * MZ headers. 25 | **/ 26 | class MzHeader 27 | { 28 | private: 29 | PELIB_IMAGE_DOS_HEADER m_idhHeader; ///< Stores all MZ header information. 30 | std::string m_headerString; ///< MZ header in string representation. 31 | LoaderError m_ldrError; 32 | 33 | /// Reads data from an InputBuffer into a MZ header struct. 34 | void read(InputBuffer& ibBuffer); 35 | 36 | /// Offset of the MZ header in the original file. 37 | unsigned int originalOffset; 38 | 39 | void setLoaderError(LoaderError ldrError); 40 | 41 | public: 42 | 43 | enum Field {e_magic, e_cblp, e_cp, e_crlc, e_cparhdr, e_minalloc, e_maxalloc, 44 | e_ss, e_sp, e_csum, e_ip, e_cs, e_lfarlc, e_ovno, e_res, e_oemid, 45 | e_oeminfo, e_res2, e_lfanew}; 46 | 47 | MzHeader(); 48 | 49 | /// Checks if the current MZ header is valid. 50 | bool isValid() const; // EXPORT 51 | 52 | bool isValid(Field field) const; // EXPORT _field 53 | 54 | /// Returns loader error for the header 55 | LoaderError loaderError() const; 56 | 57 | /// Corrects the current MZ header. 58 | void makeValid(); // EXPORT 59 | 60 | void makeValid(Field field); // EXPORT _field 61 | 62 | /// Reads the MZ header of a file. 63 | int read(std::istream& inStream); // EXPORT 64 | 65 | /// Reads the MZ header from a memory location. 66 | int read(unsigned char* pcBuffer, unsigned int uiSize, unsigned int originalOffs = 0); // EXPORT _fromMemory 67 | 68 | /// Rebuild the MZ header. 69 | void rebuild(std::vector& vBuffer) const; // EXPORT 70 | 71 | /// Returns the size of the current MZ header. 72 | unsigned int size() const; // EXPORT 73 | 74 | /// Writes the current MZ header to offset 0 of a file. 75 | int write(const std::string& strFilename, dword dwOffset) const; // EXPORT 76 | 77 | /// Gets MZ header. 78 | const PELIB_IMAGE_DOS_HEADER& getHeader() const; // EXPORT 79 | /// Gets MZ header in string representation. 80 | const std::string& getString() const; // EXPORT 81 | 82 | /// Gets the e_magic value of the MZ header. 83 | word getMagicNumber() const; // EXPORT 84 | /// Gets the e_cblp value of the MZ header. 85 | word getBytesOnLastPage() const; // EXPORT 86 | /// Gets the e_cp value of the MZ header. 87 | word getPagesInFile() const; // EXPORT 88 | /// Gets the e_crlc value of the MZ header. 89 | word getRelocations() const; // EXPORT 90 | /// Gets the e_cparhdr value of the MZ header. 91 | word getSizeOfHeader() const; // EXPORT 92 | /// Gets the e_minalloc value of the MZ header. 93 | word getMinExtraParagraphs() const; // EXPORT 94 | /// Gets the e_maxalloc value of the MZ header. 95 | word getMaxExtraParagraphs() const; // EXPORT 96 | /// Gets the e_ss value of the MZ header. 97 | word getSsValue() const; // EXPORT 98 | /// Gets the e_sp value of the MZ header. 99 | word getSpValue() const; // EXPORT 100 | /// Gets the e_csum value of the MZ header. 101 | word getChecksum() const; // EXPORT 102 | /// Gets the e_ip value of the MZ header. 103 | word getIpValue() const; // EXPORT 104 | /// Gets the e_cs value of the MZ header. 105 | word getCsValue() const; // EXPORT 106 | /// Gets the e_lfarlc value of the MZ header. 107 | word getAddrOfRelocationTable() const; // EXPORT 108 | /// Gets the e_ovnovalue of the MZ header. 109 | word getOverlayNumber() const; // EXPORT 110 | /// Gets the e_oemid value of the MZ header. 111 | word getOemIdentifier() const; // EXPORT 112 | /// Gets the e_oeminfo value of the MZ header. 113 | word getOemInformation() const; // EXPORT 114 | /// Gets the e_lfanew value of the MZ header. 115 | dword getAddressOfPeHeader() const; // EXPORT 116 | /// Gets the e_res of the MZ header. 117 | word getReservedWords1(unsigned int uiNr) const; // EXPORT 118 | /// Gets the e_res2 of the MZ header. 119 | word getReservedWords2(unsigned int uiNr) const; // EXPORT 120 | 121 | /// Sets the e_magic value of the MZ header. 122 | void setMagicNumber(word wValue); // EXPORT 123 | /// Sets the e_cblp value of the MZ header. 124 | void setBytesOnLastPage(word wValue); // EXPORT 125 | /// Sets the e_cp value of the MZ header. 126 | void setPagesInFile(word wValue); // EXPORT 127 | /// Sets the e_crlc value of the MZ header. 128 | void setRelocations(word wValue); // EXPORT 129 | /// Sets the e_cparhdr value of the MZ header. 130 | void setSizeOfHeader(word wValue); // EXPORT 131 | /// Sets the e_minalloc value of the MZ header. 132 | void setMinExtraParagraphs(word wValue); // EXPORT 133 | /// Sets the e_maxalloc value of the MZ header. 134 | void setMaxExtraParagraphs(word wValue); // EXPORT 135 | /// Sets the e_ss value of the MZ header. 136 | void setSsValue(word wValue); // EXPORT 137 | /// Sets the e_sp value of the MZ header. 138 | void setSpValue(word wValue); // EXPORT 139 | /// Sets the e_csum value of the MZ header. 140 | void setChecksum(word wValue); // EXPORT 141 | /// Sets the e_ip value of the MZ header. 142 | void setIpValue(word wValue); // EXPORT 143 | /// Sets the e_cs value of the MZ header. 144 | void setCsValue(word wValue); // EXPORT 145 | /// Sets the e_lfarlc value of the MZ header. 146 | void setAddrOfRelocationTable(word wValue); // EXPORT 147 | /// Sets the e_ovno value of the MZ header. 148 | void setOverlayNumber(word wValue); // EXPORT 149 | /// Sets the e_oemid value of the MZ header. 150 | void setOemIdentifier(word wValue); // EXPORT 151 | /// Sets the e_oeminfo value of the MZ header. 152 | void setOemInformation(word wValue); // EXPORT 153 | /// Sets the e_lfanew value of the MZ header. 154 | void setAddressOfPeHeader(dword dwValue); // EXPORT 155 | /// Sets the e_res value of the MZ header. 156 | void setReservedWords1(unsigned int uiNr, word wValue); // EXPORT 157 | /// Sets the e_res2 value of the MZ header. 158 | void setReservedWords2(unsigned int uiNr, word wValue); // EXPORT 159 | }; 160 | } 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /include/pelib/OutputBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OutputBuffer.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef OUTPUTBUFFER_H 14 | #define OUTPUTBUFFER_H 15 | 16 | #include 17 | #include 18 | 19 | namespace PeLib 20 | { 21 | class OutputBuffer 22 | { 23 | private: 24 | std::vector& m_vBuffer; 25 | 26 | public: 27 | OutputBuffer(std::vector& vBuffer); 28 | const unsigned char* data() const; 29 | unsigned long size(); 30 | 31 | template 32 | OutputBuffer& operator<<(const T& value) 33 | { 34 | const unsigned char* p = reinterpret_cast(&value); 35 | std::copy(p, p + sizeof(value), std::back_inserter(m_vBuffer)); 36 | return *this; 37 | } 38 | void add(const char* lpBuffer, unsigned long ulSize); 39 | void reset(); 40 | void resize(unsigned int uiSize); 41 | void set(unsigned int uiPosition); 42 | 43 | template 44 | void update(unsigned long ulIndex, const T& value) 45 | { 46 | *reinterpret_cast(m_vBuffer.data() + ulIndex) = value; 47 | } 48 | 49 | template 50 | void insert(unsigned long ulIndex, const T& value) 51 | { 52 | if (ulIndex + sizeof(T) >= size()) 53 | resize(ulIndex + sizeof(T)); 54 | 55 | update(ulIndex, value); 56 | } 57 | }; 58 | } 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /include/pelib/PeFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PeFile.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef PEFILE_H 14 | #define PEFILE_H 15 | 16 | #include "pelib/PeLibInc.h" 17 | #include "pelib/MzHeader.h" 18 | #include "pelib/PeHeader.h" 19 | #include "pelib/ImportDirectory.h" 20 | #include "pelib/ExportDirectory.h" 21 | #include "pelib/BoundImportDirectory.h" 22 | #include "pelib/ResourceDirectory.h" 23 | #include "pelib/RelocationsDirectory.h" 24 | #include "pelib/ComHeaderDirectory.h" 25 | #include "pelib/IatDirectory.h" 26 | #include "pelib/DebugDirectory.h" 27 | #include "pelib/TlsDirectory.h" 28 | #include "pelib/RichHeader.h" 29 | #include "pelib/CoffSymbolTable.h" 30 | #include "pelib/DelayImportDirectory.h" 31 | #include "pelib/SecurityDirectory.h" 32 | 33 | namespace PeLib 34 | { 35 | class PeFile32; 36 | class PeFile64; 37 | 38 | /** 39 | * Visitor base class for PeFiles. 40 | **/ 41 | class PeFileVisitor 42 | { 43 | public: 44 | virtual void callback(PeFile32 &file){(void) file; /* avoid warning about unused parameter */} 45 | virtual void callback(PeFile64 &file){(void) file; /* avoid warning about unused parameter */} 46 | virtual ~PeFileVisitor(){} 47 | }; 48 | 49 | /** 50 | * Traits class that's used to decide of what type the PeHeader in a PeFile is. 51 | **/ 52 | template 53 | struct PeFile_Traits; 54 | 55 | template<> 56 | struct PeFile_Traits<32> 57 | { 58 | typedef PeHeader32 PeHeader32_64; 59 | }; 60 | 61 | template<> 62 | struct PeFile_Traits<64> 63 | { 64 | typedef PeHeader64 PeHeader32_64; 65 | }; 66 | 67 | /** 68 | * This class represents the common structures of PE and PE+ files. 69 | **/ 70 | class PeFile 71 | { 72 | protected: 73 | std::string m_filename; ///< Name of the current file. 74 | MzHeader m_mzh; ///< MZ header of the current file. 75 | RichHeader m_richheader; ///< Rich header of the current file. 76 | CoffSymbolTable m_coffsymtab; ///< Symbol table of the current file. 77 | SecurityDirectory m_secdir; ///< Security directory of the current file. 78 | public: 79 | virtual ~PeFile(); 80 | 81 | /// Returns the name of the current file. 82 | virtual std::string getFileName() const = 0; // EXPORT 83 | /// Changes the name of the current file. 84 | virtual void setFileName(std::string strFilename) = 0; // EXPORT 85 | 86 | virtual void visit(PeFileVisitor &v) = 0; 87 | 88 | /// Reads the MZ header of the current file from disc. 89 | virtual int readMzHeader() = 0; // EXPORT 90 | /// Reads the export directory of the current file from disc. 91 | virtual int readExportDirectory() = 0; // EXPORT 92 | /// Reads the PE header of the current file from disc. 93 | virtual int readPeHeader() = 0; // EXPORT 94 | /// Reads the import directory of the current file from disc. 95 | virtual int readImportDirectory() = 0; // EXPORT 96 | /// Reads the bound import directory of the current file from disc. 97 | virtual int readBoundImportDirectory() = 0; // EXPORT 98 | /// Reads the resource directory of the current file from disc. 99 | virtual int readResourceDirectory() = 0; // EXPORT 100 | /// Reads the relocations directory of the current file from disc. 101 | virtual int readRelocationsDirectory() = 0; // EXPORT 102 | /// Reads the COM+ descriptor directory of the current file from disc. 103 | virtual int readComHeaderDirectory() = 0; // EXPORT 104 | /// Reads the IAT directory of the current file from disc. 105 | virtual int readIatDirectory() = 0; // EXPORT 106 | /// Reads the Debug directory of the current file. 107 | virtual int readDebugDirectory() = 0; // EXPORT 108 | /// Reads the TLS directory of the current file. 109 | virtual int readTlsDirectory() = 0; // EXPORT 110 | /// Reads rich header of the current file. 111 | virtual int readRichHeader(std::size_t offset, std::size_t size, bool ignoreInvalidKey = false) = 0; // EXPORT 112 | /// Reads the COFF symbol table of the current file. 113 | virtual int readCoffSymbolTable() = 0; // EXPORT 114 | /// Reads delay import directory of the current file. 115 | virtual int readDelayImportDirectory() = 0; // EXPORT 116 | /// Reads security directory of the current file. 117 | virtual int readSecurityDirectory() = 0; // EXPORT 118 | /// Returns a loader error, if there was any 119 | virtual LoaderError loaderError() const = 0; 120 | 121 | virtual unsigned int getBits() const = 0; 122 | 123 | /// Accessor function for the MZ header. 124 | const MzHeader& mzHeader() const; 125 | /// Accessor function for the MZ header. 126 | MzHeader& mzHeader(); // EXPORT 127 | 128 | /// Accessor function for the Rich header. 129 | const RichHeader& richHeader() const; 130 | /// Accessor function for the Rich header. 131 | RichHeader& richHeader(); // EXPORT 132 | 133 | /// Accessor function for the COFF symbol table. 134 | const CoffSymbolTable& coffSymTab() const; 135 | /// Accessor function for the COFF symbol table. 136 | CoffSymbolTable& coffSymTab(); // EXPORT 137 | 138 | /// Accessor function for the security directory. 139 | const SecurityDirectory& securityDir() const; 140 | /// Accessor function for the security directory. 141 | SecurityDirectory& securityDir(); 142 | }; 143 | 144 | /** 145 | * This class implements the common structures of PE and PE+ files. 146 | **/ 147 | template 148 | class PeFileT : public PeFile 149 | { 150 | typedef typename PeFile_Traits::PeHeader32_64 PeHeader32_64; 151 | 152 | private: 153 | std::ifstream m_ifStream; 154 | std::istream& m_iStream; 155 | 156 | PeHeader32_64 m_peh; ///< PE header of the current file. 157 | ExportDirectoryT m_expdir; ///< Export directory of the current file. 158 | ImportDirectory m_impdir; ///< Import directory of the current file. 159 | BoundImportDirectoryT m_boundimpdir; ///< BoundImportDirectory of the current file. 160 | ResourceDirectoryT m_resdir; ///< ResourceDirectory of the current file. 161 | RelocationsDirectoryT m_relocs; ///< Relocations directory of the current file. 162 | ComHeaderDirectoryT m_comdesc; ///< COM+ descriptor directory of the current file. 163 | IatDirectoryT m_iat; ///< Import address table of the current file. 164 | DebugDirectoryT m_debugdir; ///< Debug directory of the current file. 165 | DelayImportDirectory m_delayimpdir; ///< Delay import directory of the current file. 166 | TlsDirectory m_tlsdir; ///< TLS directory of the current file. 167 | 168 | public: 169 | /// Default constructor which exists only for the sake of allowing to construct files without filenames. 170 | PeFileT(); 171 | 172 | virtual ~PeFileT() {} 173 | 174 | /// Initializes a PeFile with a filename 175 | explicit PeFileT(const std::string& strFilename); 176 | PeFileT(std::istream& stream); 177 | 178 | /// Returns the name of the current file. 179 | std::string getFileName() const; 180 | /// Changes the name of the current file. 181 | void setFileName(std::string strFilename); 182 | 183 | /// Reads the MZ header of the current file from disc. 184 | int readMzHeader() ; 185 | /// Reads the export directory of the current file from disc. 186 | int readExportDirectory() ; 187 | /// Reads the PE header of the current file from disc. 188 | int readPeHeader() ; 189 | /// Reads the import directory of the current file from disc. 190 | int readImportDirectory() ; 191 | /// Reads the bound import directory of the current file from disc. 192 | int readBoundImportDirectory() ; 193 | /// Reads the resource directory of the current file from disc. 194 | int readResourceDirectory() ; 195 | /// Reads the relocations directory of the current file from disc. 196 | int readRelocationsDirectory() ; 197 | /// Reads the COM+ descriptor directory of the current file from disc. 198 | int readComHeaderDirectory() ; 199 | /// Reads the IAT directory of the current file from disc. 200 | int readIatDirectory() ; 201 | /// Reads the Debug directory of the current file. 202 | int readDebugDirectory() ; 203 | /// Reads the TLS directory of the current file. 204 | int readTlsDirectory() ; 205 | /// Reads rich header of the current file. 206 | int readRichHeader(std::size_t offset, std::size_t size, bool ignoreInvalidKey = false) ; 207 | /// Reads the COFF symbol table of the current file. 208 | int readCoffSymbolTable() ; 209 | /// Reads delay import directory of the current file. 210 | int readDelayImportDirectory() ; 211 | /// Reads the security directory of the current file. 212 | int readSecurityDirectory() ; 213 | 214 | /// Checks the entry point code 215 | LoaderError checkEntryPointErrors() const; 216 | 217 | /// Returns a loader error, if there was any 218 | LoaderError loaderError() const; 219 | 220 | unsigned int getBits() const 221 | { 222 | return bits; 223 | } 224 | 225 | /// Accessor function for the PE header. 226 | const PeHeader32_64& peHeader() const; 227 | /// Accessor function for the PE header. 228 | PeHeader32_64& peHeader(); 229 | 230 | /// Accessor function for the export directory. 231 | const ExportDirectoryT& expDir() const; 232 | /// Accessor function for the export directory. 233 | ExportDirectoryT& expDir(); // EXPORT 234 | 235 | /// Accessor function for the import directory. 236 | const ImportDirectory& impDir() const; 237 | /// Accessor function for the import directory. 238 | ImportDirectory& impDir(); 239 | 240 | /// Accessor function for the bound import directory. 241 | const BoundImportDirectoryT& boundImpDir() const; 242 | /// Accessor function for the bound import directory. 243 | BoundImportDirectoryT& boundImpDir(); // EXPORT 244 | 245 | /// Accessor function for the resource directory. 246 | const ResourceDirectoryT& resDir() const; 247 | /// Accessor function for the resource directory. 248 | ResourceDirectoryT& resDir(); // EXPORT 249 | 250 | /// Accessor function for the relocations directory. 251 | const RelocationsDirectoryT& relocDir() const; 252 | /// Accessor function for the relocations directory. 253 | RelocationsDirectoryT& relocDir(); // EXPORT 254 | 255 | /// Accessor function for the COM+ descriptor directory. 256 | const ComHeaderDirectoryT& comDir() const; 257 | /// Accessor function for the COM+ descriptor directory. 258 | ComHeaderDirectoryT& comDir(); // EXPORT 259 | 260 | /// Accessor function for the IAT directory. 261 | const IatDirectoryT& iatDir() const; 262 | /// Accessor function for the IAT directory. 263 | IatDirectoryT& iatDir(); // EXPORT 264 | 265 | /// Accessor function for the debug directory. 266 | const DebugDirectoryT& debugDir() const; 267 | /// Accessor function for the debug directory. 268 | DebugDirectoryT& debugDir(); // EXPORT 269 | 270 | /// Accessor function for the delay import directory. 271 | const DelayImportDirectory& delayImports() const; 272 | /// Accessor function for the delay import directory. 273 | DelayImportDirectory& delayImports(); // EXPORT 274 | 275 | /// Accessor function for the TLS directory. 276 | const TlsDirectory& tlsDir() const; 277 | /// Accessor function for the TLS directory. 278 | TlsDirectory& tlsDir(); 279 | }; 280 | 281 | /** 282 | * This class is the main class for handling PE files. 283 | **/ 284 | class PeFile32 : public PeFileT<32> 285 | { 286 | public: 287 | /// Default constructor which exists only for the sake of allowing to construct files without filenames. 288 | PeFile32(); 289 | 290 | /// Initializes a PeFile with a filename 291 | explicit PeFile32(const std::string& strFlename); 292 | PeFile32(std::istream& stream); 293 | virtual void visit(PeFileVisitor &v) { v.callback( *this ); } 294 | }; 295 | 296 | /** 297 | * This class is the main class for handling PE+ files. 298 | **/ 299 | class PeFile64 : public PeFileT<64> 300 | { 301 | public: 302 | /// Default constructor which exists only for the sake of allowing to construct files without filenames. 303 | PeFile64(); 304 | 305 | /// Initializes a PeFile with a filename 306 | explicit PeFile64(const std::string& strFlename); 307 | PeFile64(std::istream& stream); 308 | virtual void visit(PeFileVisitor &v) { v.callback( *this ); } 309 | }; 310 | 311 | //typedef PeFileT<32> PeFile32; 312 | //typedef PeFileT<64> PeFile64; 313 | 314 | /** 315 | * @param strFilename Name of the current file. 316 | **/ 317 | template 318 | PeFileT::PeFileT(const std::string& strFilename) : 319 | m_iStream(m_ifStream) 320 | { 321 | m_filename = strFilename; 322 | m_ifStream.open(m_filename, std::ifstream::binary); 323 | } 324 | 325 | /** 326 | * @param stream Input stream. 327 | **/ 328 | template 329 | PeFileT::PeFileT(std::istream& stream) : 330 | m_iStream(stream) 331 | { 332 | } 333 | 334 | template 335 | PeFileT::PeFileT() : 336 | m_iStream(m_ifStream) 337 | { 338 | } 339 | 340 | template 341 | int PeFileT::readPeHeader() 342 | { 343 | return peHeader().read(m_iStream, mzHeader().getAddressOfPeHeader(), mzHeader()); 344 | } 345 | 346 | /** 347 | * @return A reference to the file's PE header. 348 | **/ 349 | template 350 | const typename PeFile_Traits::PeHeader32_64& PeFileT::peHeader() const 351 | { 352 | return m_peh; 353 | } 354 | 355 | /** 356 | * @return A reference to the file's PE header. 357 | **/ 358 | template 359 | typename PeFile_Traits::PeHeader32_64& PeFileT::peHeader() 360 | { 361 | return m_peh; 362 | } 363 | 364 | /** 365 | * @return A reference to the file's import directory. 366 | **/ 367 | template 368 | const ImportDirectory& PeFileT::impDir() const 369 | { 370 | return m_impdir; 371 | } 372 | 373 | /** 374 | * @return A reference to the file's import directory. 375 | **/ 376 | template 377 | ImportDirectory& PeFileT::impDir() 378 | { 379 | return m_impdir; 380 | } 381 | 382 | template 383 | const TlsDirectory& PeFileT::tlsDir() const 384 | { 385 | return m_tlsdir; 386 | } 387 | 388 | template 389 | TlsDirectory& PeFileT::tlsDir() 390 | { 391 | return m_tlsdir; 392 | } 393 | 394 | /** 395 | * @return A reference to the file's delay import directory. 396 | **/ 397 | template 398 | const DelayImportDirectory& PeFileT::delayImports() const 399 | { 400 | return m_delayimpdir; 401 | } 402 | 403 | /** 404 | * @return A reference to the file's delay import directory. 405 | **/ 406 | template 407 | DelayImportDirectory& PeFileT::delayImports() 408 | { 409 | return m_delayimpdir; 410 | } 411 | 412 | /** 413 | * @return A reference to the file's export directory. 414 | **/ 415 | template 416 | const ExportDirectoryT& PeFileT::expDir() const 417 | { 418 | return m_expdir; 419 | } 420 | 421 | /** 422 | * @return A reference to the file's export directory. 423 | **/ 424 | template 425 | ExportDirectoryT& PeFileT::expDir() 426 | { 427 | return m_expdir; 428 | } 429 | 430 | /** 431 | * @return A reference to the file's bound import directory. 432 | **/ 433 | template 434 | const BoundImportDirectoryT& PeFileT::boundImpDir() const 435 | { 436 | return m_boundimpdir; 437 | } 438 | 439 | /** 440 | * @return A reference to the file's bound import directory. 441 | **/ 442 | template 443 | BoundImportDirectoryT& PeFileT::boundImpDir() 444 | { 445 | return m_boundimpdir; 446 | } 447 | 448 | /** 449 | * @return A reference to the file's resource directory. 450 | **/ 451 | template 452 | const ResourceDirectoryT& PeFileT::resDir() const 453 | { 454 | return m_resdir; 455 | } 456 | 457 | /** 458 | * @return A reference to the file's resource directory. 459 | **/ 460 | template 461 | ResourceDirectoryT& PeFileT::resDir() 462 | { 463 | return m_resdir; 464 | } 465 | 466 | /** 467 | * @return A reference to the file's relocations directory. 468 | **/ 469 | template 470 | const RelocationsDirectoryT& PeFileT::relocDir() const 471 | { 472 | return m_relocs; 473 | } 474 | 475 | /** 476 | * @return A reference to the file's relocations directory. 477 | **/ 478 | template 479 | RelocationsDirectoryT& PeFileT::relocDir() 480 | { 481 | return m_relocs; 482 | } 483 | 484 | /** 485 | * @return A reference to the file's COM+ descriptor directory. 486 | **/ 487 | template 488 | const ComHeaderDirectoryT& PeFileT::comDir() const 489 | { 490 | return m_comdesc; 491 | } 492 | 493 | /** 494 | * @return A reference to the file's COM+ descriptor directory. 495 | **/ 496 | template 497 | ComHeaderDirectoryT& PeFileT::comDir() 498 | { 499 | return m_comdesc; 500 | } 501 | 502 | template 503 | const IatDirectoryT& PeFileT::iatDir() const 504 | { 505 | return m_iat; 506 | } 507 | 508 | template 509 | IatDirectoryT& PeFileT::iatDir() 510 | { 511 | return m_iat; 512 | } 513 | 514 | template 515 | const DebugDirectoryT& PeFileT::debugDir() const 516 | { 517 | return m_debugdir; 518 | } 519 | 520 | template 521 | DebugDirectoryT& PeFileT::debugDir() 522 | { 523 | return m_debugdir; 524 | } 525 | 526 | /** 527 | * @return Filename of the current file. 528 | **/ 529 | template 530 | std::string PeFileT::getFileName() const 531 | { 532 | return m_filename; 533 | } 534 | 535 | /** 536 | * @param strFilename New filename. 537 | **/ 538 | template 539 | void PeFileT::setFileName(std::string strFilename) 540 | { 541 | m_filename = strFilename; 542 | if (m_ifStream.is_open()) 543 | { 544 | m_ifStream.close(); 545 | } 546 | m_ifStream.open(m_filename, std::ifstream::binary); 547 | } 548 | 549 | template 550 | int PeFileT::readMzHeader() 551 | { 552 | return mzHeader().read(m_iStream); 553 | } 554 | 555 | template 556 | int PeFileT::readRichHeader( 557 | std::size_t offset, 558 | std::size_t size, 559 | bool ignoreInvalidKey) 560 | { 561 | return richHeader().read(m_iStream, offset, size, ignoreInvalidKey); 562 | } 563 | 564 | template 565 | int PeFileT::readCoffSymbolTable() 566 | { 567 | if (peHeader().getPointerToSymbolTable() 568 | && peHeader().getNumberOfSymbols()) 569 | { 570 | return coffSymTab().read( 571 | m_iStream, 572 | static_cast(peHeader().getPointerToSymbolTable()), 573 | peHeader().getNumberOfSymbols() * PELIB_IMAGE_SIZEOF_COFF_SYMBOL); 574 | } 575 | return ERROR_COFF_SYMBOL_TABLE_DOES_NOT_EXIST; 576 | } 577 | 578 | template 579 | int PeFileT::readExportDirectory() 580 | { 581 | if (peHeader().calcNumberOfRvaAndSizes() >= 1 582 | && peHeader().getIddExportRva()) 583 | { 584 | return expDir().read(m_iStream, peHeader()); 585 | } 586 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 587 | } 588 | 589 | template 590 | int PeFileT::readImportDirectory() 591 | { 592 | if (peHeader().calcNumberOfRvaAndSizes() >= 2 593 | && peHeader().getIddImportRva()) 594 | { 595 | return impDir().read(m_iStream, peHeader()); 596 | } 597 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 598 | } 599 | 600 | template 601 | int PeFileT::readResourceDirectory() 602 | { 603 | if (peHeader().calcNumberOfRvaAndSizes() >= 3 604 | && peHeader().getIddResourceRva()) 605 | { 606 | return resDir().read(m_iStream, peHeader()); 607 | } 608 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 609 | } 610 | 611 | template 612 | int PeFileT::readSecurityDirectory() 613 | { 614 | if (peHeader().calcNumberOfRvaAndSizes() >= 5 615 | && peHeader().getIddSecurityRva() 616 | && peHeader().getIddSecuritySize()) 617 | { 618 | return securityDir().read( 619 | m_iStream, 620 | peHeader().getIddSecurityRva(), 621 | peHeader().getIddSecuritySize()); 622 | } 623 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 624 | } 625 | 626 | template 627 | int PeFileT::readRelocationsDirectory() 628 | { 629 | if (peHeader().calcNumberOfRvaAndSizes() >= 6 630 | && peHeader().getIddBaseRelocRva() && peHeader().getIddBaseRelocSize()) 631 | { 632 | return relocDir().read(m_iStream, peHeader()); 633 | } 634 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 635 | } 636 | 637 | template 638 | int PeFileT::readDebugDirectory() 639 | { 640 | if (peHeader().calcNumberOfRvaAndSizes() >= 7 641 | && peHeader().getIddDebugRva() && peHeader().getIddDebugSize()) 642 | { 643 | return debugDir().read(m_iStream, peHeader()); 644 | } 645 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 646 | } 647 | 648 | template 649 | int PeFileT::readTlsDirectory() 650 | { 651 | if (peHeader().calcNumberOfRvaAndSizes() >= 10 652 | && peHeader().getIddTlsRva() && peHeader().getIddTlsSize()) 653 | { 654 | return tlsDir().read(m_iStream, peHeader()); 655 | } 656 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 657 | } 658 | 659 | template 660 | int PeFileT::readBoundImportDirectory() 661 | { 662 | if (peHeader().calcNumberOfRvaAndSizes() >= 12 663 | && peHeader().getIddBoundImportRva() && peHeader().getIddBoundImportSize()) 664 | { 665 | return boundImpDir().read(m_iStream, peHeader()); 666 | } 667 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 668 | } 669 | 670 | template 671 | int PeFileT::readIatDirectory() 672 | { 673 | if (peHeader().calcNumberOfRvaAndSizes() >= 13 674 | && peHeader().getIddIatRva() && peHeader().getIddIatSize()) 675 | { 676 | return iatDir().read(m_iStream, peHeader()); 677 | } 678 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 679 | } 680 | 681 | template 682 | int PeFileT::readDelayImportDirectory() 683 | { 684 | // Note: Delay imports can have arbitrary size and Windows loader will still load them 685 | if (peHeader().calcNumberOfRvaAndSizes() >= 14 && peHeader().getIddDelayImportRva() /* && peHeader().getIddDelayImportSize() */) 686 | { 687 | return delayImports().read(m_iStream, peHeader()); 688 | } 689 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 690 | } 691 | 692 | template 693 | int PeFileT::readComHeaderDirectory() 694 | { 695 | if (peHeader().calcNumberOfRvaAndSizes() >= 15 696 | && peHeader().getIddComHeaderRva() && peHeader().getIddComHeaderSize()) 697 | { 698 | return comDir().read(m_iStream, peHeader()); 699 | } 700 | return ERROR_DIRECTORY_DOES_NOT_EXIST; 701 | } 702 | 703 | template 704 | LoaderError PeFileT::checkEntryPointErrors() const 705 | { 706 | unsigned int uiEntryPointRva = peHeader().getAddressOfEntryPoint(); 707 | std::uint64_t uiOffset = peHeader().rvaToOffset(uiEntryPointRva); 708 | std::uint64_t entryPointCode[2]; 709 | 710 | // No point of reading entry point that is beyond the file size 711 | std::uint64_t ulFileSize = fileSize(m_iStream); 712 | if (uiOffset > ulFileSize) 713 | { 714 | return LDR_ERROR_ENTRY_POINT_OUT_OF_IMAGE; 715 | } 716 | 717 | // Only check PE files compiled for i386 or x64 processors. 718 | if (peHeader().getMachine() == PELIB_IMAGE_FILE_MACHINE_I386 || peHeader().getMachine() == PELIB_IMAGE_FILE_MACHINE_AMD64) 719 | { 720 | // Check if 16 bytes of code are available in the file 721 | if ((uiOffset + sizeof(entryPointCode)) < ulFileSize) 722 | { 723 | // Read the entry point code 724 | m_iStream.seekg(uiOffset, std::ios::beg); 725 | m_iStream.read((char *)entryPointCode, sizeof(entryPointCode)); 726 | 727 | // Zeroed instructions at entry point map either to "add [eax], al" (i386) or "add [rax], al" (AMD64). 728 | // Neither of these instructions makes sense on the entry point. We check 16 bytes of the entry point, 729 | // in order to make sure it's really a corruption. 730 | if ((entryPointCode[0] | entryPointCode[1]) == 0) 731 | { 732 | return LDR_ERROR_ENTRY_POINT_ZEROED; 733 | } 734 | } 735 | } 736 | 737 | return LDR_ERROR_NONE; 738 | } 739 | 740 | // Returns an error code indicating loader problem. We check every part of the PE file 741 | // for possible loader problem. If anything wrong was found, we report it 742 | template 743 | LoaderError PeFileT::loaderError() const 744 | { 745 | LoaderError ldrError; 746 | 747 | // Was there a problem in the DOS header? 748 | ldrError = mzHeader().loaderError(); 749 | if (ldrError != LDR_ERROR_NONE) 750 | return ldrError; 751 | 752 | // Was there a problem in the NT headers? 753 | ldrError = peHeader().loaderError(); 754 | if (ldrError != LDR_ERROR_NONE) 755 | return ldrError; 756 | 757 | // Check the loader error 758 | ldrError = coffSymTab().loaderError(); 759 | if (ldrError != LDR_ERROR_NONE) 760 | return ldrError; 761 | 762 | // Check errors in import directory 763 | ldrError = impDir().loaderError(); 764 | if (ldrError != LDR_ERROR_NONE) 765 | return ldrError; 766 | 767 | // Check errors in resource directory 768 | ldrError = resDir().loaderError(); 769 | if (ldrError != LDR_ERROR_NONE) 770 | return ldrError; 771 | 772 | // Check errors in entry point 773 | ldrError = checkEntryPointErrors(); 774 | if (ldrError != LDR_ERROR_NONE) 775 | return ldrError; 776 | 777 | // Nothing wrond found 778 | return LDR_ERROR_NONE; 779 | } 780 | } 781 | 782 | #endif 783 | -------------------------------------------------------------------------------- /include/pelib/PeLib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PeLib.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef PELIB_H 14 | #define PELIB_H 15 | 16 | #include "pelib/PeFile.h" 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/pelib/PeLibInc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PeLibInc.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef STD_H 14 | #define STD_H 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "pelib/PeLibAux.h" 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /include/pelib/RelocationsDirectory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Relocations.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef RELOCATIONSDIRECTORY_H 14 | #define RELOCATIONSDIRECTORY_H 15 | 16 | #include "pelib/PeHeader.h" 17 | 18 | namespace PeLib 19 | { 20 | /// Class that handles the relocations directory. 21 | /** 22 | * This class handles the relocations directory. 23 | **/ 24 | class RelocationsDirectory 25 | { 26 | protected: 27 | std::vector m_vRelocations; ///< Used to store the relocation data. 28 | 29 | void read(InputBuffer& inputbuffer, unsigned int uiSize); 30 | 31 | public: 32 | virtual ~RelocationsDirectory() = default; 33 | 34 | /// Returns the number of relocations in the relocations directory. 35 | unsigned int calcNumberOfRelocations() const; // EXPORT 36 | /// Returns the number of relocation data entries of a specific relocation. 37 | unsigned int calcNumberOfRelocationData(unsigned int ulRelocation) const; // EXPORT 38 | 39 | /// Read a file's relocations directory. 40 | int read(const unsigned char* buffer, unsigned int buffersize); // EXPORT 41 | /// Returns the size of the relocations directory. 42 | unsigned int size() const; // EXPORT 43 | 44 | /// Returns the VA of a relocation. 45 | dword getVirtualAddress(unsigned int ulRelocation) const; // EXPORT 46 | /// Returns the SizeOfBlock value of a relocation. 47 | dword getSizeOfBlock(unsigned int ulRelocation) const; // EXPORT 48 | /// Returns the RelocationData of a relocation. 49 | word getRelocationData(unsigned int ulRelocation, unsigned int ulDataNumber) const; // EXPORT 50 | 51 | /// Changes the relocation data of a relocation. 52 | void setRelocationData(unsigned int ulRelocation, unsigned int ulDataNumber, word wData); // EXPORT 53 | 54 | /// Changes the VirtualAddress of a relocation. 55 | void setVirtualAddress(unsigned int ulRelocation, dword dwValue); // EXPORT 56 | /// Changes the SizeOfBlock of a relocation. 57 | void setSizeOfBlock(unsigned int ulRelocation, dword dwValue); // EXPORT 58 | 59 | void addRelocation(); // EXPORT 60 | /// Adds new data to a relocation. 61 | void addRelocationData(unsigned int ulRelocation, word wValue); // EXPORT 62 | /// Removes data from a relocation. 63 | // void removeRelocationData(unsigned int ulRelocation, word wValue); // EXPORT 64 | void removeRelocation(unsigned int index); // EXPORT 65 | void removeRelocationData(unsigned int relocindex, unsigned int dataindex); // EXPORT 66 | }; 67 | 68 | template 69 | class RelocationsDirectoryT : public RelocationsDirectory 70 | { 71 | public: 72 | /// Read a file's relocations directory. 73 | int read(std::istream& inStream, const PeHeaderT& peHeader); // EXPORT 74 | }; 75 | 76 | template 77 | int RelocationsDirectoryT::read( 78 | std::istream& inStream, 79 | const PeHeaderT& peHeader) 80 | { 81 | IStreamWrapper inStream_w(inStream); 82 | std::uint64_t ulFileSize = fileSize(inStream_w); 83 | 84 | if (!inStream_w) 85 | { 86 | return ERROR_OPENING_FILE; 87 | } 88 | 89 | unsigned int uiOffset = peHeader.rvaToOffset(peHeader.getIddBaseRelocRva()); 90 | unsigned int uiSize = peHeader.getIddBaseRelocSize(); 91 | 92 | // If uiSize is big enough it can overflow after addition with uiOffset, ulFileSize < uiOffset + uiSize can be true, 93 | // even though it should be false. 94 | if ((ulFileSize < uiSize) || (ulFileSize < uiOffset + uiSize)) 95 | { 96 | return ERROR_INVALID_FILE; 97 | } 98 | 99 | inStream_w.seekg(uiOffset, std::ios::beg); 100 | 101 | std::vector vRelocDirectory(uiSize); 102 | inStream_w.read(reinterpret_cast(vRelocDirectory.data()), uiSize); 103 | 104 | InputBuffer ibBuffer{vRelocDirectory}; 105 | RelocationsDirectory::read(ibBuffer, uiSize); 106 | 107 | return ERROR_NONE; 108 | } 109 | } 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /include/pelib/RichHeader.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file RichHeader.h 3 | * @brief Class for rich header. 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #ifndef RICHHEADER_H 8 | #define RICHHEADER_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace PeLib 15 | { 16 | /** 17 | * This class handless rich header. 18 | */ 19 | class RichHeader 20 | { 21 | public: 22 | typedef std::vector::const_iterator richHeaderIterator; 23 | private: 24 | bool headerIsValid; 25 | bool validStructure; 26 | dword key; 27 | std::size_t noOfIters; 28 | std::vector decryptedHeader; 29 | std::vector records; 30 | 31 | void init(); 32 | void setValidStructure(); 33 | void getUserFriendlyProductName(PELIB_IMAGE_RICH_HEADER_RECORD & record); 34 | bool analyze(bool ignoreInvalidKey = false); 35 | void read(InputBuffer& inputbuffer, std::size_t uiSize, bool ignoreInvalidKey); 36 | public: 37 | RichHeader(); 38 | ~RichHeader(); 39 | 40 | int read( 41 | std::istream& inStream, 42 | std::size_t uiOffset, 43 | std::size_t uiSize, 44 | bool ignoreInvalidKey); 45 | bool isHeaderValid() const; 46 | bool isStructureValid() const; 47 | std::size_t getNumberOfIterations() const; 48 | dword getKey() const; 49 | const dword* getDecryptedHeaderItem(std::size_t index) const; 50 | std::string getDecryptedHeaderItemSignature(std::size_t index) const; 51 | std::string getDecryptedHeaderItemsSignature(std::initializer_list indexes) const; 52 | std::vector getDecryptedHeaderBytes() const; 53 | richHeaderIterator begin() const; 54 | richHeaderIterator end() const; 55 | }; 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /include/pelib/SecurityDirectory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SecurityDirectory.h 3 | * @brief Class for certificate directory. 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #ifndef SECURITYDIRECTORY_H 8 | #define SECURITYDIRECTORY_H 9 | 10 | #include "pelib/PeHeader.h" 11 | 12 | namespace PeLib 13 | { 14 | class SecurityDirectory 15 | { 16 | private: 17 | std::vector m_certs; 18 | public: 19 | /// Number of certificates in the directory. 20 | unsigned int calcNumberOfCertificates() const; // EXPORT 21 | /// Returns certificate at specified index. 22 | const std::vector& getCertificate(std::size_t index) const; // EXPORT 23 | /// Read a file's certificate directory. 24 | int read( 25 | std::istream& inStream, 26 | unsigned int uiOffset, 27 | unsigned int uiSize); // EXPORT 28 | }; 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /include/pelib/TlsDirectory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TlsDirectory.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #ifndef TLSDIRECTORY_H 14 | #define TLSDIRECTORY_H 15 | 16 | #include "pelib/PeHeader.h" 17 | 18 | namespace PeLib 19 | { 20 | /// Class that handles the TLS directory. 21 | /** 22 | * This class handles the TLS (Thread Local Storage) directory. 23 | **/ 24 | template 25 | class TlsDirectory 26 | { 27 | private: 28 | PELIB_IMAGE_TLS_DIRECTORY m_tls; ///< Structure that holds all information about the directory. 29 | 30 | void read(InputBuffer& inputbuffer); 31 | 32 | public: 33 | /// Reads a file's TLS directory. 34 | int read(std::istream& inStream, const PeHeaderT &peHeader); // EXPORT 35 | int read(unsigned char* buffer, unsigned int buffersize); // EXPORT 36 | /// Rebuilds the TLS directory. 37 | void rebuild(std::vector& vBuffer) const; // EXPORT 38 | /// Returns the size of the TLS Directory. 39 | unsigned int size() const; // EXPORT 40 | /// Writes the TLS directory to a file. 41 | int write(const std::string& strFilename, unsigned int dwOffset) const; // EXPORT 42 | 43 | /// Returns the StartAddressOfRawData value of the TLS header. 44 | typename FieldSizes::VAR4_8 getStartAddressOfRawData() const; // EXPORT 45 | /// Returns the EndAddressOfRawData value of the TLS header. 46 | typename FieldSizes::VAR4_8 getEndAddressOfRawData() const; // EXPORT 47 | /// Returns the AddressOfIndex value of the TLS header. 48 | typename FieldSizes::VAR4_8 getAddressOfIndex() const; // EXPORT 49 | /// Returns the AddressOfCallBacks value of the TLS header. 50 | typename FieldSizes::VAR4_8 getAddressOfCallBacks() const; // EXPORT 51 | /// Returns the SizeOfZeroFill value of the TLS header. 52 | dword getSizeOfZeroFill() const; // EXPORT 53 | /// Returns the Characteristics value of the TLS header. 54 | dword getCharacteristics() const; // EXPORT 55 | 56 | /// Sets the StartAddressOfRawData value of the TLS header. 57 | void setStartAddressOfRawData(dword dwValue); // EXPORT 58 | /// Sets the EndAddressOfRawData value of the TLS header. 59 | void setEndAddressOfRawData(dword dwValue); // EXPORT 60 | /// Sets the AddressOfIndex value of the TLS header. 61 | void setAddressOfIndex(dword dwValue); // EXPORT 62 | /// Sets the AddressOfCallBacks value of the TLS header. 63 | void setAddressOfCallBacks(dword dwValue); // EXPORT 64 | /// Sets the SizeOfZeroFill value of the TLS header. 65 | void setSizeOfZeroFill(dword dwValue); // EXPORT 66 | /// Sets the Characteristics value of the TLS header. 67 | void setCharacteristics(dword dwValue); // EXPORT 68 | }; 69 | 70 | template 71 | void TlsDirectory::read(InputBuffer& inputBuffer) 72 | { 73 | PELIB_IMAGE_TLS_DIRECTORY itdCurr; 74 | 75 | inputBuffer >> itdCurr.StartAddressOfRawData; 76 | inputBuffer >> itdCurr.EndAddressOfRawData; 77 | inputBuffer >> itdCurr.AddressOfIndex; 78 | inputBuffer >> itdCurr.AddressOfCallBacks; 79 | inputBuffer >> itdCurr.SizeOfZeroFill; 80 | inputBuffer >> itdCurr.Characteristics; 81 | 82 | std::swap(itdCurr, m_tls); 83 | } 84 | 85 | template 86 | int TlsDirectory::read(unsigned char* buffer, unsigned int buffersize) 87 | { 88 | if (buffersize < PELIB_IMAGE_TLS_DIRECTORY::size()) 89 | { 90 | return ERROR_INVALID_FILE; 91 | } 92 | 93 | std::vector vTlsDirectory(buffer, buffer + buffersize); 94 | 95 | InputBuffer ibBuffer(vTlsDirectory); 96 | read(ibBuffer); 97 | return ERROR_NONE; 98 | } 99 | 100 | /** 101 | * Reads a file's TLS directory. 102 | * @param inStream Input stream. 103 | * @param peHeader A valid PE header. 104 | **/ 105 | template 106 | int TlsDirectory::read(std::istream& inStream, const PeHeaderT &peHeader) 107 | { 108 | IStreamWrapper inStream_w(inStream); 109 | 110 | if (!inStream_w) 111 | { 112 | return ERROR_OPENING_FILE; 113 | } 114 | 115 | std::uint64_t ulFileSize = fileSize(inStream_w); 116 | 117 | std::uint64_t uiOffset = peHeader.rvaToOffset(peHeader.getIddTlsRva()); 118 | unsigned int uiSize = peHeader.getIddTlsSize(); 119 | 120 | if (ulFileSize < uiOffset + uiSize) 121 | { 122 | return ERROR_INVALID_FILE; 123 | } 124 | 125 | inStream_w.seekg(uiOffset, std::ios::beg); 126 | 127 | std::vector vTlsDirectory(uiSize); 128 | inStream_w.read(reinterpret_cast(vTlsDirectory.data()), uiSize); 129 | 130 | InputBuffer ibBuffer{vTlsDirectory}; 131 | read(ibBuffer); 132 | return ERROR_NONE; 133 | } 134 | 135 | /** 136 | * Rebuilds the current TLS Directory. 137 | * @param vBuffer Buffer where the TLS directory will be written to. 138 | **/ 139 | template 140 | void TlsDirectory::rebuild(std::vector& vBuffer) const 141 | { 142 | OutputBuffer obBuffer(vBuffer); 143 | 144 | obBuffer << m_tls.StartAddressOfRawData; 145 | obBuffer << m_tls.EndAddressOfRawData; 146 | obBuffer << m_tls.AddressOfIndex; 147 | obBuffer << m_tls.AddressOfCallBacks; 148 | obBuffer << m_tls.SizeOfZeroFill; 149 | obBuffer << m_tls.Characteristics; 150 | } 151 | 152 | /** 153 | * Returns the size of the TLS directory. Due to the static nature of this structure the return value 154 | * will always be 24. 155 | * @return Size in bytes. 156 | **/ 157 | template 158 | unsigned int TlsDirectory::size() const 159 | { 160 | return PELIB_IMAGE_TLS_DIRECTORY::size(); 161 | } 162 | 163 | /** 164 | * @param strFilename Name of the file. 165 | * @param dwOffset File offset the TLS Directory will be written to. 166 | **/ 167 | template 168 | int TlsDirectory::write(const std::string& strFilename, unsigned int dwOffset) const 169 | { 170 | std::fstream ofFile(strFilename.c_str(), std::ios_base::in); 171 | 172 | if (!ofFile) 173 | { 174 | ofFile.clear(); 175 | ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary); 176 | } 177 | else 178 | { 179 | ofFile.close(); 180 | ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary); 181 | } 182 | 183 | if (!ofFile) 184 | { 185 | return ERROR_OPENING_FILE; 186 | } 187 | 188 | ofFile.seekp(dwOffset, std::ios::beg); 189 | 190 | std::vector vBuffer; 191 | rebuild(vBuffer); 192 | 193 | ofFile.write(reinterpret_cast(vBuffer.data()), vBuffer.size()); 194 | 195 | ofFile.close(); 196 | 197 | return ERROR_NONE; 198 | } 199 | 200 | /** 201 | * @return The StartAddressOfRawData value of the TLS directory. 202 | **/ 203 | template 204 | typename FieldSizes::VAR4_8 TlsDirectory::getStartAddressOfRawData() const 205 | { 206 | return m_tls.StartAddressOfRawData; 207 | } 208 | 209 | /** 210 | * @return The EndAddressOfRawData value of the TLS directory. 211 | **/ 212 | template 213 | typename FieldSizes::VAR4_8 TlsDirectory::getEndAddressOfRawData() const 214 | { 215 | return m_tls.EndAddressOfRawData; 216 | } 217 | 218 | /** 219 | * @return The AddressOfIndex value of the TLS directory. 220 | **/ 221 | template 222 | typename FieldSizes::VAR4_8 TlsDirectory::getAddressOfIndex() const 223 | { 224 | return m_tls.AddressOfIndex; 225 | } 226 | 227 | /** 228 | * @return The AddressOfCallBacks value of the TLS directory. 229 | **/ 230 | template 231 | typename FieldSizes::VAR4_8 TlsDirectory::getAddressOfCallBacks() const 232 | { 233 | return m_tls.AddressOfCallBacks; 234 | } 235 | 236 | /** 237 | * @return The SizeOfZeroFill value of the TLS directory. 238 | **/ 239 | template 240 | dword TlsDirectory::getSizeOfZeroFill() const 241 | { 242 | return m_tls.SizeOfZeroFill; 243 | } 244 | 245 | /** 246 | * @return The Characteristics value of the TLS directory. 247 | **/ 248 | template 249 | dword TlsDirectory::getCharacteristics() const 250 | { 251 | return m_tls.Characteristics; 252 | } 253 | 254 | /** 255 | * @param dwValue The new StartAddressOfRawData value of the TLS directory. 256 | **/ 257 | template 258 | void TlsDirectory::setStartAddressOfRawData(dword dwValue) 259 | { 260 | m_tls.StartAddressOfRawData = dwValue; 261 | } 262 | 263 | /** 264 | * @param dwValue The new EndAddressOfRawData value of the TLS directory. 265 | **/ 266 | template 267 | void TlsDirectory::setEndAddressOfRawData(dword dwValue) 268 | { 269 | m_tls.EndAddressOfRawData = dwValue; 270 | } 271 | 272 | /** 273 | * @param dwValue The new AddressOfIndex value of the TLS directory. 274 | **/ 275 | template 276 | void TlsDirectory::setAddressOfIndex(dword dwValue) 277 | { 278 | m_tls.AddressOfIndex = dwValue; 279 | } 280 | 281 | /** 282 | * @param dwValue The new AddressOfCallBacks value of the TLS directory. 283 | **/ 284 | template 285 | void TlsDirectory::setAddressOfCallBacks(dword dwValue) 286 | { 287 | m_tls.AddressOfCallBacks = dwValue; 288 | } 289 | 290 | /** 291 | * @param dwValue The new SizeOfZeroFill value of the TLS directory. 292 | **/ 293 | template 294 | void TlsDirectory::setSizeOfZeroFill(dword dwValue) 295 | { 296 | m_tls.SizeOfZeroFill = dwValue; 297 | } 298 | 299 | /** 300 | * @param dwValue The new Characteristics value of the TLS directory. 301 | **/ 302 | template 303 | void TlsDirectory::setCharacteristics(dword dwValue) 304 | { 305 | m_tls.Characteristics = dwValue; 306 | } 307 | 308 | } 309 | #endif 310 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(pelib) 2 | -------------------------------------------------------------------------------- /src/pelib/BoundImportDirectory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * BoundImportDirectory.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "pelib/PeLibInc.h" 18 | #include "pelib/BoundImportDirectory.h" 19 | 20 | namespace PeLib 21 | { 22 | /** 23 | * Adds another bound import to the BoundImport directory. 24 | * @param strModuleName Name of the PE file which will be imported. 25 | * @param dwTds Value of the TimeDateStamp of the bound import field. 26 | * @param wOmn Value of the OffsetModuleName of the bound import field. 27 | * @param wWfr Value of the NumberOfModuleForwarderRefs of the bound import field. 28 | **/ 29 | int BoundImportDirectory::addBoundImport(const std::string& strModuleName, dword dwTds, word wOmn, word wWfr) 30 | { 31 | for (unsigned int i=0;i(std::distance(m_vIbd.begin(), Iter)); 70 | } 71 | 72 | /** 73 | * @return Number of files in the current BoundImport directory. 74 | **/ 75 | unsigned int BoundImportDirectory::calcNumberOfModules() const 76 | { 77 | return static_cast(m_vIbd.size()); 78 | } 79 | 80 | int BoundImportDirectory::read(InputBuffer& inpBuffer, unsigned char* data, unsigned int dwSize) 81 | { 82 | std::vector currentDirectory; 83 | 84 | do 85 | { 86 | if (inpBuffer.get() + PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size() >= inpBuffer.size()) 87 | return ERROR_INVALID_FILE; 88 | 89 | PELIB_IMAGE_BOUND_DIRECTORY ibdCurrent; 90 | 91 | inpBuffer >> ibdCurrent.ibdDescriptor.TimeDateStamp; 92 | inpBuffer >> ibdCurrent.ibdDescriptor.OffsetModuleName; 93 | inpBuffer >> ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs; 94 | 95 | if (ibdCurrent.ibdDescriptor.TimeDateStamp == 0 && ibdCurrent.ibdDescriptor.OffsetModuleName == 0 && ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs == 0) break; 96 | 97 | for (int i=0;i= inpBuffer.size()) 100 | return ERROR_INVALID_FILE; 101 | 102 | PELIB_IMAGE_BOUND_DIRECTORY currentForwarder; 103 | 104 | inpBuffer >> currentForwarder.ibdDescriptor.TimeDateStamp; 105 | inpBuffer >> currentForwarder.ibdDescriptor.OffsetModuleName; 106 | inpBuffer >> currentForwarder.ibdDescriptor.NumberOfModuleForwarderRefs; 107 | 108 | ibdCurrent.moduleForwarders.push_back(currentForwarder); 109 | } 110 | 111 | currentDirectory.push_back(ibdCurrent); 112 | ibdCurrent.moduleForwarders.clear(); 113 | } while (true); 114 | 115 | for (unsigned int i=0;i dwSize) 119 | { 120 | return ERROR_INVALID_FILE; 121 | } 122 | 123 | currentDirectory[i].strModuleName = ""; 124 | for (int k=0;k + wOmn < dwSize && data[wOmn + k] != 0;k++) 125 | { 126 | currentDirectory[i].strModuleName += data[wOmn + k]; 127 | } 128 | 129 | for (unsigned int j=0;j dwSize) 133 | { 134 | return ERROR_INVALID_FILE; 135 | } 136 | 137 | // m_vIbd[i].moduleForwarders[j].strModuleName.assign((char*)(&vBimpDir[wOmn2])); 138 | currentDirectory[i].moduleForwarders[j].strModuleName = ""; 139 | for (int k=0;k + wOmn2 < dwSize && data[wOmn2 + k] != 0;k++) 140 | { 141 | currentDirectory[i].moduleForwarders[j].strModuleName += data[wOmn2 + k]; 142 | } 143 | } 144 | } 145 | 146 | std::swap(m_vIbd, currentDirectory); 147 | 148 | return ERROR_NONE; 149 | } 150 | 151 | int BoundImportDirectory::read(unsigned char* pcBuffer, unsigned int uiSize) 152 | { 153 | std::vector vBimpDir(pcBuffer, pcBuffer + uiSize); 154 | InputBuffer inpBuffer(vBimpDir); 155 | 156 | return read(inpBuffer, vBimpDir.data(), uiSize); 157 | } 158 | 159 | unsigned int BoundImportDirectory::totalModules() const 160 | { 161 | unsigned int modules = static_cast(m_vIbd.size()); 162 | 163 | for (unsigned int i=0;i(m_vIbd[i].moduleForwarders.size()); 166 | } 167 | 168 | return modules; 169 | } 170 | 171 | /** 172 | * Rebuilds the BoundImport directory. The rebuilded BoundImport directory can then be 173 | * written back to a PE file. 174 | * @param vBuffer Buffer where the rebuilt BoundImport directory will be stored. 175 | * @param fMakeValid If this flag is true a valid directory will be produced. 176 | **/ 177 | void BoundImportDirectory::rebuild(std::vector& vBuffer, bool fMakeValid) const 178 | { 179 | std::map filename_offsets; 180 | 181 | OutputBuffer obBuffer(vBuffer); 182 | 183 | word ulNameOffset = static_cast((totalModules() + 1) * PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size()); 184 | 185 | for (unsigned int i=0;i(m_vIbd[i].strModuleName.size() + 1); 197 | } 198 | else 199 | { 200 | obBuffer << filename_offsets[m_vIbd[i].strModuleName]; 201 | } 202 | } 203 | else // Otherwise just copy the old values into the buffer. 204 | { 205 | obBuffer << m_vIbd[i].ibdDescriptor.OffsetModuleName; 206 | } 207 | 208 | obBuffer << m_vIbd[i].ibdDescriptor.NumberOfModuleForwarderRefs; 209 | 210 | for (int j=0;j(m_vIbd[i].moduleForwarders[j].strModuleName.size() + 1); 221 | } 222 | else 223 | { 224 | obBuffer << filename_offsets[m_vIbd[i].moduleForwarders[j].strModuleName]; 225 | } 226 | } 227 | else // Otherwise just copy the old values into the buffer. 228 | { 229 | obBuffer << m_vIbd[i].moduleForwarders[j].ibdDescriptor.OffsetModuleName; 230 | } 231 | 232 | obBuffer << m_vIbd[i].moduleForwarders[j].ibdDescriptor.NumberOfModuleForwarderRefs; 233 | } 234 | } 235 | 236 | obBuffer << static_cast(0); 237 | obBuffer << static_cast(0); 238 | obBuffer << static_cast(0); 239 | 240 | for (unsigned int i=0;i(getModuleName(i).size() + 1)); 245 | filename_offsets.erase(m_vIbd[i].strModuleName); 246 | } 247 | 248 | for (int j=0;j(getModuleName(i, j).size() + 1)); 253 | filename_offsets.erase(getModuleName(i, j)); 254 | } 255 | } 256 | } 257 | } 258 | 259 | /** 260 | * Removes all bound import files. 261 | **/ 262 | void BoundImportDirectory::clear() 263 | { 264 | m_vIbd.clear(); 265 | } 266 | 267 | /** 268 | * Removes a field specified by the parameter filename from the BoundImport directory. 269 | * @param strModuleName Name of the file whose field will be removed from the BoundImport directory. 270 | **/ 271 | void BoundImportDirectory::removeBoundImport(const std::string& strModuleName) 272 | { 273 | m_vIbd.erase( 274 | std::remove_if( 275 | m_vIbd.begin(), 276 | m_vIbd.end(), 277 | [&](const auto& i) { return i.equal(strModuleName); } 278 | ), 279 | m_vIbd.end() 280 | ); 281 | } 282 | 283 | /** 284 | * Returns the size of the rebuilt BoundImportDirectory. 285 | * @return Size of the rebuilt BoundImportDirectory. 286 | **/ 287 | unsigned int BoundImportDirectory::size() const 288 | { 289 | unsigned int size2 = PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size(); 290 | 291 | std::set filenames; 292 | 293 | for (unsigned int i = 0; i < m_vIbd.size(); i++) 294 | { 295 | filenames.insert(m_vIbd[i].strModuleName); 296 | 297 | size2 += PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size(); 298 | 299 | for (unsigned int j = 0; j < m_vIbd[i].moduleForwarders.size(); j++) 300 | { 301 | filenames.insert(m_vIbd[i].moduleForwarders[j].strModuleName); 302 | 303 | size2 += PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size(); 304 | } 305 | } 306 | 307 | for (std::set::iterator iter = filenames.begin(); iter != filenames.end(); ++iter) 308 | { 309 | size2 += static_cast(iter->size()) + 1; 310 | } 311 | 312 | return size2; 313 | } 314 | 315 | /** 316 | * @param strFilename Name of the file. 317 | * @param dwOffset File offset the bound importdirectory will be written to. 318 | * @param fMakeValid If this flag is true a valid directory will be produced. 319 | **/ 320 | int BoundImportDirectory::write(const std::string& strFilename, dword dwOffset, bool fMakeValid) const 321 | { 322 | std::fstream ofFile(strFilename.c_str(), std::ios_base::in); 323 | 324 | if (!ofFile) 325 | { 326 | ofFile.clear(); 327 | ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary); 328 | } 329 | else 330 | { 331 | ofFile.close(); 332 | ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary); 333 | } 334 | 335 | if (!ofFile) 336 | { 337 | return ERROR_OPENING_FILE; 338 | } 339 | 340 | ofFile.seekp(dwOffset, std::ios::beg); 341 | 342 | std::vector vBuffer; 343 | rebuild(vBuffer, fMakeValid); 344 | 345 | ofFile.write(reinterpret_cast(vBuffer.data()), static_cast(vBuffer.size())); 346 | 347 | ofFile.close(); 348 | 349 | return ERROR_NONE; 350 | } 351 | 352 | /** 353 | * Retrieves the value of the TimeDateStamp value of a bound import field. 354 | * @param dwBidnr Number of the bound import field. 355 | * @return Value of the TimeDateStamp of the bound import field. 356 | **/ 357 | dword BoundImportDirectory::getTimeDateStamp(dword dwBidnr) const 358 | { 359 | return m_vIbd[dwBidnr].ibdDescriptor.TimeDateStamp; 360 | } 361 | 362 | /** 363 | * Retrieves the value of the OffsetModuleName value of a bound import field. 364 | * @param dwBidnr Number of the bound import field. 365 | * @return Value of the OffsetModuleName of the bound import field. 366 | **/ 367 | word BoundImportDirectory::getOffsetModuleName(dword dwBidnr) const 368 | { 369 | return m_vIbd[dwBidnr].ibdDescriptor.OffsetModuleName; 370 | } 371 | 372 | /** 373 | * Retrieves the value of the NumberOfModuleForwarderRefs value of a bound import field. 374 | * @param dwBidnr Number of the bound import field. 375 | * @return Value of the NumberOfModuleForwarderRefs of the bound import field. 376 | **/ 377 | word BoundImportDirectory::getNumberOfModuleForwarderRefs(dword dwBidnr) const 378 | { 379 | return m_vIbd[dwBidnr].ibdDescriptor.NumberOfModuleForwarderRefs; 380 | } 381 | 382 | /** 383 | * Retrieves the value of the ModuleName value of a bound import field. 384 | * @param dwBidnr Number of the bound import field. 385 | * @return Value of the ModuleName of the bound import field. 386 | **/ 387 | std::string BoundImportDirectory::getModuleName(dword dwBidnr) const 388 | { 389 | return m_vIbd[dwBidnr].strModuleName; 390 | } 391 | 392 | /** 393 | * Changes the TimeDateStamp value of an existing bound import field. 394 | * @param dwBidnr Number of the bound import field which will be changed. 395 | * @param dwTds New value of the TimeDateStamp of the bound import field. 396 | **/ 397 | void BoundImportDirectory::setTimeDateStamp(dword dwBidnr, dword dwTds) 398 | { 399 | m_vIbd[dwBidnr].ibdDescriptor.TimeDateStamp = dwTds; 400 | } 401 | 402 | /** 403 | * Changes the OffsetModuleName value of an existing bound import field. 404 | * @param dwBidnr Number of the bound import field which will be changed. 405 | * @param wOmn New value of the OffsetModuleName of the bound import field. 406 | **/ 407 | void BoundImportDirectory::setOffsetModuleName(dword dwBidnr, word wOmn) 408 | { 409 | m_vIbd[dwBidnr].ibdDescriptor.OffsetModuleName = wOmn; 410 | } 411 | 412 | /** 413 | * Changes the NumberOfModuleForwarderRefs value of an existing bound import field. 414 | * @param dwBidnr Number of the bound import field which will be changed. 415 | * @param wMfr New value of the NumberOfModuleForwarderRefs of the bound import field. 416 | **/ 417 | void BoundImportDirectory::setNumberOfModuleForwarderRefs(dword dwBidnr, word wMfr) 418 | { 419 | m_vIbd[dwBidnr].ibdDescriptor.NumberOfModuleForwarderRefs = wMfr; 420 | } 421 | 422 | /** 423 | * Changes the ModuleName value of an existing bound import field. 424 | * @param dwBidnr Number of the bound import field which will be changed. 425 | * @param strModuleName New value of the ModuleName of the bound import field. 426 | **/ 427 | void BoundImportDirectory::setModuleName(dword dwBidnr, const std::string& strModuleName) 428 | { 429 | m_vIbd[dwBidnr].strModuleName = strModuleName; 430 | } 431 | 432 | dword BoundImportDirectory::getTimeDateStamp(dword dwBidnr, dword forwardedModule) const 433 | { 434 | return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.TimeDateStamp; 435 | } 436 | 437 | word BoundImportDirectory::getOffsetModuleName(dword dwBidnr, dword forwardedModule) const 438 | { 439 | return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.OffsetModuleName; 440 | } 441 | 442 | word BoundImportDirectory::getNumberOfModuleForwarderRefs(dword dwBidnr, dword forwardedModule) const 443 | { 444 | return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.NumberOfModuleForwarderRefs; 445 | } 446 | 447 | std::string BoundImportDirectory::getModuleName(dword dwBidnr, dword forwardedModule) const 448 | { 449 | return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].strModuleName; 450 | } 451 | 452 | void BoundImportDirectory::setTimeDateStamp(dword dwBidnr, dword forwardedModule, dword dwTds) 453 | { 454 | m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.TimeDateStamp = dwTds; 455 | } 456 | 457 | void BoundImportDirectory::setOffsetModuleName(dword dwBidnr, dword forwardedModule, word wOmn) 458 | { 459 | m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.OffsetModuleName = wOmn; 460 | } 461 | 462 | void BoundImportDirectory::setNumberOfModuleForwarderRefs(dword dwBidnr, dword forwardedModule, word wMfr) 463 | { 464 | m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.NumberOfModuleForwarderRefs = wMfr; 465 | } 466 | 467 | void BoundImportDirectory::setModuleName(dword dwBidnr, dword forwardedModule, const std::string& strModuleName) 468 | { 469 | m_vIbd[dwBidnr].moduleForwarders[forwardedModule].strModuleName = strModuleName; 470 | } 471 | 472 | word BoundImportDirectory::calcNumberOfModuleForwarderRefs(dword dwBidnr) const 473 | { 474 | return static_cast(m_vIbd[dwBidnr].moduleForwarders.size()); 475 | } 476 | 477 | void BoundImportDirectory::addForwardedModule(dword dwBidnr, const std::string& name, dword timeStamp, word offsetModuleName, word forwardedModules) 478 | { 479 | // XXX: Maybe test if there are already 0xFFFF forwarded modules. 480 | // XXX: Check for duplicate entries. Is it also necessary to check 481 | // non-forwarded entries and forwarded entries in other non-forwarded 482 | // entries? 483 | // XXX: Can forwarders forward recursively? 484 | 485 | PELIB_IMAGE_BOUND_DIRECTORY ibdCurrent; 486 | ibdCurrent.strModuleName = name; 487 | ibdCurrent.ibdDescriptor.TimeDateStamp = timeStamp; 488 | ibdCurrent.ibdDescriptor.OffsetModuleName = offsetModuleName; 489 | ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs = forwardedModules; 490 | 491 | m_vIbd[dwBidnr].moduleForwarders.push_back(ibdCurrent); 492 | } 493 | 494 | void BoundImportDirectory::removeForwardedModule(dword dwBidnr, word forwardedModule) 495 | { 496 | m_vIbd[dwBidnr].moduleForwarders.erase(m_vIbd[dwBidnr].moduleForwarders.begin() + forwardedModule); 497 | } 498 | } 499 | -------------------------------------------------------------------------------- /src/pelib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(PELIB_SOURCES 2 | BoundImportDirectory.cpp 3 | CoffSymbolTable.cpp 4 | ComHeaderDirectory.cpp 5 | DebugDirectory.cpp 6 | ExportDirectory.cpp 7 | IatDirectory.cpp 8 | InputBuffer.cpp 9 | MzHeader.cpp 10 | OutputBuffer.cpp 11 | PeFile.cpp 12 | PeHeader.cpp 13 | PeLibAux.cpp 14 | RelocationsDirectory.cpp 15 | ResourceDirectory.cpp 16 | RichHeader.cpp 17 | SecurityDirectory.cpp 18 | ) 19 | 20 | add_library(pelib STATIC ${PELIB_SOURCES}) 21 | target_include_directories(pelib SYSTEM PUBLIC ${PROJECT_SOURCE_DIR}/include/) 22 | -------------------------------------------------------------------------------- /src/pelib/CoffSymbolTable.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file CoffSymbolTable.cpp 3 | * @brief Class for COFF symbol table. 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #include 8 | 9 | #include "pelib/PeLibInc.h" 10 | #include "pelib/CoffSymbolTable.h" 11 | 12 | namespace PeLib 13 | { 14 | CoffSymbolTable::CoffSymbolTable() : stringTableSize(0), numberOfStoredSymbols(0), m_ldrError(LDR_ERROR_NONE) 15 | { 16 | 17 | } 18 | 19 | CoffSymbolTable::~CoffSymbolTable() 20 | { 21 | 22 | } 23 | 24 | void CoffSymbolTable::read(InputBuffer& inputbuffer, unsigned int uiSize) 25 | { 26 | PELIB_IMAGE_COFF_SYMBOL symbol; 27 | 28 | for (std::size_t i = 0, e = uiSize / PELIB_IMAGE_SIZEOF_COFF_SYMBOL; i < e; ++i) 29 | { 30 | symbol.Name.clear(); 31 | dword Zeroes, NameOffset; 32 | inputbuffer >> Zeroes; 33 | inputbuffer >> NameOffset; 34 | inputbuffer >> symbol.Value; 35 | inputbuffer >> symbol.SectionNumber; 36 | inputbuffer >> symbol.TypeComplex; 37 | inputbuffer >> symbol.TypeSimple; 38 | inputbuffer >> symbol.StorageClass; 39 | inputbuffer >> symbol.NumberOfAuxSymbols; 40 | symbol.Index = (PeLib::dword)i; 41 | if (!Zeroes) 42 | { 43 | if (stringTableSize && NameOffset) 44 | { 45 | for (std::size_t j = NameOffset; j < stringTableSize && stringTable[j] != '\0'; ++j) 46 | { 47 | // If we have symbol name with length of 96 and it contains non-printable character, stop there because it does not seem to be valid. 48 | if (j - NameOffset == COFF_SYMBOL_NAME_MAX_LENGTH) 49 | { 50 | auto nonPrintableChars = std::count_if(symbol.Name.begin(), symbol.Name.end(), [](unsigned char c) { return !isprint(c); }); 51 | if (nonPrintableChars != 0) 52 | break; 53 | } 54 | 55 | symbol.Name += stringTable[j]; 56 | } 57 | } 58 | } 59 | else 60 | { 61 | for (std::size_t j = i * PELIB_IMAGE_SIZEOF_COFF_SYMBOL, k = 0; k < 8 && symbolTableDump[j] != '\0'; ++j, ++k) 62 | { 63 | symbol.Name += symbolTableDump[j]; 64 | } 65 | } 66 | 67 | i += symbol.NumberOfAuxSymbols; 68 | inputbuffer.move(symbol.NumberOfAuxSymbols * PELIB_IMAGE_SIZEOF_COFF_SYMBOL); 69 | symbolTable.push_back(symbol); 70 | } 71 | 72 | numberOfStoredSymbols = (dword)symbolTable.size(); 73 | } 74 | 75 | int CoffSymbolTable::read( 76 | std::istream& inStream, 77 | unsigned int uiOffset, 78 | unsigned int uiSize) 79 | { 80 | IStreamWrapper inStream_w(inStream); 81 | 82 | if (!inStream_w) 83 | { 84 | return ERROR_OPENING_FILE; 85 | } 86 | 87 | // Check for overflow 88 | if ((uiOffset + uiSize) < uiOffset) 89 | { 90 | return ERROR_INVALID_FILE; 91 | } 92 | 93 | std::uint64_t ulFileSize = fileSize(inStream_w); 94 | std::uint64_t stringTableOffset = uiOffset + uiSize; 95 | if (uiOffset >= ulFileSize || stringTableOffset >= ulFileSize) 96 | { 97 | return ERROR_INVALID_FILE; 98 | } 99 | 100 | inStream_w.seekg(uiOffset, std::ios::beg); 101 | symbolTableDump.resize(uiSize); 102 | inStream_w.read(reinterpret_cast(symbolTableDump.data()), uiSize); 103 | InputBuffer ibBuffer(symbolTableDump); 104 | 105 | // read size of string table 106 | if (ulFileSize >= stringTableOffset + 4) 107 | { 108 | stringTable.resize(4); 109 | inStream_w.read(reinterpret_cast(stringTable.data()), 4); 110 | InputBuffer strBuf(stringTable); 111 | strBuf >> stringTableSize; 112 | } 113 | 114 | if (inStream_w.gcount() < 4) 115 | { 116 | stringTableSize = (std::size_t)inStream_w.gcount(); 117 | } 118 | else if (inStream_w.gcount() == 4 && stringTableSize < 4) 119 | { 120 | stringTableSize = 4; 121 | } 122 | 123 | if (stringTableSize > ulFileSize || uiOffset + stringTableSize > ulFileSize) 124 | { 125 | stringTableSize = (std::size_t)(ulFileSize - uiOffset); 126 | } 127 | 128 | // read string table 129 | if (stringTableSize > 4) 130 | { 131 | stringTable.resize(stringTableSize); 132 | inStream_w.read(reinterpret_cast(stringTable.data() + 4), stringTableSize - 4); 133 | } 134 | 135 | read(ibBuffer, uiSize); 136 | 137 | return ERROR_NONE; 138 | } 139 | 140 | LoaderError CoffSymbolTable::loaderError() const 141 | { 142 | return m_ldrError; 143 | } 144 | 145 | void CoffSymbolTable::setLoaderError(LoaderError ldrError) 146 | { 147 | if (m_ldrError == LDR_ERROR_NONE) 148 | { 149 | m_ldrError = ldrError; 150 | } 151 | } 152 | 153 | std::size_t CoffSymbolTable::getSizeOfStringTable() const 154 | { 155 | return stringTableSize; 156 | } 157 | 158 | std::size_t CoffSymbolTable::getNumberOfStoredSymbols() const 159 | { 160 | return numberOfStoredSymbols; 161 | } 162 | 163 | dword CoffSymbolTable::getSymbolIndex(std::size_t ulSymbol) const 164 | { 165 | return symbolTable[ulSymbol].Index; 166 | } 167 | 168 | std::string CoffSymbolTable::getSymbolName(std::size_t ulSymbol) const 169 | { 170 | return symbolTable[ulSymbol].Name; 171 | } 172 | 173 | dword CoffSymbolTable::getSymbolValue(std::size_t ulSymbol) const 174 | { 175 | return symbolTable[ulSymbol].Value; 176 | } 177 | 178 | word CoffSymbolTable::getSymbolSectionNumber(std::size_t ulSymbol) const 179 | { 180 | return symbolTable[ulSymbol].SectionNumber; 181 | } 182 | 183 | byte CoffSymbolTable::getSymbolTypeComplex(std::size_t ulSymbol) const 184 | { 185 | return symbolTable[ulSymbol].TypeComplex; 186 | } 187 | 188 | byte CoffSymbolTable::getSymbolTypeSimple(std::size_t ulSymbol) const 189 | { 190 | return symbolTable[ulSymbol].TypeSimple; 191 | } 192 | 193 | byte CoffSymbolTable::getSymbolStorageClass(std::size_t ulSymbol) const 194 | { 195 | return symbolTable[ulSymbol].StorageClass; 196 | } 197 | 198 | byte CoffSymbolTable::getSymbolNumberOfAuxSymbols(std::size_t ulSymbol) const 199 | { 200 | return symbolTable[ulSymbol].NumberOfAuxSymbols; 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/pelib/ComHeaderDirectory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ComHeaderDirectory.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include "pelib/PeLibInc.h" 14 | #include "pelib/ComHeaderDirectory.h" 15 | 16 | namespace PeLib 17 | { 18 | void ComHeaderDirectory::read(InputBuffer& inputbuffer) 19 | { 20 | PELIB_IMAGE_COR20_HEADER ichCurr; 21 | 22 | inputbuffer >> ichCurr.cb; 23 | inputbuffer >> ichCurr.MajorRuntimeVersion; 24 | inputbuffer >> ichCurr.MinorRuntimeVersion; 25 | inputbuffer >> ichCurr.MetaData.VirtualAddress; 26 | inputbuffer >> ichCurr.MetaData.Size; 27 | inputbuffer >> ichCurr.Flags; 28 | inputbuffer >> ichCurr.EntryPointToken; 29 | inputbuffer >> ichCurr.Resources.VirtualAddress; 30 | inputbuffer >> ichCurr.Resources.Size; 31 | inputbuffer >> ichCurr.StrongNameSignature.VirtualAddress; 32 | inputbuffer >> ichCurr.StrongNameSignature.Size; 33 | inputbuffer >> ichCurr.CodeManagerTable.VirtualAddress; 34 | inputbuffer >> ichCurr.CodeManagerTable.Size; 35 | inputbuffer >> ichCurr.VTableFixups.VirtualAddress; 36 | inputbuffer >> ichCurr.VTableFixups.Size; 37 | inputbuffer >> ichCurr.ExportAddressTableJumps.VirtualAddress; 38 | inputbuffer >> ichCurr.ExportAddressTableJumps.Size; 39 | inputbuffer >> ichCurr.ManagedNativeHeader.VirtualAddress; 40 | inputbuffer >> ichCurr.ManagedNativeHeader.Size; 41 | 42 | std::swap(ichCurr, m_ichComHeader); 43 | } 44 | 45 | int ComHeaderDirectory::read(unsigned char* buffer, unsigned int buffersize) 46 | { 47 | if (buffersize < PELIB_IMAGE_COR20_HEADER::size()) 48 | { 49 | return ERROR_INVALID_FILE; 50 | } 51 | 52 | std::vector vComDescDirectory(buffer, buffer + buffersize); 53 | 54 | InputBuffer ibBuffer(vComDescDirectory); 55 | read(ibBuffer); 56 | return ERROR_NONE; 57 | } 58 | 59 | /** 60 | * Rebuilds the current COM+ descriptor. 61 | * @param vBuffer Buffer where the COM+ descriptor will be written to. 62 | **/ 63 | void ComHeaderDirectory::rebuild(std::vector& vBuffer) const 64 | { 65 | OutputBuffer obBuffer(vBuffer); 66 | 67 | obBuffer << m_ichComHeader.cb; 68 | obBuffer << m_ichComHeader.MajorRuntimeVersion; 69 | obBuffer << m_ichComHeader.MinorRuntimeVersion; 70 | obBuffer << m_ichComHeader.MetaData.VirtualAddress; 71 | obBuffer << m_ichComHeader.MetaData.Size; 72 | obBuffer << m_ichComHeader.Flags; 73 | obBuffer << m_ichComHeader.EntryPointToken; 74 | obBuffer << m_ichComHeader.Resources.VirtualAddress; 75 | obBuffer << m_ichComHeader.Resources.Size; 76 | obBuffer << m_ichComHeader.StrongNameSignature.VirtualAddress; 77 | obBuffer << m_ichComHeader.StrongNameSignature.Size; 78 | obBuffer << m_ichComHeader.CodeManagerTable.VirtualAddress; 79 | obBuffer << m_ichComHeader.CodeManagerTable.Size; 80 | obBuffer << m_ichComHeader.VTableFixups.VirtualAddress; 81 | obBuffer << m_ichComHeader.VTableFixups.Size; 82 | obBuffer << m_ichComHeader.ExportAddressTableJumps.VirtualAddress; 83 | obBuffer << m_ichComHeader.ExportAddressTableJumps.Size; 84 | obBuffer << m_ichComHeader.ManagedNativeHeader.VirtualAddress; 85 | obBuffer << m_ichComHeader.ManagedNativeHeader.Size; 86 | } 87 | 88 | /** 89 | * @return Size in bytes. 90 | **/ 91 | unsigned int ComHeaderDirectory::size() const 92 | { 93 | return PELIB_IMAGE_COR20_HEADER::size(); 94 | } 95 | 96 | /** 97 | * @param strFilename Name of the file. 98 | * @param dwOffset File offset the COM+ descriptor will be written to. 99 | **/ 100 | int ComHeaderDirectory::write(const std::string& strFilename, unsigned int dwOffset) const 101 | { 102 | std::fstream ofFile(strFilename.c_str(), std::ios_base::in); 103 | 104 | if (!ofFile) 105 | { 106 | ofFile.clear(); 107 | ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary); 108 | } 109 | else 110 | { 111 | ofFile.close(); 112 | ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary); 113 | } 114 | 115 | if (!ofFile) 116 | { 117 | return ERROR_OPENING_FILE; 118 | } 119 | 120 | ofFile.seekp(dwOffset, std::ios::beg); 121 | 122 | std::vector vBuffer; 123 | rebuild(vBuffer); 124 | 125 | ofFile.write(reinterpret_cast(vBuffer.data()), static_cast(vBuffer.size())); 126 | 127 | ofFile.close(); 128 | 129 | return ERROR_NONE; 130 | } 131 | 132 | /** 133 | * @return SizeOfHeader value of the current COM+ descriptor. 134 | **/ 135 | dword ComHeaderDirectory::getSizeOfHeader() const 136 | { 137 | return m_ichComHeader.cb; 138 | } 139 | 140 | /** 141 | * @return MajorRuntimeVersion value of the current COM+ descriptor. 142 | **/ 143 | word ComHeaderDirectory::getMajorRuntimeVersion() const 144 | { 145 | return m_ichComHeader.MajorRuntimeVersion; 146 | } 147 | 148 | /** 149 | * @return MinorRuntimeVersion value of the current COM+ descriptor. 150 | **/ 151 | word ComHeaderDirectory::getMinorRuntimeVersion() const 152 | { 153 | return m_ichComHeader.MinorRuntimeVersion; 154 | } 155 | 156 | /** 157 | * @return MetaData (Virtual Address) value of the current COM+ descriptor. 158 | **/ 159 | dword ComHeaderDirectory::getMetaDataVa() const 160 | { 161 | return m_ichComHeader.MetaData.VirtualAddress; 162 | } 163 | 164 | /** 165 | * @return MetaData (Size) value of the current COM+ descriptor. 166 | **/ 167 | dword ComHeaderDirectory::getMetaDataSize() const 168 | { 169 | return m_ichComHeader.MetaData.Size; 170 | } 171 | 172 | /** 173 | * @return Flags value of the current COM+ descriptor. 174 | **/ 175 | dword ComHeaderDirectory::getFlags() const 176 | { 177 | return m_ichComHeader.Flags; 178 | } 179 | 180 | /** 181 | * @return EntryPointToken value of the current COM+ descriptor. 182 | **/ 183 | dword ComHeaderDirectory::getEntryPointToken() const 184 | { 185 | return m_ichComHeader.EntryPointToken; 186 | } 187 | 188 | /** 189 | * @return Resources (Virtual Address) value of the current COM+ descriptor. 190 | **/ 191 | dword ComHeaderDirectory::getResourcesVa() const 192 | { 193 | return m_ichComHeader.Resources.VirtualAddress; 194 | } 195 | 196 | /** 197 | * @return Resources (Size) value of the current COM+ descriptor. 198 | **/ 199 | dword ComHeaderDirectory::getResourcesSize() const 200 | { 201 | return m_ichComHeader.Resources.Size; 202 | } 203 | 204 | /** 205 | * @return StrongNameSignature (Virtual Address) value of the current COM+ descriptor. 206 | **/ 207 | dword ComHeaderDirectory::getStrongNameSignatureVa() const 208 | { 209 | return m_ichComHeader.StrongNameSignature.VirtualAddress; 210 | } 211 | 212 | /** 213 | * @return StrongNameSignature (Size) value of the current COM+ descriptor. 214 | **/ 215 | dword ComHeaderDirectory::getStrongNameSignatureSize() const 216 | { 217 | return m_ichComHeader.StrongNameSignature.Size; 218 | } 219 | 220 | /** 221 | * @return CodeManagerTable (Virtual Address) value of the current COM+ descriptor. 222 | **/ 223 | dword ComHeaderDirectory::getCodeManagerTableVa() const 224 | { 225 | return m_ichComHeader.CodeManagerTable.VirtualAddress; 226 | } 227 | 228 | /** 229 | * @return CodeManagerTable (Size) value of the current COM+ descriptor. 230 | **/ 231 | dword ComHeaderDirectory::getCodeManagerTableSize() const 232 | { 233 | return m_ichComHeader.CodeManagerTable.Size; 234 | } 235 | 236 | /** 237 | * @return VTableFixups (Virtual Address) value of the current COM+ descriptor. 238 | **/ 239 | dword ComHeaderDirectory::getVTableFixupsVa() const 240 | { 241 | return m_ichComHeader.VTableFixups.VirtualAddress; 242 | } 243 | 244 | /** 245 | * @return VTableFixups (Size) value of the current COM+ descriptor. 246 | **/ 247 | dword ComHeaderDirectory::getVTableFixupsSize() const 248 | { 249 | return m_ichComHeader.VTableFixups.Size; 250 | } 251 | 252 | /** 253 | * @return ExportAddressTableJumps (Virtual Address) value of the current COM+ descriptor. 254 | **/ 255 | dword ComHeaderDirectory::getExportAddressTableJumpsVa() const 256 | { 257 | return m_ichComHeader.ExportAddressTableJumps.VirtualAddress; 258 | } 259 | 260 | /** 261 | * @return ExportAddressTableJumps (Size) value of the current COM+ descriptor. 262 | **/ 263 | dword ComHeaderDirectory::getExportAddressTableJumpsSize() const 264 | { 265 | return m_ichComHeader.ExportAddressTableJumps.Size; 266 | } 267 | 268 | /** 269 | * @return ManagedNativeHeader (Virtual Address) value of the current COM+ descriptor. 270 | **/ 271 | dword ComHeaderDirectory::getManagedNativeHeaderVa() const 272 | { 273 | return m_ichComHeader.ManagedNativeHeader.VirtualAddress; 274 | } 275 | 276 | /** 277 | * @return ManagedNativeHeader (Size) value of the current COM+ descriptor. 278 | **/ 279 | dword ComHeaderDirectory::getManagedNativeHeaderSize() const 280 | { 281 | return m_ichComHeader.ManagedNativeHeader.Size; 282 | } 283 | 284 | /** 285 | * @param dwValue New value for the current SizeOfHeader (cb) value. 286 | **/ 287 | void ComHeaderDirectory::setSizeOfHeader(dword dwValue) 288 | { 289 | m_ichComHeader.cb = dwValue; 290 | } 291 | 292 | /** 293 | * @param wValue New value for the current MajorRuntimeVersion value. 294 | **/ 295 | void ComHeaderDirectory::setMajorRuntimeVersion(word wValue) 296 | { 297 | m_ichComHeader.MajorRuntimeVersion = wValue; 298 | } 299 | 300 | /** 301 | * @param wValue New value for the current MinorRuntimeVersion value. 302 | **/ 303 | void ComHeaderDirectory::setMinorRuntimeVersion(word wValue) 304 | { 305 | m_ichComHeader.MinorRuntimeVersion = wValue; 306 | } 307 | 308 | /** 309 | * @param dwValue New value for the current MetaData (VirtualAddress) value. 310 | **/ 311 | void ComHeaderDirectory::setMetaDataVa(dword dwValue) 312 | { 313 | m_ichComHeader.MetaData.VirtualAddress = dwValue; 314 | } 315 | 316 | /** 317 | * @param dwValue New value for the current MetaData (Size) value. 318 | **/ 319 | void ComHeaderDirectory::setMetaDataSize(dword dwValue) 320 | { 321 | m_ichComHeader.MetaData.Size = dwValue; 322 | } 323 | 324 | /** 325 | * @param dwValue New value for the current Flags value. 326 | **/ 327 | void ComHeaderDirectory::setFlags(dword dwValue) 328 | { 329 | m_ichComHeader.Flags = dwValue; 330 | } 331 | 332 | /** 333 | * @param dwValue New value for the current EntryPointToken value. 334 | **/ 335 | void ComHeaderDirectory::setEntryPointToken(dword dwValue) 336 | { 337 | m_ichComHeader.EntryPointToken = dwValue; 338 | } 339 | 340 | /** 341 | * @param dwValue New value for the current Resources (VirtualAddress) value. 342 | **/ 343 | void ComHeaderDirectory::setResourcesVa(dword dwValue) 344 | { 345 | m_ichComHeader.Resources.VirtualAddress = dwValue; 346 | } 347 | 348 | /** 349 | * @param dwValue New value for the current Resources (Size) value. 350 | **/ 351 | void ComHeaderDirectory::setResourcesSize(dword dwValue) 352 | { 353 | m_ichComHeader.Resources.Size = dwValue; 354 | } 355 | 356 | /** 357 | * @param dwValue New value for the current StrongNameSignature (VirtualAddress) value. 358 | **/ 359 | void ComHeaderDirectory::setStrongNameSignatureVa(dword dwValue) 360 | { 361 | m_ichComHeader.StrongNameSignature.VirtualAddress = dwValue; 362 | } 363 | 364 | /** 365 | * @param dwValue New value for the current StrongNameSignature (Size) value. 366 | **/ 367 | void ComHeaderDirectory::setStrongNameSignagureSize(dword dwValue) 368 | { 369 | m_ichComHeader.StrongNameSignature.Size = dwValue; 370 | } 371 | 372 | /** 373 | * @param dwValue New value for the current CodeManagerTable (VirtualAddress) value. 374 | **/ 375 | void ComHeaderDirectory::setCodeManagerTableVa(dword dwValue) 376 | { 377 | m_ichComHeader.CodeManagerTable.VirtualAddress = dwValue; 378 | } 379 | 380 | /** 381 | * @param dwValue New value for the current CodeManagerTable (Size) value. 382 | **/ 383 | void ComHeaderDirectory::setCodeManagerTableSize(dword dwValue) 384 | { 385 | m_ichComHeader.CodeManagerTable.Size = dwValue; 386 | } 387 | 388 | /** 389 | * @param dwValue New value for the current VTableFixups (VirtualAddress) value. 390 | **/ 391 | void ComHeaderDirectory::setVTableFixupsVa(dword dwValue) 392 | { 393 | m_ichComHeader.VTableFixups.VirtualAddress = dwValue; 394 | } 395 | 396 | /** 397 | * @param dwValue New value for the current VTableFixups (Size) value. 398 | **/ 399 | void ComHeaderDirectory::setVTableFixupsSize(dword dwValue) 400 | { 401 | m_ichComHeader.VTableFixups.Size = dwValue; 402 | } 403 | 404 | /** 405 | * @param dwValue New value for the current ExportAddressTableJumps (VirtualAddress) value. 406 | **/ 407 | void ComHeaderDirectory::setExportAddressTableJumpsVa(dword dwValue) 408 | { 409 | m_ichComHeader.ExportAddressTableJumps.VirtualAddress = dwValue; 410 | } 411 | 412 | /** 413 | * @param dwValue New value for the current ExportAddressTableJumps (Size) value. 414 | **/ 415 | void ComHeaderDirectory::setExportAddressTableJumpsSize(dword dwValue) 416 | { 417 | m_ichComHeader.ExportAddressTableJumps.Size = dwValue; 418 | } 419 | 420 | /** 421 | * @param dwValue New value for the current ManagedNativeHeader (VirtualAddress) value. 422 | **/ 423 | void ComHeaderDirectory::setManagedNativeHeaderVa(dword dwValue) 424 | { 425 | m_ichComHeader.ManagedNativeHeader.VirtualAddress = dwValue; 426 | } 427 | 428 | /** 429 | * @param dwValue New value for the current ManagedNativeHeader (Size) value. 430 | **/ 431 | void ComHeaderDirectory::setManagedNativeHeaderSize(dword dwValue) 432 | { 433 | m_ichComHeader.ManagedNativeHeader.Size = dwValue; 434 | } 435 | 436 | } 437 | -------------------------------------------------------------------------------- /src/pelib/DebugDirectory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * DebugDirectory.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include "pelib/PeLibInc.h" 14 | #include "pelib/DebugDirectory.h" 15 | 16 | namespace PeLib 17 | { 18 | void DebugDirectory::clear() 19 | { 20 | m_vDebugInfo.clear(); 21 | } 22 | 23 | std::vector DebugDirectory::read(InputBuffer& ibBuffer, unsigned int uiRva, unsigned int uiSize) 24 | { 25 | std::vector currDebugInfo; 26 | 27 | PELIB_IMG_DEBUG_DIRECTORY iddCurr; 28 | 29 | unsigned int uiEntryCount = uiSize / PELIB_IMAGE_DEBUG_DIRECTORY::size(); 30 | for (unsigned int i = 0; i < uiEntryCount; i++) 31 | { 32 | 33 | ibBuffer >> iddCurr.idd.Characteristics; 34 | ibBuffer >> iddCurr.idd.TimeDateStamp; 35 | ibBuffer >> iddCurr.idd.MajorVersion; 36 | ibBuffer >> iddCurr.idd.MinorVersion; 37 | ibBuffer >> iddCurr.idd.Type; 38 | ibBuffer >> iddCurr.idd.SizeOfData; 39 | ibBuffer >> iddCurr.idd.AddressOfRawData; 40 | ibBuffer >> iddCurr.idd.PointerToRawData; 41 | 42 | currDebugInfo.push_back(iddCurr); 43 | } 44 | 45 | if (!currDebugInfo.empty()) 46 | { 47 | m_occupiedAddresses.emplace_back( 48 | uiRva, 49 | uiRva + uiEntryCount * PELIB_IMAGE_DEBUG_DIRECTORY::size() - 1 50 | ); 51 | } 52 | 53 | return currDebugInfo; 54 | } 55 | 56 | int DebugDirectory::read(unsigned char* buffer, unsigned int buffersize) 57 | { 58 | // XXX: Note, debug data is not read at all. This might or might not change 59 | // in the future. 60 | 61 | std::vector vDebugDirectory(buffer, buffer + buffersize); 62 | 63 | InputBuffer ibBuffer(vDebugDirectory); 64 | 65 | std::vector currDebugInfo = read(ibBuffer, 0, buffersize); 66 | 67 | std::swap(currDebugInfo, m_vDebugInfo); 68 | 69 | return ERROR_NONE; 70 | } 71 | 72 | /** 73 | * Rebuilds the current debug directory. 74 | * @param vBuffer Buffer where the rebuilt directory is stored. 75 | **/ 76 | void DebugDirectory::rebuild(std::vector& vBuffer) const 77 | { 78 | OutputBuffer obBuffer(vBuffer); 79 | 80 | for (unsigned int i=0;i(m_vDebugInfo.size()) * PELIB_IMAGE_DEBUG_DIRECTORY::size(); 99 | } 100 | 101 | /** 102 | * @param strFilename Name of the file which will be written. 103 | * @param uiOffset File offset where the debug directory will be stored. 104 | **/ 105 | int DebugDirectory::write(const std::string& strFilename, unsigned int uiOffset) const 106 | { 107 | std::fstream ofFile(strFilename.c_str(), std::ios_base::in); 108 | 109 | if (!ofFile) 110 | { 111 | ofFile.clear(); 112 | ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary); 113 | } 114 | else 115 | { 116 | ofFile.close(); 117 | ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary); 118 | } 119 | 120 | if (!ofFile) 121 | { 122 | return ERROR_OPENING_FILE; 123 | } 124 | 125 | ofFile.seekp(uiOffset, std::ios::beg); 126 | 127 | std::vector vBuffer; 128 | rebuild(vBuffer); 129 | 130 | ofFile.write(reinterpret_cast(vBuffer.data()), static_cast(vBuffer.size())); 131 | 132 | ofFile.close(); 133 | 134 | return ERROR_NONE; 135 | } 136 | 137 | /** 138 | * @return Number of debug structures in the current Debug directory. 139 | **/ 140 | unsigned int DebugDirectory::calcNumberOfEntries() const 141 | { 142 | return static_cast(m_vDebugInfo.size()); 143 | } 144 | 145 | /** 146 | * Adds a new debug structure to the debug directory. The initial values of all members of the structure 147 | * are undefined. 148 | **/ 149 | void DebugDirectory::addEntry() 150 | { 151 | PELIB_IMG_DEBUG_DIRECTORY p; 152 | m_vDebugInfo.push_back(p); 153 | } 154 | 155 | /** 156 | * Removes a debug structure from the current debug directory. If an invalid structure is specified 157 | * by the parameter uiIndex the result will be undefined behaviour. 158 | * @param uiIndex Identifies the debug structure. 159 | **/ 160 | void DebugDirectory::removeEntry(std::size_t uiIndex) 161 | { 162 | m_vDebugInfo.erase(m_vDebugInfo.begin() + uiIndex); 163 | } 164 | 165 | /** 166 | * Returns the Characteristics value of a debug structure. If an invalid structure is specified 167 | * by the parameter uiIndex the result will be undefined behaviour. 168 | * @param uiIndex Identifies the debug structure. 169 | * @return Characteristics value of the debug structure. 170 | **/ 171 | dword DebugDirectory::getCharacteristics(std::size_t uiIndex) const 172 | { 173 | return m_vDebugInfo[uiIndex].idd.Characteristics; 174 | } 175 | 176 | /** 177 | * Returns the TimeDateStamp value of a debug structure. If an invalid structure is specified 178 | * by the parameter uiIndex the result will be undefined behaviour. 179 | * @param uiIndex Identifies the debug structure. 180 | * @return TimeDateStamp value of the debug structure. 181 | **/ 182 | dword DebugDirectory::getTimeDateStamp(std::size_t uiIndex) const 183 | { 184 | return m_vDebugInfo[uiIndex].idd.TimeDateStamp; 185 | } 186 | 187 | /** 188 | * Returns the MajorVersion value of a debug structure. If an invalid structure is specified 189 | * by the parameter uiIndex the result will be undefined behaviour. 190 | * @param uiIndex Identifies the debug structure. 191 | * @return MajorVersion value of the debug structure. 192 | **/ 193 | word DebugDirectory::getMajorVersion(std::size_t uiIndex) const 194 | { 195 | return m_vDebugInfo[uiIndex].idd.MajorVersion; 196 | } 197 | 198 | /** 199 | * Returns the MinorVersion value of a debug structure. If an invalid structure is specified 200 | * by the parameter uiIndex the result will be undefined behaviour. 201 | * @param uiIndex Identifies the debug structure. 202 | * @return MinorVersion value of the debug structure. 203 | **/ 204 | word DebugDirectory::getMinorVersion(std::size_t uiIndex) const 205 | { 206 | return m_vDebugInfo[uiIndex].idd.MinorVersion; 207 | } 208 | 209 | /** 210 | * Returns the Type value of a debug structure. If an invalid structure is specified 211 | * by the parameter uiIndex the result will be undefined behaviour. 212 | * @param uiIndex Identifies the debug structure. 213 | * @return Type value of the debug structure. 214 | **/ 215 | dword DebugDirectory::getType(std::size_t uiIndex) const 216 | { 217 | return m_vDebugInfo[uiIndex].idd.Type; 218 | } 219 | 220 | /** 221 | * Returns the SizeOfData value of a debug structure. If an invalid structure is specified 222 | * by the parameter uiIndex the result will be undefined behaviour. 223 | * @param uiIndex Identifies the debug structure. 224 | * @return SizeOfData value of the debug structure. 225 | **/ 226 | dword DebugDirectory::getSizeOfData(std::size_t uiIndex) const 227 | { 228 | return m_vDebugInfo[uiIndex].idd.SizeOfData; 229 | } 230 | 231 | /** 232 | * Returns the AddressOfRawData value of a debug structure. If an invalid structure is specified 233 | * by the parameter uiIndex the result will be undefined behaviour. 234 | * @param uiIndex Identifies the debug structure. 235 | * @return AddressOfRawData value of the debug structure. 236 | **/ 237 | dword DebugDirectory::getAddressOfRawData(std::size_t uiIndex) const 238 | { 239 | return m_vDebugInfo[uiIndex].idd.AddressOfRawData; 240 | } 241 | 242 | /** 243 | * Returns the PointerToRawData value of a debug structure. If an invalid structure is specified 244 | * by the parameter uiIndex the result will be undefined behaviour. 245 | * @param uiIndex Identifies the debug structure. 246 | * @return PointerToRawData value of the debug structure. 247 | **/ 248 | dword DebugDirectory::getPointerToRawData(std::size_t uiIndex) const 249 | { 250 | return m_vDebugInfo[uiIndex].idd.PointerToRawData; 251 | } 252 | 253 | std::vector DebugDirectory::getData(std::size_t index) const 254 | { 255 | return m_vDebugInfo[index].data; 256 | } 257 | 258 | /** 259 | * Changes the Characteristics value of a debug structure. If an invalid structure is specified 260 | * by the parameter uiIndex the result will be undefined behaviour. 261 | * @param uiIndex Identifies the debug structure. 262 | * @param dwValue New value of the Characteristics value of the debug structure. 263 | **/ 264 | void DebugDirectory::setCharacteristics(std::size_t uiIndex, dword dwValue) 265 | { 266 | m_vDebugInfo[uiIndex].idd.Characteristics = dwValue; 267 | } 268 | 269 | /** 270 | * Changes the TimeDateStamp value of a debug structure. If an invalid structure is specified 271 | * by the parameter uiIndex the result will be undefined behaviour. 272 | * @param uiIndex Identifies the debug structure. 273 | * @param dwValue New value of the TimeDateStamp value of the debug structure. 274 | **/ 275 | void DebugDirectory::setTimeDateStamp(std::size_t uiIndex, dword dwValue) 276 | { 277 | m_vDebugInfo[uiIndex].idd.TimeDateStamp = dwValue; 278 | } 279 | 280 | /** 281 | * Changes the MajorVersion value of a debug structure. If an invalid structure is specified 282 | * by the parameter uiIndex the result will be undefined behaviour. 283 | * @param uiIndex Identifies the debug structure. 284 | * @param wValue New value of the MajorVersion value of the debug structure. 285 | **/ 286 | void DebugDirectory::setMajorVersion(std::size_t uiIndex, word wValue) 287 | { 288 | m_vDebugInfo[uiIndex].idd.MajorVersion = wValue; 289 | } 290 | 291 | /** 292 | * Changes the MinorVersion value of a debug structure. If an invalid structure is specified 293 | * by the parameter uiIndex the result will be undefined behaviour. 294 | * @param uiIndex Identifies the debug structure. 295 | * @param wValue New value of the MinorVersion value of the debug structure. 296 | **/ 297 | void DebugDirectory::setMinorVersion(std::size_t uiIndex, word wValue) 298 | { 299 | m_vDebugInfo[uiIndex].idd.MinorVersion = wValue; 300 | } 301 | 302 | /** 303 | * Changes the Type value of a debug structure. If an invalid structure is specified 304 | * by the parameter uiIndex the result will be undefined behaviour. 305 | * @param uiIndex Identifies the debug structure. 306 | * @param dwValue New value of the Type value of the debug structure. 307 | **/ 308 | void DebugDirectory::setType(std::size_t uiIndex, dword dwValue) 309 | { 310 | m_vDebugInfo[uiIndex].idd.Type = dwValue; 311 | } 312 | 313 | /** 314 | * Changes the SizeOfData value of a debug structure. If an invalid structure is specified 315 | * by the parameter uiIndex the result will be undefined behaviour. 316 | * @param uiIndex Identifies the debug structure. 317 | * @param dwValue New value of the SizeOfData value of the debug structure. 318 | **/ 319 | void DebugDirectory::setSizeOfData(std::size_t uiIndex, dword dwValue) 320 | { 321 | m_vDebugInfo[uiIndex].idd.SizeOfData = dwValue; 322 | } 323 | 324 | /** 325 | * Changes the AddressOfRawData value of a debug structure. If an invalid structure is specified 326 | * by the parameter uiIndex the result will be undefined behaviour. 327 | * @param uiIndex Identifies the debug structure. 328 | * @param dwValue New value of the AddressOfRawData value of the debug structure. 329 | **/ 330 | void DebugDirectory::setAddressOfRawData(std::size_t uiIndex, dword dwValue) 331 | { 332 | m_vDebugInfo[uiIndex].idd.AddressOfRawData = dwValue; 333 | } 334 | 335 | /** 336 | * Changes the PointerToRawData value of a debug structure. If an invalid structure is specified 337 | * by the parameter uiIndex the result will be undefined behaviour. 338 | * @param uiIndex Identifies the debug structure. 339 | * @param dwValue New value of the PointerToRawData value of the debug structure. 340 | **/ 341 | void DebugDirectory::setPointerToRawData(std::size_t uiIndex, dword dwValue) 342 | { 343 | m_vDebugInfo[uiIndex].idd.PointerToRawData = dwValue; 344 | } 345 | 346 | void DebugDirectory::setData(std::size_t index, const std::vector& data) 347 | { 348 | m_vDebugInfo[index].data = data; 349 | } 350 | 351 | const std::vector>& DebugDirectory::getOccupiedAddresses() const 352 | { 353 | return m_occupiedAddresses; 354 | } 355 | } 356 | -------------------------------------------------------------------------------- /src/pelib/ExportDirectory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ExportDirectory.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include "pelib/PeLibInc.h" 14 | #include "pelib/ExportDirectory.h" 15 | 16 | namespace PeLib 17 | { 18 | /** 19 | * @param strFuncname Name of the function. 20 | * @param dwFuncAddr RVA of the function. 21 | **/ 22 | void ExportDirectory::addFunction(const std::string& strFuncname, dword dwFuncAddr) 23 | { 24 | PELIB_EXP_FUNC_INFORMATION efiCurr; 25 | efiCurr.funcname = strFuncname; 26 | efiCurr.addroffunc = dwFuncAddr; 27 | m_ied.functions.push_back(efiCurr); 28 | } 29 | 30 | void ExportDirectory::removeFunction(unsigned int index) 31 | { 32 | m_ied.functions.erase(m_ied.functions.begin() + index); 33 | } 34 | 35 | void ExportDirectory::clear() 36 | { 37 | m_ied.functions.clear(); 38 | } 39 | 40 | unsigned int ExportDirectory::calcNumberOfFunctions() const 41 | { 42 | return static_cast(m_ied.functions.size()); 43 | } 44 | 45 | /** 46 | * Identifies an exported function through it's name. 47 | * @param strFunctionName Name of the function 48 | * @return Number which identifies the functions. 49 | **/ 50 | int ExportDirectory::getFunctionIndex(const std::string& strFunctionName) const 51 | { 52 | auto Iter = std::find_if( 53 | m_ied.functions.begin(), 54 | m_ied.functions.end(), 55 | [&](const auto& i) { return i.equal(strFunctionName); } 56 | ); 57 | 58 | if (Iter == m_ied.functions.end()) 59 | { 60 | // throw Exceptions::InvalidName(ExportDirectoryId, __LINE__); 61 | return -1; 62 | } 63 | 64 | return static_cast(std::distance(m_ied.functions.begin(), Iter)); 65 | } 66 | 67 | /** 68 | * @param vBuffer Buffer where the rebuilt export directory is written to. 69 | * @param dwRva RVA of the export directory. 70 | * \todo fValid flag 71 | **/ 72 | void ExportDirectory::rebuild(std::vector& vBuffer, dword dwRva) const 73 | { 74 | unsigned int uiSizeDirectory = sizeof(PELIB_IMAGE_EXPORT_DIRECTORY); 75 | 76 | unsigned int uiSizeNames = 0; 77 | unsigned int uiSizeAddrFuncs = 0; 78 | unsigned int uiSizeAddrNames = 0; 79 | unsigned int uiSizeOrdinals = 0; 80 | 81 | for (unsigned int i=0;i(m_ied.functions[i].funcname.size()) + 1; 84 | uiSizeAddrFuncs += sizeof(m_ied.functions[i].addroffunc); 85 | uiSizeAddrNames += (m_ied.functions[i].funcname.empty()) ? 0 : sizeof(m_ied.functions[i].addrofname); 86 | uiSizeOrdinals += (m_ied.functions[i].funcname.empty()) ? 0 : sizeof(m_ied.functions[i].ordinal); 87 | } 88 | 89 | unsigned int uiFilenameSize = static_cast(m_ied.name.size()) + 1; 90 | 91 | OutputBuffer obBuffer(vBuffer); 92 | 93 | obBuffer << m_ied.ied.Characteristics; 94 | obBuffer << m_ied.ied.TimeDateStamp; 95 | obBuffer << m_ied.ied.MajorVersion; 96 | obBuffer << m_ied.ied.MinorVersion; 97 | obBuffer << dwRva + uiSizeDirectory + uiSizeAddrFuncs + uiSizeAddrNames + uiSizeOrdinals; 98 | obBuffer << m_ied.ied.Base; 99 | obBuffer << static_cast(m_ied.functions.size()); 100 | 101 | // TODO: Not correct but sufficient for now. (Update: I forgot what this comment refers to, but I'll leave it in) 102 | obBuffer << static_cast(m_ied.functions.size()); 103 | obBuffer << dwRva + uiSizeDirectory; 104 | obBuffer << dwRva + uiSizeDirectory + uiSizeAddrFuncs; 105 | obBuffer << dwRva + uiSizeDirectory + uiSizeAddrFuncs + uiSizeAddrNames; 106 | 107 | for (unsigned int i=0;i(m_ied.functions[i].funcname.size()) + 1; 120 | } 121 | } 122 | 123 | for (unsigned int i=0;i(m_ied.name.size())+1); 140 | 141 | for (unsigned int i=0;i(m_ied.functions[i].funcname.size()) + 1); 146 | } 147 | } 148 | } 149 | 150 | /** 151 | * @return Size of the current export directory. 152 | **/ 153 | unsigned int ExportDirectory::size() const 154 | { 155 | return m_ied.size(); 156 | } 157 | 158 | /** 159 | * @param strFilename Name of the file. 160 | * @param uiOffset File offset the export directory will be written to. 161 | * @param uiRva RVA of the export directory. 162 | * \todo Check if ofFile.write succeeded. 163 | **/ 164 | int ExportDirectory::write(const std::string& strFilename, unsigned int uiOffset, unsigned int uiRva) const 165 | { 166 | std::fstream ofFile(strFilename.c_str(), std::ios_base::in); 167 | 168 | if (!ofFile) 169 | { 170 | ofFile.clear(); 171 | ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary); 172 | } 173 | else 174 | { 175 | ofFile.close(); 176 | ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary); 177 | } 178 | 179 | if (!ofFile) 180 | { 181 | return ERROR_OPENING_FILE; 182 | } 183 | 184 | ofFile.seekp(uiOffset, std::ios::beg); 185 | 186 | std::vector vBuffer; 187 | rebuild(vBuffer, uiRva); 188 | 189 | ofFile.write(reinterpret_cast(vBuffer.data()), static_cast(vBuffer.size())); 190 | 191 | ofFile.close(); 192 | 193 | return ERROR_NONE; 194 | } 195 | 196 | /** 197 | * Changes the filename according to the export directory. 198 | * @param strFilename New filename. 199 | **/ 200 | void ExportDirectory::setNameString(const std::string& strFilename) 201 | { 202 | m_ied.name = strFilename; 203 | } 204 | 205 | std::string ExportDirectory::getNameString() const 206 | { 207 | return m_ied.name; 208 | } 209 | 210 | /** 211 | * @param dwIndex Number which identifies an exported function. 212 | * @return The name of that function. 213 | **/ 214 | std::string ExportDirectory::getFunctionName(std::size_t dwIndex) const 215 | { 216 | return m_ied.functions[dwIndex].funcname; 217 | } 218 | 219 | /** 220 | * @param dwIndex Number which identifies an exported function. 221 | * @return The ordinal of that function. 222 | **/ 223 | word ExportDirectory::getFunctionOrdinal(std::size_t dwIndex) const 224 | { 225 | return m_ied.functions[dwIndex].ordinal; 226 | } 227 | 228 | /** 229 | * @param dwIndex Number which identifies an exported function. 230 | * @return The RVA of the name string of that function. 231 | **/ 232 | dword ExportDirectory::getAddressOfName(std::size_t dwIndex) const 233 | { 234 | return m_ied.functions[dwIndex].addrofname; 235 | } 236 | 237 | /** 238 | * @param dwIndex Number which identifies an exported function. 239 | * @return The RVA of that function. 240 | **/ 241 | dword ExportDirectory::getAddressOfFunction(std::size_t dwIndex) const 242 | { 243 | return m_ied.functions[dwIndex].addroffunc; 244 | } 245 | 246 | /** 247 | * @param dwIndex Number which identifies an exported function. 248 | * @param strName The name of that function. 249 | **/ 250 | void ExportDirectory::setFunctionName(std::size_t dwIndex, const std::string& strName) 251 | { 252 | m_ied.functions[dwIndex].funcname = strName; 253 | } 254 | 255 | /** 256 | * @param dwIndex Number which identifies an exported function. 257 | * @param wValue The ordinal of that function. 258 | **/ 259 | void ExportDirectory::setFunctionOrdinal(std::size_t dwIndex, word wValue) 260 | { 261 | m_ied.functions[dwIndex].ordinal = wValue; 262 | } 263 | 264 | /** 265 | * @param dwIndex Number which identifies an exported function. 266 | * @param dwValue The RVA of the name string of that function. 267 | **/ 268 | void ExportDirectory::setAddressOfName(std::size_t dwIndex, dword dwValue) 269 | { 270 | m_ied.functions[dwIndex].addrofname = dwValue; 271 | } 272 | 273 | /** 274 | * @param dwIndex Number which identifies an exported function. 275 | * @param dwValue The RVA of that function. 276 | **/ 277 | void ExportDirectory::setAddressOfFunction(std::size_t dwIndex, dword dwValue) 278 | { 279 | m_ied.functions[dwIndex].addroffunc = dwValue; 280 | } 281 | 282 | /** 283 | * @return The ordinal base of the export directory. 284 | **/ 285 | dword ExportDirectory::getBase() const 286 | { 287 | return m_ied.ied.Base; 288 | } 289 | 290 | /** 291 | * @return The characteristics of the export directory. 292 | **/ 293 | dword ExportDirectory::getCharacteristics() const 294 | { 295 | return m_ied.ied.Characteristics; 296 | } 297 | 298 | /** 299 | * @return The time/date stamp of the export directory. 300 | **/ 301 | dword ExportDirectory::getTimeDateStamp() const 302 | { 303 | return m_ied.ied.TimeDateStamp; 304 | } 305 | 306 | /** 307 | * @return The MajorVersion of the export directory. 308 | **/ 309 | word ExportDirectory::getMajorVersion() const 310 | { 311 | return m_ied.ied.MajorVersion; 312 | } 313 | 314 | /** 315 | * @return The MinorVersion of the export directory. 316 | **/ 317 | word ExportDirectory::getMinorVersion() const 318 | { 319 | return m_ied.ied.MinorVersion; 320 | } 321 | 322 | /** 323 | * @return The RVA of the name of the file. 324 | **/ 325 | dword ExportDirectory::getName() const 326 | { 327 | return m_ied.ied.Name; 328 | } 329 | 330 | /** 331 | * @return The NumberOfFunctions of the export directory. 332 | **/ 333 | dword ExportDirectory::getNumberOfFunctions() const 334 | { 335 | return m_ied.ied.NumberOfFunctions; 336 | } 337 | 338 | /** 339 | * @return The NumberOfNames of the export directory. 340 | **/ 341 | dword ExportDirectory::getNumberOfNames() const 342 | { 343 | return m_ied.ied.NumberOfNames; 344 | } 345 | 346 | /** 347 | * @return The AddressOfFunctions of the export directory. 348 | **/ 349 | dword ExportDirectory::getAddressOfFunctions() const 350 | { 351 | return m_ied.ied.AddressOfFunctions; 352 | } 353 | 354 | /** 355 | * @return The AddressOfNames of the export directory. 356 | **/ 357 | dword ExportDirectory::getAddressOfNames() const 358 | { 359 | return m_ied.ied.AddressOfNames; 360 | } 361 | 362 | /* dword ExportDirectory::getNumberOfNameOrdinals() const 363 | { 364 | return static_cast(m_ied.functions.size()); 365 | } 366 | 367 | dword ExportDirectory::getNumberOfAddressOfFunctionNames() const 368 | { 369 | return static_cast(m_ied.functions.size()); 370 | } 371 | 372 | dword ExportDirectory::getNumberOfAddressOfFunctions() const 373 | { 374 | return static_cast(m_ied.functions.size()); 375 | } 376 | */ 377 | /** 378 | * @return The AddressOfNameOrdinals of the export directory. 379 | **/ 380 | dword ExportDirectory::getAddressOfNameOrdinals() const 381 | { 382 | return m_ied.ied.AddressOfNameOrdinals; 383 | } 384 | 385 | /** 386 | * @param dwValue The ordinal base of the export directory. 387 | **/ 388 | void ExportDirectory::setBase(dword dwValue) 389 | { 390 | m_ied.ied.Base = dwValue; 391 | } 392 | 393 | /** 394 | * @param dwValue The Characteristics of the export directory. 395 | **/ 396 | void ExportDirectory::setCharacteristics(dword dwValue) 397 | { 398 | m_ied.ied.Characteristics = dwValue; 399 | } 400 | 401 | /** 402 | * @param dwValue The TimeDateStamp of the export directory. 403 | **/ 404 | void ExportDirectory::setTimeDateStamp(dword dwValue) 405 | { 406 | m_ied.ied.TimeDateStamp = dwValue; 407 | } 408 | 409 | /** 410 | * @param wValue The MajorVersion of the export directory. 411 | **/ 412 | void ExportDirectory::setMajorVersion(word wValue) 413 | { 414 | m_ied.ied.MajorVersion = wValue; 415 | } 416 | 417 | /** 418 | * @param wValue The MinorVersion of the export directory. 419 | **/ 420 | void ExportDirectory::setMinorVersion(word wValue) 421 | { 422 | m_ied.ied.MinorVersion = wValue; 423 | } 424 | 425 | /** 426 | * @param dwValue The Name of the export directory. 427 | **/ 428 | void ExportDirectory::setName(dword dwValue) 429 | { 430 | m_ied.ied.Name = dwValue; 431 | } 432 | 433 | /** 434 | * @param dwValue The NumberOfFunctions of the export directory. 435 | **/ 436 | void ExportDirectory::setNumberOfFunctions(dword dwValue) 437 | { 438 | m_ied.ied.NumberOfFunctions = dwValue; 439 | } 440 | 441 | /** 442 | * @param dwValue The NumberOfNames of the export directory. 443 | **/ 444 | void ExportDirectory::setNumberOfNames(dword dwValue) 445 | { 446 | m_ied.ied.NumberOfNames = dwValue; 447 | } 448 | 449 | /** 450 | * @param dwValue The AddressOfFunctions of the export directory. 451 | **/ 452 | void ExportDirectory::setAddressOfFunctions(dword dwValue) 453 | { 454 | m_ied.ied.AddressOfFunctions = dwValue; 455 | } 456 | 457 | /** 458 | * @param dwValue The AddressOfNames of the export directory. 459 | **/ 460 | void ExportDirectory::setAddressOfNames(dword dwValue) 461 | { 462 | m_ied.ied.AddressOfNames = dwValue; 463 | } 464 | 465 | void ExportDirectory::setAddressOfNameOrdinals(dword value) 466 | { 467 | m_ied.ied.AddressOfNameOrdinals = value; 468 | } 469 | 470 | const std::vector>& ExportDirectory::getOccupiedAddresses() const 471 | { 472 | return m_occupiedAddresses; 473 | } 474 | } 475 | -------------------------------------------------------------------------------- /src/pelib/IatDirectory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * IatDirectory.h - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include "pelib/IatDirectory.h" 14 | 15 | namespace PeLib 16 | { 17 | int IatDirectory::read(InputBuffer& inputBuffer, unsigned int dwOffset, unsigned int dwFileSize) 18 | { 19 | dword dwAddr; 20 | 21 | std::vector vIat; 22 | 23 | unsigned int dwCurrentOffset = dwOffset; 24 | while (dwCurrentOffset < dwFileSize) 25 | { 26 | inputBuffer >> dwAddr; 27 | if (dwAddr == 0) 28 | break; 29 | 30 | vIat.push_back(dwAddr); 31 | dwCurrentOffset += sizeof(dwAddr); 32 | } 33 | 34 | std::swap(vIat, m_vIat); 35 | 36 | return ERROR_NONE; 37 | } 38 | 39 | int IatDirectory::read(unsigned char* buffer, unsigned int buffersize) 40 | { 41 | std::vector vBuffer(buffer, buffer + buffersize); 42 | InputBuffer inpBuffer(vBuffer); 43 | return read(inpBuffer, 0, buffersize); 44 | } 45 | 46 | /** 47 | * Returns the number of fields in the IAT. This is equivalent to the number of 48 | * imported functions. 49 | * @return Number of fields in the IAT. 50 | **/ 51 | unsigned int IatDirectory::calcNumberOfAddresses() const 52 | { 53 | return static_cast(m_vIat.size()); 54 | } 55 | 56 | /** 57 | * Returns the dwValue of a field in the IAT. 58 | * @param dwAddrnr Number identifying the field. 59 | * @return dwValue of the field. 60 | **/ 61 | dword IatDirectory::getAddress(unsigned int index) const 62 | { 63 | return m_vIat[index]; 64 | } 65 | 66 | /** 67 | * Updates the dwValue of a field in the IAT. 68 | * @param dwAddrnr Number identifying the field. 69 | * @param dwValue New dwValue of the field. 70 | **/ 71 | void IatDirectory::setAddress(dword dwAddrnr, dword dwValue) 72 | { 73 | m_vIat[dwAddrnr] = dwValue; 74 | } 75 | 76 | /** 77 | * Adds another field to the IAT. 78 | * @param dwValue dwValue of the new field. 79 | **/ 80 | void IatDirectory::addAddress(dword dwValue) 81 | { 82 | m_vIat.push_back(dwValue); 83 | } 84 | 85 | /** 86 | * Removes an address from the IAT. 87 | * @param dwAddrnr Number identifying the field. 88 | **/ 89 | void IatDirectory::removeAddress(unsigned int index) 90 | { 91 | std::vector::iterator pos = m_vIat.begin() + index; 92 | m_vIat.erase(pos); 93 | } 94 | 95 | /** 96 | * Delete all entries from the IAT. 97 | **/ 98 | void IatDirectory::clear() 99 | { 100 | m_vIat.clear(); 101 | } 102 | 103 | /** 104 | * Rebuilds the complete Import Address Table. 105 | * @param vBuffer Buffer where the rebuilt IAT will be stored. 106 | **/ 107 | void IatDirectory::rebuild(std::vector& vBuffer) const 108 | { 109 | vBuffer.resize(size()); 110 | OutputBuffer obBuffer(vBuffer); 111 | 112 | for (unsigned int i=0;i(m_vIat.size())* sizeof(dword); 121 | } 122 | 123 | /// Writes the current IAT to a file. 124 | int IatDirectory::write(const std::string& strFilename, unsigned int uiOffset) const 125 | { 126 | std::fstream ofFile(strFilename.c_str(), std::ios_base::in); 127 | 128 | if (!ofFile) 129 | { 130 | ofFile.clear(); 131 | ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary); 132 | } 133 | else 134 | { 135 | ofFile.close(); 136 | ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary); 137 | } 138 | 139 | if (!ofFile) 140 | { 141 | return ERROR_OPENING_FILE; 142 | } 143 | 144 | ofFile.seekp(uiOffset, std::ios::beg); 145 | 146 | std::vector vBuffer; 147 | rebuild(vBuffer); 148 | 149 | ofFile.write(reinterpret_cast(vBuffer.data()), static_cast(vBuffer.size())); 150 | 151 | ofFile.close(); 152 | 153 | return ERROR_NONE; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/pelib/InputBuffer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * InputBuffer.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include "pelib/InputBuffer.h" 14 | 15 | namespace PeLib 16 | { 17 | InputBuffer::InputBuffer(std::vector& vBuffer) : m_vBuffer(vBuffer), ulIndex(0) 18 | { 19 | } 20 | 21 | const unsigned char* InputBuffer::data() const 22 | { 23 | return m_vBuffer.data(); 24 | } 25 | 26 | unsigned long InputBuffer::size() 27 | { 28 | return static_cast(m_vBuffer.size()); 29 | } 30 | 31 | void InputBuffer::read(char* lpBuffer, unsigned long ulSize) 32 | { 33 | if (ulIndex >= m_vBuffer.size()) 34 | return; 35 | 36 | ulSize = (unsigned long)(ulIndex + ulSize > m_vBuffer.size() ? m_vBuffer.size() - ulIndex : ulSize); 37 | 38 | std::copy(m_vBuffer.data() + ulIndex, m_vBuffer.data() + ulIndex + ulSize, lpBuffer); 39 | ulIndex += ulSize; 40 | } 41 | 42 | void InputBuffer::reset() 43 | { 44 | m_vBuffer.clear(); 45 | } 46 | 47 | void InputBuffer::set(unsigned long ulIndex2) 48 | { 49 | this->ulIndex = ulIndex2; 50 | } 51 | 52 | void InputBuffer::move(unsigned long shift) 53 | { 54 | ulIndex += shift; 55 | } 56 | 57 | unsigned long InputBuffer::get() 58 | { 59 | return ulIndex; 60 | } 61 | 62 | void InputBuffer::setBuffer(std::vector& vBuffer) 63 | { 64 | m_vBuffer = vBuffer; 65 | ulIndex = 0; 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/pelib/MzHeader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MzHeader.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include 14 | 15 | #include "pelib/MzHeader.h" 16 | 17 | namespace PeLib 18 | { 19 | /** 20 | * Reads data from an InputBuffer into the struct that represents the MZ header. 21 | * It's required that the size of the input buffer is at least as big as the 22 | * size of a MZ header. Otherwise we get undefined behaviour. 23 | * @param ibBuffer InputBuffer that holds the data. 24 | * @return A non-zero value is returned if a problem occured. 25 | **/ 26 | void MzHeader::read(InputBuffer& ibBuffer) 27 | { 28 | ibBuffer >> m_idhHeader.e_magic; 29 | ibBuffer >> m_idhHeader.e_cblp; 30 | ibBuffer >> m_idhHeader.e_cp; 31 | ibBuffer >> m_idhHeader.e_crlc; 32 | ibBuffer >> m_idhHeader.e_cparhdr; 33 | ibBuffer >> m_idhHeader.e_minalloc; 34 | ibBuffer >> m_idhHeader.e_maxalloc; 35 | ibBuffer >> m_idhHeader.e_ss; 36 | ibBuffer >> m_idhHeader.e_sp; 37 | ibBuffer >> m_idhHeader.e_csum; 38 | ibBuffer >> m_idhHeader.e_ip; 39 | ibBuffer >> m_idhHeader.e_cs; 40 | ibBuffer >> m_idhHeader.e_lfarlc; 41 | ibBuffer >> m_idhHeader.e_ovno; 42 | 43 | for (unsigned int i=0;i> m_idhHeader.e_res[i]; 46 | } 47 | 48 | ibBuffer >> m_idhHeader.e_oemid; 49 | ibBuffer >> m_idhHeader.e_oeminfo; 50 | 51 | for (unsigned int i=0;i> m_idhHeader.e_res2[i]; 54 | } 55 | 56 | ibBuffer >> m_idhHeader.e_lfanew; 57 | } 58 | 59 | MzHeader::MzHeader(): originalOffset(0), m_ldrError() {} 60 | 61 | /** 62 | * Tests if the currently loaded MZ header is a valid MZ header. 63 | * Note that this function does not check if the address to the PE header is valid as this is not possible. 64 | * Actually, the only thing this function checks is if the e_magic value is set to 0x5A4D (IMAGE_DOS_SIGNATURE). 65 | * Everything else is not relevant for Windows 2000 and that's the system PeLib is focusing on for now. 66 | * @return A boolean value that indicates if the MZ header is correct or not. 67 | **/ 68 | bool MzHeader::isValid() const 69 | { 70 | // The only thing that matters on Windows 2K is the e_magic value. The entire rest is for DOS compatibility. 71 | return isValid(e_magic); 72 | } 73 | 74 | bool MzHeader::isValid(Field f) const 75 | { 76 | if (f == e_magic) 77 | { 78 | return m_idhHeader.e_magic == PELIB_IMAGE_DOS_SIGNATURE; 79 | } 80 | else 81 | { 82 | return true; 83 | } 84 | } 85 | 86 | void MzHeader::setLoaderError(LoaderError ldrError) 87 | { 88 | // Do not override an existing loader error 89 | if (m_ldrError == LDR_ERROR_NONE) 90 | { 91 | m_ldrError = ldrError; 92 | } 93 | } 94 | 95 | LoaderError MzHeader::loaderError() const 96 | { 97 | return m_ldrError; 98 | } 99 | 100 | /** 101 | * Corrects all erroneous values of the current MZ header. Note that this function does not correct the 102 | * pointer to the PE header. 103 | * Actually, the only thing this function corrects is the e_magic value. 104 | * Everything else is not relevant for Windows 2000 and that's the system PeLib is focusing on for now. 105 | **/ 106 | void MzHeader::makeValid() 107 | { 108 | // The only thing that matters on Windows is the e_magic value. The entire rest is for DOS compatibility. 109 | setMagicNumber(PELIB_IMAGE_DOS_SIGNATURE); 110 | } 111 | 112 | void MzHeader::makeValid(Field f) 113 | { 114 | if (f == e_magic) 115 | { 116 | setMagicNumber(PELIB_IMAGE_DOS_SIGNATURE); 117 | } 118 | } 119 | 120 | /** 121 | * Reads the MZ header from a file. Note that this function does not verify if a file is actually a MZ file. 122 | * For this purpose see #PeFile::MzHeader::isValid. The reason for this is simple: Otherwise it might not 123 | * be possible to load damaged PE files to repair them. 124 | * @param inStream Input stream. 125 | * @return A non-zero value is returned if a problem occured. 126 | **/ 127 | int MzHeader::read(std::istream& inStream) 128 | { 129 | IStreamWrapper inStream_w(inStream); 130 | 131 | if (!inStream_w) 132 | { 133 | return ERROR_OPENING_FILE; 134 | } 135 | 136 | std::uint64_t ulFileSize = fileSize(inStream_w); 137 | if (ulFileSize < PELIB_IMAGE_DOS_HEADER::size()) 138 | { 139 | return ERROR_INVALID_FILE; 140 | } 141 | 142 | // Windows loader refuses to load any file which is larger than 0xFFFFFFFF 143 | if ((ulFileSize >> 32) != 0) 144 | { 145 | setLoaderError(LDR_ERROR_FILE_TOO_BIG); 146 | } 147 | 148 | inStream_w.seekg(0, std::ios::beg); 149 | 150 | originalOffset = 0; 151 | 152 | std::vector vBuffer(PELIB_IMAGE_DOS_HEADER::size()); 153 | inStream_w.read(reinterpret_cast(vBuffer.data()), static_cast(vBuffer.size())); 154 | inStream_w.seekg(0, std::ios::beg); 155 | m_headerString.clear(); 156 | m_headerString.resize(PELIB_IMAGE_DOS_HEADER::size()); 157 | inStream_w.read(&m_headerString[0], PELIB_IMAGE_DOS_HEADER::size()); 158 | 159 | InputBuffer ibBuffer(vBuffer); 160 | read(ibBuffer); 161 | 162 | // For 64-bit systems, the e_lfanew must be aligned to 4 163 | if (m_idhHeader.e_lfanew & 3) 164 | setLoaderError(LDR_ERROR_E_LFANEW_UNALIGNED); 165 | 166 | // The offset of PE header must not be out of file 167 | if (m_idhHeader.e_lfanew > (std::uint32_t)ulFileSize) 168 | setLoaderError(LDR_ERROR_E_LFANEW_OUT_OF_FILE); 169 | 170 | return ERROR_NONE; 171 | } 172 | 173 | /** 174 | * Reads the MZ header from memory. A pointer to a location in memory is passed and the data 175 | * at this location is treated like a MZ header structure. The MZ header does not need to be valid. 176 | * @param pcBuffer Pointer to a MZ header. 177 | * @param uiSize Length of the buffer. 178 | * @return A non-zero value is returned if a problem occured. 179 | **/ 180 | int MzHeader::read(unsigned char* pcBuffer, unsigned int uiSize, unsigned int originalOffs) 181 | { 182 | if (uiSize < PELIB_IMAGE_DOS_HEADER::size()) 183 | { 184 | return ERROR_INVALID_FILE; 185 | } 186 | 187 | std::vector vBuffer(pcBuffer, pcBuffer + uiSize); 188 | for (int i=0;i<0x40;i++) std::cout << std::hex << (int)vBuffer[i] << " "; 189 | 190 | originalOffset = originalOffs; 191 | 192 | InputBuffer ibBuffer(vBuffer); 193 | read(ibBuffer); 194 | return ERROR_NONE; 195 | } 196 | 197 | /** 198 | * Rebuilds the MZ header so that it can be written to a file. It's not guaranteed that the 199 | * MZ header will be valid. If you want to make sure that the MZ header will be valid you 200 | * must call #PeLib::MzHeader::makeValid first. 201 | * @param vBuffer Buffer where the rebuilt MZ header will be stored. 202 | **/ 203 | void MzHeader::rebuild(std::vector& vBuffer) const 204 | { 205 | OutputBuffer obBuffer(vBuffer); 206 | 207 | obBuffer << m_idhHeader.e_magic; 208 | obBuffer << m_idhHeader.e_cblp; 209 | obBuffer << m_idhHeader.e_cp; 210 | obBuffer << m_idhHeader.e_crlc; 211 | obBuffer << m_idhHeader.e_cparhdr; 212 | obBuffer << m_idhHeader.e_minalloc; 213 | obBuffer << m_idhHeader.e_maxalloc; 214 | obBuffer << m_idhHeader.e_ss; 215 | obBuffer << m_idhHeader.e_sp; 216 | obBuffer << m_idhHeader.e_csum; 217 | obBuffer << m_idhHeader.e_ip; 218 | obBuffer << m_idhHeader.e_cs; 219 | obBuffer << m_idhHeader.e_lfarlc; 220 | obBuffer << m_idhHeader.e_ovno; 221 | 222 | for (unsigned int i=0;i vBuffer; 279 | 280 | rebuild(vBuffer); 281 | 282 | ofFile.write(reinterpret_cast(vBuffer.data()), static_cast(vBuffer.size())); 283 | 284 | ofFile.close(); 285 | 286 | return ERROR_NONE; 287 | } 288 | 289 | /** 290 | * Returns the MZ header. 291 | **/ 292 | const PELIB_IMAGE_DOS_HEADER& MzHeader::getHeader() const 293 | { 294 | return m_idhHeader; 295 | } 296 | 297 | /** 298 | * Returns the MZ header in string representation. 299 | **/ 300 | const std::string& MzHeader::getString() const 301 | { 302 | return m_headerString; 303 | } 304 | 305 | /** 306 | * Returns the MZ header's e_magic value. 307 | **/ 308 | word MzHeader::getMagicNumber() const 309 | { 310 | return m_idhHeader.e_magic; 311 | } 312 | 313 | /** 314 | * Returns the MZ header's e_cblp value. 315 | **/ 316 | word MzHeader::getBytesOnLastPage() const 317 | { 318 | return m_idhHeader.e_cblp; 319 | } 320 | 321 | /** 322 | * Returns the MZ header's e_cp value. 323 | **/ 324 | word MzHeader::getPagesInFile() const 325 | { 326 | return m_idhHeader.e_cp; 327 | } 328 | 329 | /** 330 | * Returns the MZ header's e_crlc value. 331 | **/ 332 | word MzHeader::getRelocations() const 333 | { 334 | return m_idhHeader.e_crlc; 335 | } 336 | 337 | /** 338 | * Returns the MZ header's e_cparhdr value. 339 | **/ 340 | word MzHeader::getSizeOfHeader() const 341 | { 342 | return m_idhHeader.e_cparhdr; 343 | } 344 | 345 | /** 346 | * Returns the MZ header's e_minalloc value. 347 | **/ 348 | word MzHeader::getMinExtraParagraphs() const 349 | { 350 | return m_idhHeader.e_minalloc; 351 | } 352 | 353 | /** 354 | * Returns the MZ header's e_maxalloc value. 355 | **/ 356 | word MzHeader::getMaxExtraParagraphs() const 357 | { 358 | return m_idhHeader.e_maxalloc; 359 | } 360 | 361 | /** 362 | * Returns the MZ header's e_ss value. 363 | **/ 364 | word MzHeader::getSsValue() const 365 | { 366 | return m_idhHeader.e_ss; 367 | } 368 | 369 | /** 370 | * Returns the MZ header's e_sp value. 371 | **/ 372 | word MzHeader::getSpValue() const 373 | { 374 | return m_idhHeader.e_sp; 375 | } 376 | 377 | /** 378 | * Returns the MZ header's e_csum value. 379 | **/ 380 | word MzHeader::getChecksum() const 381 | { 382 | return m_idhHeader.e_csum; 383 | } 384 | 385 | /** 386 | * Returns the MZ header's e_ip value. 387 | **/ 388 | word MzHeader::getIpValue() const 389 | { 390 | return m_idhHeader.e_ip; 391 | } 392 | 393 | /** 394 | * Returns the MZ header's e_cs value. 395 | **/ 396 | word MzHeader::getCsValue() const 397 | { 398 | return m_idhHeader.e_cs; 399 | } 400 | 401 | /** 402 | * Returns the MZ header's e_lfarlc value. 403 | **/ 404 | word MzHeader::getAddrOfRelocationTable() const 405 | { 406 | return m_idhHeader.e_lfarlc; 407 | } 408 | 409 | /** 410 | * Returns the MZ header's e_ovno value. 411 | **/ 412 | word MzHeader::getOverlayNumber() const 413 | { 414 | return m_idhHeader.e_ovno; 415 | } 416 | 417 | /** 418 | * Returns the MZ header's e_oemid value. 419 | **/ 420 | word MzHeader::getOemIdentifier() const 421 | { 422 | return m_idhHeader.e_oemid; 423 | } 424 | 425 | /** 426 | * Returns the MZ header's e_oeminfo value. 427 | **/ 428 | word MzHeader::getOemInformation() const 429 | { 430 | return m_idhHeader.e_oeminfo; 431 | } 432 | 433 | /** 434 | * Returns the MZ header's e_lfanew value. 435 | **/ 436 | dword MzHeader::getAddressOfPeHeader() const 437 | { 438 | return m_idhHeader.e_lfanew; 439 | } 440 | 441 | /** 442 | * Returns the MZ header's e_res[uiNr] value. If the parameter uiNr is out of range 443 | * you will get undefined behaviour. 444 | * @param uiNr The index of the word in the e_res array (valid range: 0-3) 445 | **/ 446 | word MzHeader::getReservedWords1(unsigned int uiNr) const 447 | { 448 | return m_idhHeader.e_res[uiNr]; 449 | } 450 | 451 | /** 452 | * Returns the MZ header's e_res2[uiNr] value. If the parameter uiNr is out of range 453 | * you will get undefined behaviour. 454 | * @param uiNr The index of the word in the e_res array (valid range: 0-9) 455 | **/ 456 | word MzHeader::getReservedWords2(unsigned int uiNr) const 457 | { 458 | return m_idhHeader.e_res2[uiNr]; 459 | } 460 | 461 | /** 462 | * Sets the MZ header's e_magic value. 463 | * @param wValue The new value of e_magic. 464 | **/ 465 | void MzHeader::setMagicNumber(word wValue) 466 | { 467 | m_idhHeader.e_magic = wValue; 468 | } 469 | 470 | /** 471 | * Sets the MZ header's e_cblp value. 472 | * @param wValue The new value of e_cblp. 473 | **/ 474 | void MzHeader::setBytesOnLastPage(word wValue) 475 | { 476 | m_idhHeader.e_cblp = wValue; 477 | } 478 | 479 | /** 480 | * Sets the MZ header's e_cp value. 481 | * @param wValue The new value of e_cp. 482 | **/ 483 | void MzHeader::setPagesInFile(word wValue) 484 | { 485 | m_idhHeader.e_cp = wValue; 486 | } 487 | 488 | /** 489 | * Sets the MZ header's e_crlc value. 490 | * @param wValue The new value of e_crlc. 491 | **/ 492 | void MzHeader::setRelocations(word wValue) 493 | { 494 | m_idhHeader.e_crlc = wValue; 495 | } 496 | 497 | /** 498 | * Sets the MZ header's e_cparhdr value. 499 | * @param wValue The new value of e_cparhdr. 500 | **/ 501 | void MzHeader::setSizeOfHeader(word wValue) 502 | { 503 | m_idhHeader.e_cparhdr = wValue; 504 | } 505 | 506 | /** 507 | * Sets the MZ header's e_minalloc value. 508 | * @param wValue The new value of e_minalloc. 509 | **/ 510 | void MzHeader::setMinExtraParagraphs(word wValue) 511 | { 512 | m_idhHeader.e_minalloc = wValue; 513 | } 514 | 515 | /** 516 | * Sets the MZ header's e_maxalloc value. 517 | * @param wValue The new value of e_maxalloc. 518 | **/ 519 | void MzHeader::setMaxExtraParagraphs(word wValue) 520 | { 521 | m_idhHeader.e_maxalloc = wValue; 522 | } 523 | 524 | /** 525 | * Sets the MZ header's e_ss value. 526 | * @param wValue The new value of e_ss. 527 | **/ 528 | void MzHeader::setSsValue(word wValue) 529 | { 530 | m_idhHeader.e_ss = wValue; 531 | } 532 | 533 | /** 534 | * Sets the MZ header's e_sp value. 535 | * @param wValue The new value of e_sp. 536 | **/ 537 | void MzHeader::setSpValue(word wValue) 538 | { 539 | m_idhHeader.e_sp = wValue; 540 | } 541 | 542 | /** 543 | * Sets the MZ header's e_csum value. 544 | * @param wValue The new value of e_csum. 545 | **/ 546 | void MzHeader::setChecksum(word wValue) 547 | { 548 | m_idhHeader.e_csum = wValue; 549 | } 550 | 551 | /** 552 | * Sets the MZ header's e_ip value. 553 | * @param wValue The new value of e_ip. 554 | **/ 555 | void MzHeader::setIpValue(word wValue) 556 | { 557 | m_idhHeader.e_ip = wValue; 558 | } 559 | 560 | /** 561 | * Sets the MZ header's e_cs value. 562 | * @param wValue The new value of e_cs. 563 | **/ 564 | void MzHeader::setCsValue(word wValue) 565 | { 566 | m_idhHeader.e_cs = wValue; 567 | } 568 | 569 | /** 570 | * Sets the MZ header's e_lfarlc value. 571 | * @param wValue The new value of e_lfarlc. 572 | **/ 573 | void MzHeader::setAddrOfRelocationTable(word wValue) 574 | { 575 | m_idhHeader.e_lfarlc = wValue; 576 | } 577 | 578 | /** 579 | * Sets the MZ header's e_ovno value. 580 | * @param wValue The new value of e_ovno. 581 | **/ 582 | void MzHeader::setOverlayNumber(word wValue) 583 | { 584 | m_idhHeader.e_ovno = wValue; 585 | } 586 | 587 | /** 588 | * Sets the MZ header's e_oemid value. 589 | * @param wValue The new value of e_oemid. 590 | **/ 591 | void MzHeader::setOemIdentifier(word wValue) 592 | { 593 | m_idhHeader.e_oemid = wValue; 594 | } 595 | 596 | /** 597 | * Sets the MZ header's e_oeminfo value. 598 | * @param wValue The new value of e_oeminfo. 599 | **/ 600 | void MzHeader::setOemInformation(word wValue) 601 | { 602 | m_idhHeader.e_oeminfo = wValue; 603 | } 604 | 605 | /** 606 | * Sets the MZ header's e_lfanew value. 607 | * @param lValue The new value of e_lfanew. 608 | **/ 609 | void MzHeader::setAddressOfPeHeader(dword lValue) 610 | { 611 | m_idhHeader.e_lfanew = lValue; 612 | } 613 | 614 | /** 615 | * Sets the MZ header's e_res[uiNr] value. If the parameter uiNr is out of range 616 | * you will get undefined behaviour. 617 | * @param uiNr The index of the word in the e_res array (valid range: 0-3) 618 | * @param wValue The new value of e_res[nr]. 619 | **/ 620 | void MzHeader::setReservedWords1(unsigned int uiNr, word wValue) 621 | { 622 | m_idhHeader.e_res[uiNr] = wValue; 623 | } 624 | 625 | /** 626 | * Sets the MZ header's e_res2[uiNr] value. If the parameter uiNr is out of range 627 | * you will get undefined behaviour. 628 | * @param uiNr The index of the word in the e_res2 array (valid range: 0-9) 629 | * @param wValue The new value of e_res[nr]. 630 | **/ 631 | void MzHeader::setReservedWords2(unsigned int uiNr, word wValue) 632 | { 633 | m_idhHeader.e_res2[uiNr] = wValue; 634 | } 635 | 636 | } 637 | -------------------------------------------------------------------------------- /src/pelib/OutputBuffer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * OutputBuffer.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include "pelib/OutputBuffer.h" 14 | 15 | namespace PeLib 16 | { 17 | OutputBuffer::OutputBuffer(std::vector& vBuffer) : m_vBuffer(vBuffer) 18 | { 19 | m_vBuffer.clear(); 20 | } 21 | 22 | const unsigned char* OutputBuffer::data() const 23 | { 24 | return m_vBuffer.data(); 25 | } 26 | 27 | unsigned long OutputBuffer::size() 28 | { 29 | return static_cast(m_vBuffer.size()); 30 | } 31 | 32 | void OutputBuffer::add(const char* lpBuffer, unsigned long ulSize) 33 | { 34 | std::copy(lpBuffer, lpBuffer + ulSize, std::back_inserter(m_vBuffer)); 35 | } 36 | 37 | void OutputBuffer::reset() 38 | { 39 | m_vBuffer.clear(); 40 | } 41 | 42 | void OutputBuffer::resize(unsigned int uiSize) 43 | { 44 | m_vBuffer.resize(uiSize); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/pelib/PeFile.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PeLib.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include "pelib/PeFile.h" 14 | 15 | namespace PeLib 16 | { 17 | PeFile::~PeFile() 18 | { 19 | } 20 | 21 | PeFile32::PeFile32() : PeFileT<32>() 22 | { 23 | } 24 | 25 | PeFile32::PeFile32(const std::string& strFlename) : PeFileT<32>(strFlename) 26 | { 27 | } 28 | 29 | PeFile32::PeFile32(std::istream& stream) : PeFileT<32>(stream) 30 | { 31 | } 32 | 33 | PeFile64::PeFile64() : PeFileT<64>() 34 | { 35 | } 36 | 37 | PeFile64::PeFile64(const std::string& strFlename) : PeFileT<64>(strFlename) 38 | { 39 | } 40 | 41 | PeFile64::PeFile64(std::istream& stream) : PeFileT<64>(stream) 42 | { 43 | } 44 | 45 | /** 46 | * @return A reference to the file's MZ header. 47 | **/ 48 | 49 | const MzHeader& PeFile::mzHeader() const 50 | { 51 | return m_mzh; 52 | } 53 | 54 | /** 55 | * @return A reference to the file's MZ header. 56 | **/ 57 | 58 | MzHeader& PeFile::mzHeader() 59 | { 60 | return m_mzh; 61 | } 62 | 63 | const RichHeader& PeFile::richHeader() const 64 | { 65 | return m_richheader; 66 | } 67 | 68 | RichHeader& PeFile::richHeader() 69 | { 70 | return m_richheader; 71 | } 72 | 73 | const CoffSymbolTable& PeFile::coffSymTab() const 74 | { 75 | return m_coffsymtab; 76 | } 77 | 78 | CoffSymbolTable& PeFile::coffSymTab() 79 | { 80 | return m_coffsymtab; 81 | } 82 | 83 | const SecurityDirectory& PeFile::securityDir() const 84 | { 85 | return m_secdir; 86 | } 87 | 88 | SecurityDirectory& PeFile::securityDir() 89 | { 90 | return m_secdir; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/pelib/PeHeader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PeHeader.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include "pelib/PeLibInc.h" 14 | #include "pelib/PeHeader.h" 15 | 16 | namespace PeLib 17 | { 18 | template<> 19 | void PeHeaderT<32>::readBaseOfData(InputBuffer& ibBuffer, PELIB_IMAGE_NT_HEADERS<32>& header) const 20 | { 21 | ibBuffer >> header.OptionalHeader.BaseOfData; 22 | } 23 | 24 | template<> 25 | void PeHeaderT<64>::readBaseOfData(InputBuffer&, PELIB_IMAGE_NT_HEADERS<64>&) const 26 | { 27 | } 28 | 29 | template<> 30 | void PeHeaderT<32>::rebuildBaseOfData(OutputBuffer& obBuffer) const 31 | { 32 | obBuffer << m_inthHeader.OptionalHeader.BaseOfData; 33 | } 34 | 35 | template<> 36 | void PeHeaderT<64>::rebuildBaseOfData(OutputBuffer&) const 37 | { 38 | } 39 | 40 | template<> 41 | bool PeHeaderT<32>::isValid() const 42 | { 43 | return true; 44 | } 45 | 46 | template<> 47 | bool PeHeaderT<64>::isValid() const 48 | { 49 | return true; 50 | } 51 | 52 | template<> 53 | bool PeHeaderT<32>::isValid(unsigned int pehf) const 54 | { 55 | (void) pehf; /* avoid warning about unused parameter */ 56 | /* 57 | if (pehf == NtSignature) 58 | { 59 | return m_inthHeader.Signature == IMAGE_NT_SIGNATURE; 60 | } 61 | else if (pehf == NumberOfSections) 62 | { 63 | return getNumberOfSections() == calcNumberOfSections(); 64 | } */ 65 | return false; 66 | } 67 | 68 | template<> 69 | bool PeHeaderT<64>::isValid(unsigned int pehf) const 70 | { 71 | (void) pehf; /* avoid warning about unused parameter */ 72 | return false; 73 | } 74 | 75 | /** 76 | * @return The BaseOfData value from the PE header. 77 | **/ 78 | dword PeHeader32::getBaseOfData() const 79 | { 80 | return m_inthHeader.OptionalHeader.BaseOfData; 81 | } 82 | 83 | /** 84 | * Changes the file's BaseOfData. 85 | * @param dwValue New value. 86 | **/ 87 | void PeHeader32::setBaseOfData(dword dwValue) 88 | { 89 | m_inthHeader.OptionalHeader.BaseOfData = dwValue; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/pelib/PeLibAux.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PeLibAux.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include 14 | 15 | #ifdef _MSC_VER 16 | #include 17 | #endif 18 | 19 | #include "pelib/PeLibInc.h" 20 | #include "pelib/PeLibAux.h" 21 | #include "pelib/PeFile.h" 22 | 23 | namespace PeLib 24 | { 25 | const qword PELIB_IMAGE_ORDINAL_FLAGS<64>::PELIB_IMAGE_ORDINAL_FLAG = 0x8000000000000000ULL; 26 | 27 | // Keep in sync with PeLib::LoaderError!!! 28 | static const std::vector LdrErrStrings = 29 | { 30 | {"LDR_ERROR_NONE", "No error"}, 31 | {"LDR_ERROR_FILE_TOO_BIG", "The file is larger than 4GB - 1"}, 32 | {"LDR_ERROR_E_LFANEW_UNALIGNED", "The IMAGE_DOS_HEADER::e_lfanew is not aligned to 4"}, 33 | {"LDR_ERROR_E_LFANEW_OUT_OF_FILE", "The IMAGE_DOS_HEADER::e_lfanew is out of (lower 4 GB of) the file"}, 34 | {"LDR_ERROR_NTHEADER_OFFSET_OVERFLOW", "NT header offset + sizeof(IMAGE_NT_HEADERS) overflow"}, 35 | {"LDR_ERROR_NTHEADER_OUT_OF_FILE", "NT header offset + sizeof(IMAGE_NT_HEADERS) is greater than filesize"}, 36 | {"LDR_ERROR_NO_NT_SIGNATURE", "Missing IMAGE_NT_SIGNATURE in the NT headers" }, 37 | {"LDR_ERROR_FILE_HEADER_INVALID", "Invalid IMAGE_FILE_HEADER::Machine or IMAGE_FILE_HEADER::SizeOfOptionalHeader" }, 38 | {"LDR_ERROR_IMAGE_NON_EXECUTABLE", "Missing IMAGE_FILE_EXECUTABLE_IMAGE in IMAGE_FILE_HEADER::Characteristics" }, 39 | {"LDR_ERROR_NO_OPTHDR_MAGIC", "Invalid IMAGE_OPTIONAL_HEADER::Magic" }, 40 | {"LDR_ERROR_SIZE_OF_HEADERS_ZERO", "IMAGE_OPTIONAL_HEADER::SizeOfHeaders is zero" }, 41 | {"LDR_ERROR_FILE_ALIGNMENT_ZERO", "IMAGE_OPTIONAL_HEADER::FileAlignment is zero" }, 42 | {"LDR_ERROR_FILE_ALIGNMENT_NOT_POW2", "IMAGE_OPTIONAL_HEADER::FileAlignment is not power of two" }, 43 | {"LDR_ERROR_SECTION_ALIGNMENT_ZERO", "IMAGE_OPTIONAL_HEADER::SectionAlignment is zero" }, 44 | {"LDR_ERROR_SECTION_ALIGNMENT_NOT_POW2", "IMAGE_OPTIONAL_HEADER::SectionAlignment is not power of two" }, 45 | {"LDR_ERROR_SECTION_ALIGNMENT_TOO_SMALL", "IMAGE_OPTIONAL_HEADER::SectionAlignment is smaller than IMAGE_OPTIONAL_HEADER::FileAlignment" }, 46 | {"LDR_ERROR_SECTION_ALIGNMENT_INVALID", "IMAGE_OPTIONAL_HEADER::SectionAlignment must be equal to FileAlignment for small alignments" }, 47 | {"LDR_ERROR_SIZE_OF_IMAGE_TOO_BIG", "IMAGE_OPTIONAL_HEADER::SizeOfImage is too big" }, 48 | {"LDR_ERROR_INVALID_MACHINE32", "IMAGE_FILE_HEADER::Machine is invalid for 32-bit optional header" }, 49 | {"LDR_ERROR_INVALID_MACHINE64", "IMAGE_FILE_HEADER::Machine is invalid for 64-bit optional header" }, 50 | {"LDR_ERROR_SIZE_OF_HEADERS_INVALID", "IMAGE_OPTIONAL_HEADER::SizeOfHeaders is greater than IMAGE_OPTIONAL_HEADER::SizeOfImage" }, 51 | {"LDR_ERROR_SIZE_OF_OPTHDR_NOT_ALIGNED", "IMAGE_OPTIONAL_HEADER::SizeOfHeaders is not aligned to 8 (64-bit Windows only)" }, 52 | {"LDR_ERROR_SIZE_OF_IMAGE_ZERO", "Number of PTEs for the entire image is zero" }, 53 | {"LDR_ERROR_IMAGE_BASE_NOT_ALIGNED", "IMAGE_OPTIONAL_HEADER::ImageBase is not aligned to 64KB" }, 54 | {"LDR_ERROR_SIZE_OF_IMAGE_PTES_ZERO", "Number of Page Table Entries for the image is zero" }, 55 | {"LDR_ERROR_RAW_DATA_OVERFLOW", "Overflow in section's raw data size" }, 56 | {"LDR_ERROR_SECTION_HEADERS_OUT_OF_IMAGE", "Section headers are out of the image" }, 57 | {"LDR_ERROR_SECTION_HEADERS_OVERFLOW", "Image with single subsection: size of headers is near the end of range" }, 58 | {"LDR_ERROR_SECTION_SIZE_MISMATCH", "Image with single subsection: virtual values with rawdata values don't match" }, 59 | {"LDR_ERROR_INVALID_SECTION_VA", "Invalid virtual address of a section" }, 60 | {"LDR_ERROR_INVALID_SECTION_VSIZE", "Invalid virtual size of a section" }, 61 | {"LDR_ERROR_INVALID_SECTION_RAWSIZE", "Invalid raw data size of a section" }, 62 | {"LDR_ERROR_INVALID_SIZE_OF_IMAGE", "IMAGE_OPTIONAL_HEADER::SizeOfImage doesn't match the (header+sections)" }, 63 | {"LDR_ERROR_FILE_IS_CUT", "The PE file is cut" }, 64 | {"LDR_ERROR_FILE_IS_CUT_LOADABLE", "The PE file is cut, but loadable" }, 65 | 66 | // Import directory detected errors 67 | {"LDR_ERROR_IMPDIR_OUT_OF_FILE", "Offset of the import directory is out of the file" }, 68 | {"LDR_ERROR_IMPDIR_CUT", "Import directory is cut" }, 69 | {"LDR_ERROR_IMPDIR_COUNT_EXCEEDED", "Number of import descriptors exceeds maximum" }, 70 | {"LDR_ERROR_IMPDIR_NAME_RVA_INVALID", "RVA of the import name is invalid" }, 71 | {"LDR_ERROR_IMPDIR_THUNK_RVA_INVALID", "RVA of the import thunk is invalid" }, 72 | {"LDR_ERROR_IMPDIR_IMPORT_COUNT_EXCEEDED", "Number of imported functions exceeds maximum" }, 73 | 74 | // Resource directory detected errors 75 | {"LDR_ERROR_RSRC_OVER_END_OF_IMAGE", "Array of resource directory entries goes beyond end of the image" }, 76 | 77 | // Entry point error detection 78 | {"LDR_ERROR_ENTRY_POINT_OUT_OF_IMAGE", "The position of the entry point is out of the image" }, 79 | {"LDR_ERROR_ENTRY_POINT_ZEROED", "The entry point is zeroed; probably damaged file" }, 80 | }; 81 | 82 | PELIB_IMAGE_FILE_MACHINE_ITERATOR::PELIB_IMAGE_FILE_MACHINE_ITERATOR() 83 | { 84 | 85 | } 86 | 87 | PELIB_IMAGE_FILE_MACHINE_ITERATOR::~PELIB_IMAGE_FILE_MACHINE_ITERATOR() 88 | { 89 | 90 | } 91 | 92 | bool PELIB_IMAGE_FILE_MACHINE_ITERATOR::isValidMachineCode(PELIB_IMAGE_FILE_MACHINE value) const 93 | { 94 | return find(all.begin(), all.end(), value) != all.end(); 95 | } 96 | 97 | PELIB_IMAGE_FILE_MACHINE_ITERATOR::imageFileMachineIterator PELIB_IMAGE_FILE_MACHINE_ITERATOR::begin() const 98 | { 99 | return all.begin(); 100 | } 101 | 102 | PELIB_IMAGE_FILE_MACHINE_ITERATOR::imageFileMachineIterator PELIB_IMAGE_FILE_MACHINE_ITERATOR::end() const 103 | { 104 | return all.end(); 105 | } 106 | 107 | bool PELIB_IMAGE_SECTION_HEADER::biggerFileOffset(const PELIB_IMAGE_SECTION_HEADER& ish) const 108 | { 109 | return PointerToRawData < ish.PointerToRawData; 110 | } 111 | 112 | bool PELIB_IMAGE_SECTION_HEADER::biggerVirtualAddress(const PELIB_IMAGE_SECTION_HEADER& ish) const 113 | { 114 | return VirtualAddress < ish.VirtualAddress; 115 | } 116 | 117 | bool PELIB_IMAGE_SECTION_HEADER::isFullNameSet() const 118 | { 119 | return !StringTableName.empty(); 120 | } 121 | 122 | unsigned int alignOffset(unsigned int uiOffset, unsigned int uiAlignment) 123 | { 124 | if (!uiAlignment) return uiAlignment; 125 | return (uiOffset % uiAlignment) ? uiOffset + (uiAlignment - uiOffset % uiAlignment) : uiOffset; 126 | } 127 | 128 | std::uint32_t AlignToSize(std::uint32_t ByteSize, std::uint32_t AlignSize) 129 | { 130 | return ((ByteSize + (AlignSize - 1)) & ~(AlignSize - 1)); 131 | } 132 | 133 | std::uint32_t BytesToPages(std::uint32_t ByteSize) 134 | { 135 | return (ByteSize >> PELIB_PAGE_SIZE_SHIFT) + ((ByteSize & (PELIB_PAGE_SIZE - 1)) != 0); 136 | } 137 | 138 | std::uint64_t fileSize(const std::string& filename) 139 | { 140 | std::fstream file(filename.c_str()); 141 | file.seekg(0, std::ios::end); 142 | return file.tellg(); 143 | } 144 | 145 | std::uint64_t fileSize(std::istream& stream) 146 | { 147 | std::streamoff oldpos = stream.tellg(); 148 | stream.seekg(0, std::ios::end); 149 | std::streamoff filesize = stream.tellg(); 150 | stream.seekg(oldpos, std::ios::beg); 151 | return filesize; 152 | } 153 | 154 | std::uint64_t fileSize(std::fstream& file) 155 | { 156 | std::streamoff oldpos = file.tellg(); 157 | file.seekg(0, std::ios::end); 158 | std::streamoff filesize = file.tellg(); 159 | file.seekg(oldpos, std::ios::beg); 160 | return filesize; 161 | } 162 | 163 | std::uint64_t fileSize(std::ofstream& file) 164 | { 165 | std::streamoff oldpos = file.tellp(); 166 | file.seekp(0, std::ios::end); 167 | std::streamoff filesize = file.tellp(); 168 | file.seekp(oldpos, std::ios::beg); 169 | return filesize; 170 | } 171 | 172 | const char * getLoaderErrorString(LoaderError ldrError, bool userFriendly) 173 | { 174 | std::size_t index = (std::size_t)ldrError; 175 | 176 | // When the index is within range 177 | if (index < LdrErrStrings.size()) 178 | { 179 | return userFriendly ? LdrErrStrings[index].loaderErrorUserFriendly : LdrErrStrings[index].loaderErrorString; 180 | } 181 | 182 | // If this assert triggers, we need to add the missing string 183 | // to the PeLib::LdrErrStrings vector 184 | assert(false); 185 | return "LDR_ERROR_DESCRIPTIVE_STRING_MISSING"; 186 | } 187 | 188 | bool getLoaderErrorLoadableAnyway(LoaderError ldrError) 189 | { 190 | // These errors indicate damaged PE file, but the file is usually loadable anyway 191 | return (ldrError == LDR_ERROR_FILE_IS_CUT_LOADABLE || 192 | ldrError == LDR_ERROR_RSRC_OVER_END_OF_IMAGE || 193 | ldrError == LDR_ERROR_ENTRY_POINT_OUT_OF_IMAGE || 194 | ldrError == LDR_ERROR_ENTRY_POINT_ZEROED); 195 | } 196 | 197 | // Anti-assert feature. Debug version of isprint in MS Visual C++ asserts 198 | // when the character is not EOF or is >= 255 199 | bool pelibIsPrintableChar(int ch) 200 | { 201 | return ((EOF <= ch) && (ch <= 255)) ? isprint(ch) : false; 202 | } 203 | 204 | /** 205 | * @param stream 206 | * @param result 207 | * @param fileOffset 208 | * @param maxLength Maximum length of the string to get. 209 | * @param isPrintable If @c true and a non-printable characters is read, 210 | * set @p result to an empty string and return 0. 211 | * @param isNotTooLong If @c true and @p maxLength is reached, set @p result 212 | * to an empty string and return 0. 213 | * @return Length of the @p result string. 214 | */ 215 | std::size_t getStringFromFileOffset( 216 | std::istream &stream, 217 | std::string &result, 218 | std::size_t fileOffset, 219 | std::size_t maxLength/* = 0*/, 220 | bool isPrintable/* = false*/, 221 | bool isNotTooLong/* = false*/) 222 | { 223 | IStreamWrapper inStream_w(stream); 224 | 225 | result.clear(); 226 | inStream_w.clear(); 227 | inStream_w.seekg(fileOffset, std::ios::beg); 228 | if (!inStream_w) 229 | { 230 | return 0; 231 | } 232 | 233 | char namebuffer[2] = { 0 }; 234 | std::size_t size = 0; 235 | 236 | do 237 | { 238 | inStream_w.read(namebuffer, 1); 239 | if (!inStream_w || !namebuffer[0]) break; 240 | if (isPrintable && !pelibIsPrintableChar(namebuffer[0])) 241 | { 242 | result.clear(); 243 | return 0; 244 | } 245 | result += namebuffer; 246 | ++size; 247 | if (maxLength && size == maxLength) 248 | { 249 | if (isNotTooLong) 250 | { 251 | result.clear(); 252 | return 0; 253 | } 254 | else 255 | { 256 | break; 257 | } 258 | } 259 | } while (true); 260 | 261 | return size; 262 | } 263 | 264 | bool isEqualNc(const std::string& s1, const std::string& s2) 265 | { 266 | std::string t1 = s1; 267 | std::string t2 = s2; 268 | 269 | // No std:: to make VC++ happy 270 | #ifdef _MSC_VER 271 | std::transform(t1.begin(), t1.end(), t1.begin(), [](unsigned char c) { return toupper(c); }); 272 | std::transform(t2.begin(), t2.end(), t2.begin(), [](unsigned char c) { return toupper(c); }); 273 | #else 274 | // Weird syntax to make Borland C++ happy 275 | std::transform(t1.begin(), t1.end(), t1.begin(), (int(*)(int))std::toupper); 276 | std::transform(t2.begin(), t2.end(), t2.begin(), (int(*)(int))std::toupper); 277 | #endif 278 | return t1 == t2; 279 | } 280 | 281 | PELIB_IMAGE_DOS_HEADER::PELIB_IMAGE_DOS_HEADER() 282 | { 283 | e_magic = 0; 284 | e_cblp = 0; 285 | e_cp = 0; 286 | e_crlc = 0; 287 | e_cparhdr = 0; 288 | e_minalloc = 0; 289 | e_maxalloc = 0; 290 | e_ss = 0; 291 | e_sp = 0; 292 | e_csum = 0; 293 | e_ip = 0; 294 | e_cs = 0; 295 | e_lfarlc = 0; 296 | e_ovno = 0; 297 | 298 | for (unsigned int i = 0; i < sizeof(e_res) / sizeof(e_res[0]); i++) 299 | { 300 | e_res[i] = 0; 301 | } 302 | 303 | e_oemid = 0; 304 | e_oeminfo = 0; 305 | 306 | for (unsigned int i = 0; i < sizeof(e_res2) / sizeof(e_res2[0]); i++) 307 | { 308 | e_res2[i] = 0; 309 | } 310 | 311 | e_lfanew = 0; 312 | } 313 | 314 | PELIB_EXP_FUNC_INFORMATION::PELIB_EXP_FUNC_INFORMATION() 315 | { 316 | addroffunc = 0; 317 | addrofname = 0; 318 | ordinal = 0; 319 | } 320 | 321 | PELIB_IMAGE_RESOURCE_DIRECTORY::PELIB_IMAGE_RESOURCE_DIRECTORY() 322 | { 323 | Characteristics = 0; 324 | TimeDateStamp = 0; 325 | MajorVersion = 0; 326 | MinorVersion = 0; 327 | NumberOfNamedEntries = 0; 328 | NumberOfIdEntries = 0; 329 | } 330 | 331 | PELIB_IMAGE_RESOURCE_DIRECTORY_ENTRY::PELIB_IMAGE_RESOURCE_DIRECTORY_ENTRY() 332 | { 333 | Name = 0; 334 | OffsetToData = 0; 335 | } 336 | 337 | bool PELIB_IMG_RES_DIR_ENTRY::operator<(const PELIB_IMG_RES_DIR_ENTRY& first) const 338 | { 339 | if ((irde.Name & PELIB_IMAGE_RESOURCE_NAME_IS_STRING) && (first.irde.Name & PELIB_IMAGE_RESOURCE_NAME_IS_STRING)) 340 | { 341 | return wstrName < first.wstrName; 342 | } 343 | else if (irde.Name & PELIB_IMAGE_RESOURCE_NAME_IS_STRING) 344 | { 345 | return true; 346 | } 347 | else if (first.irde.Name & PELIB_IMAGE_RESOURCE_NAME_IS_STRING) 348 | { 349 | return false; 350 | } 351 | else 352 | { 353 | return irde.Name < first.irde.Name; 354 | } 355 | } 356 | 357 | PELIB_IMAGE_BASE_RELOCATION::PELIB_IMAGE_BASE_RELOCATION() 358 | { 359 | VirtualAddress = 0; 360 | SizeOfBlock = 0; 361 | } 362 | 363 | PELIB_IMAGE_COR20_HEADER::PELIB_IMAGE_COR20_HEADER() 364 | { 365 | cb = 0; 366 | MajorRuntimeVersion = 0; 367 | MinorRuntimeVersion = 0; 368 | MetaData.VirtualAddress = 0; 369 | MetaData.Size = 0; 370 | Flags = 0; 371 | EntryPointToken = 0; 372 | Resources.VirtualAddress = 0; 373 | Resources.Size = 0; 374 | StrongNameSignature.VirtualAddress = 0; 375 | StrongNameSignature.Size = 0; 376 | CodeManagerTable.VirtualAddress = 0; 377 | CodeManagerTable.Size = 0; 378 | VTableFixups.VirtualAddress = 0; 379 | VTableFixups.Size = 0; 380 | ExportAddressTableJumps.VirtualAddress = 0; 381 | ExportAddressTableJumps.Size = 0; 382 | ManagedNativeHeader.VirtualAddress = 0; 383 | ManagedNativeHeader.Size = 0; 384 | } 385 | 386 | PELIB_IMAGE_RESOURCE_DATA_ENTRY::PELIB_IMAGE_RESOURCE_DATA_ENTRY() 387 | { 388 | OffsetToData = 0; 389 | Size = 0; 390 | CodePage = 0; 391 | Reserved = 0; 392 | } 393 | 394 | PELIB_IMAGE_DEBUG_DIRECTORY::PELIB_IMAGE_DEBUG_DIRECTORY() 395 | { 396 | Characteristics = 0; 397 | TimeDateStamp = 0; 398 | MajorVersion = 0; 399 | MinorVersion = 0; 400 | Type = 0; 401 | SizeOfData = 0; 402 | AddressOfRawData = 0; 403 | PointerToRawData = 0; 404 | } 405 | 406 | /** Compares the passed filename to the struct's filename. 407 | * @param strModuleName A filename. 408 | * @return True, if the passed filename equals the struct's filename. The comparison is case-sensitive. 409 | **/ 410 | bool PELIB_IMAGE_BOUND_DIRECTORY::equal(const std::string strModuleName2) const 411 | { 412 | return this->strModuleName == strModuleName2; 413 | } 414 | 415 | bool PELIB_EXP_FUNC_INFORMATION::equal(const std::string strFunctionName) const 416 | { 417 | return isEqualNc(this->funcname, strFunctionName); 418 | } 419 | 420 | unsigned int getFileType(PeFile32& pef) 421 | { 422 | // Attempt to read the DOS file header. 423 | if (pef.readMzHeader() != ERROR_NONE) 424 | { 425 | return PEFILE_UNKNOWN; 426 | } 427 | 428 | // Verify the DOS header 429 | if (!pef.mzHeader().isValid()) 430 | { 431 | return PEFILE_UNKNOWN; 432 | } 433 | 434 | // Read PE header. Note that at this point, we read the header as if 435 | // it was 32-bit PE file. 436 | if (pef.readPeHeader() != ERROR_NONE) 437 | { 438 | return PEFILE_UNKNOWN; 439 | } 440 | 441 | word machine = pef.peHeader().getMachine(); 442 | word magic = pef.peHeader().getMagic(); 443 | 444 | // jk2012-02-20: make the PEFILE32 be the default return value 445 | if ((machine == PELIB_IMAGE_FILE_MACHINE_AMD64 446 | || machine == PELIB_IMAGE_FILE_MACHINE_IA64) 447 | && magic == PELIB_IMAGE_NT_OPTIONAL_HDR64_MAGIC) 448 | { 449 | return PEFILE64; 450 | } 451 | else 452 | { 453 | return PEFILE32; 454 | } 455 | } 456 | 457 | /** 458 | * @param strFilename Name of a file. 459 | * @return Either PEFILE32, PEFILE64 or PEFILE_UNKNOWN 460 | **/ 461 | unsigned int getFileType(const std::string strFilename) 462 | { 463 | PeFile32 pef(strFilename); 464 | return getFileType(pef); 465 | } 466 | 467 | /** 468 | * @param stream Input stream. 469 | * @return Either PEFILE32, PEFILE64 or PEFILE_UNKNOWN 470 | **/ 471 | unsigned int getFileType(std::istream& stream) 472 | { 473 | PeFile32 pef(stream); 474 | return getFileType(pef); 475 | } 476 | 477 | /** 478 | * Opens a PE file. The return type is either PeFile32 or PeFile64 object. If an error occurs the return 479 | * value is 0. 480 | * @param strFilename Name of a file. 481 | * @return Either a PeFile32 object, a PeFil64 object or 0. 482 | **/ 483 | PeFile* openPeFile(const std::string& strFilename) 484 | { 485 | unsigned int type = getFileType(strFilename); 486 | 487 | if (type == PEFILE32) 488 | { 489 | return new PeFile32(strFilename); 490 | } 491 | else if (type == PEFILE64) 492 | { 493 | return new PeFile64(strFilename); 494 | } 495 | else 496 | { 497 | return nullptr; 498 | } 499 | } 500 | 501 | PeFile* openPeFile(std::istream& stream) 502 | { 503 | unsigned int type = getFileType(stream); 504 | 505 | if (type == PEFILE32) 506 | { 507 | return new PeFile32(stream); 508 | } 509 | else if (type == PEFILE64) 510 | { 511 | return new PeFile64(stream); 512 | } 513 | else 514 | { 515 | return nullptr; 516 | } 517 | } 518 | 519 | unsigned int PELIB_IMAGE_BOUND_DIRECTORY::size() const 520 | { 521 | unsigned int size = 0; 522 | for (unsigned int i = 0; i < moduleForwarders.size(); ++i) 523 | { 524 | size += moduleForwarders[i].size(); 525 | } 526 | 527 | return (unsigned int)(size + PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size() + strModuleName.size() + 1); 528 | } 529 | } 530 | -------------------------------------------------------------------------------- /src/pelib/RelocationsDirectory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Relocations.cpp - Part of the PeLib library. 3 | * 4 | * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) 5 | * All rights reserved. 6 | * 7 | * This software is licensed under the zlib/libpng License. 8 | * For more details see http://www.opensource.org/licenses/zlib-license.php 9 | * or the license information file (license.htm) in the root directory 10 | * of PeLib. 11 | */ 12 | 13 | #include "pelib/PeLibInc.h" 14 | #include "pelib/RelocationsDirectory.h" 15 | 16 | namespace PeLib 17 | { 18 | void RelocationsDirectory::setRelocationData(unsigned int ulRelocation, unsigned int ulDataNumber, word wData) 19 | { 20 | m_vRelocations[ulRelocation].vRelocData[ulDataNumber] = wData; 21 | } 22 | 23 | void RelocationsDirectory::read(InputBuffer& inputbuffer, unsigned int uiSize) 24 | { 25 | IMG_BASE_RELOC ibrCurr; 26 | 27 | std::vector vCurrReloc; 28 | 29 | do 30 | { 31 | if (inputbuffer.get() + sizeof(ibrCurr.ibrRelocation.VirtualAddress) + sizeof(ibrCurr.ibrRelocation.SizeOfBlock) > uiSize) 32 | { 33 | break; 34 | } 35 | inputbuffer >> ibrCurr.ibrRelocation.VirtualAddress; 36 | inputbuffer >> ibrCurr.ibrRelocation.SizeOfBlock; 37 | 38 | ibrCurr.vRelocData.clear(); 39 | 40 | // That's not how to check if there are relocations, some DLLs start at VA 0. 41 | // if (!ibrCurr.ibrRelocation.VirtualAddress) break; 42 | 43 | for (unsigned int i=0;i<(ibrCurr.ibrRelocation.SizeOfBlock - PELIB_IMAGE_SIZEOF_BASE_RELOCATION) / sizeof(word);i++) 44 | { 45 | if (inputbuffer.get() + sizeof(word) > uiSize) 46 | { 47 | break; 48 | } 49 | word wData; 50 | inputbuffer >> wData; 51 | ibrCurr.vRelocData.push_back(wData); 52 | } 53 | 54 | vCurrReloc.push_back(ibrCurr); 55 | } while (ibrCurr.ibrRelocation.VirtualAddress && inputbuffer.get() < uiSize); 56 | 57 | std::swap(vCurrReloc, m_vRelocations); 58 | } 59 | 60 | // TODO: Return value is wrong if buffer was too small. 61 | int RelocationsDirectory::read(const unsigned char* buffer, unsigned int buffersize) 62 | { 63 | std::vector vRelocDirectory(buffer, buffer + buffersize); 64 | 65 | InputBuffer ibBuffer(vRelocDirectory); 66 | read(ibBuffer, buffersize); 67 | 68 | return ERROR_NONE; 69 | } 70 | 71 | unsigned int RelocationsDirectory::size() const 72 | { 73 | unsigned int size2 = static_cast(m_vRelocations.size()) * PELIB_IMAGE_BASE_RELOCATION::size(); 74 | 75 | for (unsigned int i=0;i(m_vRelocations[i].vRelocData.size()) * sizeof(word); 78 | } 79 | 80 | return size2; 81 | } 82 | 83 | unsigned int RelocationsDirectory::calcNumberOfRelocations() const 84 | { 85 | return static_cast(m_vRelocations.size()); 86 | } 87 | 88 | dword RelocationsDirectory::getVirtualAddress(unsigned int ulRelocation) const 89 | { 90 | return m_vRelocations[ulRelocation].ibrRelocation.VirtualAddress; 91 | } 92 | 93 | dword RelocationsDirectory::getSizeOfBlock(unsigned int ulRelocation) const 94 | { 95 | return m_vRelocations[ulRelocation].ibrRelocation.SizeOfBlock; 96 | } 97 | 98 | unsigned int RelocationsDirectory::calcNumberOfRelocationData(unsigned int ulRelocation) const 99 | { 100 | return static_cast(m_vRelocations[ulRelocation].vRelocData.size()); 101 | } 102 | 103 | word RelocationsDirectory::getRelocationData(unsigned int ulRelocation, unsigned int ulDataNumber) const 104 | { 105 | return m_vRelocations[ulRelocation].vRelocData[ulDataNumber]; 106 | } 107 | 108 | void RelocationsDirectory::setVirtualAddress(unsigned int ulRelocation, dword dwValue) 109 | { 110 | m_vRelocations[ulRelocation].ibrRelocation.VirtualAddress = dwValue; 111 | } 112 | 113 | void RelocationsDirectory::setSizeOfBlock(unsigned int ulRelocation, dword dwValue) 114 | { 115 | m_vRelocations[ulRelocation].ibrRelocation.SizeOfBlock = dwValue; 116 | } 117 | 118 | void RelocationsDirectory::addRelocation() 119 | { 120 | IMG_BASE_RELOC newrelocation; 121 | m_vRelocations.push_back(newrelocation); 122 | } 123 | 124 | void RelocationsDirectory::addRelocationData(unsigned int ulRelocation, word wValue) 125 | { 126 | m_vRelocations[ulRelocation].vRelocData.push_back(wValue); 127 | } 128 | 129 | /* void RelocationsDirectory::removeRelocationData(unsigned int ulRelocation, word wValue) 130 | { 131 | // If you get an error with Borland C++ here you have two options: Upgrade your compiler 132 | // or use the commented line instead of the line below. 133 | m_vRelocations[ulRelocation].vRelocData.erase(std::remove(m_vRelocations[ulRelocation].vRelocData.begin(), m_vRelocations[ulRelocation].vRelocData.end(), wValue), m_vRelocations[ulRelocation].vRelocData.end()); 134 | } 135 | */ 136 | void RelocationsDirectory::removeRelocation(unsigned int index) 137 | { 138 | m_vRelocations.erase(m_vRelocations.begin() + index); 139 | } 140 | 141 | void RelocationsDirectory::removeRelocationData(unsigned int relocindex, unsigned int dataindex) 142 | { 143 | m_vRelocations[relocindex].vRelocData.erase(m_vRelocations[relocindex].vRelocData.begin() + dataindex); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/pelib/SecurityDirectory.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SecurityDirectory.cpp 3 | * @brief Class for security directory. 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #include "pelib/PeLibInc.h" 8 | #include "pelib/SecurityDirectory.h" 9 | 10 | namespace PeLib 11 | { 12 | unsigned int SecurityDirectory::calcNumberOfCertificates() const 13 | { 14 | return (unsigned int)m_certs.size(); 15 | } 16 | 17 | const std::vector& SecurityDirectory::getCertificate(std::size_t index) const 18 | { 19 | return m_certs[index].Certificate; 20 | } 21 | 22 | int SecurityDirectory::read( 23 | std::istream& inStream, 24 | unsigned int uiOffset, 25 | unsigned int uiSize) 26 | { 27 | IStreamWrapper inStream_w(inStream); 28 | 29 | if (!inStream_w) 30 | { 31 | return ERROR_OPENING_FILE; 32 | } 33 | 34 | std::uint64_t ulFileSize = fileSize(inStream_w); 35 | if (ulFileSize < uiOffset + uiSize) 36 | { 37 | return ERROR_INVALID_FILE; 38 | } 39 | 40 | inStream_w.seekg(uiOffset, std::ios::beg); 41 | 42 | std::vector vCertDirectory(uiSize); 43 | inStream_w.read(reinterpret_cast(vCertDirectory.data()), uiSize); 44 | 45 | InputBuffer inpBuffer(vCertDirectory); 46 | 47 | unsigned bytesRead = 0; 48 | while (bytesRead < uiSize) 49 | { 50 | PELIB_IMAGE_CERTIFICATE_ENTRY cert; 51 | inpBuffer >> cert.Length; 52 | inpBuffer >> cert.Revision; 53 | inpBuffer >> cert.CertificateType; 54 | 55 | if ((cert.Length <= PELIB_IMAGE_CERTIFICATE_ENTRY::size() || 56 | ((cert.Revision != PELIB_WIN_CERT_REVISION_1_0) && (cert.Revision != PELIB_WIN_CERT_REVISION_2_0)) || 57 | (cert.CertificateType != PELIB_WIN_CERT_TYPE_PKCS_SIGNED_DATA))) 58 | { 59 | return ERROR_INVALID_FILE; 60 | } 61 | 62 | cert.Certificate.resize(cert.Length - PELIB_IMAGE_CERTIFICATE_ENTRY::size()); 63 | inpBuffer.read(reinterpret_cast(cert.Certificate.data()), cert.Certificate.size()); 64 | 65 | bytesRead += cert.Length; 66 | m_certs.push_back(cert); 67 | } 68 | 69 | return ERROR_NONE; 70 | } 71 | } 72 | --------------------------------------------------------------------------------