deps/pelib: move from external deps directly to retdec sources.

This commit is contained in:
Matula Peter 2020-01-15 14:41:24 +01:00
parent e056647d7b
commit ce7adce42c
58 changed files with 15624 additions and 134 deletions

19
LICENSE-PELIB Normal file
View File

@ -0,0 +1,19 @@
The zlib/libpng License
Copyright (c) 2004 - Sebastian Porst
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@ -14,12 +14,11 @@ RetDec uses the following third-party libraries or other resources:
6) Libelf: https://github.com/WolfgangSt/libelf
7) LLVM: https://llvm.org/
8) OpenSSL: https://www.openssl.org/
9) PeLib: https://github.com/avast/pelib
10) RapidJSON: https://github.com/Tencent/rapidjson
11) TinyXML-2: https://github.com/leethomason/tinyxml2
12) whereami: https://github.com/gpakosz/whereami
13) yara: https://virustotal.github.io/yara/
14) yaramod: https://github.com/avast/yaramod
9) RapidJSON: https://github.com/Tencent/rapidjson
10) TinyXML-2: https://github.com/leethomason/tinyxml2
11) whereami: https://github.com/gpakosz/whereami
12) yara: https://virustotal.github.io/yara/
13) yaramod: https://github.com/avast/yaramod
These third-party libraries or other resources are licensed under the
following licenses:
@ -1707,31 +1706,7 @@ SOFTWARE.
*/
===============================================================================
9) PeLib
===============================================================================
The zlib/libpng License
Copyright (c) 2004 - Sebastian Porst
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
===============================================================================
10) RapidJSON
9) RapidJSON
===============================================================================
Tencent is pleased to support the open source community by making RapidJSON available.
@ -1791,7 +1766,7 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
===============================================================================
11) TinyXML-2
10) TinyXML-2
===============================================================================
TinyXML-2 is released under the zlib license:
@ -1805,7 +1780,7 @@ Permission is granted to anyone to use this software for any purpose, including
3. This notice may not be removed or altered from any source distribution.
===============================================================================
12) whereami
11) whereami
===============================================================================
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
@ -1825,7 +1800,7 @@ Permission is granted to anyone to use this software for any purpose, including
2. Montesqieu et camembert, vive la France, zut alors!
===============================================================================
13) YARA
12) YARA
===============================================================================
Copyright (c) 2007-2016. The YARA Authors. All Rights Reserved.
@ -1856,7 +1831,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===============================================================================
14) yaramod
13) yaramod
===============================================================================
The MIT License (MIT)

View File

@ -242,7 +242,7 @@ You can pass the following additional parameters to `cmake`:
* `-DRETDEC_COMPILE_YARA=OFF` to disable YARA rules compilation at installation step (enabled by default).
* `-DCMAKE_BUILD_TYPE=Debug` to build with debugging information, which is useful during development. By default, the project is built in the `Release` mode. This has no effect on Windows, but the same thing can be achieved by running `cmake --build .` with the `--config Debug` parameter.
* `-DCMAKE_PROGRAM_PATH=<path>` to use Perl at `<path>` (probably useful only on Windows).
* `-D<dep>_LOCAL_DIR=<path>` where `<dep>` is from `{CAPSTONE, GOOGLETEST, KEYSTONE, LIBDWARF, LLVM, PELIB, YARA, YARAMOD}` (e.g. `-DCAPSTONE_LOCAL_DIR=<path>`), to use the local repository clone at `<path>` for RetDec dependency instead of downloading a fresh copy at build time. Multiple such options may be used at the same time.
* `-D<dep>_LOCAL_DIR=<path>` where `<dep>` is from `{CAPSTONE, GOOGLETEST, KEYSTONE, LIBDWARF, LLVM, YARA, YARAMOD}` (e.g. `-DCAPSTONE_LOCAL_DIR=<path>`), to use the local repository clone at `<path>` for RetDec dependency instead of downloading a fresh copy at build time. Multiple such options may be used at the same time.
* `-DRETDEC_ENABLE_<component>=ON` to build only the specified component(s) (multiple such options can be used at once), and its (theirs) dependencies. By default, all the components are built. If at least one component is enabled via this mechanism, all the other components that were not explicitly enabled (and are not needed as dependencies of enabled components) are not built. See [cmake/options.cmake](https://github.com/avast/retdec/blob/master/cmake/options.cmake) for all the available component options.
* `-DRETDEC_ENABLE_ALL=ON` can be used to (re-)enable all the components.
* Alternatively, `-DRETDEC_ENABLE=<comma-separated component list>` can be used instead of `-DRETDEC_ENABLE_<component>=ON` (e.g. `-DRETDEC_ENABLE=fileformat,loader,ctypesparser` is equivalent to `-DRETDEC_ENABLE_FILEFORMAT=ON -DRETDEC_ENABLE_LOADER=ON -DRETDEC_ENABLE_CTYPESPARSER=ON`).
@ -310,6 +310,7 @@ This repository contains the following libraries:
* `macho-extractor` - library for extracting regular Mach-O binaries from fat Mach-O binaries (based on LLVM).
* `patterngen` - binary pattern extractor library.
* `pdbparser` - Microsoft PDB files parser library.
* `pelib` - Microsoft Portable Executable files manipulation library.
* `stacofin` - static code finder library.
* `unpacker` - collection of unpacking functions.
* `utils` - general C++ utility library.
@ -359,6 +360,9 @@ See the [project documentation](https://retdec-tc.avast.com/repository/download/
Copyright (c) 2017 Avast Software, licensed under the MIT license. See the [`LICENSE`](https://github.com/avast/retdec/blob/master/LICENSE) file for more details.
RetDec incorporates a modified PeLib library. New modules added by Avast Software are licensed under the MIT license. The original sources are licensed under the following license:
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com), licensed under the zlib/libpng License. See the [`LICENSE-PELIB`](https://github.com/avast/retdec/blob/master/LICENSE-PELIB) file for more details.
RetDec uses third-party libraries or other resources listed, along with their licenses, in the [`LICENSE-THIRD-PARTY`](https://github.com/avast/retdec/blob/master/LICENSE-THIRD-PARTY) file.
## Contributing

View File

@ -41,6 +41,7 @@ option(RETDEC_ENABLE_MACHO_EXTRACTORTOOL "" OFF)
option(RETDEC_ENABLE_PAT2YARA "" OFF)
option(RETDEC_ENABLE_PATTERNGEN "" OFF)
option(RETDEC_ENABLE_PDBPARSER "" OFF)
option(RETDEC_ENABLE_PELIB "" OFF)
option(RETDEC_ENABLE_RETDEC "" OFF)
option(RETDEC_ENABLE_RETDECTOOL "" OFF)
option(RETDEC_ENABLE_RTTI_FINDER "" OFF)
@ -97,6 +98,7 @@ foreach(t ${RETDEC_ENABLE})
set_if_equal(${t} "pat2yara" RETDEC_ENABLE_PAT2YARA)
set_if_equal(${t} "patterngen" RETDEC_ENABLE_PATTERNGEN)
set_if_equal(${t} "pdbparser" RETDEC_ENABLE_PDBPARSER)
set_if_equal(${t} "pelib" RETDEC_ENABLE_PELIB)
set_if_equal(${t} "retdec" RETDEC_ENABLE_RETDEC)
set_if_equal(${t} "retdectool" RETDEC_ENABLE_RETDEC)
set_if_equal(${t} "rtti-finder" RETDEC_ENABLE_RTTI_FINDER)
@ -143,6 +145,7 @@ if (RETDEC_ENABLE_AR_EXTRACTOR
OR RETDEC_ENABLE_PAT2YARA
OR RETDEC_ENABLE_PATTERNGEN
OR RETDEC_ENABLE_PDBPARSER
OR RETDEC_ENABLE_PELIB
OR RETDEC_ENABLE_RETDEC
OR RETDEC_ENABLE_RETDECTOOL
OR RETDEC_ENABLE_RTTI_FINDER
@ -345,6 +348,10 @@ set_if_at_least_one_set(RETDEC_ENABLE_FILEFORMAT
RETDEC_ENABLE_PATTERNGEN
RETDEC_ENABLE_UNPACKERTOOL)
set_if_at_least_one_set(RETDEC_ENABLE_PELIB
RETDEC_ENABLE_FILEFORMAT
RETDEC_ENABLE_UNPACKERTOOL)
set_if_at_least_one_set(RETDEC_ENABLE_CRYPTO
RETDEC_ENABLE_ALL
RETDEC_ENABLE_FILEFORMAT)
@ -505,10 +512,6 @@ set_if_at_least_one_set(RETDEC_ENABLE_LLVM
set_if_at_least_one_set(RETDEC_ENABLE_OPENSLL
RETDEC_ENABLE_CRYPTO)
set_if_at_least_one_set(RETDEC_ENABLE_PELIB
RETDEC_ENABLE_FILEFORMAT
RETDEC_ENABLE_UNPACKERTOOL)
set_if_at_least_one_set(RETDEC_ENABLE_RAPIDJSON
RETDEC_ENABLE_AR_EXTRACTOR
RETDEC_ENABLE_AR_EXTRACTORTOOL

1
deps/CMakeLists.txt vendored
View File

@ -10,7 +10,6 @@ cond_add_subdirectory(keystone RETDEC_ENABLE_KEYSTONE)
cond_add_subdirectory(libdwarf RETDEC_ENABLE_LIBDWARF)
cond_add_subdirectory(llvm RETDEC_ENABLE_LLVM)
cond_add_subdirectory(openssl RETDEC_ENABLE_OPENSLL)
cond_add_subdirectory(pelib RETDEC_ENABLE_PELIB)
cond_add_subdirectory(rapidjson RETDEC_ENABLE_RAPIDJSON)
cond_add_subdirectory(tinyxml2 RETDEC_ENABLE_TINYXML2)
cond_add_subdirectory(whereami RETDEC_ENABLE_WHEREAMI)

View File

@ -1,70 +0,0 @@
include(ExternalProject)
if(CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER_OPTION "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}")
endif()
if(CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER_OPTION "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
endif()
if(PELIB_LOCAL_DIR)
message(STATUS "PeLib: using local PeLib directory.")
ExternalProject_Add(pelib-project
DOWNLOAD_COMMAND ""
SOURCE_DIR "${PELIB_LOCAL_DIR}"
CMAKE_ARGS
# This does not work on MSVC, but may be useful on Linux.
-DCMAKE_BUILD_TYPE=Release
# Force the use of the same compiler as used to build the top-level
# project. Otherwise, the external project may pick up a different
# compiler, which may result in link errors.
"${CMAKE_C_COMPILER_OPTION}"
"${CMAKE_CXX_COMPILER_OPTION}"
# Disable the update step.
UPDATE_COMMAND ""
# Disable the install step.
INSTALL_COMMAND ""
)
force_configure_step(pelib-project)
else()
message(STATUS "PeLib: using remote PeLib revision.")
ExternalProject_Add(pelib-project
URL https://github.com/avast/pelib/archive/cdd54dd1b2efd61c8c6e837167b15676c4bba6fa.zip
URL_HASH SHA256=32fa1370d3917497ec4464105895666417389987c826b6361eedb2b80556545f
DOWNLOAD_NAME pelib.zip
CMAKE_ARGS
# This does not work on MSVC, but may be useful on Linux.
-DCMAKE_BUILD_TYPE=Release
# Force the use of the same compiler as used to build the top-level
# project. Otherwise, the external project may pick up a different
# compiler, which may result in link errors.
"${CMAKE_C_COMPILER_OPTION}"
"${CMAKE_CXX_COMPILER_OPTION}"
# Disable the update step.
UPDATE_COMMAND ""
# Disable the install step.
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
LOG_CONFIGURE ON
LOG_BUILD ON
)
endif()
check_if_variable_changed(PELIB_LOCAL_DIR CHANGED)
if(CHANGED)
ExternalProject_Get_Property(pelib-project binary_dir)
message(STATUS "PeLib: path to PeLib directory changed -> cleaning CMake files in ${binary_dir}.")
clean_cmake_files(${binary_dir})
endif()
ExternalProject_Get_Property(pelib-project source_dir)
ExternalProject_Get_Property(pelib-project binary_dir)
# Add libraries.
add_library(pelib INTERFACE)
add_dependencies(pelib pelib-project)
target_include_directories(pelib SYSTEM INTERFACE ${source_dir}/include)
target_link_libraries(pelib INTERFACE debug ${binary_dir}/src/pelib/${DEBUG_DIR}${CMAKE_STATIC_LIBRARY_PREFIX}pelib${CMAKE_STATIC_LIBRARY_SUFFIX})
target_link_libraries(pelib INTERFACE optimized ${binary_dir}/src/pelib/${RELEASE_DIR}${CMAKE_STATIC_LIBRARY_PREFIX}pelib${CMAKE_STATIC_LIBRARY_SUFFIX})

View File

@ -7,8 +7,6 @@
#ifndef RETDEC_FILEFORMAT_FILE_FORMAT_PE_PE_FORMAT_H
#define RETDEC_FILEFORMAT_FILE_FORMAT_PE_PE_FORMAT_H
#include <pelib/PeLib.h>
#include "retdec/crypto/hash_context.h"
#include "retdec/fileformat/file_format/file_format.h"
#include "retdec/fileformat/file_format/pe/pe_format_parser/pe_format_parser.h"
@ -19,6 +17,7 @@
#include "retdec/fileformat/types/dotnet_headers/user_string_stream.h"
#include "retdec/fileformat/types/dotnet_types/dotnet_class.h"
#include "retdec/fileformat/types/visual_basic/visual_basic_info.h"
#include "retdec/pelib/PeLib.h"
namespace retdec {
namespace fileformat {

View File

@ -7,10 +7,9 @@
#ifndef RETDEC_FILEFORMAT_FILE_FORMAT_PE_PE_FORMAT_PARSER_PE_FORMAT_PARSER_H
#define RETDEC_FILEFORMAT_FILE_FORMAT_PE_PE_FORMAT_PARSER_PE_FORMAT_PARSER_H
#include <pelib/PeLib.h>
#include "retdec/common/range.h"
#include "retdec/fileformat/fftypes.h"
#include "retdec/pelib/PeLib.h"
namespace retdec {
namespace fileformat {

View File

@ -7,7 +7,7 @@
#ifndef RETDEC_FILEFORMAT_FILE_FORMAT_PE_PE_TEMPLATE_AUX_H
#define RETDEC_FILEFORMAT_FILE_FORMAT_PE_PE_TEMPLATE_AUX_H
#include <pelib/PeLib.h>
#include "retdec/pelib/PeLib.h"
namespace retdec {
namespace fileformat {

View File

@ -0,0 +1,129 @@
/*
* BoundImportDirectory.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef BOUNDIMPORTDIRECTORY_H
#define BOUNDIMPORTDIRECTORY_H
#include "pelib/PeHeader.h"
#include "pelib/PeLibAux.h"
namespace PeLib
{
/// Class that handles the BoundImport directory.
/**
* This class can read and modify the BoundImport directory table of a PE file.
**/
class BoundImportDirectory
{
protected:
std::vector<PELIB_IMAGE_BOUND_DIRECTORY> m_vIbd; ///< Stores the individual BoundImport fields.
int read(InputBuffer& inpBuffer, unsigned char* data, unsigned int dwSize);
unsigned int totalModules() const;
public:
virtual ~BoundImportDirectory() = default;
/// Adds another bound import.
int addBoundImport(const std::string& strModuleName, dword dwTds, word dwOmn, word wWfr); // EXPORT
/// Identifies a module through it's name.
int getModuleIndex(const std::string& strModuleName) const; // EXPORT
/// Returns the number of files in the BoundImport directory.
unsigned int calcNumberOfModules() const; // EXPORT
/// Reads the BoundImport directory table from a PE file.
int read(unsigned char* pcBuffer, unsigned int uiSize); // EXPORT
/// Rebuilds the BoundImport directory.
void rebuild(std::vector<byte>& vBuffer, bool fMakeValid = true) const; // EXPORT
/// Empties the BoundImport directory.
void clear(); // EXPORT
/// Removes a bound import.
void removeBoundImport(const std::string& strModuleName); // EXPORT
/// Returns the size of the BoundImport directory.
unsigned int size() const; // EXPORT
/// Writes the current bound import directory to a file.
int write(const std::string& strFilename, dword dwOffset, bool fMakeValid = true) const; // EXPORT
/// Retrieves the TimeDateStamp value of a bound import.
dword getTimeDateStamp(dword dwBidnr) const; // EXPORT
/// Retrieves the OffsetModuleName value of a bound import.
word getOffsetModuleName(dword dwBidnr) const; // EXPORT
/// Retrieves the NumberOfModuleForwarderRefs value of a bound import.
word getNumberOfModuleForwarderRefs(dword dwBidnr) const; // EXPORT
/// Retrieves the ModuleName value of a bound import.
std::string getModuleName(dword dwBidnr) const; // EXPORT
/// Updates the TimeDateStamp value of a bound import.
void setTimeDateStamp(dword dwBidnr, dword dwTds); // EXPORT
/// Updates the OffsetModuleName value of a bound import.
void setOffsetModuleName(dword dwBidnr, word wOmn); // EXPORT
/// Updates the NumberOfModuleForwarderRefs value of a bound import.
void setNumberOfModuleForwarderRefs(dword dwBidnr, word wMfr); // EXPORT
/// Updates the ModuleName value of a bound import.
void setModuleName(dword dwBidnr, const std::string& strModuleName); // EXPORT
dword getTimeDateStamp(dword dwBidnr, dword forwardedModule) const; // EXPORT _module
word getOffsetModuleName(dword dwBidnr, dword forwardedModule) const; // EXPORT _module
word getNumberOfModuleForwarderRefs(dword dwBidnr, dword forwardedModule) const; // EXPORT _module
std::string getModuleName(dword dwBidnr, dword forwardedModule) const; // EXPORT _module
void setTimeDateStamp(dword dwBidnr, dword forwardedModule, dword dwTds); // EXPORT _module
void setOffsetModuleName(dword dwBidnr, dword forwardedModule, word wOmn); // EXPORT _module
void setNumberOfModuleForwarderRefs(dword dwBidnr, dword forwardedModule, word wMfr); // EXPORT _module
void setModuleName(dword dwBidnr, dword forwardedModule, const std::string& strModuleName); // EXPORT _module
word calcNumberOfModuleForwarderRefs(dword dwBidnr) const; // EXPORT
void addForwardedModule(dword dwBidnr, const std::string& name, dword timeStamp = 0, word offsetModuleName = 0, word forwardedModules = 0); // EXPORT
void removeForwardedModule(dword dwBidnr, word forwardedModule); // EXPORT
};
template <int bits>
class BoundImportDirectoryT : public BoundImportDirectory
{
public:
/// Reads the BoundImport directory table from a PE file.
int read(std::istream& inStream, const PeHeaderT<bits>& peHeader); // EXPORT
};
/**
* Reads the BoundImport directory from a PE file.
* @param inStream Input stream.
* @param peHeader A valid PE header which is necessary because some RVA calculations need to be done.
**/
template <int bits>
int BoundImportDirectoryT<bits>::read(
std::istream& inStream,
const PeHeaderT<bits>& peHeader)
{
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
dword dwOffset = peHeader.rvaToOffset(peHeader.getIddBoundImportRva());
unsigned int uiSize = peHeader.getIddBoundImportSize();
if (fileSize(inStream_w) < dwOffset + uiSize)
{
return ERROR_INVALID_FILE;
}
std::vector<unsigned char> vBimpDir(uiSize);
inStream_w.seekg(dwOffset, std::ios::beg);
inStream_w.read(reinterpret_cast<char*>(vBimpDir.data()), uiSize);
InputBuffer inpBuffer{vBimpDir};
return BoundImportDirectory::read(inpBuffer, vBimpDir.data(), uiSize);
}
}
#endif

View File

@ -0,0 +1,52 @@
/**
* @file CoffSymbolTable.h
* @brief Class for COFF symbol table.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef COFFSYMBOLTABLE_H
#define COFFSYMBOLTABLE_H
#include <vector>
namespace PeLib
{
/**
* This class handless the COFF symbol table.
*/
class CoffSymbolTable
{
private:
std::size_t stringTableSize;
dword numberOfStoredSymbols;
std::vector<unsigned char> stringTable;
std::vector<unsigned char> symbolTableDump;
std::vector<PELIB_IMAGE_COFF_SYMBOL> symbolTable;
LoaderError m_ldrError;
void read(InputBuffer& inputbuffer, unsigned int uiSize);
public:
CoffSymbolTable();
~CoffSymbolTable();
LoaderError loaderError() const;
void setLoaderError(LoaderError ldrError);
int read(
std::istream& inStream,
unsigned int uiOffset,
unsigned int uiSize);
std::size_t getSizeOfStringTable() const;
std::size_t getNumberOfStoredSymbols() const;
dword getSymbolIndex(std::size_t ulSymbol) const;
std::string getSymbolName(std::size_t ulSymbol) const;
dword getSymbolValue(std::size_t ulSymbol) const;
word getSymbolSectionNumber(std::size_t ulSymbol) const;
byte getSymbolTypeComplex(std::size_t ulSymbol) const;
byte getSymbolTypeSimple(std::size_t ulSymbol) const;
byte getSymbolStorageClass(std::size_t ulSymbol) const;
byte getSymbolNumberOfAuxSymbols(std::size_t ulSymbol) const;
};
}
#endif

View File

@ -0,0 +1,166 @@
/*
* ComHeaderDirectory.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef COMHEADERDIRECTORY_H
#define COMHEADERDIRECTORY_H
#include "pelib/PeHeader.h"
namespace PeLib
{
/// Class that handles the COM+ descriptor directory.
/**
* This class handles the COM+ Descriptor directory which was added to PE files
* which work with the .NET runtime modules.
**/
class ComHeaderDirectory
{
protected:
PELIB_IMAGE_COR20_HEADER m_ichComHeader; ///< The COM+ descriptor.
void read(InputBuffer& inputbuffer);
public:
virtual ~ComHeaderDirectory() = default;
/// Read a file's COM+ runtime descriptor directory.
int read(unsigned char* buffer, unsigned int buffersize); // EXPORT
/// Rebuild the COM+ descriptor.
void rebuild(std::vector<byte>& vBuffer) const; // EXPORT
/// Returns the size of the current COM+ descriptor.
unsigned int size() const; // EXPORT
/// Writes the current COM+ descriptor directory to a file.
int write(const std::string& strFilename, unsigned int dwOffset) const; // EXPORT
/// Get the COM+ descriptor's SizeOfHeader (cb) value.
dword getSizeOfHeader() const; // EXPORT
/// Get the COM+ descriptor's MajorRuntimeVersion value.
word getMajorRuntimeVersion() const; // EXPORT
/// Get the COM+ descriptor's MinorRuntimeVersion value.
word getMinorRuntimeVersion() const; // EXPORT
/// Get the COM+ descriptor's MetaData (Virtual Address) value.
dword getMetaDataVa() const; // EXPORT
/// Get the COM+ descriptor's MetaData (Size) value.
dword getMetaDataSize() const; // EXPORT
/// Get the COM+ descriptor's Flags value.
dword getFlags() const; // EXPORT
/// Get the COM+ descriptor's EntryPointToken value.
dword getEntryPointToken() const; // EXPORT
/// Get the COM+ descriptor's Resources (Virtual Address) value.
dword getResourcesVa() const; // EXPORT
/// Get the COM+ descriptor's Resources (Size) value.
dword getResourcesSize() const; // EXPORT
/// Get the COM+ descriptor's StrongNameSignature (Virtual Address) value.
dword getStrongNameSignatureVa() const; // EXPORT
/// Get the COM+ descriptor's StrongNameSignature (Size) value.
dword getStrongNameSignatureSize() const; // EXPORT
/// Get the COM+ descriptor's CodeManagerTable (Virtual Address) value.
dword getCodeManagerTableVa() const; // EXPORT
/// Get the COM+ descriptor's CodeManagerTable (Size) value.
dword getCodeManagerTableSize() const; // EXPORT
/// Get the COM+ descriptor's VTableFixup (Virtual Address) value.
dword getVTableFixupsVa() const; // EXPORT
/// Get the COM+ descriptor's VTableFixup (Size) value.
dword getVTableFixupsSize() const; // EXPORT
/// Get the COM+ descriptor's ExportAddressTable (Virtual Address) value.
dword getExportAddressTableJumpsVa() const; // EXPORT
/// Get the COM+ descriptor's ExportAddressTable (Size) value.
dword getExportAddressTableJumpsSize() const; // EXPORT
/// Get the COM+ descriptor's ManagedNativeHeader (Virtual Address) value.
dword getManagedNativeHeaderVa() const; // EXPORT
/// Get the COM+ descriptor's ManagedNativeHeader (Size) value.
dword getManagedNativeHeaderSize() const; // EXPORT
/// Change the COM+ descriptor's SizeOfHeader (cb) value.
void setSizeOfHeader(dword dwValue); // EXPORT
/// Change the COM+ descriptor's MajorRuntimeVersion value.
void setMajorRuntimeVersion(word wValue); // EXPORT
/// Change the COM+ descriptor's MinorRuntimeVersion value.
void setMinorRuntimeVersion(word wValue); // EXPORT
/// Change the COM+ descriptor's MetaData (VirtualAddress) value.
void setMetaDataVa(dword dwValue); // EXPORT
/// Change the COM+ descriptor's MetaData (Size) value.
void setMetaDataSize(dword dwValue); // EXPORT
/// Change the COM+ descriptor's Flags value.
void setFlags(dword dwValue); // EXPORT
/// Change the COM+ descriptor's EntryPointToken value.
void setEntryPointToken(dword dwValue); // EXPORT
/// Change the COM+ descriptor's Resources (VirtualAddress) value.
void setResourcesVa(dword dwValue); // EXPORT
/// Change the COM+ descriptor's Resources (Size) value.
void setResourcesSize(dword dwValue); // EXPORT
/// Change the COM+ descriptor's StrongNameSignatureVa (VirtualAddress) value.
void setStrongNameSignatureVa(dword dwValue); // EXPORT
/// Change the COM+ descriptor's StrongNameSignatureVa (Size) value.
void setStrongNameSignagureSize(dword dwValue); // EXPORT
/// Change the COM+ descriptor's CodeManagerTable (VirtualAddress) value.
void setCodeManagerTableVa(dword dwValue); // EXPORT
/// Change the COM+ descriptor's CodeManagerTable (Size) value.
void setCodeManagerTableSize(dword dwValue); // EXPORT
/// Change the COM+ descriptor's VTableFixups (VirtualAddress) value.
void setVTableFixupsVa(dword dwValue); // EXPORT
/// Change the COM+ descriptor's VTableFixups (Size) value.
void setVTableFixupsSize(dword dwValue); // EXPORT
/// Change the COM+ descriptor's ExportAddressTableJumps (VirtualAddress) value.
void setExportAddressTableJumpsVa(dword dwValue); // EXPORT
/// Change the COM+ descriptor's ExportAddressTableJumps (Size) value.
void setExportAddressTableJumpsSize(dword dwValue); // EXPORT
/// Change the COM+ descriptor's ManagedNativeHeader (VirtualAddress) value.
void setManagedNativeHeaderVa(dword dwValue); // EXPORT
/// Change the COM+ descriptor's ManagedNativeHeader (Size) value.
void setManagedNativeHeaderSize(dword dwValue); // EXPORT
};
template <int bits>
class ComHeaderDirectoryT : public ComHeaderDirectory
{
public:
/// Read a file's COM+ runtime descriptor directory.
int read(std::istream& inStream, const PeHeaderT<bits>& peHeader); // EXPORT
};
/**
* Reads a file's COM+ descriptor.
* @param inStream Input stream.
* @param peHeader A valid PE header which is necessary because some RVA calculations need to be done.
**/
template <int bits>
int ComHeaderDirectoryT<bits>::read(std::istream& inStream, const PeHeaderT<bits>& peHeader)
{
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
std::uint64_t ulFileSize = fileSize(inStream_w);
unsigned int uiOffset = peHeader.rvaToOffset(peHeader.getIddComHeaderRva());
unsigned int uiSize = peHeader.getIddComHeaderSize();
if (ulFileSize < uiOffset + uiSize)
{
return ERROR_INVALID_FILE;
}
inStream_w.seekg(uiOffset, std::ios::beg);
std::vector<byte> vComDescDirectory(uiSize);
inStream_w.read(reinterpret_cast<char*>(vComDescDirectory.data()), uiSize);
InputBuffer ibBuffer{vComDescDirectory};
ComHeaderDirectory::read(ibBuffer);
return ERROR_NONE;
}
}
#endif

View File

@ -0,0 +1,161 @@
/*
* DebugDirectory.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef DEBUGDIRECTORY_H
#define DEBUGDIRECTORY_H
#include "pelib/PeHeader.h"
namespace PeLib
{
/// Class that handles the Debug directory.
class DebugDirectory
{
protected:
/// Stores the various DebugDirectory structures.
std::vector<PELIB_IMG_DEBUG_DIRECTORY> m_vDebugInfo;
/// Stores RVAs which are occupied by this debug directory.
std::vector<std::pair<unsigned int, unsigned int>> m_occupiedAddresses;
std::vector<PELIB_IMG_DEBUG_DIRECTORY> read(InputBuffer& ibBuffer, unsigned int uiRva, unsigned int uiSize);
public:
virtual ~DebugDirectory() = default;
void clear(); // EXPORT
/// Reads the Debug directory from a file.
int read(unsigned char* buffer, unsigned int buffersize);
/// Rebuilds the current Debug directory.
void rebuild(std::vector<byte>& obBuffer) const; // EXPORT
/// Returns the size the current Debug directory needs after rebuilding.
unsigned int size() const;
/// Writes the current Debug directory back to a file.
int write(const std::string& strFilename, unsigned int uiOffset) const; // EXPORT
/// Returns the number of DebugDirectory image structures in the current DebugDirectory.
unsigned int calcNumberOfEntries() const; // EXPORT
/// Adds a new debug structure.
void addEntry(); // EXPORT
/// Removes a debug structure.
void removeEntry(std::size_t uiIndex); // EXPORT
/// Returns the Characteristics value of a debug structure.
dword getCharacteristics(std::size_t uiIndex) const; // EXPORT
/// Returns the TimeDateStamp value of a debug structure.
dword getTimeDateStamp(std::size_t uiIndex) const; // EXPORT
/// Returns the MajorVersion value of a debug structure.
word getMajorVersion(std::size_t uiIndex) const; // EXPORT
/// Returns the MinorVersion value of a debug structure.
word getMinorVersion(std::size_t uiIndex) const; // EXPORT
/// Returns the Type value of a debug structure.
dword getType(std::size_t uiIndex) const; // EXPORT
/// Returns the SizeOfData value of a debug structure.
dword getSizeOfData(std::size_t uiIndex) const; // EXPORT
/// Returns the AddressOfRawData value of a debug structure.
dword getAddressOfRawData(std::size_t uiIndex) const; // EXPORT
/// Returns the PointerToRawData value of a debug structure.
dword getPointerToRawData(std::size_t uiIndex) const; // EXPORT
std::vector<byte> getData(std::size_t index) const; // EXPORT
/// Sets the Characteristics value of a debug structure.
void setCharacteristics(std::size_t uiIndex, dword dwValue); // EXPORT
/// Sets the TimeDateStamp value of a debug structure.
void setTimeDateStamp(std::size_t uiIndex, dword dwValue); // EXPORT
/// Sets the MajorVersion value of a debug structure.
void setMajorVersion(std::size_t uiIndex, word wValue); // EXPORT
/// Sets the MinorVersion value of a debug structure.
void setMinorVersion(std::size_t uiIndex, word wValue); // EXPORT
/// Sets the Type value of a debug structure.
void setType(std::size_t uiIndex, dword dwValue); // EXPORT
/// Sets the SizeOfData value of a debug structure.
void setSizeOfData(std::size_t uiIndex, dword dwValue); // EXPORT
/// Sets the AddressOfRawData value of a debug structure.
void setAddressOfRawData(std::size_t uiIndex, dword dwValue); // EXPORT
/// Sets the PointerToRawData value of a debug structure.
void setPointerToRawData(std::size_t uiIndex, dword dwValue); // EXPORT
void setData(std::size_t index, const std::vector<byte>& data); // EXPORT
const std::vector<std::pair<unsigned int, unsigned int>>& getOccupiedAddresses() const;
};
template <int bits>
class DebugDirectoryT : public DebugDirectory
{
public:
/// Reads the Debug directory from a file.
int read(std::istream& inStream, const PeHeaderT<bits>& peHeader);
};
/**
* @param inStream Input stream.
* @param peHeader A valid PE header which is necessary because some RVA calculations need to be done.
**/
template <int bits>
int DebugDirectoryT<bits>::read(std::istream& inStream, const PeHeaderT<bits>& peHeader)
{
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
std::uint64_t ulFileSize = fileSize(inStream_w);
unsigned int uiRva = peHeader.getIddDebugRva();
unsigned int uiOffset = peHeader.rvaToOffset(uiRva);
unsigned int uiSize = peHeader.getIddDebugSize();
if (ulFileSize < uiOffset + uiSize)
{
return ERROR_INVALID_FILE;
}
inStream_w.seekg(uiOffset, std::ios::beg);
std::vector<byte> vDebugDirectory(uiSize);
inStream_w.read(reinterpret_cast<char*>(vDebugDirectory.data()), uiSize);
InputBuffer ibBuffer{vDebugDirectory};
std::vector<PELIB_IMG_DEBUG_DIRECTORY> currDebugInfo = DebugDirectory::read(ibBuffer, uiRva, uiSize);
for (unsigned int i=0;i<currDebugInfo.size();i++)
{
if ((currDebugInfo[i].idd.PointerToRawData >= ulFileSize) ||
(currDebugInfo[i].idd.PointerToRawData + currDebugInfo[i].idd.SizeOfData >= ulFileSize))
{
return ERROR_INVALID_FILE;
}
inStream_w.seekg(currDebugInfo[i].idd.PointerToRawData, std::ios::beg);
currDebugInfo[i].data.resize(currDebugInfo[i].idd.SizeOfData);
inStream_w.read(reinterpret_cast<char*>(currDebugInfo[i].data.data()), currDebugInfo[i].idd.SizeOfData);
if (!inStream_w) return ERROR_INVALID_FILE;
if (currDebugInfo[i].idd.SizeOfData > 0)
{
m_occupiedAddresses.push_back(
std::make_pair(
currDebugInfo[i].idd.AddressOfRawData,
currDebugInfo[i].idd.AddressOfRawData + currDebugInfo[i].idd.SizeOfData - 1
));
}
}
std::swap(currDebugInfo, m_vDebugInfo);
return ERROR_NONE;
}
}
#endif

View File

@ -0,0 +1,271 @@
/**
* @file DelayImportDirectory.h
* @brief Class for delay import directory.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef DELAY_IMPORT_DIRECTORY_H
#define DELAY_IMPORT_DIRECTORY_H
#include "pelib/PeLibInc.h"
#include "pelib/PeHeader.h"
namespace PeLib
{
/**
* This class handless delay import directory.
*/
template<int bits>
class DelayImportDirectory
{
typedef typename std::vector<PELIB_IMAGE_DELAY_IMPORT_DIRECTORY_RECORD<bits> >::const_iterator DelayImportDirectoryIterator;
typedef typename FieldSizes<bits>::VAR4_8 VAR4_8;
private:
std::vector<PELIB_IMAGE_DELAY_IMPORT_DIRECTORY_RECORD<bits> > records;
void init()
{
records.clear();
}
public:
DelayImportDirectory()
{
init();
}
~DelayImportDirectory()
{
}
// Delay-import descriptors made by MS Visual C++ 6.0 has an old format
// of delay import directory, where all entries are VAs (as opposite to RVAs from newer MS compilers).
// We convert the delay-import directory entries to RVAs by checking the lowest bit in the delay-import descriptor's Attributes value
VAR4_8 normalizeDelayImportValue(const PELIB_IMAGE_DELAY_IMPORT_DIRECTORY_RECORD<bits> & rec, const PeHeaderT<bits>& peHeader, VAR4_8 valueToConvert)
{
// Ignore zero items
if (valueToConvert != 0)
{
// Is this the old format version?
if((rec.Attributes & 0x01) == 0)
{
// Sample: 0fc4cb0620f95bdd624f2c78eea4d2b59594244c6671cf249526adf2f2cb71ec
// Contains artificially created delay import directory with incorrect values:
//
// Attributes 0x00000000 <-- Old MS delay import record, contains VAs
// NameRva 0x004010e6
// ModuleHandleRva 0x00000000
// DelayImportAddressTableRva 0x00001140 <-- WRONG! This is an RVA
// DelayImportNameTableRva 0x004010c0
// BoundDelayImportTableRva 0x00000000
// ...
if (valueToConvert > peHeader.getImageBase())
{
valueToConvert = valueToConvert - peHeader.getImageBase();
}
}
}
return valueToConvert;
}
int read(std::istream& inStream, const PeHeaderT<bits>& peHeader)
{
init();
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
std::uint64_t ulFileSize = fileSize(inStream_w);
std::uint64_t uiOffset = peHeader.rvaToOffset(peHeader.getIddDelayImportRva());
if (uiOffset >= ulFileSize)
{
return ERROR_INVALID_FILE;
}
PELIB_IMAGE_DELAY_IMPORT_DIRECTORY_RECORD<bits> rec;
std::vector<unsigned char> dump;
dump.resize(PELIB_IMAGE_SIZEOF_DELAY_IMPORT_DIRECTORY_RECORD);
// Keep loading until we encounter an entry filles with zeros
for(std::size_t i = 0;; i += PELIB_IMAGE_SIZEOF_DELAY_IMPORT_DIRECTORY_RECORD)
{
InputBuffer inputbuffer(dump);
// Read the n-th import sdirectory entry
if (!inStream_w.seekg(uiOffset + i, std::ios::beg))
break;
if (!inStream_w.read(reinterpret_cast<char*>(dump.data()), PELIB_IMAGE_SIZEOF_DELAY_IMPORT_DIRECTORY_RECORD))
break;
rec.init();
inputbuffer >> rec.Attributes;
inputbuffer >> rec.NameRva;
inputbuffer >> rec.ModuleHandleRva;
inputbuffer >> rec.DelayImportAddressTableRva;
inputbuffer >> rec.DelayImportNameTableRva;
inputbuffer >> rec.BoundDelayImportTableRva;
inputbuffer >> rec.UnloadDelayImportTableRva;
inputbuffer >> rec.TimeStamp;
if ( rec.Attributes == 0 && rec.NameRva == 0 && rec.ModuleHandleRva == 0 && rec.DelayImportAddressTableRva == 0 &&
rec.DelayImportNameTableRva == 0 && rec.BoundDelayImportTableRva == 0 && rec.UnloadDelayImportTableRva == 0 &&
rec.TimeStamp == 0)
{
break;
}
// Convert older (MS Visual C++ 6.0) delay-import descriptor to newer one.
// These delay-import descriptors are distinguishable by lowest bit in rec.Attributes to be zero.
// Sample: 2775d97f8bdb3311ace960a42eee35dbec84b9d71a6abbacb26c14e83f5897e4
rec.NameRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.NameRva);
rec.ModuleHandleRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.ModuleHandleRva);
rec.DelayImportAddressTableRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.DelayImportAddressTableRva);
rec.DelayImportNameTableRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.DelayImportNameTableRva);
rec.BoundDelayImportTableRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.BoundDelayImportTableRva);
rec.UnloadDelayImportTableRva = (dword)normalizeDelayImportValue(rec, peHeader, rec.UnloadDelayImportTableRva);
rec.DelayImportAddressTableOffset = (dword)peHeader.rvaToOffset(rec.DelayImportAddressTableRva);
rec.DelayImportNameTableOffset = (dword)peHeader.rvaToOffset(rec.DelayImportNameTableRva);
// Get name of library
getStringFromFileOffset(inStream_w, rec.Name, (std::size_t)peHeader.rvaToOffset(rec.NameRva), IMPORT_LIBRARY_MAX_LENGTH);
//
// LOADING NAME ADDRESSES/NAME ORDINALS
//
// Address table is not guaranteed to be null-terminated and therefore we need to first read name table.
inStream_w.seekg(rec.DelayImportNameTableOffset, std::ios::beg);
if(!inStream_w)
{
return ERROR_INVALID_FILE;
}
// Read all RVAs (or VAs) of import names
std::vector<PELIB_VAR_SIZE<bits>> nameAddresses;
for(;;)
{
PELIB_VAR_SIZE<bits> nameAddr;
std::vector<byte> vBuffer(sizeof(nameAddr.Value));
// Read the value from the file
inStream_w.read(reinterpret_cast<char*>(vBuffer.data()), sizeof(nameAddr.Value));
if (!inStream_w || inStream_w.gcount() < sizeof(nameAddr.Value))
break;
InputBuffer inb(vBuffer);
inb >> nameAddr.Value;
// Value of zero means that this is the end of the bound import name table
if (nameAddr.Value == 0)
break;
nameAddresses.push_back(nameAddr);
}
//
// LOADING FUNCTION POINTERS
//
// Move to the offset of function addresses
inStream_w.seekg(rec.DelayImportAddressTableOffset, std::ios::beg);
if (!inStream_w)
{
return ERROR_INVALID_FILE;
}
// Read all (VAs) of import names
std::vector<PELIB_VAR_SIZE<bits>> funcAddresses;
for (std::size_t i = 0, e = nameAddresses.size(); i < e; ++i)
{
PELIB_VAR_SIZE<bits> funcAddr;
std::vector<byte> vBuffer(sizeof(funcAddr.Value));
// Read the value from the file
inStream_w.read(reinterpret_cast<char*>(vBuffer.data()), sizeof(funcAddr.Value));
if (!inStream_w || inStream_w.gcount() < sizeof(funcAddr.Value))
break;
InputBuffer inb(vBuffer);
inb >> funcAddr.Value;
// The value of zero means terminator of the function table
if (funcAddr.Value == 0)
break;
funcAddresses.push_back(funcAddr);
}
//
// MERGE BOTH TOGETHER
//
std::size_t numberOfFunctions = std::min(nameAddresses.size(), funcAddresses.size());
for (std::size_t i = 0; i < numberOfFunctions; i++)
{
PELIB_DELAY_IMPORT<bits> function;
PELIB_VAR_SIZE<bits> nameAddr = nameAddresses[i];
PELIB_VAR_SIZE<bits> funcAddr = funcAddresses[i];
// Check name address. It could be ordinal, VA or RVA
if (!(nameAddr.Value & PELIB_IMAGE_ORDINAL_FLAGS<bits>::PELIB_IMAGE_ORDINAL_FLAG))
{
// Convert value to RVA, if needed
nameAddr.Value = normalizeDelayImportValue(rec, peHeader, nameAddr.Value);
// Read the function hint
inStream_w.seekg(peHeader.rvaToOffset(nameAddr.Value), std::ios::beg);
inStream_w.read(reinterpret_cast<char*>(&function.hint), sizeof(function.hint));
if (!inStream_w || inStream_w.gcount() < sizeof(function.hint))
break;
// Read the function name
getStringFromFileOffset(inStream_w, function.fname, inStream_w.tellg(), IMPORT_SYMBOL_MAX_LENGTH);
}
else
{
function.hint = (word)(nameAddr.Value & 0xFFFF);
}
// Fill-in function address. The table is always in the image itself
if (peHeader.getImageBase() <= funcAddr.Value && funcAddr.Value < peHeader.getImageBase() + peHeader.getSizeOfImage())
funcAddr.Value -= peHeader.getImageBase();
function.address.Value = funcAddr.Value;
// Insert the function to the list
rec.addFunction(function);
}
records.push_back(rec);
}
return ERROR_NONE;
}
std::size_t getNumberOfFiles() const
{
return records.size();
}
const PELIB_IMAGE_DELAY_IMPORT_DIRECTORY_RECORD<bits> *getFile(std::size_t index) const
{
return index < getNumberOfFiles() ? &records[index] : nullptr;
}
DelayImportDirectoryIterator begin() const
{
return records.begin();
}
DelayImportDirectoryIterator end() const
{
return records.end();
}
};
}
#endif

View File

@ -0,0 +1,296 @@
/*
* ExportDirectory.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef EXPORTDIRECTORY_H
#define EXPORTDIRECTORY_H
#include "pelib/PeHeader.h"
namespace PeLib
{
/// Class that handles the export directory.
/**
* This class handles the export directory.
* \todo getNameString
**/
class ExportDirectory
{
protected:
/// Used to store all necessary information about a file's exported functions.
PELIB_IMAGE_EXP_DIRECTORY m_ied;
/// Stores RVAs which are occupied by this export directory.
std::vector<std::pair<unsigned int, unsigned int>> m_occupiedAddresses;
public:
virtual ~ExportDirectory() = default;
/// Add another function to be exported.
void addFunction(const std::string& strFuncname, dword dwFuncAddr); // EXPORT
unsigned int calcNumberOfFunctions() const; // EXPORT
void clear(); // EXPORT
/// Identifies a function through it's name.
int getFunctionIndex(const std::string& strFunctionName) const; // EXPORT
/// Rebuild the current export directory.
void rebuild(std::vector<byte>& vBuffer, dword dwRva) const; // EXPORT
void removeFunction(unsigned int index); // EXPORT
/// Returns the size of the current export directory.
unsigned int size() const; // EXPORT
/// Writes the current export directory to a file.
int write(const std::string& strFilename, unsigned int uiOffset, unsigned int uiRva) const; // EXPORT
/// Changes the name of the file (according to the export directory).
void setNameString(const std::string& strFilename); // EXPORT
std::string getNameString() const; // EXPORT
/// Get the name of an exported function.
std::string getFunctionName(std::size_t index) const; // EXPORT
/// Get the ordinal of an exported function.
word getFunctionOrdinal(std::size_t index) const; // EXPORT
/// Get the address of the name of an exported function.
dword getAddressOfName(std::size_t index) const; // EXPORT
/// Get the address of an exported function.
dword getAddressOfFunction(std::size_t index) const; // EXPORT
/// Change the name of an exported function.
void setFunctionName(std::size_t index, const std::string& strName); // EXPORT
/// Change the ordinal of an exported function.
void setFunctionOrdinal(std::size_t index, word wValue); // EXPORT
/// Change the address of the name of an exported function.
void setAddressOfName(std::size_t index, dword dwValue); // EXPORT
/// Change the address of an exported function.
void setAddressOfFunction(std::size_t index, dword dwValue); // EXPORT
/*
word getFunctionOrdinal(std::string strFuncname) const;
dword getAddressOfName(std::string strFuncname) const;
dword getAddressOfFunction(std::string strFuncname) const;
void setFunctionOrdinal(std::string strFuncname, word wValue);
void setAddressOfName(std::string strFuncname, dword dwValue);
void setAddressOfFunction(std::string strFuncname, dword dwValue);
*/
/// Return the Base value of the export directory.
dword getBase() const; // EXPORT
/// Return the Characteristics value of the export directory.
dword getCharacteristics() const; // EXPORT
/// Return the TimeDateStamp value of the export directory.
dword getTimeDateStamp() const; // EXPORT
/// Return the MajorVersion value of the export directory.
word getMajorVersion() const; // EXPORT
/// Return the MinorVersion value of the export directory.
word getMinorVersion() const; // EXPORT
/// Return the Name value of the export directory.
dword getName() const; // EXPORT
/// Return the NumberOfFunctions value of the export directory.
dword getNumberOfFunctions() const; // EXPORT
/// Return the NumberOfNames value of the export directory.
dword getNumberOfNames() const; // EXPORT
/// Return the AddressOfFunctions value of the export directory.
dword getAddressOfFunctions() const; // EXPORT
/// Return the AddressOfNames value of the export directory.
dword getAddressOfNames() const; // EXPORT
/// Returns the AddressOfNameOrdinals value.
dword getAddressOfNameOrdinals() const; // EXPORT
/* /// Returns the number of NameOrdinals.
dword getNumberOfNameOrdinals() const; // EXPORT
/// Returns the number of AddressOfFunctionNames values.
dword getNumberOfAddressOfFunctionNames() const; // EXPORT
/// Returns the number of AddressOfFunction values.
dword getNumberOfAddressOfFunctions() const; // EXPORT
*/
/// Set the Base value of the export directory.
void setBase(dword dwValue); // EXPORT
/// Set the Characteristics value of the export directory.
void setCharacteristics(dword dwValue); // EXPORT
/// Set the TimeDateStamp value of the export directory.
void setTimeDateStamp(dword dwValue); // EXPORT
/// Set the MajorVersion value of the export directory.
void setMajorVersion(word wValue); // EXPORT
/// Set the MinorVersion value of the export directory.
void setMinorVersion(word wValue); // EXPORT
/// Set the Name value of the export directory.
void setName(dword dwValue); // EXPORT
/// Set the NumberOfFunctions value of the export directory.
void setNumberOfFunctions(dword dwValue); // EXPORT
/// Set the NumberOfNames value of the export directory.
void setNumberOfNames(dword dwValue); // EXPORT
/// Set the AddressOfFunctions value of the export directory.
void setAddressOfFunctions(dword dwValue); // EXPORT
/// Set the AddressOfNames value of the export directory.
void setAddressOfNames(dword dwValue); // EXPORT
void setAddressOfNameOrdinals(dword value); // EXPORT
const std::vector<std::pair<unsigned int, unsigned int>>& getOccupiedAddresses() const;
};
template <int bits>
class ExportDirectoryT : public ExportDirectory
{
public:
/// Read a file's export directory.
int read(std::istream& inStream, const PeHeaderT<bits>& peHeader); // EXPORT
};
/**
* @param inStream Input stream.
* @param peHeader A valid PE header which is necessary because some RVA calculations need to be done.
* \todo: Proper use of InputBuffer
**/
template <int bits>
int ExportDirectoryT<bits>::read(
std::istream& inStream,
const PeHeaderT<bits>& peHeader)
{
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
std::uint64_t ulFileSize = fileSize(inStream_w);
unsigned int dirRva = peHeader.getIddExportRva();
unsigned int dirOffset = peHeader.rvaToOffset(dirRva);
if (ulFileSize < dirOffset + PELIB_IMAGE_EXPORT_DIRECTORY::size())
{
return ERROR_INVALID_FILE;
}
inStream_w.seekg(dirOffset, std::ios::beg);
std::vector<unsigned char> vExportDirectory(PELIB_IMAGE_EXPORT_DIRECTORY::size());
inStream_w.read(reinterpret_cast<char*>(vExportDirectory.data()), PELIB_IMAGE_EXPORT_DIRECTORY::size());
InputBuffer inpBuffer(vExportDirectory);
PELIB_IMAGE_EXP_DIRECTORY iedCurr;
inpBuffer >> iedCurr.ied.Characteristics;
inpBuffer >> iedCurr.ied.TimeDateStamp;
inpBuffer >> iedCurr.ied.MajorVersion;
inpBuffer >> iedCurr.ied.MinorVersion;
inpBuffer >> iedCurr.ied.Name;
inpBuffer >> iedCurr.ied.Base;
inpBuffer >> iedCurr.ied.NumberOfFunctions;
inpBuffer >> iedCurr.ied.NumberOfNames;
inpBuffer >> iedCurr.ied.AddressOfFunctions;
inpBuffer >> iedCurr.ied.AddressOfNames;
inpBuffer >> iedCurr.ied.AddressOfNameOrdinals;
m_occupiedAddresses.emplace_back(dirRva, dirRva + PELIB_IMAGE_EXPORT_DIRECTORY::size() - 1);
// Verify the export directory. Do not allow more functions than the limit
// Sample: CCE461B6EB23728BA3B8A97B9BE84C0FB9175DB31B9949E64144198AB3F702CE
if (iedCurr.ied.NumberOfFunctions > PELIB_MAX_EXPORTED_FUNCTIONS || iedCurr.ied.NumberOfNames > PELIB_MAX_EXPORTED_FUNCTIONS)
return ERROR_INVALID_FILE;
unsigned int offset = peHeader.rvaToOffset(iedCurr.ied.Name);
if (offset >= ulFileSize)
return ERROR_INVALID_FILE;
inStream_w.seekg(offset, std::ios::beg);
char c = 0;
std::string strFname = "";
do
{
inStream_w.read(reinterpret_cast<char*>(&c), sizeof(c));
if (!inStream_w) return ERROR_INVALID_FILE;
if (c) strFname += c;
}
while (c != 0);
iedCurr.name = strFname;
m_occupiedAddresses.push_back(std::make_pair(iedCurr.ied.Name, iedCurr.ied.Name + strFname.length() + 1));
PELIB_EXP_FUNC_INFORMATION efiCurr;
efiCurr.ordinal = 0; efiCurr.addroffunc = 0; efiCurr.addrofname = 0;
for (unsigned int i=0;i<iedCurr.ied.NumberOfFunctions;i++)
{
unsigned int offset = peHeader.rvaToOffset(iedCurr.ied.AddressOfFunctions) + i * sizeof(efiCurr.addroffunc);
if (offset >= ulFileSize)
return ERROR_INVALID_FILE;
inStream_w.seekg(offset, std::ios::beg);
inStream_w.read(reinterpret_cast<char*>(&efiCurr.addroffunc), sizeof(efiCurr.addroffunc));
if (!inStream_w)
return ERROR_INVALID_FILE;
efiCurr.ordinal = iedCurr.ied.Base + i;
iedCurr.functions.push_back(efiCurr);
m_occupiedAddresses.emplace_back(
iedCurr.ied.AddressOfFunctions + i*sizeof(efiCurr.addroffunc),
iedCurr.ied.AddressOfFunctions + i*sizeof(efiCurr.addroffunc) + sizeof(efiCurr.addroffunc) - 1
);
}
for (unsigned int i=0;i<iedCurr.ied.NumberOfNames;i++)
{
unsigned int offset = peHeader.rvaToOffset(iedCurr.ied.AddressOfNameOrdinals) + i*sizeof(efiCurr.ordinal);
if (offset >= ulFileSize)
return ERROR_INVALID_FILE;
inStream_w.seekg(offset, std::ios::beg);
word ordinal;
inStream_w.read(reinterpret_cast<char*>(&ordinal), sizeof(ordinal));
m_occupiedAddresses.emplace_back(
iedCurr.ied.AddressOfNameOrdinals + i*sizeof(efiCurr.ordinal),
iedCurr.ied.AddressOfNameOrdinals + i*sizeof(efiCurr.ordinal) + sizeof(efiCurr.ordinal) - 1
);
if (!inStream_w)
return ERROR_INVALID_FILE;
else if (ordinal >= iedCurr.functions.size())
continue;
iedCurr.functions[ordinal].ordinal = iedCurr.ied.Base + ordinal;
offset = peHeader.rvaToOffset(iedCurr.ied.AddressOfNames) + i*sizeof(efiCurr.addrofname);
if (offset >= ulFileSize)
return ERROR_INVALID_FILE;
inStream_w.seekg(offset, std::ios::beg);
inStream_w.read(reinterpret_cast<char*>(&iedCurr.functions[ordinal].addrofname), sizeof(iedCurr.functions[ordinal].addrofname));
if (!inStream_w)
return ERROR_INVALID_FILE;
m_occupiedAddresses.emplace_back(
iedCurr.ied.AddressOfNames + i*sizeof(efiCurr.addrofname),
iedCurr.ied.AddressOfNames + i*sizeof(efiCurr.addrofname) + sizeof(iedCurr.functions[ordinal].addrofname) - 1
);
offset = peHeader.rvaToOffset(iedCurr.functions[ordinal].addrofname);
if (offset >= ulFileSize)
return ERROR_INVALID_FILE;
inStream_w.seekg(offset, std::ios::beg);
char cc = 0;
std::string strFname2 = "";
do
{
inStream_w.read(reinterpret_cast<char*>(&cc), sizeof(cc));
if (!inStream_w)
return ERROR_INVALID_FILE;
if (cc) strFname2 += cc;
}
while (cc != 0);
iedCurr.functions[ordinal].funcname = strFname2;
m_occupiedAddresses.emplace_back(
iedCurr.functions[ordinal].addrofname,
iedCurr.functions[ordinal].addrofname + strFname2.length() + 1
);
}
std::swap(m_ied, iedCurr);
return ERROR_NONE;
}
}
#endif

View File

@ -0,0 +1,102 @@
/*
* IatDirectory.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef IATDIRECTORY_H
#define IATDIRECTORY_H
#include "pelib/PeLibInc.h"
#include "pelib/PeHeader.h"
namespace PeLib
{
/// Class that handles the Import Address Table (IAT)
/**
* This class can read and modify the Import Address Table of a PE file.
**/
class IatDirectory
{
protected:
std::vector<dword> m_vIat; ///< Stores the individual IAT fields.
int read(InputBuffer& inputBuffer, unsigned int dwOffset, unsigned int dwFileSize);
public:
virtual ~IatDirectory() = default;
/// Reads the Import Address Table from a PE file.
int read(unsigned char* buffer, unsigned int buffersize); // EXPORT
/// Returns the number of fields in the IAT.
unsigned int calcNumberOfAddresses() const; // EXPORT
/// Adds another address to the IAT.
void addAddress(dword dwValue); // EXPORT
/// Removes an address from the IAT.
void removeAddress(unsigned int index); // EXPORT
/// Empties the IAT.
void clear(); // EXPORT
// Rebuilds the IAT.
void rebuild(std::vector<byte>& vBuffer) const; // EXPORT
/// Returns the size of the current IAT.
unsigned int size() const; // EXPORT
/// Writes the current IAT to a file.
int write(const std::string& strFilename, unsigned int uiOffset) const; // EXPORT
/// Retrieve the value of a field in the IAT.
dword getAddress(unsigned int index) const; // EXPORT
/// Change the value of a field in the IAT.
void setAddress(dword dwAddrnr, dword dwValue); // EXPORT
};
template <int bits>
class IatDirectoryT : public IatDirectory
{
public:
int read(std::istream& inStream, const PeHeaderT<bits>& peHeader); // EXPORT
};
/**
* Reads the Import Address table from a file.
* @param inStream Input stream.
* @param peHeader A valid PE header which is necessary because some RVA calculations need to be done.
**/
template <int bits>
int IatDirectoryT<bits>::read(std::istream& inStream, const PeHeaderT<bits>& peHeader)
{
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
std::uint64_t ulFileSize = fileSize(inStream_w);
std::uint64_t dwOffset = peHeader.rvaToOffset(peHeader.getIddIatRva());
std::uint64_t dwSize = peHeader.getIddIatSize();
if (ulFileSize <= dwOffset)
{
return ERROR_INVALID_FILE;
}
dwSize = std::min(ulFileSize - dwOffset, dwSize);
inStream_w.seekg(dwOffset, std::ios::beg);
std::vector<byte> vBuffer(dwSize);
inStream_w.read(reinterpret_cast<char*>(vBuffer.data()), dwSize);
InputBuffer inpBuffer{vBuffer};
return IatDirectory::read(inpBuffer, dwOffset, ulFileSize);
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
/*
* InputBuffer.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef INPUTBUFFER_H
#define INPUTBUFFER_H
#include <vector>
#include <iterator>
#include <cassert>
namespace PeLib
{
class InputBuffer
{
private:
std::vector<unsigned char>& m_vBuffer;
unsigned long ulIndex;
public:
InputBuffer(std::vector<unsigned char>& vBuffer);
const unsigned char* data() const;
unsigned long size();
template<typename T>
InputBuffer& operator>>(T& value)
{
//jk: temporarily disabled because of fails on 64bit systems
// assert(ulIndex + sizeof(value) <= m_vBuffer.size());
std::vector<char> data(sizeof(T), 0);
std::size_t size = ulIndex + sizeof(T) > m_vBuffer.size() ? m_vBuffer.size() - ulIndex : sizeof(T);
read(data.data(), (unsigned long)size);
value = *reinterpret_cast<T*>(data.data());
return *this;
}
void read(char* lpBuffer, unsigned long ulSize);
void reset();
void set(unsigned long ulIndex2);
void move(unsigned long shift);
unsigned long get();
void setBuffer(std::vector<unsigned char>& vBuffer);
// void updateData(unsigned long ulIndex,
};
}
#endif

View File

@ -0,0 +1,162 @@
/*
* MzHeader.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef MZHEADER_H
#define MZHEADER_H
#include "pelib/PeLibInc.h"
namespace PeLib
{
/// Class that handles the MZ header of files.
/**
* This class can read and modify MZ headers. It provides set- and get functions to access
* all individual members of a MZ header. Furthermore it's possible to validate and rebuild
* MZ headers.
**/
class MzHeader
{
private:
PELIB_IMAGE_DOS_HEADER m_idhHeader; ///< Stores all MZ header information.
std::string m_headerString; ///< MZ header in string representation.
LoaderError m_ldrError;
/// Reads data from an InputBuffer into a MZ header struct.
void read(InputBuffer& ibBuffer);
/// Offset of the MZ header in the original file.
unsigned int originalOffset;
void setLoaderError(LoaderError ldrError);
public:
enum Field {e_magic, e_cblp, e_cp, e_crlc, e_cparhdr, e_minalloc, e_maxalloc,
e_ss, e_sp, e_csum, e_ip, e_cs, e_lfarlc, e_ovno, e_res, e_oemid,
e_oeminfo, e_res2, e_lfanew};
MzHeader();
/// Checks if the current MZ header is valid.
bool isValid() const; // EXPORT
bool isValid(Field field) const; // EXPORT _field
/// Returns loader error for the header
LoaderError loaderError() const;
/// Corrects the current MZ header.
void makeValid(); // EXPORT
void makeValid(Field field); // EXPORT _field
/// Reads the MZ header of a file.
int read(std::istream& inStream); // EXPORT
/// Reads the MZ header from a memory location.
int read(unsigned char* pcBuffer, unsigned int uiSize, unsigned int originalOffs = 0); // EXPORT _fromMemory
/// Rebuild the MZ header.
void rebuild(std::vector<byte>& vBuffer) const; // EXPORT
/// Returns the size of the current MZ header.
unsigned int size() const; // EXPORT
/// Writes the current MZ header to offset 0 of a file.
int write(const std::string& strFilename, dword dwOffset) const; // EXPORT
/// Gets MZ header.
const PELIB_IMAGE_DOS_HEADER& getHeader() const; // EXPORT
/// Gets MZ header in string representation.
const std::string& getString() const; // EXPORT
/// Gets the e_magic value of the MZ header.
word getMagicNumber() const; // EXPORT
/// Gets the e_cblp value of the MZ header.
word getBytesOnLastPage() const; // EXPORT
/// Gets the e_cp value of the MZ header.
word getPagesInFile() const; // EXPORT
/// Gets the e_crlc value of the MZ header.
word getRelocations() const; // EXPORT
/// Gets the e_cparhdr value of the MZ header.
word getSizeOfHeader() const; // EXPORT
/// Gets the e_minalloc value of the MZ header.
word getMinExtraParagraphs() const; // EXPORT
/// Gets the e_maxalloc value of the MZ header.
word getMaxExtraParagraphs() const; // EXPORT
/// Gets the e_ss value of the MZ header.
word getSsValue() const; // EXPORT
/// Gets the e_sp value of the MZ header.
word getSpValue() const; // EXPORT
/// Gets the e_csum value of the MZ header.
word getChecksum() const; // EXPORT
/// Gets the e_ip value of the MZ header.
word getIpValue() const; // EXPORT
/// Gets the e_cs value of the MZ header.
word getCsValue() const; // EXPORT
/// Gets the e_lfarlc value of the MZ header.
word getAddrOfRelocationTable() const; // EXPORT
/// Gets the e_ovnovalue of the MZ header.
word getOverlayNumber() const; // EXPORT
/// Gets the e_oemid value of the MZ header.
word getOemIdentifier() const; // EXPORT
/// Gets the e_oeminfo value of the MZ header.
word getOemInformation() const; // EXPORT
/// Gets the e_lfanew value of the MZ header.
dword getAddressOfPeHeader() const; // EXPORT
/// Gets the e_res of the MZ header.
word getReservedWords1(unsigned int uiNr) const; // EXPORT
/// Gets the e_res2 of the MZ header.
word getReservedWords2(unsigned int uiNr) const; // EXPORT
/// Sets the e_magic value of the MZ header.
void setMagicNumber(word wValue); // EXPORT
/// Sets the e_cblp value of the MZ header.
void setBytesOnLastPage(word wValue); // EXPORT
/// Sets the e_cp value of the MZ header.
void setPagesInFile(word wValue); // EXPORT
/// Sets the e_crlc value of the MZ header.
void setRelocations(word wValue); // EXPORT
/// Sets the e_cparhdr value of the MZ header.
void setSizeOfHeader(word wValue); // EXPORT
/// Sets the e_minalloc value of the MZ header.
void setMinExtraParagraphs(word wValue); // EXPORT
/// Sets the e_maxalloc value of the MZ header.
void setMaxExtraParagraphs(word wValue); // EXPORT
/// Sets the e_ss value of the MZ header.
void setSsValue(word wValue); // EXPORT
/// Sets the e_sp value of the MZ header.
void setSpValue(word wValue); // EXPORT
/// Sets the e_csum value of the MZ header.
void setChecksum(word wValue); // EXPORT
/// Sets the e_ip value of the MZ header.
void setIpValue(word wValue); // EXPORT
/// Sets the e_cs value of the MZ header.
void setCsValue(word wValue); // EXPORT
/// Sets the e_lfarlc value of the MZ header.
void setAddrOfRelocationTable(word wValue); // EXPORT
/// Sets the e_ovno value of the MZ header.
void setOverlayNumber(word wValue); // EXPORT
/// Sets the e_oemid value of the MZ header.
void setOemIdentifier(word wValue); // EXPORT
/// Sets the e_oeminfo value of the MZ header.
void setOemInformation(word wValue); // EXPORT
/// Sets the e_lfanew value of the MZ header.
void setAddressOfPeHeader(dword dwValue); // EXPORT
/// Sets the e_res value of the MZ header.
void setReservedWords1(unsigned int uiNr, word wValue); // EXPORT
/// Sets the e_res2 value of the MZ header.
void setReservedWords2(unsigned int uiNr, word wValue); // EXPORT
};
}
#endif

View File

@ -0,0 +1,60 @@
/*
* OutputBuffer.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef OUTPUTBUFFER_H
#define OUTPUTBUFFER_H
#include <vector>
#include <iterator>
namespace PeLib
{
class OutputBuffer
{
private:
std::vector<unsigned char>& m_vBuffer;
public:
OutputBuffer(std::vector<unsigned char>& vBuffer);
const unsigned char* data() const;
unsigned long size();
template<typename T>
OutputBuffer& operator<<(const T& value)
{
const unsigned char* p = reinterpret_cast<const unsigned char*>(&value);
std::copy(p, p + sizeof(value), std::back_inserter(m_vBuffer));
return *this;
}
void add(const char* lpBuffer, unsigned long ulSize);
void reset();
void resize(unsigned int uiSize);
void set(unsigned int uiPosition);
template<typename T>
void update(unsigned long ulIndex, const T& value)
{
*reinterpret_cast<T*>(m_vBuffer.data() + ulIndex) = value;
}
template<typename T>
void insert(unsigned long ulIndex, const T& value)
{
if (ulIndex + sizeof(T) >= size())
resize(ulIndex + sizeof(T));
update(ulIndex, value);
}
};
}
#endif

View File

@ -0,0 +1,736 @@
/*
* PeFile.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef PEFILE_H
#define PEFILE_H
#include "pelib/PeLibInc.h"
#include "pelib/MzHeader.h"
#include "pelib/PeHeader.h"
#include "pelib/ImportDirectory.h"
#include "pelib/ExportDirectory.h"
#include "pelib/BoundImportDirectory.h"
#include "pelib/ResourceDirectory.h"
#include "pelib/RelocationsDirectory.h"
#include "pelib/ComHeaderDirectory.h"
#include "pelib/IatDirectory.h"
#include "pelib/DebugDirectory.h"
#include "pelib/TlsDirectory.h"
#include "pelib/RichHeader.h"
#include "pelib/CoffSymbolTable.h"
#include "pelib/DelayImportDirectory.h"
#include "pelib/SecurityDirectory.h"
namespace PeLib
{
class PeFile32;
class PeFile64;
/**
* Visitor base class for PeFiles.
**/
class PeFileVisitor
{
public:
virtual void callback(PeFile32 &file){(void) file; /* avoid warning about unused parameter */}
virtual void callback(PeFile64 &file){(void) file; /* avoid warning about unused parameter */}
virtual ~PeFileVisitor(){}
};
/**
* Traits class that's used to decide of what type the PeHeader in a PeFile is.
**/
template<int>
struct PeFile_Traits;
template<>
struct PeFile_Traits<32>
{
typedef PeHeader32 PeHeader32_64;
};
template<>
struct PeFile_Traits<64>
{
typedef PeHeader64 PeHeader32_64;
};
/**
* This class represents the common structures of PE and PE+ files.
**/
class PeFile
{
protected:
std::string m_filename; ///< Name of the current file.
MzHeader m_mzh; ///< MZ header of the current file.
RichHeader m_richheader; ///< Rich header of the current file.
CoffSymbolTable m_coffsymtab; ///< Symbol table of the current file.
SecurityDirectory m_secdir; ///< Security directory of the current file.
public:
virtual ~PeFile();
/// Returns the name of the current file.
virtual std::string getFileName() const = 0; // EXPORT
/// Changes the name of the current file.
virtual void setFileName(std::string strFilename) = 0; // EXPORT
virtual void visit(PeFileVisitor &v) = 0;
/// Reads the MZ header of the current file from disc.
virtual int readMzHeader() = 0; // EXPORT
/// Reads the export directory of the current file from disc.
virtual int readExportDirectory() = 0; // EXPORT
/// Reads the PE header of the current file from disc.
virtual int readPeHeader() = 0; // EXPORT
/// Reads the import directory of the current file from disc.
virtual int readImportDirectory() = 0; // EXPORT
/// Reads the bound import directory of the current file from disc.
virtual int readBoundImportDirectory() = 0; // EXPORT
/// Reads the resource directory of the current file from disc.
virtual int readResourceDirectory() = 0; // EXPORT
/// Reads the relocations directory of the current file from disc.
virtual int readRelocationsDirectory() = 0; // EXPORT
/// Reads the COM+ descriptor directory of the current file from disc.
virtual int readComHeaderDirectory() = 0; // EXPORT
/// Reads the IAT directory of the current file from disc.
virtual int readIatDirectory() = 0; // EXPORT
/// Reads the Debug directory of the current file.
virtual int readDebugDirectory() = 0; // EXPORT
/// Reads the TLS directory of the current file.
virtual int readTlsDirectory() = 0; // EXPORT
/// Reads rich header of the current file.
virtual int readRichHeader(std::size_t offset, std::size_t size, bool ignoreInvalidKey = false) = 0; // EXPORT
/// Reads the COFF symbol table of the current file.
virtual int readCoffSymbolTable() = 0; // EXPORT
/// Reads delay import directory of the current file.
virtual int readDelayImportDirectory() = 0; // EXPORT
/// Reads security directory of the current file.
virtual int readSecurityDirectory() = 0; // EXPORT
/// Returns a loader error, if there was any
virtual LoaderError loaderError() const = 0;
virtual unsigned int getBits() const = 0;
/// Accessor function for the MZ header.
const MzHeader& mzHeader() const;
/// Accessor function for the MZ header.
MzHeader& mzHeader(); // EXPORT
/// Accessor function for the Rich header.
const RichHeader& richHeader() const;
/// Accessor function for the Rich header.
RichHeader& richHeader(); // EXPORT
/// Accessor function for the COFF symbol table.
const CoffSymbolTable& coffSymTab() const;
/// Accessor function for the COFF symbol table.
CoffSymbolTable& coffSymTab(); // EXPORT
/// Accessor function for the security directory.
const SecurityDirectory& securityDir() const;
/// Accessor function for the security directory.
SecurityDirectory& securityDir();
};
/**
* This class implements the common structures of PE and PE+ files.
**/
template<int bits>
class PeFileT : public PeFile
{
typedef typename PeFile_Traits<bits>::PeHeader32_64 PeHeader32_64;
private:
std::ifstream m_ifStream;
std::istream& m_iStream;
PeHeader32_64 m_peh; ///< PE header of the current file.
ExportDirectoryT<bits> m_expdir; ///< Export directory of the current file.
ImportDirectory<bits> m_impdir; ///< Import directory of the current file.
BoundImportDirectoryT<bits> m_boundimpdir; ///< BoundImportDirectory of the current file.
ResourceDirectoryT<bits> m_resdir; ///< ResourceDirectory of the current file.
RelocationsDirectoryT<bits> m_relocs; ///< Relocations directory of the current file.
ComHeaderDirectoryT<bits> m_comdesc; ///< COM+ descriptor directory of the current file.
IatDirectoryT<bits> m_iat; ///< Import address table of the current file.
DebugDirectoryT<bits> m_debugdir; ///< Debug directory of the current file.
DelayImportDirectory<bits> m_delayimpdir; ///< Delay import directory of the current file.
TlsDirectory<bits> m_tlsdir; ///< TLS directory of the current file.
public:
/// Default constructor which exists only for the sake of allowing to construct files without filenames.
PeFileT();
virtual ~PeFileT() {}
/// Initializes a PeFile with a filename
explicit PeFileT(const std::string& strFilename);
PeFileT(std::istream& stream);
/// Returns the name of the current file.
std::string getFileName() const;
/// Changes the name of the current file.
void setFileName(std::string strFilename);
/// Reads the MZ header of the current file from disc.
int readMzHeader() ;
/// Reads the export directory of the current file from disc.
int readExportDirectory() ;
/// Reads the PE header of the current file from disc.
int readPeHeader() ;
/// Reads the import directory of the current file from disc.
int readImportDirectory() ;
/// Reads the bound import directory of the current file from disc.
int readBoundImportDirectory() ;
/// Reads the resource directory of the current file from disc.
int readResourceDirectory() ;
/// Reads the relocations directory of the current file from disc.
int readRelocationsDirectory() ;
/// Reads the COM+ descriptor directory of the current file from disc.
int readComHeaderDirectory() ;
/// Reads the IAT directory of the current file from disc.
int readIatDirectory() ;
/// Reads the Debug directory of the current file.
int readDebugDirectory() ;
/// Reads the TLS directory of the current file.
int readTlsDirectory() ;
/// Reads rich header of the current file.
int readRichHeader(std::size_t offset, std::size_t size, bool ignoreInvalidKey = false) ;
/// Reads the COFF symbol table of the current file.
int readCoffSymbolTable() ;
/// Reads delay import directory of the current file.
int readDelayImportDirectory() ;
/// Reads the security directory of the current file.
int readSecurityDirectory() ;
/// Returns a loader error, if there was any
LoaderError loaderError() const;
unsigned int getBits() const
{
return bits;
}
/// Accessor function for the PE header.
const PeHeader32_64& peHeader() const;
/// Accessor function for the PE header.
PeHeader32_64& peHeader();
/// Accessor function for the export directory.
const ExportDirectoryT<bits>& expDir() const;
/// Accessor function for the export directory.
ExportDirectoryT<bits>& expDir(); // EXPORT
/// Accessor function for the import directory.
const ImportDirectory<bits>& impDir() const;
/// Accessor function for the import directory.
ImportDirectory<bits>& impDir();
/// Accessor function for the bound import directory.
const BoundImportDirectoryT<bits>& boundImpDir() const;
/// Accessor function for the bound import directory.
BoundImportDirectoryT<bits>& boundImpDir(); // EXPORT
/// Accessor function for the resource directory.
const ResourceDirectoryT<bits>& resDir() const;
/// Accessor function for the resource directory.
ResourceDirectoryT<bits>& resDir(); // EXPORT
/// Accessor function for the relocations directory.
const RelocationsDirectoryT<bits>& relocDir() const;
/// Accessor function for the relocations directory.
RelocationsDirectoryT<bits>& relocDir(); // EXPORT
/// Accessor function for the COM+ descriptor directory.
const ComHeaderDirectoryT<bits>& comDir() const;
/// Accessor function for the COM+ descriptor directory.
ComHeaderDirectoryT<bits>& comDir(); // EXPORT
/// Accessor function for the IAT directory.
const IatDirectoryT<bits>& iatDir() const;
/// Accessor function for the IAT directory.
IatDirectoryT<bits>& iatDir(); // EXPORT
/// Accessor function for the debug directory.
const DebugDirectoryT<bits>& debugDir() const;
/// Accessor function for the debug directory.
DebugDirectoryT<bits>& debugDir(); // EXPORT
/// Accessor function for the delay import directory.
const DelayImportDirectory<bits>& delayImports() const;
/// Accessor function for the delay import directory.
DelayImportDirectory<bits>& delayImports(); // EXPORT
/// Accessor function for the TLS directory.
const TlsDirectory<bits>& tlsDir() const;
/// Accessor function for the TLS directory.
TlsDirectory<bits>& tlsDir();
};
/**
* This class is the main class for handling PE files.
**/
class PeFile32 : public PeFileT<32>
{
public:
/// Default constructor which exists only for the sake of allowing to construct files without filenames.
PeFile32();
/// Initializes a PeFile with a filename
explicit PeFile32(const std::string& strFlename);
PeFile32(std::istream& stream);
virtual void visit(PeFileVisitor &v) { v.callback( *this ); }
};
/**
* This class is the main class for handling PE+ files.
**/
class PeFile64 : public PeFileT<64>
{
public:
/// Default constructor which exists only for the sake of allowing to construct files without filenames.
PeFile64();
/// Initializes a PeFile with a filename
explicit PeFile64(const std::string& strFlename);
PeFile64(std::istream& stream);
virtual void visit(PeFileVisitor &v) { v.callback( *this ); }
};
//typedef PeFileT<32> PeFile32;
//typedef PeFileT<64> PeFile64;
/**
* @param strFilename Name of the current file.
**/
template<int bits>
PeFileT<bits>::PeFileT(const std::string& strFilename) :
m_iStream(m_ifStream)
{
m_filename = strFilename;
m_ifStream.open(m_filename, std::ifstream::binary);
}
/**
* @param stream Input stream.
**/
template<int bits>
PeFileT<bits>::PeFileT(std::istream& stream) :
m_iStream(stream)
{
}
template<int bits>
PeFileT<bits>::PeFileT() :
m_iStream(m_ifStream)
{
}
template<int bits>
int PeFileT<bits>::readPeHeader()
{
return peHeader().read(m_iStream, mzHeader().getAddressOfPeHeader(), mzHeader());
}
/**
* @return A reference to the file's PE header.
**/
template<int bits>
const typename PeFile_Traits<bits>::PeHeader32_64& PeFileT<bits>::peHeader() const
{
return m_peh;
}
/**
* @return A reference to the file's PE header.
**/
template<int bits>
typename PeFile_Traits<bits>::PeHeader32_64& PeFileT<bits>::peHeader()
{
return m_peh;
}
/**
* @return A reference to the file's import directory.
**/
template<int bits>
const ImportDirectory<bits>& PeFileT<bits>::impDir() const
{
return m_impdir;
}
/**
* @return A reference to the file's import directory.
**/
template<int bits>
ImportDirectory<bits>& PeFileT<bits>::impDir()
{
return m_impdir;
}
template<int bits>
const TlsDirectory<bits>& PeFileT<bits>::tlsDir() const
{
return m_tlsdir;
}
template<int bits>
TlsDirectory<bits>& PeFileT<bits>::tlsDir()
{
return m_tlsdir;
}
/**
* @return A reference to the file's delay import directory.
**/
template<int bits>
const DelayImportDirectory<bits>& PeFileT<bits>::delayImports() const
{
return m_delayimpdir;
}
/**
* @return A reference to the file's delay import directory.
**/
template<int bits>
DelayImportDirectory<bits>& PeFileT<bits>::delayImports()
{
return m_delayimpdir;
}
/**
* @return A reference to the file's export directory.
**/
template <int bits>
const ExportDirectoryT<bits>& PeFileT<bits>::expDir() const
{
return m_expdir;
}
/**
* @return A reference to the file's export directory.
**/
template <int bits>
ExportDirectoryT<bits>& PeFileT<bits>::expDir()
{
return m_expdir;
}
/**
* @return A reference to the file's bound import directory.
**/
template <int bits>
const BoundImportDirectoryT<bits>& PeFileT<bits>::boundImpDir() const
{
return m_boundimpdir;
}
/**
* @return A reference to the file's bound import directory.
**/
template <int bits>
BoundImportDirectoryT<bits>& PeFileT<bits>::boundImpDir()
{
return m_boundimpdir;
}
/**
* @return A reference to the file's resource directory.
**/
template <int bits>
const ResourceDirectoryT<bits>& PeFileT<bits>::resDir() const
{
return m_resdir;
}
/**
* @return A reference to the file's resource directory.
**/
template <int bits>
ResourceDirectoryT<bits>& PeFileT<bits>::resDir()
{
return m_resdir;
}
/**
* @return A reference to the file's relocations directory.
**/
template <int bits>
const RelocationsDirectoryT<bits>& PeFileT<bits>::relocDir() const
{
return m_relocs;
}
/**
* @return A reference to the file's relocations directory.
**/
template <int bits>
RelocationsDirectoryT<bits>& PeFileT<bits>::relocDir()
{
return m_relocs;
}
/**
* @return A reference to the file's COM+ descriptor directory.
**/
template <int bits>
const ComHeaderDirectoryT<bits>& PeFileT<bits>::comDir() const
{
return m_comdesc;
}
/**
* @return A reference to the file's COM+ descriptor directory.
**/
template <int bits>
ComHeaderDirectoryT<bits>& PeFileT<bits>::comDir()
{
return m_comdesc;
}
template <int bits>
const IatDirectoryT<bits>& PeFileT<bits>::iatDir() const
{
return m_iat;
}
template <int bits>
IatDirectoryT<bits>& PeFileT<bits>::iatDir()
{
return m_iat;
}
template <int bits>
const DebugDirectoryT<bits>& PeFileT<bits>::debugDir() const
{
return m_debugdir;
}
template <int bits>
DebugDirectoryT<bits>& PeFileT<bits>::debugDir()
{
return m_debugdir;
}
/**
* @return Filename of the current file.
**/
template<int bits>
std::string PeFileT<bits>::getFileName() const
{
return m_filename;
}
/**
* @param strFilename New filename.
**/
template<int bits>
void PeFileT<bits>::setFileName(std::string strFilename)
{
m_filename = strFilename;
if (m_ifStream.is_open())
{
m_ifStream.close();
}
m_ifStream.open(m_filename, std::ifstream::binary);
}
template<int bits>
int PeFileT<bits>::readMzHeader()
{
return mzHeader().read(m_iStream);
}
template<int bits>
int PeFileT<bits>::readRichHeader(
std::size_t offset,
std::size_t size,
bool ignoreInvalidKey)
{
return richHeader().read(m_iStream, offset, size, ignoreInvalidKey);
}
template<int bits>
int PeFileT<bits>::readCoffSymbolTable()
{
if (peHeader().getPointerToSymbolTable()
&& peHeader().getNumberOfSymbols())
{
return coffSymTab().read(
m_iStream,
static_cast<unsigned int>(peHeader().getPointerToSymbolTable()),
peHeader().getNumberOfSymbols() * PELIB_IMAGE_SIZEOF_COFF_SYMBOL);
}
return ERROR_COFF_SYMBOL_TABLE_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readExportDirectory()
{
if (peHeader().calcNumberOfRvaAndSizes() >= 1
&& peHeader().getIddExportRva())
{
return expDir().read(m_iStream, peHeader());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readImportDirectory()
{
if (peHeader().calcNumberOfRvaAndSizes() >= 2
&& peHeader().getIddImportRva())
{
return impDir().read(m_iStream, peHeader());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readResourceDirectory()
{
if (peHeader().calcNumberOfRvaAndSizes() >= 3
&& peHeader().getIddResourceRva())
{
return resDir().read(m_iStream, peHeader());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readSecurityDirectory()
{
if (peHeader().calcNumberOfRvaAndSizes() >= 5
&& peHeader().getIddSecurityRva()
&& peHeader().getIddSecuritySize())
{
return securityDir().read(
m_iStream,
peHeader().getIddSecurityRva(),
peHeader().getIddSecuritySize());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readRelocationsDirectory()
{
if (peHeader().calcNumberOfRvaAndSizes() >= 6
&& peHeader().getIddBaseRelocRva() && peHeader().getIddBaseRelocSize())
{
return relocDir().read(m_iStream, peHeader());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readDebugDirectory()
{
if (peHeader().calcNumberOfRvaAndSizes() >= 7
&& peHeader().getIddDebugRva() && peHeader().getIddDebugSize())
{
return debugDir().read(m_iStream, peHeader());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readTlsDirectory()
{
if (peHeader().calcNumberOfRvaAndSizes() >= 10
&& peHeader().getIddTlsRva() && peHeader().getIddTlsSize())
{
return tlsDir().read(m_iStream, peHeader());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readBoundImportDirectory()
{
if (peHeader().calcNumberOfRvaAndSizes() >= 12
&& peHeader().getIddBoundImportRva() && peHeader().getIddBoundImportSize())
{
return boundImpDir().read(m_iStream, peHeader());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readIatDirectory()
{
if (peHeader().calcNumberOfRvaAndSizes() >= 13
&& peHeader().getIddIatRva() && peHeader().getIddIatSize())
{
return iatDir().read(m_iStream, peHeader());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readDelayImportDirectory()
{
// Note: Delay imports can have arbitrary size and Windows loader will still load them
if (peHeader().calcNumberOfRvaAndSizes() >= 14 && peHeader().getIddDelayImportRva() /* && peHeader().getIddDelayImportSize() */)
{
return delayImports().read(m_iStream, peHeader());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
template<int bits>
int PeFileT<bits>::readComHeaderDirectory()
{
if (peHeader().calcNumberOfRvaAndSizes() >= 15
&& peHeader().getIddComHeaderRva() && peHeader().getIddComHeaderSize())
{
return comDir().read(m_iStream, peHeader());
}
return ERROR_DIRECTORY_DOES_NOT_EXIST;
}
// Returns an error code indicating loader problem. We check every part of the PE file
// for possible loader problem. If anything wrong was found, we report it
template<int bits>
LoaderError PeFileT<bits>::loaderError() const
{
LoaderError ldrError;
// Was there a problem in the DOS header?
ldrError = mzHeader().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
// Was there a problem in the NT headers?
ldrError = peHeader().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
// Check the loader error
ldrError = coffSymTab().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
// Check errors in import directory
ldrError = impDir().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
// Check errors in resource directory
ldrError = resDir().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
// Nothing wrond found
return LDR_ERROR_NONE;
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
/*
* PeLib.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef PELIB_H
#define PELIB_H
#include "pelib/PeFile.h"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
/*
* PeLibInc.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef STD_H
#define STD_H
#include <algorithm>
#include <climits>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include "pelib/PeLibAux.h"
#endif

View File

@ -0,0 +1,111 @@
/*
* Relocations.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef RELOCATIONSDIRECTORY_H
#define RELOCATIONSDIRECTORY_H
#include "pelib/PeHeader.h"
namespace PeLib
{
/// Class that handles the relocations directory.
/**
* This class handles the relocations directory.
**/
class RelocationsDirectory
{
protected:
std::vector<IMG_BASE_RELOC> m_vRelocations; ///< Used to store the relocation data.
void read(InputBuffer& inputbuffer, unsigned int uiSize);
public:
virtual ~RelocationsDirectory() = default;
/// Returns the number of relocations in the relocations directory.
unsigned int calcNumberOfRelocations() const; // EXPORT
/// Returns the number of relocation data entries of a specific relocation.
unsigned int calcNumberOfRelocationData(unsigned int ulRelocation) const; // EXPORT
/// Read a file's relocations directory.
int read(const unsigned char* buffer, unsigned int buffersize); // EXPORT
/// Returns the size of the relocations directory.
unsigned int size() const; // EXPORT
/// Returns the VA of a relocation.
dword getVirtualAddress(unsigned int ulRelocation) const; // EXPORT
/// Returns the SizeOfBlock value of a relocation.
dword getSizeOfBlock(unsigned int ulRelocation) const; // EXPORT
/// Returns the RelocationData of a relocation.
word getRelocationData(unsigned int ulRelocation, unsigned int ulDataNumber) const; // EXPORT
/// Changes the relocation data of a relocation.
void setRelocationData(unsigned int ulRelocation, unsigned int ulDataNumber, word wData); // EXPORT
/// Changes the VirtualAddress of a relocation.
void setVirtualAddress(unsigned int ulRelocation, dword dwValue); // EXPORT
/// Changes the SizeOfBlock of a relocation.
void setSizeOfBlock(unsigned int ulRelocation, dword dwValue); // EXPORT
void addRelocation(); // EXPORT
/// Adds new data to a relocation.
void addRelocationData(unsigned int ulRelocation, word wValue); // EXPORT
/// Removes data from a relocation.
// void removeRelocationData(unsigned int ulRelocation, word wValue); // EXPORT
void removeRelocation(unsigned int index); // EXPORT
void removeRelocationData(unsigned int relocindex, unsigned int dataindex); // EXPORT
};
template <int bits>
class RelocationsDirectoryT : public RelocationsDirectory
{
public:
/// Read a file's relocations directory.
int read(std::istream& inStream, const PeHeaderT<bits>& peHeader); // EXPORT
};
template <int bits>
int RelocationsDirectoryT<bits>::read(
std::istream& inStream,
const PeHeaderT<bits>& peHeader)
{
IStreamWrapper inStream_w(inStream);
std::uint64_t ulFileSize = fileSize(inStream_w);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
unsigned int uiOffset = peHeader.rvaToOffset(peHeader.getIddBaseRelocRva());
unsigned int uiSize = peHeader.getIddBaseRelocSize();
// If uiSize is big enough it can overflow after addition with uiOffset, ulFileSize < uiOffset + uiSize can be true,
// even though it should be false.
if ((ulFileSize < uiSize) || (ulFileSize < uiOffset + uiSize))
{
return ERROR_INVALID_FILE;
}
inStream_w.seekg(uiOffset, std::ios::beg);
std::vector<unsigned char> vRelocDirectory(uiSize);
inStream_w.read(reinterpret_cast<char*>(vRelocDirectory.data()), uiSize);
InputBuffer ibBuffer{vRelocDirectory};
RelocationsDirectory::read(ibBuffer, uiSize);
return ERROR_NONE;
}
}
#endif

View File

@ -0,0 +1,840 @@
/*
* ResourceDirectory.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef RESOURCEDIRECTORY_H
#define RESOURCEDIRECTORY_H
#include <set>
#include "pelib/PeLibInc.h"
#include "pelib/PeHeader.h"
namespace PeLib
{
class ResourceElement;
class ResourceDirectory;
template <int bits> class ResourceDirectoryT;
/// The class ResourceChild is used to store information about a resource node.
class ResourceChild
{
friend class ResourceElement;
friend class ResourceDirectory;
friend class ResourceNode;
friend class ResourceLeaf;
template <int bits> friend class ResourceDirectoryT;
/// Stores name and offset of a resource node.
PELIB_IMG_RES_DIR_ENTRY entry;
/// A pointer to one of the node's child nodes.
ResourceElement* child;
public:
/// Function which compares a resource ID to the node's resource ID.
bool equalId(dword wId) const; // EXPORT
/// Function which compares a string to the node's resource name.
bool equalName(std::string strName) const; // EXPORT
/// Predicate that determines if a child is identified by name or by ID.
bool isNamedResource() const; // EXPORT
/// Used for sorting a node's children.
bool operator<(const ResourceChild& rc) const; // EXPORT
/// A comparison function for searching a resource element by its ID.
bool hasEqual(dword id) const { return equalId(id); }
/// A comparison function for searching a resource element by its name.
bool hasEqual(const std::string& name) const { return equalName(name); }
/// Returns the node's number of children.
unsigned int getNumberOfChildren() const; // EXPORT
/// Returns a child of this child.
ResourceChild* getChildOfThisChild(std::size_t uiIndex); // EXPORT
const ResourceChild* getChildOfThisChild(std::size_t uiIndex) const; // EXPORT
/// Returns a pointer to ResourceElement.
ResourceElement* getNode();
const ResourceElement* getNode() const;
/// Sets a pointer to ResourceElement.
void setNode(ResourceElement* node);
/// Returns the name of the node.
std::string getName() const; // EXPORT
/// Returns the Name value of the node.
dword getOffsetToName() const; // EXPORT
/// Returns the OffsetToData value of the node.
dword getOffsetToData() const; // EXPORT
/// Sets the name of the node.
void setName(const std::string& strNewName); // EXPORT
/// Sets the Name value of the node.
void setOffsetToName(dword dwNewOffset); // EXPORT
/// Sets the OffsetToData value of the node.
void setOffsetToData(dword dwNewOffset); // EXPORT
/// Returns the size of a resource child.
// unsigned int size() const;
/// Standard constructor. Does absolutely nothing.
ResourceChild();
/// Makes a deep copy of a ResourceChild object.
ResourceChild(const ResourceChild& rhs);
/// Makes a deep copy of a ResourceChild object.
ResourceChild& operator=(const ResourceChild& rhs);
/// Deletes a ResourceChild object.
~ResourceChild();
};
/// Base class for ResourceNode and ResourceLeaf, the elements of the resource tree.
/// \todo write
class ResourceElement
{
friend class ResourceChild;
friend class ResourceNode;
friend class ResourceLeaf;
protected:
/// Stores RVA of the resource element in the file.
unsigned int uiElementRva;
/// Reads the next resource element from the InputBuffer.
virtual int read(std::istream&, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, ResourceDirectory* resDir) = 0;
/// Writes the next resource element into the OutputBuffer.
virtual void rebuild(OutputBuffer&, unsigned int, unsigned int, const std::string&) const = 0;
/// Recalculates the tree for different RVA.
virtual void recalculate(unsigned int& uiCurrentOffset, unsigned int uiNewRva) = 0;
public:
/// Returns the RVA of the element in the file.
unsigned int getElementRva() const; // EXPORT
/// Indicates if the resource element is a leaf or a node.
virtual bool isLeaf() const = 0; // EXPORT
/// Corrects erroneous values in the ResourceElement.
virtual void makeValid() = 0; // EXPORT
/// Returns the size of a resource element.
// virtual unsigned int size() const = 0;
/// Constructor
ResourceElement();
/// Necessary virtual destructor.
virtual ~ResourceElement() {}
};
/// ResourceLeafs represent the leafs of the resource tree: The actual resources.
class ResourceLeaf : public ResourceElement
{
friend class ResourceChild;
friend class ResourceDirectory;
template <typename T> friend struct fixNumberOfEntries;
template <int bits> friend class ResourceDirectoryT;
private:
/// The resource data.
std::vector<byte> m_data;
/// PeLib equivalent of the Win32 structure IMAGE_RESOURCE_DATA_ENTRY
PELIB_IMAGE_RESOURCE_DATA_ENTRY entry;
protected:
int read(std::istream& inStream, unsigned int uiRsrcOffset, unsigned int uiOffset, unsigned int uiRva, unsigned int uiFileSize, unsigned int uiSizeOfImage, ResourceDirectory* resDir);
/// Writes the next resource leaf into the OutputBuffer.
void rebuild(OutputBuffer&, unsigned int uiOffset, unsigned int uiRva, const std::string&) const;
/// Recalculates the tree for different RVA.
virtual void recalculate(unsigned int& uiCurrentOffset, unsigned int uiNewRva) override;
public:
/// Indicates if the resource element is a leaf or a node.
bool isLeaf() const; // EXPORT
/// Corrects erroneous values in the ResourceLeaf.
void makeValid(); // EXPORT
/// Reads the next resource leaf from the InputBuffer.
/// Returns the size of a resource lead.
// unsigned int size() const;
/// Returns the resource data of this resource leaf.
std::vector<byte> getData() const; // EXPORT
/// Sets the resource data of this resource leaf.
void setData(const std::vector<byte>& vData); // EXPORT
/// Returns the OffsetToData value of this resource leaf.
dword getOffsetToData() const; // EXPORT
/// Returns the Size value of this resource leaf.
dword getSize() const; // EXPORT
/// Returns the CodePage value of this resource leaf.
dword getCodePage() const; // EXPORT
/// Returns the Reserved value of this resource leaf.
dword getReserved() const; // EXPORT
/// Sets the OffsetToData value of this resource leaf.
void setOffsetToData(dword dwValue); // EXPORT
/// Sets the Size value of this resource leaf.
void setSize(dword dwValue); // EXPORT
/// Sets the CodePage value of this resource leaf.
void setCodePage(dword dwValue); // EXPORT
/// Sets the Reserved value of this resource leaf.
void setReserved(dword dwValue); // EXPORT
/// Constructor
ResourceLeaf();
/// Destructor
virtual ~ResourceLeaf() override;
};
/// ResourceNodes represent the nodes in the resource tree.
class ResourceNode : public ResourceElement
{
friend class ResourceChild;
friend class ResourceDirectory;
template <typename T> friend struct fixNumberOfEntries;
template <int bits> friend class ResourceDirectoryT;
/// The node's children.
std::vector<ResourceChild> children;
/// The node's header. Equivalent to IMAGE_RESOURCE_DIRECTORY from the Win32 API.
PELIB_IMAGE_RESOURCE_DIRECTORY header;
protected:
/// Reads the next resource node.
int read(std::istream& inStream, unsigned int uiRsrcOffset, unsigned int uiOffset, unsigned int uiRva, unsigned int uiFileSize, unsigned int uiSizeOfImage, ResourceDirectory* resDir);
/// Writes the next resource node into the OutputBuffer.
void rebuild(OutputBuffer&, unsigned int uiOffset, unsigned int uiRva, const std::string&) const;
/// Recalculates the tree for different RVA.
virtual void recalculate(unsigned int& uiCurrentOffset, unsigned int uiNewRva) override;
public:
/// Indicates if the resource element is a leaf or a node.
bool isLeaf() const; // EXPORT
/// Corrects erroneous values in the ResourceNode.
void makeValid(); // EXPORT
/// Returns the node's number of children.
unsigned int getNumberOfChildren() const; // EXPORT
/// Adds another child to node.
ResourceChild* addChild(); // EXPORT
/// Returns a node's child.
ResourceChild* getChild(std::size_t uiIndex); // EXPORT
const ResourceChild* getChild(std::size_t uiIndex) const; // EXPORT
/// Removes a node's child.
void removeChild(unsigned int uiIndex); // EXPORT
/// Returns the name of one of the node's children.
std::string getChildName(unsigned int uiIndex) const; // EXPORT
/// Returns the Name value of one of the node's children.
dword getOffsetToChildName(unsigned int uiIndex) const; // EXPORT
/// Returns the OffsetToData value of one of the node's children.
dword getOffsetToChildData(unsigned int uiIndex) const; // EXPORT
/// Sets the name of one of the node's children.
void setChildName(unsigned int uiIndex, const std::string& strNewName); // EXPORT
/// Sets the Name value of one of the node's children.
void setOffsetToChildName(unsigned int uiIndex, dword dwNewOffset); // EXPORT
/// Sets the OffsetToData value of one of the node's children.
void setOffsetToChildData(unsigned int uiIndex, dword dwNewOffset); // EXPORT
/// Returns the node's Characteristics value.
dword getCharacteristics() const; // EXPORT
/// Returns the node's TimeDateStamp value.
dword getTimeDateStamp() const; // EXPORT
/// Returns the node's MajorVersion value.
word getMajorVersion() const; // EXPORT
/// Returns the node's MinorVersion value.
word getMinorVersion() const; // EXPORT
/// Returns the node's NumberOfNamedEntries value.
word getNumberOfNamedEntries() const; // EXPORT
/// Returns the node's NumberOfIdEntries value.
word getNumberOfIdEntries() const; // EXPORT
/// Sets the node's Characteristics value.
void setCharacteristics(dword value); // EXPORT
/// Sets the node's TimeDateStamp value.
void setTimeDateStamp(dword value); // EXPORT
/// Sets the node's MajorVersion value.
void setMajorVersion(word value); // EXPORT
/// Sets the node's MinorVersion value.
void setMinorVersion(word value); // EXPORT
/// Sets the node's NumberOfNamedEntries value.
void setNumberOfNamedEntries(word value); // EXPORT
/// Sets the node's NumberOfIdEntries value.
void setNumberOfIdEntries(word value); // EXPORT
/// Returns the size of a resource node.
// unsigned int size() const;
/// Constructor
ResourceNode();
/// Destructor
virtual ~ResourceNode() override;
};
/// Unspecialized function that's used as base template for the specialized versions below.
template<typename T>
struct fixNumberOfEntries
{
/// Fixes a resource node's header.
static void fix(ResourceNode*);
};
/// Fixes NumberOfIdEntries value of a node.
template<>
struct fixNumberOfEntries<dword>
{
/// Fixes a resource node's NumberOfIdEntries value.
static void fix(ResourceNode* node)
{
node->header.NumberOfIdEntries = static_cast<PeLib::word>(
node->children.size() - std::count_if(
node->children.begin(),
node->children.end(),
[](const auto& i) { return i.isNamedResource(); }
)
);
}
};
/// Fixes NumberOfNamedEntries value of a node.
template<>
struct fixNumberOfEntries<std::string>
{
/// Fixes a resource node's NumberOfNamedEntries value.
static void fix(ResourceNode* node)
{
node->header.NumberOfNamedEntries = static_cast<PeLib::word>(
std::count_if(
node->children.begin(),
node->children.end(),
[](const auto& i) { return i.isNamedResource(); }
)
);
}
};
/// Class that represents the resource directory of a PE file.
/**
* The class ResourceDirectory represents the resource directory of a PE file. This class is fundamentally
* different from the other classes of the PeLib library due to the structure of the ResourceDirectory.
* For once, it's possible to manipulate the ResourceDirectory through a set of "high level" functions and
* and through a set of "low level" functions. The "high level" functions are the functions inside the
* ResourceDirectory class with the exception of getRoot.<br><br>
* getRoot on the other hand is the first "low level" function. Use it to retrieve the root node of the
* resource tree. Then you can traverse through the tree and manipulate individual nodes and leafs
* directly using the functions provided by the classes ResourceNode and ResourceLeaf.<br><br>
* There's another difference between the ResourceDirectory class and the other PeLib classes, which is
* once again caused by the special structure of the PE resource directory. The nodes of the resource
* tree must be in a certain order. Manipulating the resource tree does not directly sort the nodes
* correctly as this would cause more trouble than it fixes. That means it's your responsibility to
* fix the resource tree after manipulating it. PeLib makes the job easy for you, just call the
* ResourceDirectory<bits>::makeValid function.<br><br>
* You might also wonder why there's no size() function in this class. I did not forget it. It's just
* that it's impossible to calculate the size of the resource directory without rebuilding it. So why
* should PeLib do this if you can do it just as easily by calling rebuild() and then checking the length
* of the returned vector.<br><br>
* There are also different ways to serialize (rebuild) the resource tree as it's not a fixed structure
* that can easily be minimized like most other PE directories.<br><br>
* This means it's entirely possible that the resource tree you read from a file differs from the one
* PeLib creates. This might cause a minor issue. The original resource tree might be smaller (due to
* different padding) so it's crucial that you check if there's enough space in the original resource
* directory before you write the rebuilt resource directory back to the file.
**/
class ResourceDirectory
{
protected:
/// Start offset of directory in file.
unsigned int m_readOffset;
/// The root node of the resource directory.
ResourceNode m_rnRoot;
/// Detection of invalid structure of nodes in directory.
std::set<std::size_t> m_resourceNodeOffsets;
/// Stores RVAs which are occupied by this export directory.
std::vector<std::pair<unsigned int, unsigned int>> m_occupiedAddresses;
/// Error detected by the import table parser
LoaderError m_ldrError;
// Prepare for some crazy syntax below to make Digital Mars happy.
/// Retrieves an iterator to a specified resource child.
template<typename S, typename T>
std::vector<ResourceChild>::const_iterator locateResourceT(S restypeid, T resid) const;
/// Retrieves an iterator to a specified resource child.
template<typename S, typename T>
std::vector<ResourceChild>::iterator locateResourceT(S restypeid, T resid);
/// Adds a new resource.
template<typename S, typename T>
int addResourceT(S restypeid, T resid, ResourceChild& rc);
/// Removes new resource.
template<typename S, typename T>
int removeResourceT(S restypeid, T resid);
/// Returns the data of a resource.
template<typename S, typename T>
int getResourceDataT(S restypeid, T resid, std::vector<byte>& data) const;
/// Sets the data of a resource.
template<typename S, typename T>
int setResourceDataT(S restypeid, T resid, std::vector<byte>& data);
/// Returns the ID of a resource.
template<typename S, typename T>
dword getResourceIdT(S restypeid, T resid) const;
/// Sets the ID of a resource.
template<typename S, typename T>
int setResourceIdT(S restypeid, T resid, dword dwNewResId);
/// Returns the name of a resource.
template<typename S, typename T>
std::string getResourceNameT(S restypeid, T resid) const;
/// Sets the name of a resource.
template<typename S, typename T>
int setResourceNameT(S restypeid, T resid, std::string strNewResName);
public:
/// Constructor
ResourceDirectory();
/// Destructor
virtual ~ResourceDirectory() = default;
ResourceNode* getRoot();
const ResourceNode* getRoot() const;
/// Retrieve the loader error
LoaderError loaderError() const;
void setLoaderError(LoaderError ldrError);
/// Corrects a erroneous resource directory.
void makeValid();
/// Rebuilds the resource directory.
void rebuild(std::vector<byte>& vBuffer, unsigned int uiRva) const;
/// Recalculate the tree for different RVA
void recalculate(unsigned int& uiNewSize, unsigned int uiNewRva);
/// Returns the size of the rebuilt resource directory.
// unsigned int size() const;
/// Writes the resource directory to a file.
int write(const std::string& strFilename, unsigned int uiOffset, unsigned int uiRva) const;
/// Adds a new resource type.
int addResourceType(dword dwResTypeId);
/// Adds a new resource type.
int addResourceType(const std::string& strResTypeName);
/// Removes a resource type and all of it's resources.
int removeResourceType(dword dwResTypeId);
/// Removes a resource type and all of it's resources.
int removeResourceType(const std::string& strResTypeName);
/// Removes a resource type and all of it's resources.
int removeResourceTypeByIndex(unsigned int uiIndex);
/// Adds a new resource.
int addResource(dword dwResTypeId, dword dwResId);
/// Adds a new resource.
int addResource(dword dwResTypeId, const std::string& strResName);
/// Adds a new resource.
int addResource(const std::string& strResTypeName, dword dwResId);
/// Adds a new resource.
int addResource(const std::string& strResTypeName, const std::string& strResName);
/// Removes a resource.
int removeResource(dword dwResTypeId, dword dwResId);
/// Removes a resource.
int removeResource(dword dwResTypeId, const std::string& strResName);
/// Removes a resource.
int removeResource(const std::string& strResTypeName, dword dwResId);
/// Removes a resource.
int removeResource(const std::string& strResTypeName, const std::string& strResName);
/// Returns start offset of resource directory in file.
unsigned int getOffset() const;
/// Returns the number of resource types.
unsigned int getNumberOfResourceTypes() const;
/// Returns the ID of a resource type.
dword getResourceTypeIdByIndex(unsigned int uiIndex) const;
/// Returns the name of a resource type.
std::string getResourceTypeNameByIndex(unsigned int uiIndex) const;
/// Converts a resource type ID to an index.
int resourceTypeIdToIndex(dword dwResTypeId) const;
/// Converts a resource type name to an index.
int resourceTypeNameToIndex(const std::string& strResTypeName) const;
/// Returns the number of resources of a certain resource type.
unsigned int getNumberOfResources(dword dwId) const;
/// Returns the number of resources of a certain resource type.
unsigned int getNumberOfResources(const std::string& strResTypeName) const;
/// Returns the number of resources of a certain resource type.
unsigned int getNumberOfResourcesByIndex(unsigned int uiIndex) const;
/// Returns the data of a certain resource.
void getResourceData(dword dwResTypeId, dword dwResId, std::vector<byte>& data) const;
/// Returns the data of a certain resource.
void getResourceData(dword dwResTypeId, const std::string& strResName, std::vector<byte>& data) const;
/// Returns the data of a certain resource.
void getResourceData(const std::string& strResTypeName, dword dwResId, std::vector<byte>& data) const;
/// Returns the data of a certain resource.
void getResourceData(const std::string& strResTypeName, const std::string& strResName, std::vector<byte>& data) const;
/// Returns the data of a certain resource.
void getResourceDataByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex, std::vector<byte>& data) const;
/// Sets the data of a certain resource.
void setResourceData(dword dwResTypeId, dword dwResId, std::vector<byte>& data);
/// Sets the data of a certain resource.
void setResourceData(dword dwResTypeId, const std::string& strResName, std::vector<byte>& data);
/// Sets the data of a certain resource.
void setResourceData(const std::string& strResTypeName, dword dwResId, std::vector<byte>& data);
/// Sets the data of a certain resource.
void setResourceData(const std::string& strResTypeName, const std::string& strResName, std::vector<byte>& data);
/// Sets the data of a certain resource.
void setResourceDataByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex, std::vector<byte>& data);
/// Returns the ID of a certain resource.
dword getResourceId(dword dwResTypeId, const std::string& strResName) const;
/// Returns the ID of a certain resource.
dword getResourceId(const std::string& strResTypeName, const std::string& strResName) const;
/// Returns the ID of a certain resource.
dword getResourceIdByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex) const;
/// Sets the ID of a certain resource.
void setResourceId(dword dwResTypeId, dword dwResId, dword dwNewResId);
/// Sets the ID of a certain resource.
void setResourceId(dword dwResTypeId, const std::string& strResName, dword dwNewResId);
/// Sets the ID of a certain resource.
void setResourceId(const std::string& strResTypeName, dword dwResId, dword dwNewResId);
/// Sets the ID of a certain resource.
void setResourceId(const std::string& strResTypeName, const std::string& strResName, dword dwNewResId);
/// Sets the ID of a certain resource.
void setResourceIdByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex, dword dwNewResId);
/// Returns the name of a certain resource.
std::string getResourceName(dword dwResTypeId, dword dwResId) const;
/// Returns the name of a certain resource.
std::string getResourceName(const std::string& strResTypeName, dword dwResId) const;
/// Returns the name of a certain resource.
std::string getResourceNameByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex) const;
/// Sets the name of a certain resource.
void setResourceName(dword dwResTypeId, dword dwResId, const std::string& strNewResName);
/// Sets the name of a certain resource.
void setResourceName(dword dwResTypeId, const std::string& strResName, const std::string& strNewResName);
/// Sets the name of a certain resource.
void setResourceName(const std::string& strResTypeName, dword dwResId, const std::string& strNewResName);
/// Sets the name of a certain resource.
void setResourceName(const std::string& strResTypeName, const std::string& strResName, const std::string& strNewResName);
/// Sets the name of a certain resource.
void setResourceNameByIndex(unsigned int uiResTypeIndex, unsigned int uiResIndex, const std::string& strNewResName);
/// Insert offset of loaded node.
void insertNodeOffset(std::size_t nodeOffset);
/// Check if node with specified offset was loaded.
bool hasNodeOffset(std::size_t nodeOffset) const;
void addOccupiedAddressRange(unsigned int start, unsigned int end);
const std::vector<std::pair<unsigned int, unsigned int>>& getOccupiedAddresses() const;
};
/**
* Looks through the entire resource tree and returns a const_iterator to the resource specified
* by the parameters.
* @param restypeid Identifier of the resource type (either ID or name).
* @param resid Identifier of the resource (either ID or name).
* @return A const_iterator to the specified resource.
**/
template<typename S, typename T>
std::vector<ResourceChild>::const_iterator ResourceDirectory::locateResourceT(S restypeid, T resid) const
{
auto Iter = std::find_if(
m_rnRoot.children.begin(),
m_rnRoot.children.end(),
[&](const auto& res) { return res.hasEqual(restypeid); }
);
if (Iter == m_rnRoot.children.end())
{
return Iter;
}
ResourceNode* currNode = static_cast<ResourceNode*>(Iter->child);
auto ResIter = std::find_if(
currNode->children.begin(),
currNode->children.end(),
[&](const auto& res) { return res.hasEqual(resid); }
);
if (ResIter == currNode->children.end())
{
return ResIter;
}
return ResIter;
}
/**
* Looks through the entire resource tree and returns an iterator to the resource specified
* by the parameters.
* @param restypeid Identifier of the resource type (either ID or name).
* @param resid Identifier of the resource (either ID or name).
* @return An iterator to the specified resource.
**/
template<typename S, typename T>
std::vector<ResourceChild>::iterator ResourceDirectory::locateResourceT(S restypeid, T resid)
{
auto Iter = std::find_if(
m_rnRoot.children.begin(),
m_rnRoot.children.end(),
[&](const auto& res) { return res.hasEqual(restypeid); }
);
if (Iter == m_rnRoot.children.end())
{
return Iter;
}
ResourceNode* currNode = static_cast<ResourceNode*>(Iter->child);
auto ResIter = std::find_if(
currNode->children.begin(),
currNode->children.end(),
[&](const auto& res) { return res.hasEqual(resid); }
);
if (ResIter == currNode->children.end())
{
return ResIter;
}
return ResIter;
}
/**
* Adds a new resource, resource type and ID are specified by the parameters.
* @param restypeid Identifier of the resource type (either ID or name).
* @param resid Identifier of the resource (either ID or name).
* @param rc ResourceChild that will be added.
**/
template<typename S, typename T>
int ResourceDirectory::addResourceT(S restypeid, T resid, ResourceChild& rc)
{
auto Iter = std::find_if(
m_rnRoot.children.begin(),
m_rnRoot.children.end(),
[&](const auto& res) { return res.hasEqual(restypeid); }
);
if (Iter == m_rnRoot.children.end())
{
return ERROR_ENTRY_NOT_FOUND;
// throw Exceptions::ResourceTypeDoesNotExist(ResourceDirectoryId, __LINE__);
}
ResourceNode* currNode = static_cast<ResourceNode*>(Iter->child);
auto ResIter = std::find_if(
currNode->children.begin(),
currNode->children.end(),
[&](const auto& res) { return res.hasEqual(resid); }
);
if (ResIter != currNode->children.end())
{
return ERROR_DUPLICATE_ENTRY;
// throw Exceptions::EntryAlreadyExists(ResourceDirectoryId, __LINE__);
}
rc.child = new ResourceNode;
ResourceChild rlnew;
rlnew.child = new ResourceLeaf;
ResourceNode* currNode2 = static_cast<ResourceNode*>(rc.child);
currNode2->children.push_back(rlnew);
currNode->children.push_back(rc);
fixNumberOfEntries<T>::fix(currNode);
fixNumberOfEntries<T>::fix(currNode2);
return ERROR_NONE;
}
/**
* Removes a resource, resource type and ID are specified by the parameters.
* @param restypeid Identifier of the resource type (either ID or name).
* @param resid Identifier of the resource (either ID or name).
**/
template<typename S, typename T>
int ResourceDirectory::removeResourceT(S restypeid, T resid)
{
auto Iter = std::find_if(
m_rnRoot.children.begin(),
m_rnRoot.children.end(),
[&](const auto& res) { return res.hasEqual(restypeid); }
);
if (Iter == m_rnRoot.children.end())
{
return ERROR_ENTRY_NOT_FOUND;
//throw Exceptions::ResourceTypeDoesNotExist(ResourceDirectoryId, __LINE__);
}
ResourceNode* currNode = static_cast<ResourceNode*>(Iter->child);
auto ResIter = std::find_if(
currNode->children.begin(),
currNode->children.end(),
[&](const auto& res) { return res.hasEqual(resid); }
);
if (ResIter == currNode->children.end())
{
return ERROR_ENTRY_NOT_FOUND;
// throw Exceptions::InvalidName(ResourceDirectoryId, __LINE__);
}
currNode->children.erase(ResIter);
fixNumberOfEntries<T>::fix(currNode);
return ERROR_NONE;
}
/**
* Returns the data of a resource, resource type and ID are specified by the parameters.
* @param restypeid Identifier of the resource type (either ID or name).
* @param resid Identifier of the resource (either ID or name).
* @param data The data of the resource will be written into this vector.
**/
template<typename S, typename T>
int ResourceDirectory::getResourceDataT(S restypeid, T resid, std::vector<byte>& data) const
{
std::vector<ResourceChild>::const_iterator ResIter = locateResourceT(restypeid, resid);
ResourceNode* currNode = static_cast<ResourceNode*>(ResIter->child);
ResourceLeaf* currLeaf = static_cast<ResourceLeaf*>(currNode->children[0].child);
data.assign(currLeaf->m_data.begin(), currLeaf->m_data.end());
return ERROR_NONE;
}
/**
* Sets the data of a resource, resource type and ID are specified by the parameters.
* @param restypeid Identifier of the resource type (either ID or name).
* @param resid Identifier of the resource (either ID or name).
* @param data The new data of the resource is taken from this vector.
**/
template<typename S, typename T>
int ResourceDirectory::setResourceDataT(S restypeid, T resid, std::vector<byte>& data)
{
std::vector<ResourceChild>::iterator ResIter = locateResourceT(restypeid, resid);
ResourceNode* currNode = static_cast<ResourceNode*>(ResIter->child);
ResourceLeaf* currLeaf = static_cast<ResourceLeaf*>(currNode->children[0].child);
currLeaf->m_data.assign(data.begin(), data.end());
return ERROR_NONE;
}
/**
* Returns the id of a resource, resource type and ID are specified by the parameters.
* Note: Calling this function with resid == the ID of the resource makes no sense at all.
* @param restypeid Identifier of the resource type (either ID or name).
* @param resid Identifier of the resource (either ID or name).
* @return The ID of the specified resource.
**/
template<typename S, typename T>
dword ResourceDirectory::getResourceIdT(S restypeid, T resid) const
{
std::vector<ResourceChild>::const_iterator ResIter = locateResourceT(restypeid, resid);
return ResIter->entry.irde.Name;
}
/**
* Sets the id of a resource, resource type and ID are specified by the parameters.
* @param restypeid Identifier of the resource type (either ID or name).
* @param resid Identifier of the resource (either ID or name).
* @param dwNewResId New ID of the resource.
**/
template<typename S, typename T>
int ResourceDirectory::setResourceIdT(S restypeid, T resid, dword dwNewResId)
{
std::vector<ResourceChild>::iterator ResIter = locateResourceT(restypeid, resid);
ResIter->entry.irde.Name = dwNewResId;
return ERROR_NONE;
}
/**
* Returns the name of a resource, resource type and ID are specified by the parameters.
* Note: Calling this function with resid == the name of the resource makes no sense at all.
* @param restypeid Identifier of the resource type (either ID or name).
* @param resid Identifier of the resource (either ID or name).
* @return The name of the specified resource.
**/
template<typename S, typename T>
std::string ResourceDirectory::getResourceNameT(S restypeid, T resid) const
{
std::vector<ResourceChild>::const_iterator ResIter = locateResourceT(restypeid, resid);
return ResIter->entry.wstrName;
}
/**
* Sets the name of a resource, resource type and ID are specified by the parameters.
* @param restypeid Identifier of the resource type (either ID or name).
* @param resid Identifier of the resource (either ID or name).
* @param strNewResName The new name of the resource.
**/
template<typename S, typename T>
int ResourceDirectory::setResourceNameT(S restypeid, T resid, std::string strNewResName)
{
std::vector<ResourceChild>::iterator ResIter = locateResourceT(restypeid, resid);
ResIter->entry.wstrName = strNewResName;
return ERROR_NONE;
}
template <int bits>
class ResourceDirectoryT : public ResourceDirectory
{
public:
/// Reads the resource directory from a file.
int read(std::istream& inStream, const PeHeaderT<bits>& peHeader);
};
/**
* Reads the resource directory from a file.
* @param inStream Input stream.
* @param peHeader A valid PE header which is necessary because some RVA
* calculations need to be done.
**/
template <int bits>
int ResourceDirectoryT<bits>::read(
std::istream& inStream,
const PeHeaderT<bits>& peHeader)
{
unsigned int uiResDirRva = peHeader.getIddResourceRva();
unsigned int uiOffset = peHeader.rvaToOffset(uiResDirRva);
m_resourceNodeOffsets.clear();
m_readOffset = uiOffset;
if (!uiOffset)
{
return ERROR_INVALID_FILE;
}
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
std::uint64_t ulFileSize = fileSize(inStream_w);
if (ulFileSize < uiOffset)
{
return ERROR_INVALID_FILE;
}
inStream_w.seekg(uiOffset, std::ios::beg);
return m_rnRoot.read(inStream_w, uiOffset, 0, uiResDirRva, ulFileSize, peHeader.getSizeOfImage(), this);
}
}
#endif

View File

@ -0,0 +1,56 @@
/**
* @file RichHeader.h
* @brief Class for rich header.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RICHHEADER_H
#define RICHHEADER_H
#include <cstdint>
#include <vector>
namespace PeLib
{
/**
* This class handless rich header.
*/
class RichHeader
{
public:
typedef std::vector<PELIB_IMAGE_RICH_HEADER_RECORD>::const_iterator richHeaderIterator;
private:
bool headerIsValid;
bool validStructure;
dword key;
std::size_t noOfIters;
std::vector<dword> decryptedHeader;
std::vector<PELIB_IMAGE_RICH_HEADER_RECORD> records;
void init();
void setValidStructure();
bool analyze(bool ignoreInvalidKey = false);
void read(InputBuffer& inputbuffer, std::size_t uiSize, bool ignoreInvalidKey);
public:
RichHeader();
~RichHeader();
int read(
std::istream& inStream,
std::size_t uiOffset,
std::size_t uiSize,
bool ignoreInvalidKey);
bool isHeaderValid() const;
bool isStructureValid() const;
std::size_t getNumberOfIterations() const;
dword getKey() const;
const dword* getDecryptedHeaderItem(std::size_t index) const;
std::string getDecryptedHeaderItemSignature(std::size_t index) const;
std::string getDecryptedHeaderItemsSignature(std::initializer_list<std::size_t> indexes) const;
std::vector<std::uint8_t> getDecryptedHeaderBytes() const;
richHeaderIterator begin() const;
richHeaderIterator end() const;
};
}
#endif

View File

@ -0,0 +1,31 @@
/**
* @file SecurityDirectory.h
* @brief Class for certificate directory.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef SECURITYDIRECTORY_H
#define SECURITYDIRECTORY_H
#include "pelib/PeHeader.h"
namespace PeLib
{
class SecurityDirectory
{
private:
std::vector<PELIB_IMAGE_CERTIFICATE_ENTRY> m_certs;
public:
/// Number of certificates in the directory.
unsigned int calcNumberOfCertificates() const; // EXPORT
/// Returns certificate at specified index.
const std::vector<unsigned char>& getCertificate(std::size_t index) const; // EXPORT
/// Read a file's certificate directory.
int read(
std::istream& inStream,
unsigned int uiOffset,
unsigned int uiSize); // EXPORT
};
}
#endif

View File

@ -0,0 +1,309 @@
/*
* TlsDirectory.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#ifndef TLSDIRECTORY_H
#define TLSDIRECTORY_H
#include "pelib/PeHeader.h"
namespace PeLib
{
/// Class that handles the TLS directory.
/**
* This class handles the TLS (Thread Local Storage) directory.
**/
template<int bits>
class TlsDirectory
{
private:
PELIB_IMAGE_TLS_DIRECTORY<bits> m_tls; ///< Structure that holds all information about the directory.
void read(InputBuffer& inputbuffer);
public:
/// Reads a file's TLS directory.
int read(std::istream& inStream, const PeHeaderT<bits> &peHeader); // EXPORT
int read(unsigned char* buffer, unsigned int buffersize); // EXPORT
/// Rebuilds the TLS directory.
void rebuild(std::vector<byte>& vBuffer) const; // EXPORT
/// Returns the size of the TLS Directory.
unsigned int size() const; // EXPORT
/// Writes the TLS directory to a file.
int write(const std::string& strFilename, unsigned int dwOffset) const; // EXPORT
/// Returns the StartAddressOfRawData value of the TLS header.
typename FieldSizes<bits>::VAR4_8 getStartAddressOfRawData() const; // EXPORT
/// Returns the EndAddressOfRawData value of the TLS header.
typename FieldSizes<bits>::VAR4_8 getEndAddressOfRawData() const; // EXPORT
/// Returns the AddressOfIndex value of the TLS header.
typename FieldSizes<bits>::VAR4_8 getAddressOfIndex() const; // EXPORT
/// Returns the AddressOfCallBacks value of the TLS header.
typename FieldSizes<bits>::VAR4_8 getAddressOfCallBacks() const; // EXPORT
/// Returns the SizeOfZeroFill value of the TLS header.
dword getSizeOfZeroFill() const; // EXPORT
/// Returns the Characteristics value of the TLS header.
dword getCharacteristics() const; // EXPORT
/// Sets the StartAddressOfRawData value of the TLS header.
void setStartAddressOfRawData(dword dwValue); // EXPORT
/// Sets the EndAddressOfRawData value of the TLS header.
void setEndAddressOfRawData(dword dwValue); // EXPORT
/// Sets the AddressOfIndex value of the TLS header.
void setAddressOfIndex(dword dwValue); // EXPORT
/// Sets the AddressOfCallBacks value of the TLS header.
void setAddressOfCallBacks(dword dwValue); // EXPORT
/// Sets the SizeOfZeroFill value of the TLS header.
void setSizeOfZeroFill(dword dwValue); // EXPORT
/// Sets the Characteristics value of the TLS header.
void setCharacteristics(dword dwValue); // EXPORT
};
template<int bits>
void TlsDirectory<bits>::read(InputBuffer& inputBuffer)
{
PELIB_IMAGE_TLS_DIRECTORY<bits> itdCurr;
inputBuffer >> itdCurr.StartAddressOfRawData;
inputBuffer >> itdCurr.EndAddressOfRawData;
inputBuffer >> itdCurr.AddressOfIndex;
inputBuffer >> itdCurr.AddressOfCallBacks;
inputBuffer >> itdCurr.SizeOfZeroFill;
inputBuffer >> itdCurr.Characteristics;
std::swap(itdCurr, m_tls);
}
template<int bits>
int TlsDirectory<bits>::read(unsigned char* buffer, unsigned int buffersize)
{
if (buffersize < PELIB_IMAGE_TLS_DIRECTORY<bits>::size())
{
return ERROR_INVALID_FILE;
}
std::vector<byte> vTlsDirectory(buffer, buffer + buffersize);
InputBuffer ibBuffer(vTlsDirectory);
read(ibBuffer);
return ERROR_NONE;
}
/**
* Reads a file's TLS directory.
* @param inStream Input stream.
* @param peHeader A valid PE header.
**/
template<int bits>
int TlsDirectory<bits>::read(std::istream& inStream, const PeHeaderT<bits> &peHeader)
{
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
std::uint64_t ulFileSize = fileSize(inStream_w);
std::uint64_t uiOffset = peHeader.rvaToOffset(peHeader.getIddTlsRva());
unsigned int uiSize = peHeader.getIddTlsSize();
if (ulFileSize < uiOffset + uiSize)
{
return ERROR_INVALID_FILE;
}
inStream_w.seekg(uiOffset, std::ios::beg);
std::vector<byte> vTlsDirectory(uiSize);
inStream_w.read(reinterpret_cast<char*>(vTlsDirectory.data()), uiSize);
InputBuffer ibBuffer{vTlsDirectory};
read(ibBuffer);
return ERROR_NONE;
}
/**
* Rebuilds the current TLS Directory.
* @param vBuffer Buffer where the TLS directory will be written to.
**/
template<int bits>
void TlsDirectory<bits>::rebuild(std::vector<byte>& vBuffer) const
{
OutputBuffer obBuffer(vBuffer);
obBuffer << m_tls.StartAddressOfRawData;
obBuffer << m_tls.EndAddressOfRawData;
obBuffer << m_tls.AddressOfIndex;
obBuffer << m_tls.AddressOfCallBacks;
obBuffer << m_tls.SizeOfZeroFill;
obBuffer << m_tls.Characteristics;
}
/**
* Returns the size of the TLS directory. Due to the static nature of this structure the return value
* will always be 24.
* @return Size in bytes.
**/
template<int bits>
unsigned int TlsDirectory<bits>::size() const
{
return PELIB_IMAGE_TLS_DIRECTORY<bits>::size();
}
/**
* @param strFilename Name of the file.
* @param dwOffset File offset the TLS Directory will be written to.
**/
template<int bits>
int TlsDirectory<bits>::write(const std::string& strFilename, unsigned int dwOffset) const
{
std::fstream ofFile(strFilename.c_str(), std::ios_base::in);
if (!ofFile)
{
ofFile.clear();
ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary);
}
else
{
ofFile.close();
ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
}
if (!ofFile)
{
return ERROR_OPENING_FILE;
}
ofFile.seekp(dwOffset, std::ios::beg);
std::vector<unsigned char> vBuffer;
rebuild(vBuffer);
ofFile.write(reinterpret_cast<const char*>(vBuffer.data()), vBuffer.size());
ofFile.close();
return ERROR_NONE;
}
/**
* @return The StartAddressOfRawData value of the TLS directory.
**/
template<int bits>
typename FieldSizes<bits>::VAR4_8 TlsDirectory<bits>::getStartAddressOfRawData() const
{
return m_tls.StartAddressOfRawData;
}
/**
* @return The EndAddressOfRawData value of the TLS directory.
**/
template<int bits>
typename FieldSizes<bits>::VAR4_8 TlsDirectory<bits>::getEndAddressOfRawData() const
{
return m_tls.EndAddressOfRawData;
}
/**
* @return The AddressOfIndex value of the TLS directory.
**/
template<int bits>
typename FieldSizes<bits>::VAR4_8 TlsDirectory<bits>::getAddressOfIndex() const
{
return m_tls.AddressOfIndex;
}
/**
* @return The AddressOfCallBacks value of the TLS directory.
**/
template<int bits>
typename FieldSizes<bits>::VAR4_8 TlsDirectory<bits>::getAddressOfCallBacks() const
{
return m_tls.AddressOfCallBacks;
}
/**
* @return The SizeOfZeroFill value of the TLS directory.
**/
template<int bits>
dword TlsDirectory<bits>::getSizeOfZeroFill() const
{
return m_tls.SizeOfZeroFill;
}
/**
* @return The Characteristics value of the TLS directory.
**/
template<int bits>
dword TlsDirectory<bits>::getCharacteristics() const
{
return m_tls.Characteristics;
}
/**
* @param dwValue The new StartAddressOfRawData value of the TLS directory.
**/
template<int bits>
void TlsDirectory<bits>::setStartAddressOfRawData(dword dwValue)
{
m_tls.StartAddressOfRawData = dwValue;
}
/**
* @param dwValue The new EndAddressOfRawData value of the TLS directory.
**/
template<int bits>
void TlsDirectory<bits>::setEndAddressOfRawData(dword dwValue)
{
m_tls.EndAddressOfRawData = dwValue;
}
/**
* @param dwValue The new AddressOfIndex value of the TLS directory.
**/
template<int bits>
void TlsDirectory<bits>::setAddressOfIndex(dword dwValue)
{
m_tls.AddressOfIndex = dwValue;
}
/**
* @param dwValue The new AddressOfCallBacks value of the TLS directory.
**/
template<int bits>
void TlsDirectory<bits>::setAddressOfCallBacks(dword dwValue)
{
m_tls.AddressOfCallBacks = dwValue;
}
/**
* @param dwValue The new SizeOfZeroFill value of the TLS directory.
**/
template<int bits>
void TlsDirectory<bits>::setSizeOfZeroFill(dword dwValue)
{
m_tls.SizeOfZeroFill = dwValue;
}
/**
* @param dwValue The new Characteristics value of the TLS directory.
**/
template<int bits>
void TlsDirectory<bits>::setCharacteristics(dword dwValue)
{
m_tls.Characteristics = dwValue;
}
}
#endif

View File

@ -30,6 +30,7 @@ cond_add_subdirectory(macho-extractortool RETDEC_ENABLE_MACHO_EXTRACTORTOOL)
cond_add_subdirectory(pat2yara RETDEC_ENABLE_PAT2YARA)
cond_add_subdirectory(patterngen RETDEC_ENABLE_PATTERNGEN)
cond_add_subdirectory(pdbparser RETDEC_ENABLE_PDBPARSER)
cond_add_subdirectory(pelib RETDEC_ENABLE_PELIB)
cond_add_subdirectory(retdec RETDEC_ENABLE_RETDEC)
cond_add_subdirectory(retdectool RETDEC_ENABLE_RETDECTOOL)
cond_add_subdirectory(rtti-finder RETDEC_ENABLE_RTTI_FINDER)

View File

@ -8,10 +8,10 @@
#include <system_error>
#include <llvm/Object/COFF.h>
#include <pelib/PeLibInc.h>
#include "retdec/utils/string.h"
#include "retdec/fileformat/file_format/coff/coff_format.h"
#include "retdec/pelib/PeLibInc.h"
using namespace retdec::utils;
using namespace llvm;

View File

@ -12,15 +12,12 @@
#include <iostream>
#include <sstream>
#include <pelib/PeLibInc.h>
#include "retdec/crypto/crypto.h"
#include "retdec/utils/conversion.h"
#include "retdec/utils/file_io.h"
#include "retdec/utils/string.h"
#include "retdec/utils/system.h"
#include "retdec/fileformat/file_format/file_format.h"
#include "retdec/fileformat/utils/byte_array_buffer.h"
#include "retdec/fileformat/file_format/intel_hex/intel_hex_format.h"
#include "retdec/fileformat/file_format/raw_data/raw_data_format.h"
@ -28,6 +25,7 @@
#include "retdec/fileformat/utils/conversions.h"
#include "retdec/fileformat/utils/file_io.h"
#include "retdec/fileformat/utils/other.h"
#include "retdec/pelib/PeLibInc.h"
using namespace retdec::utils;
using namespace PeLib;

View File

@ -11,12 +11,12 @@
#include <llvm/Object/COFF.h>
#include <llvm/Support/Host.h>
#include <pelib/PeLib.h>
#include "retdec/utils/conversion.h"
#include "retdec/utils/string.h"
#include "retdec/fileformat/utils/byte_array_buffer.h"
#include "retdec/fileformat/utils/format_detection.h"
#include "retdec/pelib/PeLib.h"
using namespace retdec::utils;
using namespace llvm;

View File

@ -7,12 +7,12 @@
#include <sstream>
#include <llvm/Object/COFF.h>
#include <pelib/PeLibInc.h>
#include "fileinfo/file_detector/coff_detector.h"
#include "retdec/utils/array.h"
#include "retdec/utils/conversion.h"
#include "retdec/fileformat/utils/other.h"
#include "fileinfo/file_detector/coff_detector.h"
#include "retdec/pelib/PeLibInc.h"
using namespace retdec::utils;
using namespace llvm;

View File

@ -7,9 +7,8 @@
#ifndef FILEINFO_FILE_WRAPPER_PE_PE_WRAPPER_PARSER_PE_WRAPPER_PARSER32_H
#define FILEINFO_FILE_WRAPPER_PE_PE_WRAPPER_PARSER_PE_WRAPPER_PARSER32_H
#include <pelib/PeLib.h>
#include "fileinfo/file_wrapper/pe/pe_wrapper_parser/pe_wrapper_parser.h"
#include "retdec/pelib/PeLib.h"
namespace fileinfo {

View File

@ -7,9 +7,8 @@
#ifndef FILEINFO_FILE_WRAPPER_PE_PE_WRAPPER_PARSER_PE_WRAPPER_PARSER64_H
#define FILEINFO_FILE_WRAPPER_PE_PE_WRAPPER_PARSER_PE_WRAPPER_PARSER64_H
#include <pelib/PeLib.h>
#include "fileinfo/file_wrapper/pe/pe_wrapper_parser/pe_wrapper_parser.h"
#include "retdec/pelib/PeLib.h"
namespace fileinfo {

View File

@ -0,0 +1,498 @@
/*
* BoundImportDirectory.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include <numeric>
#include <set>
#include <map>
#include "pelib/PeLibInc.h"
#include "pelib/BoundImportDirectory.h"
namespace PeLib
{
/**
* Adds another bound import to the BoundImport directory.
* @param strModuleName Name of the PE file which will be imported.
* @param dwTds Value of the TimeDateStamp of the bound import field.
* @param wOmn Value of the OffsetModuleName of the bound import field.
* @param wWfr Value of the NumberOfModuleForwarderRefs of the bound import field.
**/
int BoundImportDirectory::addBoundImport(const std::string& strModuleName, dword dwTds, word wOmn, word wWfr)
{
for (unsigned int i=0;i<m_vIbd.size();i++)
{
if (isEqualNc(strModuleName, m_vIbd[i].strModuleName))
{
return ERROR_DUPLICATE_ENTRY;
}
}
PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR ibidCurrent;
ibidCurrent.TimeDateStamp = dwTds;
ibidCurrent.OffsetModuleName = wOmn;
ibidCurrent.NumberOfModuleForwarderRefs = wWfr;
PELIB_IMAGE_BOUND_DIRECTORY ibdCurrent;
ibdCurrent.ibdDescriptor = ibidCurrent;
ibdCurrent.strModuleName = strModuleName;
m_vIbd.push_back(ibdCurrent);
return ERROR_NONE;
}
/**
* Searches for the first instance of a module with the given modulename.
* @param strModuleName The name of a module.
* @return The id of the module.
**/
int BoundImportDirectory::getModuleIndex(const std::string& strModuleName) const
{
auto Iter = std::find_if(
m_vIbd.begin(),
m_vIbd.end(),
[&](const auto& i) { return i.equal(strModuleName); }
);
if (Iter == m_vIbd.end())
{
return ERROR_ENTRY_NOT_FOUND;
}
return static_cast<int>(std::distance(m_vIbd.begin(), Iter));
}
/**
* @return Number of files in the current BoundImport directory.
**/
unsigned int BoundImportDirectory::calcNumberOfModules() const
{
return static_cast<unsigned int>(m_vIbd.size());
}
int BoundImportDirectory::read(InputBuffer& inpBuffer, unsigned char* data, unsigned int dwSize)
{
std::vector<PELIB_IMAGE_BOUND_DIRECTORY> currentDirectory;
do
{
if (inpBuffer.get() + PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size() >= inpBuffer.size())
return ERROR_INVALID_FILE;
PELIB_IMAGE_BOUND_DIRECTORY ibdCurrent;
inpBuffer >> ibdCurrent.ibdDescriptor.TimeDateStamp;
inpBuffer >> ibdCurrent.ibdDescriptor.OffsetModuleName;
inpBuffer >> ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs;
if (ibdCurrent.ibdDescriptor.TimeDateStamp == 0 && ibdCurrent.ibdDescriptor.OffsetModuleName == 0 && ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs == 0) break;
for (int i=0;i<ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs;i++)
{
if (inpBuffer.get() + PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size() >= inpBuffer.size())
return ERROR_INVALID_FILE;
PELIB_IMAGE_BOUND_DIRECTORY currentForwarder;
inpBuffer >> currentForwarder.ibdDescriptor.TimeDateStamp;
inpBuffer >> currentForwarder.ibdDescriptor.OffsetModuleName;
inpBuffer >> currentForwarder.ibdDescriptor.NumberOfModuleForwarderRefs;
ibdCurrent.moduleForwarders.push_back(currentForwarder);
}
currentDirectory.push_back(ibdCurrent);
ibdCurrent.moduleForwarders.clear();
} while (true);
for (unsigned int i=0;i<currentDirectory.size();i++)
{
dword wOmn = currentDirectory[i].ibdDescriptor.OffsetModuleName;
if (wOmn > dwSize)
{
return ERROR_INVALID_FILE;
}
currentDirectory[i].strModuleName = "";
for (int k=0;k + wOmn < dwSize && data[wOmn + k] != 0;k++)
{
currentDirectory[i].strModuleName += data[wOmn + k];
}
for (unsigned int j=0;j<currentDirectory[i].moduleForwarders.size();j++)
{
dword wOmn2 = currentDirectory[i].moduleForwarders[j].ibdDescriptor.OffsetModuleName;
if (wOmn2 > dwSize)
{
return ERROR_INVALID_FILE;
}
// m_vIbd[i].moduleForwarders[j].strModuleName.assign((char*)(&vBimpDir[wOmn2]));
currentDirectory[i].moduleForwarders[j].strModuleName = "";
for (int k=0;k + wOmn2 < dwSize && data[wOmn2 + k] != 0;k++)
{
currentDirectory[i].moduleForwarders[j].strModuleName += data[wOmn2 + k];
}
}
}
std::swap(m_vIbd, currentDirectory);
return ERROR_NONE;
}
int BoundImportDirectory::read(unsigned char* pcBuffer, unsigned int uiSize)
{
std::vector<unsigned char> vBimpDir(pcBuffer, pcBuffer + uiSize);
InputBuffer inpBuffer(vBimpDir);
return read(inpBuffer, vBimpDir.data(), uiSize);
}
unsigned int BoundImportDirectory::totalModules() const
{
unsigned int modules = static_cast<unsigned int>(m_vIbd.size());
for (unsigned int i=0;i<m_vIbd.size();i++)
{
modules += static_cast<unsigned int>(m_vIbd[i].moduleForwarders.size());
}
return modules;
}
/**
* Rebuilds the BoundImport directory. The rebuilded BoundImport directory can then be
* written back to a PE file.
* @param vBuffer Buffer where the rebuilt BoundImport directory will be stored.
* @param fMakeValid If this flag is true a valid directory will be produced.
**/
void BoundImportDirectory::rebuild(std::vector<byte>& vBuffer, bool fMakeValid) const
{
std::map<std::string, word> filename_offsets;
OutputBuffer obBuffer(vBuffer);
word ulNameOffset = static_cast<word>((totalModules() + 1) * PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size());
for (unsigned int i=0;i<m_vIbd.size();i++)
{
obBuffer << m_vIbd[i].ibdDescriptor.TimeDateStamp;
// Recalculate the offsets if a valid directory is wanted.
if (fMakeValid)
{
if (filename_offsets.find(m_vIbd[i].strModuleName) == filename_offsets.end())
{
filename_offsets[m_vIbd[i].strModuleName] = ulNameOffset;
obBuffer << ulNameOffset;
ulNameOffset += static_cast<word>(m_vIbd[i].strModuleName.size() + 1);
}
else
{
obBuffer << filename_offsets[m_vIbd[i].strModuleName];
}
}
else // Otherwise just copy the old values into the buffer.
{
obBuffer << m_vIbd[i].ibdDescriptor.OffsetModuleName;
}
obBuffer << m_vIbd[i].ibdDescriptor.NumberOfModuleForwarderRefs;
for (int j=0;j<calcNumberOfModuleForwarderRefs(i);j++)
{
obBuffer << m_vIbd[i].moduleForwarders[j].ibdDescriptor.TimeDateStamp;
if (fMakeValid)
{
if (filename_offsets.find(m_vIbd[i].strModuleName) == filename_offsets.end())
{
filename_offsets[m_vIbd[i].moduleForwarders[j].strModuleName] = ulNameOffset;
obBuffer << ulNameOffset;
ulNameOffset += static_cast<word>(m_vIbd[i].moduleForwarders[j].strModuleName.size() + 1);
}
else
{
obBuffer << filename_offsets[m_vIbd[i].moduleForwarders[j].strModuleName];
}
}
else // Otherwise just copy the old values into the buffer.
{
obBuffer << m_vIbd[i].moduleForwarders[j].ibdDescriptor.OffsetModuleName;
}
obBuffer << m_vIbd[i].moduleForwarders[j].ibdDescriptor.NumberOfModuleForwarderRefs;
}
}
obBuffer << static_cast<dword>(0);
obBuffer << static_cast<word>(0);
obBuffer << static_cast<word>(0);
for (unsigned int i=0;i<m_vIbd.size();i++)
{
if (filename_offsets.find(m_vIbd[i].strModuleName) != filename_offsets.end())
{
obBuffer.add(getModuleName(i).c_str(), static_cast<unsigned long>(getModuleName(i).size() + 1));
filename_offsets.erase(m_vIbd[i].strModuleName);
}
for (int j=0;j<calcNumberOfModuleForwarderRefs(i);j++)
{
if (filename_offsets.find(getModuleName(i, j)) != filename_offsets.end())
{
obBuffer.add(getModuleName(i, j).c_str(), static_cast<unsigned long>(getModuleName(i, j).size() + 1));
filename_offsets.erase(getModuleName(i, j));
}
}
}
}
/**
* Removes all bound import files.
**/
void BoundImportDirectory::clear()
{
m_vIbd.clear();
}
/**
* Removes a field specified by the parameter filename from the BoundImport directory.
* @param strModuleName Name of the file whose field will be removed from the BoundImport directory.
**/
void BoundImportDirectory::removeBoundImport(const std::string& strModuleName)
{
m_vIbd.erase(
std::remove_if(
m_vIbd.begin(),
m_vIbd.end(),
[&](const auto& i) { return i.equal(strModuleName); }
),
m_vIbd.end()
);
}
/**
* Returns the size of the rebuilt BoundImportDirectory.
* @return Size of the rebuilt BoundImportDirectory.
**/
unsigned int BoundImportDirectory::size() const
{
unsigned int size2 = PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size();
std::set<std::string> filenames;
for (unsigned int i = 0; i < m_vIbd.size(); i++)
{
filenames.insert(m_vIbd[i].strModuleName);
size2 += PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size();
for (unsigned int j = 0; j < m_vIbd[i].moduleForwarders.size(); j++)
{
filenames.insert(m_vIbd[i].moduleForwarders[j].strModuleName);
size2 += PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size();
}
}
for (std::set<std::string>::iterator iter = filenames.begin(); iter != filenames.end(); ++iter)
{
size2 += static_cast<unsigned int>(iter->size()) + 1;
}
return size2;
}
/**
* @param strFilename Name of the file.
* @param dwOffset File offset the bound importdirectory will be written to.
* @param fMakeValid If this flag is true a valid directory will be produced.
**/
int BoundImportDirectory::write(const std::string& strFilename, dword dwOffset, bool fMakeValid) const
{
std::fstream ofFile(strFilename.c_str(), std::ios_base::in);
if (!ofFile)
{
ofFile.clear();
ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary);
}
else
{
ofFile.close();
ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
}
if (!ofFile)
{
return ERROR_OPENING_FILE;
}
ofFile.seekp(dwOffset, std::ios::beg);
std::vector<unsigned char> vBuffer;
rebuild(vBuffer, fMakeValid);
ofFile.write(reinterpret_cast<const char*>(vBuffer.data()), static_cast<std::streamsize>(vBuffer.size()));
ofFile.close();
return ERROR_NONE;
}
/**
* Retrieves the value of the TimeDateStamp value of a bound import field.
* @param dwBidnr Number of the bound import field.
* @return Value of the TimeDateStamp of the bound import field.
**/
dword BoundImportDirectory::getTimeDateStamp(dword dwBidnr) const
{
return m_vIbd[dwBidnr].ibdDescriptor.TimeDateStamp;
}
/**
* Retrieves the value of the OffsetModuleName value of a bound import field.
* @param dwBidnr Number of the bound import field.
* @return Value of the OffsetModuleName of the bound import field.
**/
word BoundImportDirectory::getOffsetModuleName(dword dwBidnr) const
{
return m_vIbd[dwBidnr].ibdDescriptor.OffsetModuleName;
}
/**
* Retrieves the value of the NumberOfModuleForwarderRefs value of a bound import field.
* @param dwBidnr Number of the bound import field.
* @return Value of the NumberOfModuleForwarderRefs of the bound import field.
**/
word BoundImportDirectory::getNumberOfModuleForwarderRefs(dword dwBidnr) const
{
return m_vIbd[dwBidnr].ibdDescriptor.NumberOfModuleForwarderRefs;
}
/**
* Retrieves the value of the ModuleName value of a bound import field.
* @param dwBidnr Number of the bound import field.
* @return Value of the ModuleName of the bound import field.
**/
std::string BoundImportDirectory::getModuleName(dword dwBidnr) const
{
return m_vIbd[dwBidnr].strModuleName;
}
/**
* Changes the TimeDateStamp value of an existing bound import field.
* @param dwBidnr Number of the bound import field which will be changed.
* @param dwTds New value of the TimeDateStamp of the bound import field.
**/
void BoundImportDirectory::setTimeDateStamp(dword dwBidnr, dword dwTds)
{
m_vIbd[dwBidnr].ibdDescriptor.TimeDateStamp = dwTds;
}
/**
* Changes the OffsetModuleName value of an existing bound import field.
* @param dwBidnr Number of the bound import field which will be changed.
* @param wOmn New value of the OffsetModuleName of the bound import field.
**/
void BoundImportDirectory::setOffsetModuleName(dword dwBidnr, word wOmn)
{
m_vIbd[dwBidnr].ibdDescriptor.OffsetModuleName = wOmn;
}
/**
* Changes the NumberOfModuleForwarderRefs value of an existing bound import field.
* @param dwBidnr Number of the bound import field which will be changed.
* @param wMfr New value of the NumberOfModuleForwarderRefs of the bound import field.
**/
void BoundImportDirectory::setNumberOfModuleForwarderRefs(dword dwBidnr, word wMfr)
{
m_vIbd[dwBidnr].ibdDescriptor.NumberOfModuleForwarderRefs = wMfr;
}
/**
* Changes the ModuleName value of an existing bound import field.
* @param dwBidnr Number of the bound import field which will be changed.
* @param strModuleName New value of the ModuleName of the bound import field.
**/
void BoundImportDirectory::setModuleName(dword dwBidnr, const std::string& strModuleName)
{
m_vIbd[dwBidnr].strModuleName = strModuleName;
}
dword BoundImportDirectory::getTimeDateStamp(dword dwBidnr, dword forwardedModule) const
{
return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.TimeDateStamp;
}
word BoundImportDirectory::getOffsetModuleName(dword dwBidnr, dword forwardedModule) const
{
return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.OffsetModuleName;
}
word BoundImportDirectory::getNumberOfModuleForwarderRefs(dword dwBidnr, dword forwardedModule) const
{
return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.NumberOfModuleForwarderRefs;
}
std::string BoundImportDirectory::getModuleName(dword dwBidnr, dword forwardedModule) const
{
return m_vIbd[dwBidnr].moduleForwarders[forwardedModule].strModuleName;
}
void BoundImportDirectory::setTimeDateStamp(dword dwBidnr, dword forwardedModule, dword dwTds)
{
m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.TimeDateStamp = dwTds;
}
void BoundImportDirectory::setOffsetModuleName(dword dwBidnr, dword forwardedModule, word wOmn)
{
m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.OffsetModuleName = wOmn;
}
void BoundImportDirectory::setNumberOfModuleForwarderRefs(dword dwBidnr, dword forwardedModule, word wMfr)
{
m_vIbd[dwBidnr].moduleForwarders[forwardedModule].ibdDescriptor.NumberOfModuleForwarderRefs = wMfr;
}
void BoundImportDirectory::setModuleName(dword dwBidnr, dword forwardedModule, const std::string& strModuleName)
{
m_vIbd[dwBidnr].moduleForwarders[forwardedModule].strModuleName = strModuleName;
}
word BoundImportDirectory::calcNumberOfModuleForwarderRefs(dword dwBidnr) const
{
return static_cast<word>(m_vIbd[dwBidnr].moduleForwarders.size());
}
void BoundImportDirectory::addForwardedModule(dword dwBidnr, const std::string& name, dword timeStamp, word offsetModuleName, word forwardedModules)
{
// XXX: Maybe test if there are already 0xFFFF forwarded modules.
// XXX: Check for duplicate entries. Is it also necessary to check
// non-forwarded entries and forwarded entries in other non-forwarded
// entries?
// XXX: Can forwarders forward recursively?
PELIB_IMAGE_BOUND_DIRECTORY ibdCurrent;
ibdCurrent.strModuleName = name;
ibdCurrent.ibdDescriptor.TimeDateStamp = timeStamp;
ibdCurrent.ibdDescriptor.OffsetModuleName = offsetModuleName;
ibdCurrent.ibdDescriptor.NumberOfModuleForwarderRefs = forwardedModules;
m_vIbd[dwBidnr].moduleForwarders.push_back(ibdCurrent);
}
void BoundImportDirectory::removeForwardedModule(dword dwBidnr, word forwardedModule)
{
m_vIbd[dwBidnr].moduleForwarders.erase(m_vIbd[dwBidnr].moduleForwarders.begin() + forwardedModule);
}
}

30
src/pelib/CMakeLists.txt Normal file
View File

@ -0,0 +1,30 @@
set(PELIB_SOURCES
BoundImportDirectory.cpp
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
)
add_library(pelib STATIC ${PELIB_SOURCES})
target_include_directories(pelib
PUBLIC ${PROJECT_SOURCE_DIR}/include/
PUBLIC ${PROJECT_SOURCE_DIR}/include/retdec)
# Disable all warnings from this library.
if(MSVC)
target_compile_options(pelib PUBLIC "/w")
else()
target_compile_options(pelib PUBLIC "-w")
endif()

View File

@ -0,0 +1,202 @@
/**
* @file CoffSymbolTable.cpp
* @brief Class for COFF symbol table.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include <algorithm>
#include "pelib/PeLibInc.h"
#include "pelib/CoffSymbolTable.h"
namespace PeLib
{
CoffSymbolTable::CoffSymbolTable() : stringTableSize(0), numberOfStoredSymbols(0), m_ldrError(LDR_ERROR_NONE)
{
}
CoffSymbolTable::~CoffSymbolTable()
{
}
void CoffSymbolTable::read(InputBuffer& inputbuffer, unsigned int uiSize)
{
PELIB_IMAGE_COFF_SYMBOL symbol;
for (std::size_t i = 0, e = uiSize / PELIB_IMAGE_SIZEOF_COFF_SYMBOL; i < e; ++i)
{
symbol.Name.clear();
dword Zeroes, NameOffset;
inputbuffer >> Zeroes;
inputbuffer >> NameOffset;
inputbuffer >> symbol.Value;
inputbuffer >> symbol.SectionNumber;
inputbuffer >> symbol.TypeComplex;
inputbuffer >> symbol.TypeSimple;
inputbuffer >> symbol.StorageClass;
inputbuffer >> symbol.NumberOfAuxSymbols;
symbol.Index = (PeLib::dword)i;
if (!Zeroes)
{
if (stringTableSize && NameOffset)
{
for (std::size_t j = NameOffset; j < stringTableSize && stringTable[j] != '\0'; ++j)
{
// 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.
if (j - NameOffset == COFF_SYMBOL_NAME_MAX_LENGTH)
{
auto nonPrintableChars = std::count_if(symbol.Name.begin(), symbol.Name.end(), [](unsigned char c) { return !isprint(c); });
if (nonPrintableChars != 0)
break;
}
symbol.Name += stringTable[j];
}
}
}
else
{
for (std::size_t j = i * PELIB_IMAGE_SIZEOF_COFF_SYMBOL, k = 0; k < 8 && symbolTableDump[j] != '\0'; ++j, ++k)
{
symbol.Name += symbolTableDump[j];
}
}
i += symbol.NumberOfAuxSymbols;
inputbuffer.move(symbol.NumberOfAuxSymbols * PELIB_IMAGE_SIZEOF_COFF_SYMBOL);
symbolTable.push_back(symbol);
}
numberOfStoredSymbols = (dword)symbolTable.size();
}
int CoffSymbolTable::read(
std::istream& inStream,
unsigned int uiOffset,
unsigned int uiSize)
{
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
// Check for overflow
if ((uiOffset + uiSize) < uiOffset)
{
return ERROR_INVALID_FILE;
}
std::uint64_t ulFileSize = fileSize(inStream_w);
std::uint64_t stringTableOffset = uiOffset + uiSize;
if (uiOffset >= ulFileSize || stringTableOffset >= ulFileSize)
{
return ERROR_INVALID_FILE;
}
inStream_w.seekg(uiOffset, std::ios::beg);
symbolTableDump.resize(uiSize);
inStream_w.read(reinterpret_cast<char*>(symbolTableDump.data()), uiSize);
InputBuffer ibBuffer(symbolTableDump);
// read size of string table
if (ulFileSize >= stringTableOffset + 4)
{
stringTable.resize(4);
inStream_w.read(reinterpret_cast<char*>(stringTable.data()), 4);
InputBuffer strBuf(stringTable);
strBuf >> stringTableSize;
}
if (inStream_w.gcount() < 4)
{
stringTableSize = (std::size_t)inStream_w.gcount();
}
else if (inStream_w.gcount() == 4 && stringTableSize < 4)
{
stringTableSize = 4;
}
if (stringTableSize > ulFileSize || uiOffset + stringTableSize > ulFileSize)
{
stringTableSize = (std::size_t)(ulFileSize - uiOffset);
}
// read string table
if (stringTableSize > 4)
{
stringTable.resize(stringTableSize);
inStream_w.read(reinterpret_cast<char*>(stringTable.data() + 4), stringTableSize - 4);
}
read(ibBuffer, uiSize);
return ERROR_NONE;
}
LoaderError CoffSymbolTable::loaderError() const
{
return m_ldrError;
}
void CoffSymbolTable::setLoaderError(LoaderError ldrError)
{
if (m_ldrError == LDR_ERROR_NONE)
{
m_ldrError = ldrError;
}
}
std::size_t CoffSymbolTable::getSizeOfStringTable() const
{
return stringTableSize;
}
std::size_t CoffSymbolTable::getNumberOfStoredSymbols() const
{
return numberOfStoredSymbols;
}
dword CoffSymbolTable::getSymbolIndex(std::size_t ulSymbol) const
{
return symbolTable[ulSymbol].Index;
}
std::string CoffSymbolTable::getSymbolName(std::size_t ulSymbol) const
{
return symbolTable[ulSymbol].Name;
}
dword CoffSymbolTable::getSymbolValue(std::size_t ulSymbol) const
{
return symbolTable[ulSymbol].Value;
}
word CoffSymbolTable::getSymbolSectionNumber(std::size_t ulSymbol) const
{
return symbolTable[ulSymbol].SectionNumber;
}
byte CoffSymbolTable::getSymbolTypeComplex(std::size_t ulSymbol) const
{
return symbolTable[ulSymbol].TypeComplex;
}
byte CoffSymbolTable::getSymbolTypeSimple(std::size_t ulSymbol) const
{
return symbolTable[ulSymbol].TypeSimple;
}
byte CoffSymbolTable::getSymbolStorageClass(std::size_t ulSymbol) const
{
return symbolTable[ulSymbol].StorageClass;
}
byte CoffSymbolTable::getSymbolNumberOfAuxSymbols(std::size_t ulSymbol) const
{
return symbolTable[ulSymbol].NumberOfAuxSymbols;
}
}

View File

@ -0,0 +1,436 @@
/*
* ComHeaderDirectory.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include "pelib/PeLibInc.h"
#include "pelib/ComHeaderDirectory.h"
namespace PeLib
{
void ComHeaderDirectory::read(InputBuffer& inputbuffer)
{
PELIB_IMAGE_COR20_HEADER ichCurr;
inputbuffer >> ichCurr.cb;
inputbuffer >> ichCurr.MajorRuntimeVersion;
inputbuffer >> ichCurr.MinorRuntimeVersion;
inputbuffer >> ichCurr.MetaData.VirtualAddress;
inputbuffer >> ichCurr.MetaData.Size;
inputbuffer >> ichCurr.Flags;
inputbuffer >> ichCurr.EntryPointToken;
inputbuffer >> ichCurr.Resources.VirtualAddress;
inputbuffer >> ichCurr.Resources.Size;
inputbuffer >> ichCurr.StrongNameSignature.VirtualAddress;
inputbuffer >> ichCurr.StrongNameSignature.Size;
inputbuffer >> ichCurr.CodeManagerTable.VirtualAddress;
inputbuffer >> ichCurr.CodeManagerTable.Size;
inputbuffer >> ichCurr.VTableFixups.VirtualAddress;
inputbuffer >> ichCurr.VTableFixups.Size;
inputbuffer >> ichCurr.ExportAddressTableJumps.VirtualAddress;
inputbuffer >> ichCurr.ExportAddressTableJumps.Size;
inputbuffer >> ichCurr.ManagedNativeHeader.VirtualAddress;
inputbuffer >> ichCurr.ManagedNativeHeader.Size;
std::swap(ichCurr, m_ichComHeader);
}
int ComHeaderDirectory::read(unsigned char* buffer, unsigned int buffersize)
{
if (buffersize < PELIB_IMAGE_COR20_HEADER::size())
{
return ERROR_INVALID_FILE;
}
std::vector<byte> vComDescDirectory(buffer, buffer + buffersize);
InputBuffer ibBuffer(vComDescDirectory);
read(ibBuffer);
return ERROR_NONE;
}
/**
* Rebuilds the current COM+ descriptor.
* @param vBuffer Buffer where the COM+ descriptor will be written to.
**/
void ComHeaderDirectory::rebuild(std::vector<byte>& vBuffer) const
{
OutputBuffer obBuffer(vBuffer);
obBuffer << m_ichComHeader.cb;
obBuffer << m_ichComHeader.MajorRuntimeVersion;
obBuffer << m_ichComHeader.MinorRuntimeVersion;
obBuffer << m_ichComHeader.MetaData.VirtualAddress;
obBuffer << m_ichComHeader.MetaData.Size;
obBuffer << m_ichComHeader.Flags;
obBuffer << m_ichComHeader.EntryPointToken;
obBuffer << m_ichComHeader.Resources.VirtualAddress;
obBuffer << m_ichComHeader.Resources.Size;
obBuffer << m_ichComHeader.StrongNameSignature.VirtualAddress;
obBuffer << m_ichComHeader.StrongNameSignature.Size;
obBuffer << m_ichComHeader.CodeManagerTable.VirtualAddress;
obBuffer << m_ichComHeader.CodeManagerTable.Size;
obBuffer << m_ichComHeader.VTableFixups.VirtualAddress;
obBuffer << m_ichComHeader.VTableFixups.Size;
obBuffer << m_ichComHeader.ExportAddressTableJumps.VirtualAddress;
obBuffer << m_ichComHeader.ExportAddressTableJumps.Size;
obBuffer << m_ichComHeader.ManagedNativeHeader.VirtualAddress;
obBuffer << m_ichComHeader.ManagedNativeHeader.Size;
}
/**
* @return Size in bytes.
**/
unsigned int ComHeaderDirectory::size() const
{
return PELIB_IMAGE_COR20_HEADER::size();
}
/**
* @param strFilename Name of the file.
* @param dwOffset File offset the COM+ descriptor will be written to.
**/
int ComHeaderDirectory::write(const std::string& strFilename, unsigned int dwOffset) const
{
std::fstream ofFile(strFilename.c_str(), std::ios_base::in);
if (!ofFile)
{
ofFile.clear();
ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary);
}
else
{
ofFile.close();
ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
}
if (!ofFile)
{
return ERROR_OPENING_FILE;
}
ofFile.seekp(dwOffset, std::ios::beg);
std::vector<unsigned char> vBuffer;
rebuild(vBuffer);
ofFile.write(reinterpret_cast<const char*>(vBuffer.data()), static_cast<unsigned int>(vBuffer.size()));
ofFile.close();
return ERROR_NONE;
}
/**
* @return SizeOfHeader value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getSizeOfHeader() const
{
return m_ichComHeader.cb;
}
/**
* @return MajorRuntimeVersion value of the current COM+ descriptor.
**/
word ComHeaderDirectory::getMajorRuntimeVersion() const
{
return m_ichComHeader.MajorRuntimeVersion;
}
/**
* @return MinorRuntimeVersion value of the current COM+ descriptor.
**/
word ComHeaderDirectory::getMinorRuntimeVersion() const
{
return m_ichComHeader.MinorRuntimeVersion;
}
/**
* @return MetaData (Virtual Address) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getMetaDataVa() const
{
return m_ichComHeader.MetaData.VirtualAddress;
}
/**
* @return MetaData (Size) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getMetaDataSize() const
{
return m_ichComHeader.MetaData.Size;
}
/**
* @return Flags value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getFlags() const
{
return m_ichComHeader.Flags;
}
/**
* @return EntryPointToken value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getEntryPointToken() const
{
return m_ichComHeader.EntryPointToken;
}
/**
* @return Resources (Virtual Address) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getResourcesVa() const
{
return m_ichComHeader.Resources.VirtualAddress;
}
/**
* @return Resources (Size) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getResourcesSize() const
{
return m_ichComHeader.Resources.Size;
}
/**
* @return StrongNameSignature (Virtual Address) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getStrongNameSignatureVa() const
{
return m_ichComHeader.StrongNameSignature.VirtualAddress;
}
/**
* @return StrongNameSignature (Size) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getStrongNameSignatureSize() const
{
return m_ichComHeader.StrongNameSignature.Size;
}
/**
* @return CodeManagerTable (Virtual Address) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getCodeManagerTableVa() const
{
return m_ichComHeader.CodeManagerTable.VirtualAddress;
}
/**
* @return CodeManagerTable (Size) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getCodeManagerTableSize() const
{
return m_ichComHeader.CodeManagerTable.Size;
}
/**
* @return VTableFixups (Virtual Address) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getVTableFixupsVa() const
{
return m_ichComHeader.VTableFixups.VirtualAddress;
}
/**
* @return VTableFixups (Size) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getVTableFixupsSize() const
{
return m_ichComHeader.VTableFixups.Size;
}
/**
* @return ExportAddressTableJumps (Virtual Address) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getExportAddressTableJumpsVa() const
{
return m_ichComHeader.ExportAddressTableJumps.VirtualAddress;
}
/**
* @return ExportAddressTableJumps (Size) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getExportAddressTableJumpsSize() const
{
return m_ichComHeader.ExportAddressTableJumps.Size;
}
/**
* @return ManagedNativeHeader (Virtual Address) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getManagedNativeHeaderVa() const
{
return m_ichComHeader.ManagedNativeHeader.VirtualAddress;
}
/**
* @return ManagedNativeHeader (Size) value of the current COM+ descriptor.
**/
dword ComHeaderDirectory::getManagedNativeHeaderSize() const
{
return m_ichComHeader.ManagedNativeHeader.Size;
}
/**
* @param dwValue New value for the current SizeOfHeader (cb) value.
**/
void ComHeaderDirectory::setSizeOfHeader(dword dwValue)
{
m_ichComHeader.cb = dwValue;
}
/**
* @param wValue New value for the current MajorRuntimeVersion value.
**/
void ComHeaderDirectory::setMajorRuntimeVersion(word wValue)
{
m_ichComHeader.MajorRuntimeVersion = wValue;
}
/**
* @param wValue New value for the current MinorRuntimeVersion value.
**/
void ComHeaderDirectory::setMinorRuntimeVersion(word wValue)
{
m_ichComHeader.MinorRuntimeVersion = wValue;
}
/**
* @param dwValue New value for the current MetaData (VirtualAddress) value.
**/
void ComHeaderDirectory::setMetaDataVa(dword dwValue)
{
m_ichComHeader.MetaData.VirtualAddress = dwValue;
}
/**
* @param dwValue New value for the current MetaData (Size) value.
**/
void ComHeaderDirectory::setMetaDataSize(dword dwValue)
{
m_ichComHeader.MetaData.Size = dwValue;
}
/**
* @param dwValue New value for the current Flags value.
**/
void ComHeaderDirectory::setFlags(dword dwValue)
{
m_ichComHeader.Flags = dwValue;
}
/**
* @param dwValue New value for the current EntryPointToken value.
**/
void ComHeaderDirectory::setEntryPointToken(dword dwValue)
{
m_ichComHeader.EntryPointToken = dwValue;
}
/**
* @param dwValue New value for the current Resources (VirtualAddress) value.
**/
void ComHeaderDirectory::setResourcesVa(dword dwValue)
{
m_ichComHeader.Resources.VirtualAddress = dwValue;
}
/**
* @param dwValue New value for the current Resources (Size) value.
**/
void ComHeaderDirectory::setResourcesSize(dword dwValue)
{
m_ichComHeader.Resources.Size = dwValue;
}
/**
* @param dwValue New value for the current StrongNameSignature (VirtualAddress) value.
**/
void ComHeaderDirectory::setStrongNameSignatureVa(dword dwValue)
{
m_ichComHeader.StrongNameSignature.VirtualAddress = dwValue;
}
/**
* @param dwValue New value for the current StrongNameSignature (Size) value.
**/
void ComHeaderDirectory::setStrongNameSignagureSize(dword dwValue)
{
m_ichComHeader.StrongNameSignature.Size = dwValue;
}
/**
* @param dwValue New value for the current CodeManagerTable (VirtualAddress) value.
**/
void ComHeaderDirectory::setCodeManagerTableVa(dword dwValue)
{
m_ichComHeader.CodeManagerTable.VirtualAddress = dwValue;
}
/**
* @param dwValue New value for the current CodeManagerTable (Size) value.
**/
void ComHeaderDirectory::setCodeManagerTableSize(dword dwValue)
{
m_ichComHeader.CodeManagerTable.Size = dwValue;
}
/**
* @param dwValue New value for the current VTableFixups (VirtualAddress) value.
**/
void ComHeaderDirectory::setVTableFixupsVa(dword dwValue)
{
m_ichComHeader.VTableFixups.VirtualAddress = dwValue;
}
/**
* @param dwValue New value for the current VTableFixups (Size) value.
**/
void ComHeaderDirectory::setVTableFixupsSize(dword dwValue)
{
m_ichComHeader.VTableFixups.Size = dwValue;
}
/**
* @param dwValue New value for the current ExportAddressTableJumps (VirtualAddress) value.
**/
void ComHeaderDirectory::setExportAddressTableJumpsVa(dword dwValue)
{
m_ichComHeader.ExportAddressTableJumps.VirtualAddress = dwValue;
}
/**
* @param dwValue New value for the current ExportAddressTableJumps (Size) value.
**/
void ComHeaderDirectory::setExportAddressTableJumpsSize(dword dwValue)
{
m_ichComHeader.ExportAddressTableJumps.Size = dwValue;
}
/**
* @param dwValue New value for the current ManagedNativeHeader (VirtualAddress) value.
**/
void ComHeaderDirectory::setManagedNativeHeaderVa(dword dwValue)
{
m_ichComHeader.ManagedNativeHeader.VirtualAddress = dwValue;
}
/**
* @param dwValue New value for the current ManagedNativeHeader (Size) value.
**/
void ComHeaderDirectory::setManagedNativeHeaderSize(dword dwValue)
{
m_ichComHeader.ManagedNativeHeader.Size = dwValue;
}
}

View File

@ -0,0 +1,355 @@
/*
* DebugDirectory.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include "pelib/PeLibInc.h"
#include "pelib/DebugDirectory.h"
namespace PeLib
{
void DebugDirectory::clear()
{
m_vDebugInfo.clear();
}
std::vector<PELIB_IMG_DEBUG_DIRECTORY> DebugDirectory::read(InputBuffer& ibBuffer, unsigned int uiRva, unsigned int uiSize)
{
std::vector<PELIB_IMG_DEBUG_DIRECTORY> currDebugInfo;
PELIB_IMG_DEBUG_DIRECTORY iddCurr;
unsigned int uiEntryCount = uiSize / PELIB_IMAGE_DEBUG_DIRECTORY::size();
for (unsigned int i = 0; i < uiEntryCount; i++)
{
ibBuffer >> iddCurr.idd.Characteristics;
ibBuffer >> iddCurr.idd.TimeDateStamp;
ibBuffer >> iddCurr.idd.MajorVersion;
ibBuffer >> iddCurr.idd.MinorVersion;
ibBuffer >> iddCurr.idd.Type;
ibBuffer >> iddCurr.idd.SizeOfData;
ibBuffer >> iddCurr.idd.AddressOfRawData;
ibBuffer >> iddCurr.idd.PointerToRawData;
currDebugInfo.push_back(iddCurr);
}
if (!currDebugInfo.empty())
{
m_occupiedAddresses.emplace_back(
uiRva,
uiRva + uiEntryCount * PELIB_IMAGE_DEBUG_DIRECTORY::size() - 1
);
}
return currDebugInfo;
}
int DebugDirectory::read(unsigned char* buffer, unsigned int buffersize)
{
// XXX: Note, debug data is not read at all. This might or might not change
// in the future.
std::vector<byte> vDebugDirectory(buffer, buffer + buffersize);
InputBuffer ibBuffer(vDebugDirectory);
std::vector<PELIB_IMG_DEBUG_DIRECTORY> currDebugInfo = read(ibBuffer, 0, buffersize);
std::swap(currDebugInfo, m_vDebugInfo);
return ERROR_NONE;
}
/**
* Rebuilds the current debug directory.
* @param vBuffer Buffer where the rebuilt directory is stored.
**/
void DebugDirectory::rebuild(std::vector<byte>& vBuffer) const
{
OutputBuffer obBuffer(vBuffer);
for (unsigned int i=0;i<m_vDebugInfo.size();i++)
{
obBuffer << m_vDebugInfo[i].idd.Characteristics;
obBuffer << m_vDebugInfo[i].idd.TimeDateStamp;
obBuffer << m_vDebugInfo[i].idd.MajorVersion;
obBuffer << m_vDebugInfo[i].idd.MinorVersion;
obBuffer << m_vDebugInfo[i].idd.Type;
obBuffer << m_vDebugInfo[i].idd.SizeOfData;
obBuffer << m_vDebugInfo[i].idd.AddressOfRawData;
obBuffer << m_vDebugInfo[i].idd.PointerToRawData;
}
}
/**
* @return Size of the debug directory.
**/
unsigned int DebugDirectory::size() const
{
return static_cast<unsigned int>(m_vDebugInfo.size()) * PELIB_IMAGE_DEBUG_DIRECTORY::size();
}
/**
* @param strFilename Name of the file which will be written.
* @param uiOffset File offset where the debug directory will be stored.
**/
int DebugDirectory::write(const std::string& strFilename, unsigned int uiOffset) const
{
std::fstream ofFile(strFilename.c_str(), std::ios_base::in);
if (!ofFile)
{
ofFile.clear();
ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary);
}
else
{
ofFile.close();
ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
}
if (!ofFile)
{
return ERROR_OPENING_FILE;
}
ofFile.seekp(uiOffset, std::ios::beg);
std::vector<unsigned char> vBuffer;
rebuild(vBuffer);
ofFile.write(reinterpret_cast<const char*>(vBuffer.data()), static_cast<unsigned int>(vBuffer.size()));
ofFile.close();
return ERROR_NONE;
}
/**
* @return Number of debug structures in the current Debug directory.
**/
unsigned int DebugDirectory::calcNumberOfEntries() const
{
return static_cast<unsigned int>(m_vDebugInfo.size());
}
/**
* Adds a new debug structure to the debug directory. The initial values of all members of the structure
* are undefined.
**/
void DebugDirectory::addEntry()
{
PELIB_IMG_DEBUG_DIRECTORY p;
m_vDebugInfo.push_back(p);
}
/**
* Removes a debug structure from the current debug directory. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
**/
void DebugDirectory::removeEntry(std::size_t uiIndex)
{
m_vDebugInfo.erase(m_vDebugInfo.begin() + uiIndex);
}
/**
* Returns the Characteristics value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @return Characteristics value of the debug structure.
**/
dword DebugDirectory::getCharacteristics(std::size_t uiIndex) const
{
return m_vDebugInfo[uiIndex].idd.Characteristics;
}
/**
* Returns the TimeDateStamp value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @return TimeDateStamp value of the debug structure.
**/
dword DebugDirectory::getTimeDateStamp(std::size_t uiIndex) const
{
return m_vDebugInfo[uiIndex].idd.TimeDateStamp;
}
/**
* Returns the MajorVersion value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @return MajorVersion value of the debug structure.
**/
word DebugDirectory::getMajorVersion(std::size_t uiIndex) const
{
return m_vDebugInfo[uiIndex].idd.MajorVersion;
}
/**
* Returns the MinorVersion value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @return MinorVersion value of the debug structure.
**/
word DebugDirectory::getMinorVersion(std::size_t uiIndex) const
{
return m_vDebugInfo[uiIndex].idd.MinorVersion;
}
/**
* Returns the Type value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @return Type value of the debug structure.
**/
dword DebugDirectory::getType(std::size_t uiIndex) const
{
return m_vDebugInfo[uiIndex].idd.Type;
}
/**
* Returns the SizeOfData value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @return SizeOfData value of the debug structure.
**/
dword DebugDirectory::getSizeOfData(std::size_t uiIndex) const
{
return m_vDebugInfo[uiIndex].idd.SizeOfData;
}
/**
* Returns the AddressOfRawData value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @return AddressOfRawData value of the debug structure.
**/
dword DebugDirectory::getAddressOfRawData(std::size_t uiIndex) const
{
return m_vDebugInfo[uiIndex].idd.AddressOfRawData;
}
/**
* Returns the PointerToRawData value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @return PointerToRawData value of the debug structure.
**/
dword DebugDirectory::getPointerToRawData(std::size_t uiIndex) const
{
return m_vDebugInfo[uiIndex].idd.PointerToRawData;
}
std::vector<byte> DebugDirectory::getData(std::size_t index) const
{
return m_vDebugInfo[index].data;
}
/**
* Changes the Characteristics value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @param dwValue New value of the Characteristics value of the debug structure.
**/
void DebugDirectory::setCharacteristics(std::size_t uiIndex, dword dwValue)
{
m_vDebugInfo[uiIndex].idd.Characteristics = dwValue;
}
/**
* Changes the TimeDateStamp value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @param dwValue New value of the TimeDateStamp value of the debug structure.
**/
void DebugDirectory::setTimeDateStamp(std::size_t uiIndex, dword dwValue)
{
m_vDebugInfo[uiIndex].idd.TimeDateStamp = dwValue;
}
/**
* Changes the MajorVersion value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @param wValue New value of the MajorVersion value of the debug structure.
**/
void DebugDirectory::setMajorVersion(std::size_t uiIndex, word wValue)
{
m_vDebugInfo[uiIndex].idd.MajorVersion = wValue;
}
/**
* Changes the MinorVersion value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @param wValue New value of the MinorVersion value of the debug structure.
**/
void DebugDirectory::setMinorVersion(std::size_t uiIndex, word wValue)
{
m_vDebugInfo[uiIndex].idd.MinorVersion = wValue;
}
/**
* Changes the Type value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @param dwValue New value of the Type value of the debug structure.
**/
void DebugDirectory::setType(std::size_t uiIndex, dword dwValue)
{
m_vDebugInfo[uiIndex].idd.Type = dwValue;
}
/**
* Changes the SizeOfData value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @param dwValue New value of the SizeOfData value of the debug structure.
**/
void DebugDirectory::setSizeOfData(std::size_t uiIndex, dword dwValue)
{
m_vDebugInfo[uiIndex].idd.SizeOfData = dwValue;
}
/**
* Changes the AddressOfRawData value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @param dwValue New value of the AddressOfRawData value of the debug structure.
**/
void DebugDirectory::setAddressOfRawData(std::size_t uiIndex, dword dwValue)
{
m_vDebugInfo[uiIndex].idd.AddressOfRawData = dwValue;
}
/**
* Changes the PointerToRawData value of a debug structure. If an invalid structure is specified
* by the parameter uiIndex the result will be undefined behaviour.
* @param uiIndex Identifies the debug structure.
* @param dwValue New value of the PointerToRawData value of the debug structure.
**/
void DebugDirectory::setPointerToRawData(std::size_t uiIndex, dword dwValue)
{
m_vDebugInfo[uiIndex].idd.PointerToRawData = dwValue;
}
void DebugDirectory::setData(std::size_t index, const std::vector<byte>& data)
{
m_vDebugInfo[index].data = data;
}
const std::vector<std::pair<unsigned int, unsigned int>>& DebugDirectory::getOccupiedAddresses() const
{
return m_occupiedAddresses;
}
}

View File

@ -0,0 +1,474 @@
/*
* ExportDirectory.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include "pelib/PeLibInc.h"
#include "pelib/ExportDirectory.h"
namespace PeLib
{
/**
* @param strFuncname Name of the function.
* @param dwFuncAddr RVA of the function.
**/
void ExportDirectory::addFunction(const std::string& strFuncname, dword dwFuncAddr)
{
PELIB_EXP_FUNC_INFORMATION efiCurr;
efiCurr.funcname = strFuncname;
efiCurr.addroffunc = dwFuncAddr;
m_ied.functions.push_back(efiCurr);
}
void ExportDirectory::removeFunction(unsigned int index)
{
m_ied.functions.erase(m_ied.functions.begin() + index);
}
void ExportDirectory::clear()
{
m_ied.functions.clear();
}
unsigned int ExportDirectory::calcNumberOfFunctions() const
{
return static_cast<unsigned int>(m_ied.functions.size());
}
/**
* Identifies an exported function through it's name.
* @param strFunctionName Name of the function
* @return Number which identifies the functions.
**/
int ExportDirectory::getFunctionIndex(const std::string& strFunctionName) const
{
auto Iter = std::find_if(
m_ied.functions.begin(),
m_ied.functions.end(),
[&](const auto& i) { return i.equal(strFunctionName); }
);
if (Iter == m_ied.functions.end())
{
// throw Exceptions::InvalidName(ExportDirectoryId, __LINE__);
return -1;
}
return static_cast<int>(std::distance(m_ied.functions.begin(), Iter));
}
/**
* @param vBuffer Buffer where the rebuilt export directory is written to.
* @param dwRva RVA of the export directory.
* \todo fValid flag
**/
void ExportDirectory::rebuild(std::vector<byte>& vBuffer, dword dwRva) const
{
unsigned int uiSizeDirectory = sizeof(PELIB_IMAGE_EXPORT_DIRECTORY);
unsigned int uiSizeNames = 0;
unsigned int uiSizeAddrFuncs = 0;
unsigned int uiSizeAddrNames = 0;
unsigned int uiSizeOrdinals = 0;
for (unsigned int i=0;i<m_ied.functions.size();i++)
{
uiSizeNames += (m_ied.functions[i].funcname.empty()) ? 0 : static_cast<unsigned int>(m_ied.functions[i].funcname.size()) + 1;
uiSizeAddrFuncs += sizeof(m_ied.functions[i].addroffunc);
uiSizeAddrNames += (m_ied.functions[i].funcname.empty()) ? 0 : sizeof(m_ied.functions[i].addrofname);
uiSizeOrdinals += (m_ied.functions[i].funcname.empty()) ? 0 : sizeof(m_ied.functions[i].ordinal);
}
unsigned int uiFilenameSize = static_cast<unsigned int>(m_ied.name.size()) + 1;
OutputBuffer obBuffer(vBuffer);
obBuffer << m_ied.ied.Characteristics;
obBuffer << m_ied.ied.TimeDateStamp;
obBuffer << m_ied.ied.MajorVersion;
obBuffer << m_ied.ied.MinorVersion;
obBuffer << dwRva + uiSizeDirectory + uiSizeAddrFuncs + uiSizeAddrNames + uiSizeOrdinals;
obBuffer << m_ied.ied.Base;
obBuffer << static_cast<unsigned int>(m_ied.functions.size());
// TODO: Not correct but sufficient for now. (Update: I forgot what this comment refers to, but I'll leave it in)
obBuffer << static_cast<unsigned int>(m_ied.functions.size());
obBuffer << dwRva + uiSizeDirectory;
obBuffer << dwRva + uiSizeDirectory + uiSizeAddrFuncs;
obBuffer << dwRva + uiSizeDirectory + uiSizeAddrFuncs + uiSizeAddrNames;
for (unsigned int i=0;i<m_ied.functions.size();i++)
{
obBuffer << m_ied.functions[i].addroffunc;
}
unsigned int ulFuncCounter = dwRva + uiSizeDirectory + uiSizeAddrFuncs + uiSizeAddrNames + uiSizeOrdinals + uiFilenameSize;
for (unsigned int i=0;i<m_ied.functions.size();i++)
{
if (!m_ied.functions[i].funcname.empty())
{
obBuffer << ulFuncCounter;
ulFuncCounter += static_cast<unsigned int>(m_ied.functions[i].funcname.size()) + 1;
}
}
for (unsigned int i=0;i<m_ied.functions.size();i++)
{
if (!m_ied.functions[i].funcname.empty())
{
obBuffer << m_ied.functions[i].ordinal;
}
}
for (unsigned int i=0;i<m_ied.functions.size();i++)
{
if (m_ied.functions[i].funcname.empty() && m_ied.functions[i].addroffunc)
{
obBuffer << m_ied.functions[i].ordinal;
}
}
obBuffer.add(m_ied.name.c_str(), static_cast<unsigned int>(m_ied.name.size())+1);
for (unsigned int i=0;i<m_ied.functions.size();i++)
{
if (!m_ied.functions[i].funcname.empty())
{
obBuffer.add(m_ied.functions[i].funcname.c_str(), static_cast<unsigned int>(m_ied.functions[i].funcname.size()) + 1);
}
}
}
/**
* @return Size of the current export directory.
**/
unsigned int ExportDirectory::size() const
{
return m_ied.size();
}
/**
* @param strFilename Name of the file.
* @param uiOffset File offset the export directory will be written to.
* @param uiRva RVA of the export directory.
* \todo Check if ofFile.write succeeded.
**/
int ExportDirectory::write(const std::string& strFilename, unsigned int uiOffset, unsigned int uiRva) const
{
std::fstream ofFile(strFilename.c_str(), std::ios_base::in);
if (!ofFile)
{
ofFile.clear();
ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary);
}
else
{
ofFile.close();
ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
}
if (!ofFile)
{
return ERROR_OPENING_FILE;
}
ofFile.seekp(uiOffset, std::ios::beg);
std::vector<unsigned char> vBuffer;
rebuild(vBuffer, uiRva);
ofFile.write(reinterpret_cast<const char*>(vBuffer.data()), static_cast<unsigned int>(vBuffer.size()));
ofFile.close();
return ERROR_NONE;
}
/**
* Changes the filename according to the export directory.
* @param strFilename New filename.
**/
void ExportDirectory::setNameString(const std::string& strFilename)
{
m_ied.name = strFilename;
}
std::string ExportDirectory::getNameString() const
{
return m_ied.name;
}
/**
* @param dwIndex Number which identifies an exported function.
* @return The name of that function.
**/
std::string ExportDirectory::getFunctionName(std::size_t dwIndex) const
{
return m_ied.functions[dwIndex].funcname;
}
/**
* @param dwIndex Number which identifies an exported function.
* @return The ordinal of that function.
**/
word ExportDirectory::getFunctionOrdinal(std::size_t dwIndex) const
{
return m_ied.functions[dwIndex].ordinal;
}
/**
* @param dwIndex Number which identifies an exported function.
* @return The RVA of the name string of that function.
**/
dword ExportDirectory::getAddressOfName(std::size_t dwIndex) const
{
return m_ied.functions[dwIndex].addrofname;
}
/**
* @param dwIndex Number which identifies an exported function.
* @return The RVA of that function.
**/
dword ExportDirectory::getAddressOfFunction(std::size_t dwIndex) const
{
return m_ied.functions[dwIndex].addroffunc;
}
/**
* @param dwIndex Number which identifies an exported function.
* @param strName The name of that function.
**/
void ExportDirectory::setFunctionName(std::size_t dwIndex, const std::string& strName)
{
m_ied.functions[dwIndex].funcname = strName;
}
/**
* @param dwIndex Number which identifies an exported function.
* @param wValue The ordinal of that function.
**/
void ExportDirectory::setFunctionOrdinal(std::size_t dwIndex, word wValue)
{
m_ied.functions[dwIndex].ordinal = wValue;
}
/**
* @param dwIndex Number which identifies an exported function.
* @param dwValue The RVA of the name string of that function.
**/
void ExportDirectory::setAddressOfName(std::size_t dwIndex, dword dwValue)
{
m_ied.functions[dwIndex].addrofname = dwValue;
}
/**
* @param dwIndex Number which identifies an exported function.
* @param dwValue The RVA of that function.
**/
void ExportDirectory::setAddressOfFunction(std::size_t dwIndex, dword dwValue)
{
m_ied.functions[dwIndex].addroffunc = dwValue;
}
/**
* @return The ordinal base of the export directory.
**/
dword ExportDirectory::getBase() const
{
return m_ied.ied.Base;
}
/**
* @return The characteristics of the export directory.
**/
dword ExportDirectory::getCharacteristics() const
{
return m_ied.ied.Characteristics;
}
/**
* @return The time/date stamp of the export directory.
**/
dword ExportDirectory::getTimeDateStamp() const
{
return m_ied.ied.TimeDateStamp;
}
/**
* @return The MajorVersion of the export directory.
**/
word ExportDirectory::getMajorVersion() const
{
return m_ied.ied.MajorVersion;
}
/**
* @return The MinorVersion of the export directory.
**/
word ExportDirectory::getMinorVersion() const
{
return m_ied.ied.MinorVersion;
}
/**
* @return The RVA of the name of the file.
**/
dword ExportDirectory::getName() const
{
return m_ied.ied.Name;
}
/**
* @return The NumberOfFunctions of the export directory.
**/
dword ExportDirectory::getNumberOfFunctions() const
{
return m_ied.ied.NumberOfFunctions;
}
/**
* @return The NumberOfNames of the export directory.
**/
dword ExportDirectory::getNumberOfNames() const
{
return m_ied.ied.NumberOfNames;
}
/**
* @return The AddressOfFunctions of the export directory.
**/
dword ExportDirectory::getAddressOfFunctions() const
{
return m_ied.ied.AddressOfFunctions;
}
/**
* @return The AddressOfNames of the export directory.
**/
dword ExportDirectory::getAddressOfNames() const
{
return m_ied.ied.AddressOfNames;
}
/* dword ExportDirectory::getNumberOfNameOrdinals() const
{
return static_cast<dword>(m_ied.functions.size());
}
dword ExportDirectory::getNumberOfAddressOfFunctionNames() const
{
return static_cast<dword>(m_ied.functions.size());
}
dword ExportDirectory::getNumberOfAddressOfFunctions() const
{
return static_cast<dword>(m_ied.functions.size());
}
*/
/**
* @return The AddressOfNameOrdinals of the export directory.
**/
dword ExportDirectory::getAddressOfNameOrdinals() const
{
return m_ied.ied.AddressOfNameOrdinals;
}
/**
* @param dwValue The ordinal base of the export directory.
**/
void ExportDirectory::setBase(dword dwValue)
{
m_ied.ied.Base = dwValue;
}
/**
* @param dwValue The Characteristics of the export directory.
**/
void ExportDirectory::setCharacteristics(dword dwValue)
{
m_ied.ied.Characteristics = dwValue;
}
/**
* @param dwValue The TimeDateStamp of the export directory.
**/
void ExportDirectory::setTimeDateStamp(dword dwValue)
{
m_ied.ied.TimeDateStamp = dwValue;
}
/**
* @param wValue The MajorVersion of the export directory.
**/
void ExportDirectory::setMajorVersion(word wValue)
{
m_ied.ied.MajorVersion = wValue;
}
/**
* @param wValue The MinorVersion of the export directory.
**/
void ExportDirectory::setMinorVersion(word wValue)
{
m_ied.ied.MinorVersion = wValue;
}
/**
* @param dwValue The Name of the export directory.
**/
void ExportDirectory::setName(dword dwValue)
{
m_ied.ied.Name = dwValue;
}
/**
* @param dwValue The NumberOfFunctions of the export directory.
**/
void ExportDirectory::setNumberOfFunctions(dword dwValue)
{
m_ied.ied.NumberOfFunctions = dwValue;
}
/**
* @param dwValue The NumberOfNames of the export directory.
**/
void ExportDirectory::setNumberOfNames(dword dwValue)
{
m_ied.ied.NumberOfNames = dwValue;
}
/**
* @param dwValue The AddressOfFunctions of the export directory.
**/
void ExportDirectory::setAddressOfFunctions(dword dwValue)
{
m_ied.ied.AddressOfFunctions = dwValue;
}
/**
* @param dwValue The AddressOfNames of the export directory.
**/
void ExportDirectory::setAddressOfNames(dword dwValue)
{
m_ied.ied.AddressOfNames = dwValue;
}
void ExportDirectory::setAddressOfNameOrdinals(dword value)
{
m_ied.ied.AddressOfNameOrdinals = value;
}
const std::vector<std::pair<unsigned int, unsigned int>>& ExportDirectory::getOccupiedAddresses() const
{
return m_occupiedAddresses;
}
}

155
src/pelib/IatDirectory.cpp Normal file
View File

@ -0,0 +1,155 @@
/*
* IatDirectory.h - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include "pelib/IatDirectory.h"
namespace PeLib
{
int IatDirectory::read(InputBuffer& inputBuffer, unsigned int dwOffset, unsigned int dwFileSize)
{
dword dwAddr;
std::vector<dword> vIat;
unsigned int dwCurrentOffset = dwOffset;
while (dwCurrentOffset < dwFileSize)
{
inputBuffer >> dwAddr;
if (dwAddr == 0)
break;
vIat.push_back(dwAddr);
dwCurrentOffset += sizeof(dwAddr);
}
std::swap(vIat, m_vIat);
return ERROR_NONE;
}
int IatDirectory::read(unsigned char* buffer, unsigned int buffersize)
{
std::vector<byte> vBuffer(buffer, buffer + buffersize);
InputBuffer inpBuffer(vBuffer);
return read(inpBuffer, 0, buffersize);
}
/**
* Returns the number of fields in the IAT. This is equivalent to the number of
* imported functions.
* @return Number of fields in the IAT.
**/
unsigned int IatDirectory::calcNumberOfAddresses() const
{
return static_cast<unsigned int>(m_vIat.size());
}
/**
* Returns the dwValue of a field in the IAT.
* @param dwAddrnr Number identifying the field.
* @return dwValue of the field.
**/
dword IatDirectory::getAddress(unsigned int index) const
{
return m_vIat[index];
}
/**
* Updates the dwValue of a field in the IAT.
* @param dwAddrnr Number identifying the field.
* @param dwValue New dwValue of the field.
**/
void IatDirectory::setAddress(dword dwAddrnr, dword dwValue)
{
m_vIat[dwAddrnr] = dwValue;
}
/**
* Adds another field to the IAT.
* @param dwValue dwValue of the new field.
**/
void IatDirectory::addAddress(dword dwValue)
{
m_vIat.push_back(dwValue);
}
/**
* Removes an address from the IAT.
* @param dwAddrnr Number identifying the field.
**/
void IatDirectory::removeAddress(unsigned int index)
{
std::vector<dword>::iterator pos = m_vIat.begin() + index;
m_vIat.erase(pos);
}
/**
* Delete all entries from the IAT.
**/
void IatDirectory::clear()
{
m_vIat.clear();
}
/**
* Rebuilds the complete Import Address Table.
* @param vBuffer Buffer where the rebuilt IAT will be stored.
**/
void IatDirectory::rebuild(std::vector<byte>& vBuffer) const
{
vBuffer.resize(size());
OutputBuffer obBuffer(vBuffer);
for (unsigned int i=0;i<m_vIat.size();i++)
{
obBuffer << m_vIat[i];
}
}
unsigned int IatDirectory::size() const
{
return static_cast<unsigned int>(m_vIat.size())* sizeof(dword);
}
/// Writes the current IAT to a file.
int IatDirectory::write(const std::string& strFilename, unsigned int uiOffset) const
{
std::fstream ofFile(strFilename.c_str(), std::ios_base::in);
if (!ofFile)
{
ofFile.clear();
ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary);
}
else
{
ofFile.close();
ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
}
if (!ofFile)
{
return ERROR_OPENING_FILE;
}
ofFile.seekp(uiOffset, std::ios::beg);
std::vector<unsigned char> vBuffer;
rebuild(vBuffer);
ofFile.write(reinterpret_cast<const char*>(vBuffer.data()), static_cast<unsigned int>(vBuffer.size()));
ofFile.close();
return ERROR_NONE;
}
}

68
src/pelib/InputBuffer.cpp Normal file
View File

@ -0,0 +1,68 @@
/*
* InputBuffer.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include "pelib/InputBuffer.h"
namespace PeLib
{
InputBuffer::InputBuffer(std::vector<unsigned char>& vBuffer) : m_vBuffer(vBuffer), ulIndex(0)
{
}
const unsigned char* InputBuffer::data() const
{
return m_vBuffer.data();
}
unsigned long InputBuffer::size()
{
return static_cast<unsigned long>(m_vBuffer.size());
}
void InputBuffer::read(char* lpBuffer, unsigned long ulSize)
{
if (ulIndex >= m_vBuffer.size())
return;
ulSize = (unsigned long)(ulIndex + ulSize > m_vBuffer.size() ? m_vBuffer.size() - ulIndex : ulSize);
std::copy(m_vBuffer.data() + ulIndex, m_vBuffer.data() + ulIndex + ulSize, lpBuffer);
ulIndex += ulSize;
}
void InputBuffer::reset()
{
m_vBuffer.clear();
}
void InputBuffer::set(unsigned long ulIndex2)
{
this->ulIndex = ulIndex2;
}
void InputBuffer::move(unsigned long shift)
{
ulIndex += shift;
}
unsigned long InputBuffer::get()
{
return ulIndex;
}
void InputBuffer::setBuffer(std::vector<unsigned char>& vBuffer)
{
m_vBuffer = vBuffer;
ulIndex = 0;
}
}

636
src/pelib/MzHeader.cpp Normal file
View File

@ -0,0 +1,636 @@
/*
* MzHeader.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include <iostream>
#include "pelib/MzHeader.h"
namespace PeLib
{
/**
* Reads data from an InputBuffer into the struct that represents the MZ header.
* It's required that the size of the input buffer is at least as big as the
* size of a MZ header. Otherwise we get undefined behaviour.
* @param ibBuffer InputBuffer that holds the data.
* @return A non-zero value is returned if a problem occured.
**/
void MzHeader::read(InputBuffer& ibBuffer)
{
ibBuffer >> m_idhHeader.e_magic;
ibBuffer >> m_idhHeader.e_cblp;
ibBuffer >> m_idhHeader.e_cp;
ibBuffer >> m_idhHeader.e_crlc;
ibBuffer >> m_idhHeader.e_cparhdr;
ibBuffer >> m_idhHeader.e_minalloc;
ibBuffer >> m_idhHeader.e_maxalloc;
ibBuffer >> m_idhHeader.e_ss;
ibBuffer >> m_idhHeader.e_sp;
ibBuffer >> m_idhHeader.e_csum;
ibBuffer >> m_idhHeader.e_ip;
ibBuffer >> m_idhHeader.e_cs;
ibBuffer >> m_idhHeader.e_lfarlc;
ibBuffer >> m_idhHeader.e_ovno;
for (unsigned int i=0;i<sizeof(m_idhHeader.e_res)/sizeof(m_idhHeader.e_res[0]);i++)
{
ibBuffer >> m_idhHeader.e_res[i];
}
ibBuffer >> m_idhHeader.e_oemid;
ibBuffer >> m_idhHeader.e_oeminfo;
for (unsigned int i=0;i<sizeof(m_idhHeader.e_res2)/sizeof(m_idhHeader.e_res2[0]);i++)
{
ibBuffer >> m_idhHeader.e_res2[i];
}
ibBuffer >> m_idhHeader.e_lfanew;
}
MzHeader::MzHeader(): originalOffset(0), m_ldrError() {}
/**
* Tests if the currently loaded MZ header is a valid MZ header.
* Note that this function does not check if the address to the PE header is valid as this is not possible.
* Actually, the only thing this function checks is if the e_magic value is set to 0x5A4D (IMAGE_DOS_SIGNATURE).
* Everything else is not relevant for Windows 2000 and that's the system PeLib is focusing on for now.
* @return A boolean value that indicates if the MZ header is correct or not.
**/
bool MzHeader::isValid() const
{
// The only thing that matters on Windows 2K is the e_magic value. The entire rest is for DOS compatibility.
return isValid(e_magic);
}
bool MzHeader::isValid(Field f) const
{
if (f == e_magic)
{
return m_idhHeader.e_magic == PELIB_IMAGE_DOS_SIGNATURE;
}
else
{
return true;
}
}
void MzHeader::setLoaderError(LoaderError ldrError)
{
// Do not override an existing loader error
if (m_ldrError == LDR_ERROR_NONE)
{
m_ldrError = ldrError;
}
}
LoaderError MzHeader::loaderError() const
{
return m_ldrError;
}
/**
* Corrects all erroneous values of the current MZ header. Note that this function does not correct the
* pointer to the PE header.
* Actually, the only thing this function corrects is the e_magic value.
* Everything else is not relevant for Windows 2000 and that's the system PeLib is focusing on for now.
**/
void MzHeader::makeValid()
{
// The only thing that matters on Windows is the e_magic value. The entire rest is for DOS compatibility.
setMagicNumber(PELIB_IMAGE_DOS_SIGNATURE);
}
void MzHeader::makeValid(Field f)
{
if (f == e_magic)
{
setMagicNumber(PELIB_IMAGE_DOS_SIGNATURE);
}
}
/**
* Reads the MZ header from a file. Note that this function does not verify if a file is actually a MZ file.
* For this purpose see #PeFile::MzHeader::isValid. The reason for this is simple: Otherwise it might not
* be possible to load damaged PE files to repair them.
* @param inStream Input stream.
* @return A non-zero value is returned if a problem occured.
**/
int MzHeader::read(std::istream& inStream)
{
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
std::uint64_t ulFileSize = fileSize(inStream_w);
if (ulFileSize < PELIB_IMAGE_DOS_HEADER::size())
{
return ERROR_INVALID_FILE;
}
// Windows loader refuses to load any file which is larger than 0xFFFFFFFF
if ((ulFileSize >> 32) != 0)
{
setLoaderError(LDR_ERROR_FILE_TOO_BIG);
}
inStream_w.seekg(0, std::ios::beg);
originalOffset = 0;
std::vector<byte> vBuffer(PELIB_IMAGE_DOS_HEADER::size());
inStream_w.read(reinterpret_cast<char*>(vBuffer.data()), static_cast<unsigned int>(vBuffer.size()));
inStream_w.seekg(0, std::ios::beg);
m_headerString.clear();
m_headerString.resize(PELIB_IMAGE_DOS_HEADER::size());
inStream_w.read(&m_headerString[0], PELIB_IMAGE_DOS_HEADER::size());
InputBuffer ibBuffer(vBuffer);
read(ibBuffer);
// For 64-bit systems, the e_lfanew must be aligned to 4
if (m_idhHeader.e_lfanew & 3)
setLoaderError(LDR_ERROR_E_LFANEW_UNALIGNED);
// The offset of PE header must not be out of file
if (m_idhHeader.e_lfanew > (std::uint32_t)ulFileSize)
setLoaderError(LDR_ERROR_E_LFANEW_OUT_OF_FILE);
return ERROR_NONE;
}
/**
* Reads the MZ header from memory. A pointer to a location in memory is passed and the data
* at this location is treated like a MZ header structure. The MZ header does not need to be valid.
* @param pcBuffer Pointer to a MZ header.
* @param uiSize Length of the buffer.
* @return A non-zero value is returned if a problem occured.
**/
int MzHeader::read(unsigned char* pcBuffer, unsigned int uiSize, unsigned int originalOffs)
{
if (uiSize < PELIB_IMAGE_DOS_HEADER::size())
{
return ERROR_INVALID_FILE;
}
std::vector<byte> vBuffer(pcBuffer, pcBuffer + uiSize);
for (int i=0;i<0x40;i++) std::cout << std::hex << (int)vBuffer[i] << " ";
originalOffset = originalOffs;
InputBuffer ibBuffer(vBuffer);
read(ibBuffer);
return ERROR_NONE;
}
/**
* Rebuilds the MZ header so that it can be written to a file. It's not guaranteed that the
* MZ header will be valid. If you want to make sure that the MZ header will be valid you
* must call #PeLib::MzHeader::makeValid first.
* @param vBuffer Buffer where the rebuilt MZ header will be stored.
**/
void MzHeader::rebuild(std::vector<byte>& vBuffer) const
{
OutputBuffer obBuffer(vBuffer);
obBuffer << m_idhHeader.e_magic;
obBuffer << m_idhHeader.e_cblp;
obBuffer << m_idhHeader.e_cp;
obBuffer << m_idhHeader.e_crlc;
obBuffer << m_idhHeader.e_cparhdr;
obBuffer << m_idhHeader.e_minalloc;
obBuffer << m_idhHeader.e_maxalloc;
obBuffer << m_idhHeader.e_ss;
obBuffer << m_idhHeader.e_sp;
obBuffer << m_idhHeader.e_csum;
obBuffer << m_idhHeader.e_ip;
obBuffer << m_idhHeader.e_cs;
obBuffer << m_idhHeader.e_lfarlc;
obBuffer << m_idhHeader.e_ovno;
for (unsigned int i=0;i<sizeof(m_idhHeader.e_res)/sizeof(m_idhHeader.e_res[0]);i++)
{
obBuffer << m_idhHeader.e_res[i];
}
obBuffer << m_idhHeader.e_oemid;
obBuffer << m_idhHeader.e_oeminfo;
for (unsigned int i=0;i<sizeof(m_idhHeader.e_res2)/sizeof(m_idhHeader.e_res2[0]);i++)
{
obBuffer << m_idhHeader.e_res2[i];
}
obBuffer << m_idhHeader.e_lfanew;
}
/**
* Returns the size of the MZ header. This size is actually always sizeof(IMAGE_DOS_HEADER) (== 0x40)
* because the MZ header is a header of constant size if you disregard the dos stub. If you want to know the
* size of the MZ header + the size of the dos stub check #PeLib::MzHeader::getAddressOfPeHeader.
* @return Size of the MZ header.
**/
unsigned int MzHeader::size() const
{
return sizeof(m_idhHeader);
}
/**
* Writes the current MZ header to a file. The file does not have to exist. If it doesn't exist
* it will be created.
* @param strFilename Name of the file the header will be written to.
* @param dwOffset Offset the header will be written to (defaults to 0).
* @return A non-zero value is returned if a problem occured.
**/
int MzHeader::write(const std::string& strFilename, dword dwOffset = 0) const
{
std::fstream ofFile(strFilename.c_str(), std::ios_base::in);
if (!ofFile)
{
ofFile.clear();
ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary);
}
else
{
ofFile.close();
ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
}
if (!ofFile)
{
return ERROR_OPENING_FILE;
}
ofFile.seekp(dwOffset, std::ios::beg);
std::vector<unsigned char> vBuffer;
rebuild(vBuffer);
ofFile.write(reinterpret_cast<const char*>(vBuffer.data()), static_cast<unsigned int>(vBuffer.size()));
ofFile.close();
return ERROR_NONE;
}
/**
* Returns the MZ header.
**/
const PELIB_IMAGE_DOS_HEADER& MzHeader::getHeader() const
{
return m_idhHeader;
}
/**
* Returns the MZ header in string representation.
**/
const std::string& MzHeader::getString() const
{
return m_headerString;
}
/**
* Returns the MZ header's e_magic value.
**/
word MzHeader::getMagicNumber() const
{
return m_idhHeader.e_magic;
}
/**
* Returns the MZ header's e_cblp value.
**/
word MzHeader::getBytesOnLastPage() const
{
return m_idhHeader.e_cblp;
}
/**
* Returns the MZ header's e_cp value.
**/
word MzHeader::getPagesInFile() const
{
return m_idhHeader.e_cp;
}
/**
* Returns the MZ header's e_crlc value.
**/
word MzHeader::getRelocations() const
{
return m_idhHeader.e_crlc;
}
/**
* Returns the MZ header's e_cparhdr value.
**/
word MzHeader::getSizeOfHeader() const
{
return m_idhHeader.e_cparhdr;
}
/**
* Returns the MZ header's e_minalloc value.
**/
word MzHeader::getMinExtraParagraphs() const
{
return m_idhHeader.e_minalloc;
}
/**
* Returns the MZ header's e_maxalloc value.
**/
word MzHeader::getMaxExtraParagraphs() const
{
return m_idhHeader.e_maxalloc;
}
/**
* Returns the MZ header's e_ss value.
**/
word MzHeader::getSsValue() const
{
return m_idhHeader.e_ss;
}
/**
* Returns the MZ header's e_sp value.
**/
word MzHeader::getSpValue() const
{
return m_idhHeader.e_sp;
}
/**
* Returns the MZ header's e_csum value.
**/
word MzHeader::getChecksum() const
{
return m_idhHeader.e_csum;
}
/**
* Returns the MZ header's e_ip value.
**/
word MzHeader::getIpValue() const
{
return m_idhHeader.e_ip;
}
/**
* Returns the MZ header's e_cs value.
**/
word MzHeader::getCsValue() const
{
return m_idhHeader.e_cs;
}
/**
* Returns the MZ header's e_lfarlc value.
**/
word MzHeader::getAddrOfRelocationTable() const
{
return m_idhHeader.e_lfarlc;
}
/**
* Returns the MZ header's e_ovno value.
**/
word MzHeader::getOverlayNumber() const
{
return m_idhHeader.e_ovno;
}
/**
* Returns the MZ header's e_oemid value.
**/
word MzHeader::getOemIdentifier() const
{
return m_idhHeader.e_oemid;
}
/**
* Returns the MZ header's e_oeminfo value.
**/
word MzHeader::getOemInformation() const
{
return m_idhHeader.e_oeminfo;
}
/**
* Returns the MZ header's e_lfanew value.
**/
dword MzHeader::getAddressOfPeHeader() const
{
return m_idhHeader.e_lfanew;
}
/**
* Returns the MZ header's e_res[uiNr] value. If the parameter uiNr is out of range
* you will get undefined behaviour.
* @param uiNr The index of the word in the e_res array (valid range: 0-3)
**/
word MzHeader::getReservedWords1(unsigned int uiNr) const
{
return m_idhHeader.e_res[uiNr];
}
/**
* Returns the MZ header's e_res2[uiNr] value. If the parameter uiNr is out of range
* you will get undefined behaviour.
* @param uiNr The index of the word in the e_res array (valid range: 0-9)
**/
word MzHeader::getReservedWords2(unsigned int uiNr) const
{
return m_idhHeader.e_res2[uiNr];
}
/**
* Sets the MZ header's e_magic value.
* @param wValue The new value of e_magic.
**/
void MzHeader::setMagicNumber(word wValue)
{
m_idhHeader.e_magic = wValue;
}
/**
* Sets the MZ header's e_cblp value.
* @param wValue The new value of e_cblp.
**/
void MzHeader::setBytesOnLastPage(word wValue)
{
m_idhHeader.e_cblp = wValue;
}
/**
* Sets the MZ header's e_cp value.
* @param wValue The new value of e_cp.
**/
void MzHeader::setPagesInFile(word wValue)
{
m_idhHeader.e_cp = wValue;
}
/**
* Sets the MZ header's e_crlc value.
* @param wValue The new value of e_crlc.
**/
void MzHeader::setRelocations(word wValue)
{
m_idhHeader.e_crlc = wValue;
}
/**
* Sets the MZ header's e_cparhdr value.
* @param wValue The new value of e_cparhdr.
**/
void MzHeader::setSizeOfHeader(word wValue)
{
m_idhHeader.e_cparhdr = wValue;
}
/**
* Sets the MZ header's e_minalloc value.
* @param wValue The new value of e_minalloc.
**/
void MzHeader::setMinExtraParagraphs(word wValue)
{
m_idhHeader.e_minalloc = wValue;
}
/**
* Sets the MZ header's e_maxalloc value.
* @param wValue The new value of e_maxalloc.
**/
void MzHeader::setMaxExtraParagraphs(word wValue)
{
m_idhHeader.e_maxalloc = wValue;
}
/**
* Sets the MZ header's e_ss value.
* @param wValue The new value of e_ss.
**/
void MzHeader::setSsValue(word wValue)
{
m_idhHeader.e_ss = wValue;
}
/**
* Sets the MZ header's e_sp value.
* @param wValue The new value of e_sp.
**/
void MzHeader::setSpValue(word wValue)
{
m_idhHeader.e_sp = wValue;
}
/**
* Sets the MZ header's e_csum value.
* @param wValue The new value of e_csum.
**/
void MzHeader::setChecksum(word wValue)
{
m_idhHeader.e_csum = wValue;
}
/**
* Sets the MZ header's e_ip value.
* @param wValue The new value of e_ip.
**/
void MzHeader::setIpValue(word wValue)
{
m_idhHeader.e_ip = wValue;
}
/**
* Sets the MZ header's e_cs value.
* @param wValue The new value of e_cs.
**/
void MzHeader::setCsValue(word wValue)
{
m_idhHeader.e_cs = wValue;
}
/**
* Sets the MZ header's e_lfarlc value.
* @param wValue The new value of e_lfarlc.
**/
void MzHeader::setAddrOfRelocationTable(word wValue)
{
m_idhHeader.e_lfarlc = wValue;
}
/**
* Sets the MZ header's e_ovno value.
* @param wValue The new value of e_ovno.
**/
void MzHeader::setOverlayNumber(word wValue)
{
m_idhHeader.e_ovno = wValue;
}
/**
* Sets the MZ header's e_oemid value.
* @param wValue The new value of e_oemid.
**/
void MzHeader::setOemIdentifier(word wValue)
{
m_idhHeader.e_oemid = wValue;
}
/**
* Sets the MZ header's e_oeminfo value.
* @param wValue The new value of e_oeminfo.
**/
void MzHeader::setOemInformation(word wValue)
{
m_idhHeader.e_oeminfo = wValue;
}
/**
* Sets the MZ header's e_lfanew value.
* @param lValue The new value of e_lfanew.
**/
void MzHeader::setAddressOfPeHeader(dword lValue)
{
m_idhHeader.e_lfanew = lValue;
}
/**
* Sets the MZ header's e_res[uiNr] value. If the parameter uiNr is out of range
* you will get undefined behaviour.
* @param uiNr The index of the word in the e_res array (valid range: 0-3)
* @param wValue The new value of e_res[nr].
**/
void MzHeader::setReservedWords1(unsigned int uiNr, word wValue)
{
m_idhHeader.e_res[uiNr] = wValue;
}
/**
* Sets the MZ header's e_res2[uiNr] value. If the parameter uiNr is out of range
* you will get undefined behaviour.
* @param uiNr The index of the word in the e_res2 array (valid range: 0-9)
* @param wValue The new value of e_res[nr].
**/
void MzHeader::setReservedWords2(unsigned int uiNr, word wValue)
{
m_idhHeader.e_res2[uiNr] = wValue;
}
}

View File

@ -0,0 +1,46 @@
/*
* OutputBuffer.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include "pelib/OutputBuffer.h"
namespace PeLib
{
OutputBuffer::OutputBuffer(std::vector<unsigned char>& vBuffer) : m_vBuffer(vBuffer)
{
m_vBuffer.clear();
}
const unsigned char* OutputBuffer::data() const
{
return m_vBuffer.data();
}
unsigned long OutputBuffer::size()
{
return static_cast<unsigned long>(m_vBuffer.size());
}
void OutputBuffer::add(const char* lpBuffer, unsigned long ulSize)
{
std::copy(lpBuffer, lpBuffer + ulSize, std::back_inserter(m_vBuffer));
}
void OutputBuffer::reset()
{
m_vBuffer.clear();
}
void OutputBuffer::resize(unsigned int uiSize)
{
m_vBuffer.resize(uiSize);
}
}

92
src/pelib/PeFile.cpp Normal file
View File

@ -0,0 +1,92 @@
/*
* PeLib.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include "pelib/PeFile.h"
namespace PeLib
{
PeFile::~PeFile()
{
}
PeFile32::PeFile32() : PeFileT<32>()
{
}
PeFile32::PeFile32(const std::string& strFlename) : PeFileT<32>(strFlename)
{
}
PeFile32::PeFile32(std::istream& stream) : PeFileT<32>(stream)
{
}
PeFile64::PeFile64() : PeFileT<64>()
{
}
PeFile64::PeFile64(const std::string& strFlename) : PeFileT<64>(strFlename)
{
}
PeFile64::PeFile64(std::istream& stream) : PeFileT<64>(stream)
{
}
/**
* @return A reference to the file's MZ header.
**/
const MzHeader& PeFile::mzHeader() const
{
return m_mzh;
}
/**
* @return A reference to the file's MZ header.
**/
MzHeader& PeFile::mzHeader()
{
return m_mzh;
}
const RichHeader& PeFile::richHeader() const
{
return m_richheader;
}
RichHeader& PeFile::richHeader()
{
return m_richheader;
}
const CoffSymbolTable& PeFile::coffSymTab() const
{
return m_coffsymtab;
}
CoffSymbolTable& PeFile::coffSymTab()
{
return m_coffsymtab;
}
const SecurityDirectory& PeFile::securityDir() const
{
return m_secdir;
}
SecurityDirectory& PeFile::securityDir()
{
return m_secdir;
}
}

92
src/pelib/PeHeader.cpp Normal file
View File

@ -0,0 +1,92 @@
/*
* PeHeader.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include "pelib/PeLibInc.h"
#include "pelib/PeHeader.h"
namespace PeLib
{
template<>
void PeHeaderT<32>::readBaseOfData(InputBuffer& ibBuffer, PELIB_IMAGE_NT_HEADERS<32>& header) const
{
ibBuffer >> header.OptionalHeader.BaseOfData;
}
template<>
void PeHeaderT<64>::readBaseOfData(InputBuffer&, PELIB_IMAGE_NT_HEADERS<64>&) const
{
}
template<>
void PeHeaderT<32>::rebuildBaseOfData(OutputBuffer& obBuffer) const
{
obBuffer << m_inthHeader.OptionalHeader.BaseOfData;
}
template<>
void PeHeaderT<64>::rebuildBaseOfData(OutputBuffer&) const
{
}
template<>
bool PeHeaderT<32>::isValid() const
{
return true;
}
template<>
bool PeHeaderT<64>::isValid() const
{
return true;
}
template<>
bool PeHeaderT<32>::isValid(unsigned int pehf) const
{
(void) pehf; /* avoid warning about unused parameter */
/*
if (pehf == NtSignature)
{
return m_inthHeader.Signature == IMAGE_NT_SIGNATURE;
}
else if (pehf == NumberOfSections)
{
return getNumberOfSections() == calcNumberOfSections();
} */
return false;
}
template<>
bool PeHeaderT<64>::isValid(unsigned int pehf) const
{
(void) pehf; /* avoid warning about unused parameter */
return false;
}
/**
* @return The BaseOfData value from the PE header.
**/
dword PeHeader32::getBaseOfData() const
{
return m_inthHeader.OptionalHeader.BaseOfData;
}
/**
* Changes the file's BaseOfData.
* @param dwValue New value.
**/
void PeHeader32::setBaseOfData(dword dwValue)
{
m_inthHeader.OptionalHeader.BaseOfData = dwValue;
}
}

523
src/pelib/PeLibAux.cpp Normal file
View File

@ -0,0 +1,523 @@
/*
* PeLibAux.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include <vector>
#ifdef _MSC_VER
#include <ctype.h>
#endif
#include "pelib/PeLibInc.h"
#include "pelib/PeLibAux.h"
#include "pelib/PeFile.h"
namespace PeLib
{
const qword PELIB_IMAGE_ORDINAL_FLAGS<64>::PELIB_IMAGE_ORDINAL_FLAG = 0x8000000000000000ULL;
// Keep in sync with PeLib::LoaderError!!!
static const std::vector<LoaderErrorString> LdrErrStrings =
{
{"LDR_ERROR_NONE", "No error"},
{"LDR_ERROR_FILE_TOO_BIG", "The file is larger than 4GB - 1"},
{"LDR_ERROR_E_LFANEW_UNALIGNED", "The IMAGE_DOS_HEADER::e_lfanew is not aligned to 4"},
{"LDR_ERROR_E_LFANEW_OUT_OF_FILE", "The IMAGE_DOS_HEADER::e_lfanew is out of (lower 4 GB of) the file"},
{"LDR_ERROR_NTHEADER_OFFSET_OVERFLOW", "NT header offset + sizeof(IMAGE_NT_HEADERS) overflow"},
{"LDR_ERROR_NTHEADER_OUT_OF_FILE", "NT header offset + sizeof(IMAGE_NT_HEADERS) is greater than filesize"},
{"LDR_ERROR_NO_NT_SIGNATURE", "Missing IMAGE_NT_SIGNATURE in the NT headers" },
{"LDR_ERROR_FILE_HEADER_INVALID", "Invalid IMAGE_FILE_HEADER::Machine or IMAGE_FILE_HEADER::SizeOfOptionalHeader" },
{"LDR_ERROR_IMAGE_NON_EXECUTABLE", "Missing IMAGE_FILE_EXECUTABLE_IMAGE in IMAGE_FILE_HEADER::Characteristics" },
{"LDR_ERROR_NO_OPTHDR_MAGIC", "Invalid IMAGE_OPTIONAL_HEADER::Magic" },
{"LDR_ERROR_SIZE_OF_HEADERS_ZERO", "IMAGE_OPTIONAL_HEADER::SizeOfHeaders is zero" },
{"LDR_ERROR_FILE_ALIGNMENT_ZERO", "IMAGE_OPTIONAL_HEADER::FileAlignment is zero" },
{"LDR_ERROR_FILE_ALIGNMENT_NOT_POW2", "IMAGE_OPTIONAL_HEADER::FileAlignment is not power of two" },
{"LDR_ERROR_SECTION_ALIGNMENT_ZERO", "IMAGE_OPTIONAL_HEADER::SectionAlignment is zero" },
{"LDR_ERROR_SECTION_ALIGNMENT_NOT_POW2", "IMAGE_OPTIONAL_HEADER::SectionAlignment is not power of two" },
{"LDR_ERROR_SECTION_ALIGNMENT_TOO_SMALL", "IMAGE_OPTIONAL_HEADER::SectionAlignment is smaller than IMAGE_OPTIONAL_HEADER::FileAlignment" },
{"LDR_ERROR_SECTION_ALIGNMENT_INVALID", "IMAGE_OPTIONAL_HEADER::SectionAlignment must be equal to FileAlignment for small alignments" },
{"LDR_ERROR_SIZE_OF_IMAGE_TOO_BIG", "IMAGE_OPTIONAL_HEADER::SizeOfImage is too big" },
{"LDR_ERROR_INVALID_MACHINE32", "IMAGE_FILE_HEADER::Machine is invalid for 32-bit optional header" },
{"LDR_ERROR_INVALID_MACHINE64", "IMAGE_FILE_HEADER::Machine is invalid for 64-bit optional header" },
{"LDR_ERROR_SIZE_OF_HEADERS_INVALID", "IMAGE_OPTIONAL_HEADER::SizeOfHeaders is greater than IMAGE_OPTIONAL_HEADER::SizeOfImage" },
{"LDR_ERROR_SIZE_OF_OPTHDR_NOT_ALIGNED", "IMAGE_OPTIONAL_HEADER::SizeOfHeaders is not aligned to 8 (64-bit Windows only)" },
{"LDR_ERROR_SIZE_OF_IMAGE_ZERO", "Number of PTEs for the entire image is zero" },
{"LDR_ERROR_IMAGE_BASE_NOT_ALIGNED", "IMAGE_OPTIONAL_HEADER::ImageBase is not aligned to 64KB" },
{"LDR_ERROR_SIZE_OF_IMAGE_PTES_ZERO", "Number of Page Table Entries for the image is zero" },
{"LDR_ERROR_RAW_DATA_OVERFLOW", "Overflow in section's raw data size" },
{"LDR_ERROR_SECTION_HEADERS_OUT_OF_IMAGE", "Section headers are out of the image" },
{"LDR_ERROR_SECTION_HEADERS_OVERFLOW", "Image with single subsection: size of headers is near the end of range" },
{"LDR_ERROR_SECTION_SIZE_MISMATCH", "Image with single subsection: virtual values with rawdata values don't match" },
{"LDR_ERROR_INVALID_SECTION_VA", "Invalid virtual address of a section" },
{"LDR_ERROR_INVALID_SECTION_VSIZE", "Invalid virtual size of a section" },
{"LDR_ERROR_INVALID_SECTION_RAWSIZE", "Invalid raw data size of a section" },
{"LDR_ERROR_INVALID_SIZE_OF_IMAGE", "IMAGE_OPTIONAL_HEADER::SizeOfImage doesn't match the (header+sections)" },
{"LDR_ERROR_FILE_IS_CUT", "The PE file is cut" },
{"LDR_ERROR_FILE_IS_CUT_LOADABLE", "The PE file is cut, but loadable" },
// Import directory detected errors
{"LDR_ERROR_IMPDIR_OUT_OF_FILE", "Offset of the import directory is out of the file" },
{"LDR_ERROR_IMPDIR_CUT", "Import directory is cut" },
{"LDR_ERROR_IMPDIR_COUNT_EXCEEDED", "Number of import descriptors exceeds maximum" },
{"LDR_ERROR_IMPDIR_NAME_RVA_INVALID", "RVA of the import name is invalid" },
{"LDR_ERROR_IMPDIR_THUNK_RVA_INVALID", "RVA of the import thunk is invalid" },
{"LDR_ERROR_IMPDIR_IMPORT_COUNT_EXCEEDED", "Number of imported functions exceeds maximum" },
// Resource directory detected errors
{"LDR_ERROR_RSRC_OVER_END_OF_IMAGE", "Array of resource directory entries goes beyond end of the image" },
};
PELIB_IMAGE_FILE_MACHINE_ITERATOR::PELIB_IMAGE_FILE_MACHINE_ITERATOR()
{
}
PELIB_IMAGE_FILE_MACHINE_ITERATOR::~PELIB_IMAGE_FILE_MACHINE_ITERATOR()
{
}
bool PELIB_IMAGE_FILE_MACHINE_ITERATOR::isValidMachineCode(PELIB_IMAGE_FILE_MACHINE value) const
{
return find(all.begin(), all.end(), value) != all.end();
}
PELIB_IMAGE_FILE_MACHINE_ITERATOR::imageFileMachineIterator PELIB_IMAGE_FILE_MACHINE_ITERATOR::begin() const
{
return all.begin();
}
PELIB_IMAGE_FILE_MACHINE_ITERATOR::imageFileMachineIterator PELIB_IMAGE_FILE_MACHINE_ITERATOR::end() const
{
return all.end();
}
bool PELIB_IMAGE_SECTION_HEADER::biggerFileOffset(const PELIB_IMAGE_SECTION_HEADER& ish) const
{
return PointerToRawData < ish.PointerToRawData;
}
bool PELIB_IMAGE_SECTION_HEADER::biggerVirtualAddress(const PELIB_IMAGE_SECTION_HEADER& ish) const
{
return VirtualAddress < ish.VirtualAddress;
}
bool PELIB_IMAGE_SECTION_HEADER::isFullNameSet() const
{
return !StringTableName.empty();
}
unsigned int alignOffset(unsigned int uiOffset, unsigned int uiAlignment)
{
if (!uiAlignment) return uiAlignment;
return (uiOffset % uiAlignment) ? uiOffset + (uiAlignment - uiOffset % uiAlignment) : uiOffset;
}
std::uint32_t AlignToSize(std::uint32_t ByteSize, std::uint32_t AlignSize)
{
return ((ByteSize + (AlignSize - 1)) & ~(AlignSize - 1));
}
std::uint32_t BytesToPages(std::uint32_t ByteSize)
{
return (ByteSize >> PELIB_PAGE_SIZE_SHIFT) + ((ByteSize & (PELIB_PAGE_SIZE - 1)) != 0);
}
std::uint64_t fileSize(const std::string& filename)
{
std::fstream file(filename.c_str());
file.seekg(0, std::ios::end);
return file.tellg();
}
std::uint64_t fileSize(std::istream& stream)
{
std::streamoff oldpos = stream.tellg();
stream.seekg(0, std::ios::end);
std::streamoff filesize = stream.tellg();
stream.seekg(oldpos, std::ios::beg);
return filesize;
}
std::uint64_t fileSize(std::fstream& file)
{
std::streamoff oldpos = file.tellg();
file.seekg(0, std::ios::end);
std::streamoff filesize = file.tellg();
file.seekg(oldpos, std::ios::beg);
return filesize;
}
std::uint64_t fileSize(std::ofstream& file)
{
std::streamoff oldpos = file.tellp();
file.seekp(0, std::ios::end);
std::streamoff filesize = file.tellp();
file.seekp(oldpos, std::ios::beg);
return filesize;
}
const char * getLoaderErrorString(LoaderError ldrError, bool userFriendly)
{
std::size_t index = (std::size_t)ldrError;
// When the index is within range
if (index < LdrErrStrings.size())
{
return userFriendly ? LdrErrStrings[index].loaderErrorUserFriendly : LdrErrStrings[index].loaderErrorString;
}
// If this assert triggers, we need to add the missing string
// to the PeLib::LdrErrStrings vector
assert(false);
return "LDR_ERROR_DESCRIPTIVE_STRING_MISSING";
}
bool getLoaderErrorLoadableAnyway(LoaderError ldrError)
{
// These errors indicate damaged PE file, but the file is usually loadable anyway
return (ldrError == LDR_ERROR_FILE_IS_CUT_LOADABLE || ldrError == LDR_ERROR_RSRC_OVER_END_OF_IMAGE);
}
// Anti-assert feature. Debug version of isprint in MS Visual C++ asserts
// when the character is not EOF or is >= 255
bool pelibIsPrintableChar(int ch)
{
return ((EOF <= ch) && (ch <= 255)) ? isprint(ch) : false;
}
/**
* @param stream
* @param result
* @param fileOffset
* @param maxLength Maximum length of the string to get.
* @param isPrintable If @c true and a non-printable characters is read,
* set @p result to an empty string and return 0.
* @param isNotTooLong If @c true and @p maxLength is reached, set @p result
* to an empty string and return 0.
* @return Length of the @p result string.
*/
std::size_t getStringFromFileOffset(
std::istream &stream,
std::string &result,
std::size_t fileOffset,
std::size_t maxLength/* = 0*/,
bool isPrintable/* = false*/,
bool isNotTooLong/* = false*/)
{
IStreamWrapper inStream_w(stream);
result.clear();
inStream_w.clear();
inStream_w.seekg(fileOffset, std::ios::beg);
if (!inStream_w)
{
return 0;
}
char namebuffer[2] = { 0 };
std::size_t size = 0;
do
{
inStream_w.read(namebuffer, 1);
if (!inStream_w || !namebuffer[0]) break;
if (isPrintable && !pelibIsPrintableChar(namebuffer[0]))
{
result.clear();
return 0;
}
result += namebuffer;
++size;
if (maxLength && size == maxLength)
{
if (isNotTooLong)
{
result.clear();
return 0;
}
else
{
break;
}
}
} while (true);
return size;
}
bool isEqualNc(const std::string& s1, const std::string& s2)
{
std::string t1 = s1;
std::string t2 = s2;
// No std:: to make VC++ happy
#ifdef _MSC_VER
std::transform(t1.begin(), t1.end(), t1.begin(), [](unsigned char c) { return toupper(c); });
std::transform(t2.begin(), t2.end(), t2.begin(), [](unsigned char c) { return toupper(c); });
#else
// Weird syntax to make Borland C++ happy
std::transform(t1.begin(), t1.end(), t1.begin(), (int(*)(int))std::toupper);
std::transform(t2.begin(), t2.end(), t2.begin(), (int(*)(int))std::toupper);
#endif
return t1 == t2;
}
PELIB_IMAGE_DOS_HEADER::PELIB_IMAGE_DOS_HEADER()
{
e_magic = 0;
e_cblp = 0;
e_cp = 0;
e_crlc = 0;
e_cparhdr = 0;
e_minalloc = 0;
e_maxalloc = 0;
e_ss = 0;
e_sp = 0;
e_csum = 0;
e_ip = 0;
e_cs = 0;
e_lfarlc = 0;
e_ovno = 0;
for (unsigned int i = 0; i < sizeof(e_res) / sizeof(e_res[0]); i++)
{
e_res[i] = 0;
}
e_oemid = 0;
e_oeminfo = 0;
for (unsigned int i = 0; i < sizeof(e_res2) / sizeof(e_res2[0]); i++)
{
e_res2[i] = 0;
}
e_lfanew = 0;
}
PELIB_EXP_FUNC_INFORMATION::PELIB_EXP_FUNC_INFORMATION()
{
addroffunc = 0;
addrofname = 0;
ordinal = 0;
}
PELIB_IMAGE_RESOURCE_DIRECTORY::PELIB_IMAGE_RESOURCE_DIRECTORY()
{
Characteristics = 0;
TimeDateStamp = 0;
MajorVersion = 0;
MinorVersion = 0;
NumberOfNamedEntries = 0;
NumberOfIdEntries = 0;
}
PELIB_IMAGE_RESOURCE_DIRECTORY_ENTRY::PELIB_IMAGE_RESOURCE_DIRECTORY_ENTRY()
{
Name = 0;
OffsetToData = 0;
}
bool PELIB_IMG_RES_DIR_ENTRY::operator<(const PELIB_IMG_RES_DIR_ENTRY& first) const
{
if ((irde.Name & PELIB_IMAGE_RESOURCE_NAME_IS_STRING) && (first.irde.Name & PELIB_IMAGE_RESOURCE_NAME_IS_STRING))
{
return wstrName < first.wstrName;
}
else if (irde.Name & PELIB_IMAGE_RESOURCE_NAME_IS_STRING)
{
return true;
}
else if (first.irde.Name & PELIB_IMAGE_RESOURCE_NAME_IS_STRING)
{
return false;
}
else
{
return irde.Name < first.irde.Name;
}
}
PELIB_IMAGE_BASE_RELOCATION::PELIB_IMAGE_BASE_RELOCATION()
{
VirtualAddress = 0;
SizeOfBlock = 0;
}
PELIB_IMAGE_COR20_HEADER::PELIB_IMAGE_COR20_HEADER()
{
cb = 0;
MajorRuntimeVersion = 0;
MinorRuntimeVersion = 0;
MetaData.VirtualAddress = 0;
MetaData.Size = 0;
Flags = 0;
EntryPointToken = 0;
Resources.VirtualAddress = 0;
Resources.Size = 0;
StrongNameSignature.VirtualAddress = 0;
StrongNameSignature.Size = 0;
CodeManagerTable.VirtualAddress = 0;
CodeManagerTable.Size = 0;
VTableFixups.VirtualAddress = 0;
VTableFixups.Size = 0;
ExportAddressTableJumps.VirtualAddress = 0;
ExportAddressTableJumps.Size = 0;
ManagedNativeHeader.VirtualAddress = 0;
ManagedNativeHeader.Size = 0;
}
PELIB_IMAGE_RESOURCE_DATA_ENTRY::PELIB_IMAGE_RESOURCE_DATA_ENTRY()
{
OffsetToData = 0;
Size = 0;
CodePage = 0;
Reserved = 0;
}
PELIB_IMAGE_DEBUG_DIRECTORY::PELIB_IMAGE_DEBUG_DIRECTORY()
{
Characteristics = 0;
TimeDateStamp = 0;
MajorVersion = 0;
MinorVersion = 0;
Type = 0;
SizeOfData = 0;
AddressOfRawData = 0;
PointerToRawData = 0;
}
/** Compares the passed filename to the struct's filename.
* @param strModuleName A filename.
* @return True, if the passed filename equals the struct's filename. The comparison is case-sensitive.
**/
bool PELIB_IMAGE_BOUND_DIRECTORY::equal(const std::string strModuleName2) const
{
return this->strModuleName == strModuleName2;
}
bool PELIB_EXP_FUNC_INFORMATION::equal(const std::string strFunctionName) const
{
return isEqualNc(this->funcname, strFunctionName);
}
unsigned int getFileType(PeFile32& pef)
{
// Attempt to read the DOS file header.
if (pef.readMzHeader() != ERROR_NONE)
{
return PEFILE_UNKNOWN;
}
// Verify the DOS header
if (!pef.mzHeader().isValid())
{
return PEFILE_UNKNOWN;
}
// Read PE header. Note that at this point, we read the header as if
// it was 32-bit PE file.
if (pef.readPeHeader() != ERROR_NONE)
{
return PEFILE_UNKNOWN;
}
word machine = pef.peHeader().getMachine();
word magic = pef.peHeader().getMagic();
// jk2012-02-20: make the PEFILE32 be the default return value
if ((machine == PELIB_IMAGE_FILE_MACHINE_AMD64
|| machine == PELIB_IMAGE_FILE_MACHINE_IA64)
&& magic == PELIB_IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
return PEFILE64;
}
else
{
return PEFILE32;
}
}
/**
* @param strFilename Name of a file.
* @return Either PEFILE32, PEFILE64 or PEFILE_UNKNOWN
**/
unsigned int getFileType(const std::string strFilename)
{
PeFile32 pef(strFilename);
return getFileType(pef);
}
/**
* @param stream Input stream.
* @return Either PEFILE32, PEFILE64 or PEFILE_UNKNOWN
**/
unsigned int getFileType(std::istream& stream)
{
PeFile32 pef(stream);
return getFileType(pef);
}
/**
* Opens a PE file. The return type is either PeFile32 or PeFile64 object. If an error occurs the return
* value is 0.
* @param strFilename Name of a file.
* @return Either a PeFile32 object, a PeFil64 object or 0.
**/
PeFile* openPeFile(const std::string& strFilename)
{
unsigned int type = getFileType(strFilename);
if (type == PEFILE32)
{
return new PeFile32(strFilename);
}
else if (type == PEFILE64)
{
return new PeFile64(strFilename);
}
else
{
return nullptr;
}
}
PeFile* openPeFile(std::istream& stream)
{
unsigned int type = getFileType(stream);
if (type == PEFILE32)
{
return new PeFile32(stream);
}
else if (type == PEFILE64)
{
return new PeFile64(stream);
}
else
{
return nullptr;
}
}
unsigned int PELIB_IMAGE_BOUND_DIRECTORY::size() const
{
unsigned int size = 0;
for (unsigned int i = 0; i < moduleForwarders.size(); ++i)
{
size += moduleForwarders[i].size();
}
return (unsigned int)(size + PELIB_IMAGE_BOUND_IMPORT_DESCRIPTOR::size() + strModuleName.size() + 1);
}
}

View File

@ -0,0 +1,145 @@
/*
* Relocations.cpp - Part of the PeLib library.
*
* Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
* All rights reserved.
*
* This software is licensed under the zlib/libpng License.
* For more details see http://www.opensource.org/licenses/zlib-license.php
* or the license information file (license.htm) in the root directory
* of PeLib.
*/
#include "pelib/PeLibInc.h"
#include "pelib/RelocationsDirectory.h"
namespace PeLib
{
void RelocationsDirectory::setRelocationData(unsigned int ulRelocation, unsigned int ulDataNumber, word wData)
{
m_vRelocations[ulRelocation].vRelocData[ulDataNumber] = wData;
}
void RelocationsDirectory::read(InputBuffer& inputbuffer, unsigned int uiSize)
{
IMG_BASE_RELOC ibrCurr;
std::vector<IMG_BASE_RELOC> vCurrReloc;
do
{
if (inputbuffer.get() + sizeof(ibrCurr.ibrRelocation.VirtualAddress) + sizeof(ibrCurr.ibrRelocation.SizeOfBlock) > uiSize)
{
break;
}
inputbuffer >> ibrCurr.ibrRelocation.VirtualAddress;
inputbuffer >> ibrCurr.ibrRelocation.SizeOfBlock;
ibrCurr.vRelocData.clear();
// That's not how to check if there are relocations, some DLLs start at VA 0.
// if (!ibrCurr.ibrRelocation.VirtualAddress) break;
for (unsigned int i=0;i<(ibrCurr.ibrRelocation.SizeOfBlock - PELIB_IMAGE_SIZEOF_BASE_RELOCATION) / sizeof(word);i++)
{
if (inputbuffer.get() + sizeof(word) > uiSize)
{
break;
}
word wData;
inputbuffer >> wData;
ibrCurr.vRelocData.push_back(wData);
}
vCurrReloc.push_back(ibrCurr);
} while (ibrCurr.ibrRelocation.VirtualAddress && inputbuffer.get() < uiSize);
std::swap(vCurrReloc, m_vRelocations);
}
// TODO: Return value is wrong if buffer was too small.
int RelocationsDirectory::read(const unsigned char* buffer, unsigned int buffersize)
{
std::vector<unsigned char> vRelocDirectory(buffer, buffer + buffersize);
InputBuffer ibBuffer(vRelocDirectory);
read(ibBuffer, buffersize);
return ERROR_NONE;
}
unsigned int RelocationsDirectory::size() const
{
unsigned int size2 = static_cast<unsigned int>(m_vRelocations.size()) * PELIB_IMAGE_BASE_RELOCATION::size();
for (unsigned int i=0;i<m_vRelocations.size();i++)
{
size2 += static_cast<unsigned int>(m_vRelocations[i].vRelocData.size()) * sizeof(word);
}
return size2;
}
unsigned int RelocationsDirectory::calcNumberOfRelocations() const
{
return static_cast<unsigned int>(m_vRelocations.size());
}
dword RelocationsDirectory::getVirtualAddress(unsigned int ulRelocation) const
{
return m_vRelocations[ulRelocation].ibrRelocation.VirtualAddress;
}
dword RelocationsDirectory::getSizeOfBlock(unsigned int ulRelocation) const
{
return m_vRelocations[ulRelocation].ibrRelocation.SizeOfBlock;
}
unsigned int RelocationsDirectory::calcNumberOfRelocationData(unsigned int ulRelocation) const
{
return static_cast<unsigned int>(m_vRelocations[ulRelocation].vRelocData.size());
}
word RelocationsDirectory::getRelocationData(unsigned int ulRelocation, unsigned int ulDataNumber) const
{
return m_vRelocations[ulRelocation].vRelocData[ulDataNumber];
}
void RelocationsDirectory::setVirtualAddress(unsigned int ulRelocation, dword dwValue)
{
m_vRelocations[ulRelocation].ibrRelocation.VirtualAddress = dwValue;
}
void RelocationsDirectory::setSizeOfBlock(unsigned int ulRelocation, dword dwValue)
{
m_vRelocations[ulRelocation].ibrRelocation.SizeOfBlock = dwValue;
}
void RelocationsDirectory::addRelocation()
{
IMG_BASE_RELOC newrelocation;
m_vRelocations.push_back(newrelocation);
}
void RelocationsDirectory::addRelocationData(unsigned int ulRelocation, word wValue)
{
m_vRelocations[ulRelocation].vRelocData.push_back(wValue);
}
/* void RelocationsDirectory::removeRelocationData(unsigned int ulRelocation, word wValue)
{
// If you get an error with Borland C++ here you have two options: Upgrade your compiler
// or use the commented line instead of the line below.
m_vRelocations[ulRelocation].vRelocData.erase(std::remove(m_vRelocations[ulRelocation].vRelocData.begin(), m_vRelocations[ulRelocation].vRelocData.end(), wValue), m_vRelocations[ulRelocation].vRelocData.end());
}
*/
void RelocationsDirectory::removeRelocation(unsigned int index)
{
m_vRelocations.erase(m_vRelocations.begin() + index);
}
void RelocationsDirectory::removeRelocationData(unsigned int relocindex, unsigned int dataindex)
{
m_vRelocations[relocindex].vRelocData.erase(m_vRelocations[relocindex].vRelocData.begin() + dataindex);
}
}

File diff suppressed because it is too large Load Diff

228
src/pelib/RichHeader.cpp Normal file
View File

@ -0,0 +1,228 @@
/**
* @file RichHeader.cpp
* @brief Class for rich header.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include <cstring>
#include <sstream>
#include <iomanip>
#include "pelib/PeLibInc.h"
#include "pelib/RichHeader.h"
namespace PeLib
{
namespace
{
std::string makeSignature(dword value)
{
std::stringstream signature;
signature << std::hex << std::setfill('0') << std::setw(2 * sizeof(dword)) << std::uppercase << value;
return signature.str();
}
std::string makeSignature(dword first, dword second)
{
return makeSignature(first) + makeSignature(second);
}
}
RichHeader::RichHeader()
{
init();
}
RichHeader::~RichHeader()
{
}
void RichHeader::init()
{
headerIsValid = false;
validStructure = false;
key = 0;
noOfIters = 0;
decryptedHeader.clear();
records.clear();
}
void RichHeader::setValidStructure()
{
validStructure = (decryptedHeader.size() >= 4);
}
bool RichHeader::analyze(bool ignoreInvalidKey)
{
bool hValid = true;
size_t decSize = decryptedHeader.size();
if (decSize < 4)
{
return false;
}
else if (decryptedHeader[0] != 0x536e6144 || decryptedHeader[1] != 0 ||
decryptedHeader[2] != 0 || decryptedHeader[3] != 0)
{
if (ignoreInvalidKey)
{
hValid = false;
}
else
{
return false;
}
}
const word mask1 = (1 << (8 * sizeof(word))) - 1;
const word mask2 = (1 << (8 * sizeof(byte))) - 1;
PELIB_IMAGE_RICH_HEADER_RECORD record;
for (size_t i = 4; i + 1 < decSize; i += 2)
{
headerIsValid = hValid;
const word id = decryptedHeader[i] >> (8 * sizeof(word));
record.MajorVersion = id & mask2;
record.MinorVersion = id >> (8 * sizeof(byte));
record.Build = decryptedHeader[i] & mask1;
record.Count = decryptedHeader[i + 1];
record.Signature = makeSignature(decryptedHeader[i], decryptedHeader[i + 1]);
records.push_back(record);
}
return true;
}
void RichHeader::read(InputBuffer& inputbuffer, std::size_t uiSize, bool ignoreInvalidKey)
{
init();
std::vector<dword> rich;
for (std::size_t i = 0, e = uiSize / sizeof(dword); i < e; ++i)
{
dword actInput;
inputbuffer >> actInput;
rich.push_back(actInput);
}
dword sign[] = {0x68636952};
auto lastPos = rich.end();
// try to find signature of rich header and key for decryption
do
{
auto richSignature = find_end(rich.begin(), lastPos, sign, sign + 1);
if (richSignature == lastPos || richSignature + 1 == rich.end())
{
break;
}
lastPos = richSignature;
key = *(richSignature + 1);
decryptedHeader.clear();
++noOfIters;
for (auto i = rich.begin(); i != richSignature; ++i)
{
decryptedHeader.push_back(*i ^ key);
}
setValidStructure();
} while (!analyze());
if (ignoreInvalidKey && noOfIters)
{
analyze(true);
}
}
int RichHeader::read(
std::istream& inStream,
std::size_t uiOffset,
std::size_t uiSize,
bool ignoreInvalidKey)
{
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
const auto ulFileSize = fileSize(inStream_w);
if (ulFileSize < uiOffset + uiSize)
{
return ERROR_INVALID_FILE;
}
inStream_w.seekg(uiOffset, std::ios::beg);
std::vector<unsigned char> tableDump;
tableDump.resize(uiSize);
inStream_w.read(reinterpret_cast<char*>(tableDump.data()), uiSize);
InputBuffer ibBuffer(tableDump);
read(ibBuffer, uiSize, ignoreInvalidKey);
return ERROR_NONE;
}
bool RichHeader::isHeaderValid() const
{
return headerIsValid;
}
bool RichHeader::isStructureValid() const
{
return validStructure;
}
std::size_t RichHeader::getNumberOfIterations() const
{
return noOfIters;
}
dword RichHeader::getKey() const
{
return key;
}
const dword* RichHeader::getDecryptedHeaderItem(std::size_t index) const
{
return (index < decryptedHeader.size()) ? &decryptedHeader[index] : nullptr;
}
std::string RichHeader::getDecryptedHeaderItemSignature(std::size_t index) const
{
const auto *dhI = getDecryptedHeaderItem(index);
return dhI ? makeSignature(*dhI) : "";
}
std::string RichHeader::getDecryptedHeaderItemsSignature(std::initializer_list<std::size_t> indexes) const
{
std::string result;
for (const auto index : indexes)
{
result += getDecryptedHeaderItemSignature(index);
}
return result;
}
std::vector<std::uint8_t> RichHeader::getDecryptedHeaderBytes() const
{
std::vector<std::uint8_t> result(decryptedHeader.size() * sizeof(dword));
std::memcpy(result.data(), reinterpret_cast<const std::uint8_t*>(decryptedHeader.data()), result.size());
return result;
}
RichHeader::richHeaderIterator RichHeader::begin() const
{
return records.begin();
}
RichHeader::richHeaderIterator RichHeader::end() const
{
return records.end();
}
}

View File

@ -0,0 +1,71 @@
/**
* @file SecurityDirectory.cpp
* @brief Class for security directory.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include "pelib/PeLibInc.h"
#include "pelib/SecurityDirectory.h"
namespace PeLib
{
unsigned int SecurityDirectory::calcNumberOfCertificates() const
{
return (unsigned int)m_certs.size();
}
const std::vector<unsigned char>& SecurityDirectory::getCertificate(std::size_t index) const
{
return m_certs[index].Certificate;
}
int SecurityDirectory::read(
std::istream& inStream,
unsigned int uiOffset,
unsigned int uiSize)
{
IStreamWrapper inStream_w(inStream);
if (!inStream_w)
{
return ERROR_OPENING_FILE;
}
std::uint64_t ulFileSize = fileSize(inStream_w);
if (ulFileSize < uiOffset + uiSize)
{
return ERROR_INVALID_FILE;
}
inStream_w.seekg(uiOffset, std::ios::beg);
std::vector<unsigned char> vCertDirectory(uiSize);
inStream_w.read(reinterpret_cast<char*>(vCertDirectory.data()), uiSize);
InputBuffer inpBuffer(vCertDirectory);
unsigned bytesRead = 0;
while (bytesRead < uiSize)
{
PELIB_IMAGE_CERTIFICATE_ENTRY cert;
inpBuffer >> cert.Length;
inpBuffer >> cert.Revision;
inpBuffer >> cert.CertificateType;
if ((cert.Length <= PELIB_IMAGE_CERTIFICATE_ENTRY::size() ||
((cert.Revision != PELIB_WIN_CERT_REVISION_1_0) && (cert.Revision != PELIB_WIN_CERT_REVISION_2_0)) ||
(cert.CertificateType != PELIB_WIN_CERT_TYPE_PKCS_SIGNED_DATA)))
{
return ERROR_INVALID_FILE;
}
cert.Certificate.resize(cert.Length - PELIB_IMAGE_CERTIFICATE_ENTRY::size());
inpBuffer.read(reinterpret_cast<char*>(cert.Certificate.data()), cert.Certificate.size());
bytesRead += cert.Length;
m_certs.push_back(cert);
}
return ERROR_NONE;
}
}

View File

@ -7,9 +7,8 @@
#ifndef UNPACKERTOOL_PLUGINS_MPRESS_MPRESS_H
#define UNPACKERTOOL_PLUGINS_MPRESS_MPRESS_H
#include <pelib/PeLib.h>
#include "retdec/loader/loader.h"
#include "retdec/pelib/PeLib.h"
#include "retdec/utils/dynamic_buffer.h"
#include "retdec/unpacker/plugin.h"

View File

@ -7,8 +7,7 @@
#include <algorithm>
#include <cstring>
#include <pelib/PeLib.h>
#include "retdec/pelib/PeLib.h"
#include "retdec/utils/alignment.h"
#include "retdec/utils/file_io.h"
#include "unpackertool/plugins/upx/decompressors/decompressors.h"

View File

@ -9,9 +9,8 @@
#include <unordered_set>
#include <pelib/PeLib.h>
#include "unpackertool/plugins/upx/upx_stub.h"
#include "retdec/pelib/PeLib.h"
#include "retdec/utils/dynamic_buffer.h"
#include "retdec/unpacker/signature.h"

View File

@ -7,12 +7,12 @@
#include <memory>
#include <elfio/elfio.hpp>
#include <pelib/PeLib.h>
#include "retdec/loader/loader.h"
#include "unpackertool/plugins/upx/upx.h"
#include "unpackertool/plugins/upx/upx_exceptions.h"
#include "unpackertool/plugins/upx/upx_stub_signatures.h"
#include "retdec/pelib/PeLib.h"
#include "retdec/unpacker/unpacker_exception.h"
using namespace retdec::unpacker;