Skip to content

Commit

Permalink
Lz memory dump detection (#770)
Browse files Browse the repository at this point in the history
* Added detection of in-memory layout PE files

* Fixed indentation

* Added check for section alignment

Co-authored-by: Ladislav Zezula <[email protected]>
  • Loading branch information
ladislav-zezula and Ladislav Zezula authored May 23, 2020
1 parent 64769c5 commit c213750
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 29 deletions.
90 changes: 61 additions & 29 deletions include/retdec/pelib/PeFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ namespace PeLib

/// Checks the entry point code
LoaderError checkEntryPointErrors() const;
LoaderError checkForInMemoryLayout(LoaderError ldrError) const;

/// Returns a loader error, if there was any
LoaderError loaderError() const;
Expand Down Expand Up @@ -738,55 +739,86 @@ namespace PeLib
return LDR_ERROR_NONE;
}

template<int bits>
LoaderError PeFileT<bits>::checkForInMemoryLayout(LoaderError ldrError) const
{
std::uint64_t ulFileSize = fileSize(m_iStream);
std::uint64_t sizeOfImage = peHeader().getSizeOfImage();

// The file size must be greater or equal to SizeOfImage
if(ulFileSize >= sizeOfImage)
{
dword sectionAlignment = peHeader().getSectionAlignment();
dword fileAlignment = peHeader().getFileAlignment();
dword sizeOfHeaders = peHeader().getSizeOfHeaders();

// SectionAlignment must be greater than file alignment
if(sectionAlignment >= PELIB_PAGE_SIZE && sectionAlignment > fileAlignment)
{
// SizeOfHeaders must be smaller than SectionAlignment
if(sizeOfHeaders < sectionAlignment)
{
std::size_t headerDataSize = sectionAlignment - sizeOfHeaders;

// Read the entire after-header-data
std::vector<unsigned char> headerData(headerDataSize);
m_iStream.seekg(peHeader().getSizeOfHeaders(), std::ios::beg);
m_iStream.read(reinterpret_cast<char *>(headerData.data()), headerDataSize);

// Check whether there are zeros only. If yes, we consider
// the file to be an in-memory image
if(std::all_of(headerData.begin(), headerData.end(), [](char item) { return item == 0; }))
ldrError = LDR_ERROR_INMEMORY_IMAGE;
}
}
}

return ldrError;
}

// 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;
// Check for problems in DOS header
LoaderError ldrError = mzHeader().loaderError();

// Was there a problem in the NT headers?
ldrError = peHeader().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
if (ldrError == LDR_ERROR_NONE)
ldrError = peHeader().loaderError();

// Check the loader error
ldrError = coffSymTab().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
if (ldrError == LDR_ERROR_NONE)
ldrError = coffSymTab().loaderError();

// Check errors in import directory
ldrError = impDir().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
if (ldrError == LDR_ERROR_NONE)
ldrError = impDir().loaderError();

// Check errors in resource directory
ldrError = resDir().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
if (ldrError == LDR_ERROR_NONE)
ldrError = resDir().loaderError();

// Check errors in relocations directory
ldrError = relocDir().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
if (ldrError == LDR_ERROR_NONE)
ldrError = relocDir().loaderError();

// Check errors in security directory
if (ldrError == LDR_ERROR_NONE)
ldrError = securityDir().loaderError();

// Check errors in entry point
ldrError = checkEntryPointErrors();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
if (ldrError == LDR_ERROR_NONE)
ldrError = checkEntryPointErrors();

// Check errors in security directory
ldrError = securityDir().loaderError();
if (ldrError != LDR_ERROR_NONE)
return ldrError;
// If there was a loaded error, we'll check whether
// the file can't actually be an in-memory version
if(ldrError != LDR_ERROR_NONE)
ldrError = checkForInMemoryLayout(ldrError);

// Nothing wrond found
return LDR_ERROR_NONE;
return ldrError;
}
}

Expand Down
3 changes: 3 additions & 0 deletions include/retdec/pelib/PeLibAux.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ namespace PeLib
LDR_ERROR_RELOC_BLOCK_INVALID_LENGTH, // A relocation block has invalid length
LDR_ERROR_RELOC_ENTRY_BAD_TYPE, // A relocation entry has invalid type

// Other errors
LDR_ERROR_INMEMORY_IMAGE, // The file is a 1:1 in-memory image

LDR_ERROR_MAX

};
Expand Down
3 changes: 3 additions & 0 deletions src/pelib/PeLibAux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ namespace PeLib
{"LDR_ERROR_RELOC_BLOCK_INVALID_LENGTH", "A relocation block has invalid length", true },
{"LDR_ERROR_RELOC_ENTRY_BAD_TYPE", "A relocation entry has invalid type", true },

// Other errors
{"LDR_ERROR_INMEMORY_IMAGE", "The file is an in-memory image", false },

};

PELIB_IMAGE_FILE_MACHINE_ITERATOR::PELIB_IMAGE_FILE_MACHINE_ITERATOR()
Expand Down

0 comments on commit c213750

Please sign in to comment.