Skip to content

Commit

Permalink
Anomalies scanner (#570)
Browse files Browse the repository at this point in the history
* section-related anomaly detection

* section-related anomaly detection

* import/export/resource/OptHeader/CoffFileHeader anomalies

* add source link

* add source link

* anomaly json presentation

* anomalies plain presentation

* presentation fixed

* duplicit anomalies fixed

* emplace_back and rvalues fixed

* doxygen fixed

* rebased and chars replaced

* Minor modifications in anomalies nomenclature

* Removed some anomalies which didn't prove to be useful that much

* Scan for entry point anomalies only if the sample really has entry point
  • Loading branch information
JakubPruzinec authored and metthal committed Jul 1, 2019
1 parent 0344f29 commit 10941c0
Show file tree
Hide file tree
Showing 24 changed files with 714 additions and 3 deletions.
4 changes: 4 additions & 0 deletions include/retdec/fileformat/file_format/file_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <initializer_list>
#include <map>
#include <set>
#include <utility>
#include <vector>

#include "retdec/utils/byte_value_storage.h"
Expand Down Expand Up @@ -91,6 +92,7 @@ class FileFormat : public retdec::utils::ByteValueStorage, private retdec::utils
std::vector<std::pair<std::size_t, std::size_t>> secHashInfo; ///< information for calculation of section table hash
retdec::utils::Maybe<bool> signatureVerified; ///< indicates whether the signature is present and also verified
retdec::utils::RangeContainer<std::uint64_t> nonDecodableRanges; ///< Address ranges which should not be decoded for instructions.
std::vector<std::pair<std::string, std::string>> anomalies; ///< file format anomalies

/// @name Clear methods
/// @{
Expand Down Expand Up @@ -212,6 +214,7 @@ class FileFormat : public retdec::utils::ByteValueStorage, private retdec::utils
bool getHexBytesFromEnd(std::string &result, unsigned long long numberOfBytes) const;
bool getString(std::string &result, unsigned long long offset, unsigned long long numberOfBytes) const;
bool getStringFromEnd(std::string &result, unsigned long long numberOfBytes) const;
bool isObjectStretchedOverSections(std::size_t addr, std::size_t size) const;
const Section* getEpSection();
const Section* getSection(const std::string &secName) const;
const Section* getSection(unsigned long long secIndex) const;
Expand Down Expand Up @@ -265,6 +268,7 @@ class FileFormat : public retdec::utils::ByteValueStorage, private retdec::utils
const std::vector<String>& getStrings() const;
const std::vector<ElfNoteSecSeg>& getElfNoteSecSegs() const;
const std::set<std::uint64_t>& getUnknownRelocations() const;
const std::vector<std::pair<std::string,std::string>> &getAnomalies() const;
/// @}

/// @name Address interpretation methods
Expand Down
13 changes: 13 additions & 0 deletions include/retdec/fileformat/file_format/pe/pe_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ class PeFormat : public FileFormat
bool parseVisualBasicComRegistrationInfo(std::size_t structureOffset,
std::size_t comRegDataOffset);
/// @}
/// @name Auxiliary scanning methods
/// @{
void scanForSectionAnomalies();
void scanForResourceAnomalies();
void scanForImportAnomalies();
void scanForExportAnomalies();
void scanForOptHeaderAnomalies();
/// @}
protected:
PeLib::PeFile *file; ///< PeLib representation of PE file
PeLib::PeHeaderT<32> *peHeader32; ///< header of 32-bit PE file
Expand Down Expand Up @@ -207,6 +215,11 @@ class PeFormat : public FileFormat
const std::string& getTypeRefhashSha256() const;
const VisualBasicInfo* getVisualBasicInfo() const;
/// @}

/// @name Scanning methods
/// @{
void scanForAnomalies();
/// @}
};

} // namespace fileformat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class PeFormatParser
virtual unsigned long long getFileFlags() const = 0;
virtual unsigned long long getTimeStamp() const = 0;
virtual unsigned long long getOptionalHeaderSize() const = 0;
virtual bool isSizeOfHeaderMultipleOfFileAlignment() const = 0;
virtual unsigned long long getFileAlignment() const = 0;
virtual unsigned long long getSectionAlignment() const = 0;
virtual unsigned long long getSizeOfImage() const = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class PeFormatParser32 : public PeFormatParser
virtual unsigned long long getFileFlags() const override;
virtual unsigned long long getTimeStamp() const override;
virtual unsigned long long getOptionalHeaderSize() const override;
virtual bool isSizeOfHeaderMultipleOfFileAlignment() const override;
virtual unsigned long long getFileAlignment() const override;
virtual unsigned long long getSectionAlignment() const override;
virtual unsigned long long getSizeOfImage() const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class PeFormatParser64 : public PeFormatParser
virtual unsigned long long getFileFlags() const override;
virtual unsigned long long getTimeStamp() const override;
virtual unsigned long long getOptionalHeaderSize() const override;
virtual bool isSizeOfHeaderMultipleOfFileAlignment() const override;
virtual unsigned long long getFileAlignment() const override;
virtual unsigned long long getSectionAlignment() const override;
virtual unsigned long long getSizeOfImage() const override;
Expand Down
17 changes: 15 additions & 2 deletions include/retdec/fileformat/file_format/pe/pe_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <memory>

#include "retdec/utils/alignment.h"
#include "retdec/utils/range.h"
#include "retdec/utils/string.h"
#include "retdec/fileformat/file_format/pe/pe_template_aux.h"
Expand Down Expand Up @@ -171,6 +172,18 @@ template<int bits> unsigned long long peSizeOfOptionalHeader(const PeLib::PeHead
return peHeader.getSizeOfOptionalHeader();
}

/**
* Find out if optional header SizeOfHeaders is rounded up to multiple of FileAlignment
* @param peHeader Parser of PE header
* @return @c true if SizeOfHeaders is rounded up to multiple of FileAlignment, @c false otherwise
*/
template<int bits> unsigned long long peIsSizeOfHeaderMultipleOfFileAlignment(
const PeLib::PeHeaderT<bits> &peHeader)
{
std::uint64_t remainder;
return retdec::utils::isAligned(peHeader.getSizeOfHeaders(), peHeader.getFileAlignment(), remainder);
}

/**
* Get file alignment
* @param peHeader Parser of PE header
Expand Down Expand Up @@ -322,9 +335,9 @@ template<int bits> unsigned long long peNumberOfDelayImportedLibraries(const PeL
}

/**
* Get number of data directories
* Find out if is DLL
* @param peHeader Parser of PE header
* @return Number of data directories
* @return @c true if is DLL, @c false otherwise
*/
template<int bits> bool peIsDll(const PeLib::PeHeaderT<bits> &peHeader)
{
Expand Down
1 change: 1 addition & 0 deletions src/fileformat/file_format/coff/coff_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -791,5 +791,6 @@ bool CoffFormat::is32BitArchitecture() const
return (getFileFlags() & IMAGE_FILE_32BIT_MACHINE) || getWordLength() == 32;
}


} // namespace fileformat
} // namespace retdec
37 changes: 37 additions & 0 deletions src/fileformat/file_format/file_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,33 @@ bool FileFormat::getStringFromEnd(std::string &result, unsigned long long number
return getString(result, getLoadedFileLength() - numberOfBytes, numberOfBytes);
}

/**
* Find out if object is stretched over multiple sections
* @param addr Addres of object
* @param size Object size
* @return @c true if object is stretched over multiple sections, @c false otherwise
*/
bool FileFormat::isObjectStretchedOverSections(std::size_t addr, std::size_t size) const
{
for (const auto sec : sections)
{
if (!sec)
{
continue;
}

std::size_t secStart = sec->getOffset();
std::size_t secEnd = secStart + sec->getSizeInFile();
std::size_t addrEnd = addr + size;
if (secStart <= addr && addr < secEnd)
{
return (addrEnd > secEnd);
}
}

return false;
}

/**
* Get information about section containing entry point
* @return Pointer to EP section if file has entry point and EP section was detected, @c nullptr otherwise
Expand Down Expand Up @@ -1905,6 +1932,16 @@ const std::set<std::uint64_t> &FileFormat::getUnknownRelocations() const
return unknownRelocs;
}

/**
* Get all anomalies
* @return Reference to anomalies
*/
const std::vector<std::pair<std::string,std::string>> &FileFormat::getAnomalies() const
{
return anomalies;
}


/**
* Get integer (@a x bytes) located at provided address using the specified endian or default file endian
* @param address Address to get integer from
Expand Down
Loading

0 comments on commit 10941c0

Please sign in to comment.