Skip to content

Commit

Permalink
fileformat: Delayed imports in PE are no longer considered when calcu…
Browse files Browse the repository at this point in the history
…lating

imphash (#287)

Calculation of imphash is also postponed until all imports are loaded.
This is related to #285.
  • Loading branch information
metthal committed May 15, 2018
1 parent 7023ed4 commit 7523e07
Show file tree
Hide file tree
Showing 21 changed files with 276 additions and 141 deletions.
1 change: 1 addition & 0 deletions include/retdec/fileformat/fftypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "retdec/fileformat/types/dynamic_table/dynamic_table.h"
#include "retdec/fileformat/types/export_table/export_table.h"
#include "retdec/fileformat/types/import_table/import_table.h"
#include "retdec/fileformat/types/import_table/pe_import.h"
#include "retdec/fileformat/types/note_section/elf_notes.h"
#include "retdec/fileformat/types/note_section/elf_core.h"
#include "retdec/fileformat/types/pdb_info/pdb_info.h"
Expand Down
2 changes: 1 addition & 1 deletion include/retdec/fileformat/file_format/macho/macho_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class MachOFormat : public FileFormat
void parseIndirectTable(std::uint32_t offset, std::uint32_t size);
void dySymtabCommand();
void dyldInfoCommand(const llvm::object::MachOObjectFile::LoadCommandInfo &commandInfo);
bool getImportFromBindEntry(const llvm::object::MachOBindEntry &input, Import &result);
std::unique_ptr<Import> getImportFromBindEntry(const llvm::object::MachOBindEntry &input);
/// @}

/// @name Load commands methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ class PeFormatParser
virtual bool getDataDirectoryAbsolute(unsigned long long index, unsigned long long &absAddr, unsigned long long &size) const = 0;
virtual bool getImportedLibraryFileName(unsigned long long index, std::string &fileName) const = 0;
virtual bool getDelayImportedLibraryFileName(unsigned long long index, std::string &fileName) const = 0;
virtual bool getImport(unsigned long long fileIndex, unsigned long long importIndex, Import &import) const = 0;
virtual bool getDelayImport(unsigned long long fileIndex, unsigned long long importIndex, Import &import) const = 0;
virtual std::unique_ptr<Import> getImport(unsigned long long fileIndex, unsigned long long importIndex) const = 0;
virtual std::unique_ptr<Import> getDelayImport(unsigned long long fileIndex, unsigned long long importIndex) const = 0;
virtual unsigned long long getNumberOfExportedFunctions() const = 0;
virtual bool getExportedFunction(unsigned long long index, Export& exportedFunction) const = 0;
virtual unsigned long long getNumberOfDebugEntries() const = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ class PeFormatParser32 : public PeFormatParser
virtual bool getDataDirectoryAbsolute(unsigned long long index, unsigned long long &absAddr, unsigned long long &size) const override;
virtual bool getImportedLibraryFileName(unsigned long long index, std::string &fileName) const override;
virtual bool getDelayImportedLibraryFileName(unsigned long long index, std::string &fileName) const override;
virtual bool getImport(unsigned long long fileIndex, unsigned long long importIndex, Import &import) const override;
virtual bool getDelayImport(unsigned long long fileIndex, unsigned long long importIndex, Import &import) const override;
virtual std::unique_ptr<Import> getImport(unsigned long long fileIndex, unsigned long long importIndex) const override;
virtual std::unique_ptr<Import> getDelayImport(unsigned long long fileIndex, unsigned long long importIndex) const override;
virtual unsigned long long getNumberOfExportedFunctions() const override;
virtual bool getExportedFunction(unsigned long long index, Export& exportedFunction) const override;
virtual unsigned long long getNumberOfDebugEntries() const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ class PeFormatParser64 : public PeFormatParser
virtual bool getDataDirectoryAbsolute(unsigned long long index, unsigned long long &absAddr, unsigned long long &size) const override;
virtual bool getImportedLibraryFileName(unsigned long long index, std::string &fileName) const override;
virtual bool getDelayImportedLibraryFileName(unsigned long long index, std::string &fileName) const override;
virtual bool getImport(unsigned long long fileIndex, unsigned long long importIndex, Import &import) const override;
virtual bool getDelayImport(unsigned long long fileIndex, unsigned long long importIndex, Import &import) const override;
virtual std::unique_ptr<Import> getImport(unsigned long long fileIndex, unsigned long long importIndex) const override;
virtual std::unique_ptr<Import> getDelayImport(unsigned long long fileIndex, unsigned long long importIndex) const override;
virtual unsigned long long getNumberOfExportedFunctions() const override;
virtual bool getExportedFunction(unsigned long long index, Export& exportedFunction) const override;
virtual unsigned long long getNumberOfDebugEntries() const override;
Expand Down
47 changes: 24 additions & 23 deletions include/retdec/fileformat/file_format/pe/pe_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "retdec/fileformat/types/dotnet_headers/clr_header.h"
#include "retdec/fileformat/types/export_table/export.h"
#include "retdec/fileformat/types/import_table/import.h"
#include "retdec/fileformat/types/import_table/pe_import.h"
#include "retdec/fileformat/types/sec_seg/pe_coff_section.h"
#include "retdec/fileformat/types/sec_seg/section.h"

Expand Down Expand Up @@ -497,21 +498,20 @@ template<int bits> bool peDelayImportedLibraryFileName(const PeLib::DelayImportD
* Get information about import
* @param peHeader Parser of PE header
* @param peImports Parser of PE import directory
* @param import Into this parameter is stored information about selected import
* @param fileIndex Index of selected library (indexed from 0)
* @param importIndex Index of selected import (indexed from 0)
* @return @c true if index of library and index of import are valid, @c false otherwise
*
* If function returns @c false, @a import is left unchanged.
* If function returns info about import, or @c nullptr if invalid import is requested.
*/
template<int bits> bool peImport(const PeLib::PeHeaderT<bits> &peHeader,
const PeLib::ImportDirectory<bits> &peImports, Import &import,
template<int bits> std::unique_ptr<Import> peImport(const PeLib::PeHeaderT<bits> &peHeader,
const PeLib::ImportDirectory<bits> &peImports,
unsigned long long fileIndex, unsigned long long importIndex)
{
if(fileIndex >= peNumberOfImportedLibraries(peImports) ||
importIndex >= peImports.getNumberOfFunctions(fileIndex, PeLib::OLDDIR))
{
return false;
return nullptr;
}

auto isOrdinalNumberValid = true;
Expand All @@ -534,57 +534,58 @@ template<int bits> bool peImport(const PeLib::PeHeaderT<bits> &peHeader,
}
}

auto import = std::make_unique<PeImport>(PeImportFlag::None);
if(isOrdinalNumberValid)
{
import.setOrdinalNumber(ordinalNumber);
import->setOrdinalNumber(ordinalNumber);
}
else
{
import.invalidateOrdinalNumber();
import->invalidateOrdinalNumber();
}
import.setName(peImports.getFunctionName(fileIndex, importIndex, PeLib::OLDDIR));
import.setAddress(peImageBase(peHeader) + peImports.getFirstThunk(fileIndex, PeLib::OLDDIR) + importIndex * (bits / 8));
import.setLibraryIndex(fileIndex);
return true;
import->setName(peImports.getFunctionName(fileIndex, importIndex, PeLib::OLDDIR));
import->setAddress(peImageBase(peHeader) + peImports.getFirstThunk(fileIndex, PeLib::OLDDIR) + importIndex * (bits / 8));
import->setLibraryIndex(fileIndex);
return import;
}

/**
* Get information about delay import
* @param peHeader Parser of PE header
* @param delay Parser of PE delay import directory
* @param import Into this parameter is stored information about selected delay import
* @param fileIndex Index of selected library (indexed from 0)
* @param importIndex Index of selected delay import (indexed from 0)
* @return @c true if index of library and index of delay import are valid, @c false otherwise
*
* If function returns @c false, @a import is left unchanged.
* If function returns info about delayed import, or @c nullptr if invalid import is requested.
*/
template<int bits> bool peDelayImport(const PeLib::PeHeaderT<bits> &peHeader,
const PeLib::DelayImportDirectory<bits> &delay, Import &import,
template<int bits> std::unique_ptr<Import> peDelayImport(const PeLib::PeHeaderT<bits> &peHeader,
const PeLib::DelayImportDirectory<bits> &delay,
unsigned long long fileIndex, unsigned long long importIndex)
{
const auto *library = delay.getFile(fileIndex);
if(!library)
{
return false;
return nullptr;
}

const auto *function = library->getFunction(importIndex);
if(!function)
{
return false;
return nullptr;
}

import.setName(function->fname);
import.setAddress(peImageBase(peHeader) + function->address.Value);
import.setLibraryIndex(fileIndex);
import.invalidateOrdinalNumber();
auto import = std::make_unique<PeImport>(PeImportFlag::Delayed);
import->setName(function->fname);
import->setAddress(peImageBase(peHeader) + function->address.Value);
import->setLibraryIndex(fileIndex);
import->invalidateOrdinalNumber();
if(library->ordinalNumbersAreValid() && function->hint != 0)
{
import.setOrdinalNumber(function->hint);
import->setOrdinalNumber(function->hint);
}

return true;
return import;
}

/**
Expand Down
1 change: 1 addition & 0 deletions include/retdec/fileformat/types/import_table/import.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class Import

/// @name Other methods
/// @{
virtual bool isUsedForImphash() const;
void invalidateOrdinalNumber();
bool hasEmptyName() const;
/// @}
Expand Down
17 changes: 9 additions & 8 deletions include/retdec/fileformat/types/import_table/import_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#ifndef RETDEC_FILEFORMAT_TYPES_IMPORT_TABLE_IMPORT_TABLE_H
#define RETDEC_FILEFORMAT_TYPES_IMPORT_TABLE_IMPORT_TABLE_H

#include <memory>
#include <vector>

#include "retdec/fileformat/types/import_table/import.h"
Expand All @@ -20,13 +21,13 @@ namespace fileformat {
class ImportTable
{
private:
using importsIterator = std::vector<Import>::const_iterator;
std::vector<std::string> libraries; ///< name of libraries
std::vector<Import> imports; ///< stored imports
std::vector<unsigned char> impHashBytes; ///< bytes for calculation of imphash
std::string impHashCrc32; ///< imphash CRC32
std::string impHashMd5; ///< imphash MD5
std::string impHashSha256; ///< imphash SHA256
using importsIterator = std::vector<std::unique_ptr<Import>>::const_iterator;
std::vector<std::string> libraries; ///< name of libraries
std::vector<std::unique_ptr<Import>> imports; ///< stored imports
std::vector<unsigned char> impHashBytes; ///< bytes for calculation of imphash
std::string impHashCrc32; ///< imphash CRC32
std::string impHashMd5; ///< imphash MD5
std::string impHashSha256; ///< imphash SHA256
public:
ImportTable();
~ImportTable();
Expand Down Expand Up @@ -58,7 +59,7 @@ class ImportTable
void computeHashes();
void clear();
void addLibrary(std::string name);
void addImport(const Import &import);
void addImport(std::unique_ptr<Import>&& import);
bool hasLibraries() const;
bool hasLibrary(const std::string &name) const;
bool hasLibraryCaseInsensitive(const std::string &name) const;
Expand Down
51 changes: 51 additions & 0 deletions include/retdec/fileformat/types/import_table/pe_import.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @file include/retdec/fileformat/types/import_table/pe_import.h
* @brief Class for one PE import.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/

#ifndef RETDEC_FILEFORMAT_TYPES_IMPORT_TABLE_PE_IMPORT_H
#define RETDEC_FILEFORMAT_TYPES_IMPORT_TABLE_PE_IMPORT_H

#include "retdec/fileformat/types/import_table/import.h"

namespace retdec {
namespace fileformat {

enum PeImportFlag : std::uint32_t
{
None = 0,
Delayed = 1,
};

/**
* One import
*/
class PeImport : public Import
{
private:
std::uint32_t flags;
public:
PeImport(std::uint32_t flags);
~PeImport();

/// @name Getters
/// @{
bool isDelayed() const;
/// @}

/// @name Setters
/// @{
void setDelayed(bool importDelayed);
/// @}

/// @name Other methods
/// @{
virtual bool isUsedForImphash() const override;
/// @}
};

} // namespace fileformat
} // namespace retdec

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class MachOSymbol

/// @name Interpretation methods
/// @{
Import getAsImport() const;
std::unique_ptr<Import> getAsImport() const;
Export getAsExport() const;
std::shared_ptr<Symbol> getAsSymbol() const;
/// @}
Expand Down
1 change: 1 addition & 0 deletions src/fileformat/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ set(FILEFORMAT_SOURCES
types/rich_header/linker_info.cpp
types/import_table/import.cpp
types/import_table/import_table.cpp
types/import_table/pe_import.cpp
types/export_table/export.cpp
types/export_table/export_table.cpp
types/relocation_table/relocation_table.cpp
Expand Down
14 changes: 8 additions & 6 deletions src/fileformat/file_format/elf/elf_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1661,7 +1661,6 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio
}

auto *symtab = new SymbolTable();
Import import;
Export newExport;
std::string name;
Elf_Half link = 0;
Expand Down Expand Up @@ -1695,7 +1694,6 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio
// Ignore first STN_UNDEF STT_NOTYPE symbol when considering imports
if(link == SHN_UNDEF && i != 0)
{
import.setName(name);
if(!importTable)
{
importTable = new ImportTable();
Expand All @@ -1705,13 +1703,17 @@ void ElfFormat::loadSymbols(const ELFIO::elfio *file, const ELFIO::symbol_sectio
std::set<std::pair<std::string, unsigned long long>> addresses(keyIter.first, keyIter.second);
for(const auto &address : addresses)
{
import.setAddress(address.second);
importTable->addImport(import);
auto import = std::make_unique<Import>();
import->setName(name);
import->setAddress(address.second);
importTable->addImport(std::move(import));
}
if(keyIter.first == keyIter.second && getSectionFromAddress(value))
{
import.setAddress(value);
importTable->addImport(import);
auto import = std::make_unique<Import>();
import->setName(name);
import->setAddress(value);
importTable->addImport(std::move(import));
}
}
}
Expand Down
Loading

0 comments on commit 7523e07

Please sign in to comment.