From 122887a27b3e69d54e3da13aba6d9e3b1165961f Mon Sep 17 00:00:00 2001 From: HoundThe Date: Tue, 2 Nov 2021 15:58:57 +0100 Subject: [PATCH] Check for ELF damage (#1036) * Check if LOAD segments are within the file * Separate segment checking into its own function, set loadable anyway --- .../fileformat/file_format/elf/elf_format.h | 7 +++++++ .../fileformat/file_format/file_format.h | 11 ++++------ src/fileformat/file_format/elf/elf_format.cpp | 21 +++++++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/include/retdec/fileformat/file_format/elf/elf_format.h b/include/retdec/fileformat/file_format/elf/elf_format.h index cd24701e7..f84574792 100644 --- a/include/retdec/fileformat/file_format/elf/elf_format.h +++ b/include/retdec/fileformat/file_format/elf/elf_format.h @@ -18,6 +18,12 @@ namespace retdec { namespace fileformat { +enum ElfLoaderError : std::uint32_t +{ + LDR_ERROR_NONE = 0, + LDR_ERROR_SEGMENT_OUT_OF_FILE +}; + /** * ElfFormat - wrapper for parsing ELF files */ @@ -75,6 +81,7 @@ class ElfFormat : public FileFormat const ELFIO::dynamic_section_accessor *elfDynamicTable, const ELFIO::section *sec); void loadSections(); + void checkSegmentLoadable(const ELFIO::segment* seg); void loadSegments(); void loadDynamicSegmentSection(); void loadInfoFromDynamicTables(DynamicTable &dynTab, ELFIO::section *sec); diff --git a/include/retdec/fileformat/file_format/file_format.h b/include/retdec/fileformat/file_format/file_format.h index 2181629a3..48a043695 100644 --- a/include/retdec/fileformat/file_format/file_format.h +++ b/include/retdec/fileformat/file_format/file_format.h @@ -29,13 +29,10 @@ namespace fileformat { struct LoaderErrorInfo { - LoaderErrorInfo() : loaderErrorCode(0), loaderError(nullptr), loaderErrorUserFriendly(nullptr) - {} - - std::uint32_t loaderErrorCode; // Loader error code, cast to uint32_t - const char * loaderError; - const char * loaderErrorUserFriendly; - bool isLoadableAnyway; + std::uint32_t loaderErrorCode = 0; // Loader error code, cast to uint32_t - 0 means OK + const char *loaderError = nullptr; + const char *loaderErrorUserFriendly = nullptr; + bool isLoadableAnyway = false; }; /** diff --git a/src/fileformat/file_format/elf/elf_format.cpp b/src/fileformat/file_format/elf/elf_format.cpp index edc5771de..2d5d40c0f 100644 --- a/src/fileformat/file_format/elf/elf_format.cpp +++ b/src/fileformat/file_format/elf/elf_format.cpp @@ -2062,6 +2062,25 @@ void ElfFormat::loadSections() } } +void ElfFormat::checkSegmentLoadable(const segment* seg) +{ + if (!seg) + return; + + auto filesize = seg->get_file_size(); + auto fileoffset = seg->get_offset(); + int segtype = seg->get_type(); + + // Check if LOAD segments are actually in the file + if (segtype == PT_LOAD && getFileLength() < fileoffset + filesize) + { + _ldrErrInfo.isLoadableAnyway = false; + _ldrErrInfo.loaderErrorCode = ElfLoaderError::LDR_ERROR_SEGMENT_OUT_OF_FILE; + _ldrErrInfo.loaderError = "LOAD Segment data is not within file bounds"; + _ldrErrInfo.loaderErrorUserFriendly = "LOAD Segment data is not within file bounds"; + } +} + /** * Load information about segments */ @@ -2088,6 +2107,8 @@ void ElfFormat::loadSegments() fSeg->setElfAlign(seg->get_align()); fSeg->load(this); segments.push_back(fSeg); + + checkSegmentLoadable(seg); } }