Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lz memory dump detection #770

Merged
merged 3 commits into from
May 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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