trailofbits / trailofbits/pe-parse
Problem in parsing 2 files
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 911
- Forks
- 171
- PR merge metrics
- No merged PRs in 30d
Description
Thanks for the great project! I'm trying to use it for reading versions from executables.
I've built it with Qt Creator, gcc, qbs (see my .qbs and .cpp files in the archive): pe-parse.zip
Most EXE and DLL files I've tried were parsed fine but two of them failed:
- System.Text.Json.dll - getDebugDir fails. Since this file has an Authenticode signature of .NET project, it's unlikely that the file is currupt.
- ConfKarat.exe - incorrect version resource is passed to IterRsrc callback. Windows explorer file properties box shows the version. I can also see the version in a hex editor. But res.buf->buf in my code doesn't point to anything containing VS_VERSION_INFO and 0xfeef04bd signature.
Here is my code:
struct MY_VS_FIXEDFILEINFO
{
quint32 dwSignature;
quint32 dwStrucVersion;
quint32 dwFileVersionMS;
quint32 dwFileVersionLS;
quint32 dwProductVersionMS;
quint32 dwProductVersionLS;
quint32 dwFileFlagsMask;
quint32 dwFileFlags;
quint32 dwFileOS;
quint32 dwFileType;
quint32 dwFileSubtype;
quint32 dwFileDateMS;
quint32 dwFileDateLS;
};
int extractVersionFromResourceCallback(void* ptr, const peparse::resource& res)
{
// Skip all resource types execpt RT_VERSION
if(res.type != 16) return 0;
// Find VS_FIXEDFILEINFO in the buffer
auto structSize = sizeof(MY_VS_FIXEDFILEINFO);
for(size_t offset = 0; offset + structSize <= res.size; offset += 4)
{
auto verInfo = (const MY_VS_FIXEDFILEINFO*)(res.buf->buf + offset);
if (verInfo->dwSignature == 0xfeef04bd)
{
QString& result = *(QString*)ptr;
result = QStringLiteral("%1.%2.%3.%4")
.arg(( verInfo->dwFileVersionMS >> 16 ) & 0xffff)
.arg(( verInfo->dwFileVersionMS >> 0 ) & 0xffff)
.arg(( verInfo->dwFileVersionLS >> 16 ) & 0xffff)
.arg(( verInfo->dwFileVersionLS >> 0 ) & 0xffff);
return 1;
}
}
// Maybe there's another version resource we'll understand
return 0;
}
...
// Have to use mutex because pe-parse library uses globals
static QMutex peparseMutex;
QMutexLocker locker(&peparseMutex);
// Try to parse PE
auto peptr = peparse::ParsePEFromPointer((std::uint8_t*)m_data.data(), m_data.size());
if (peptr == nullptr)
{
qWarning() << "Failed to parse PE. Code:" << peparse::GetPEErr() << endl
<< "Error:" << QString::fromStdString(peparse::GetPEErrString()) << endl
<< "Location:" << QString::fromStdString(peparse::GetPEErrLoc());
return QString();
}
// Make sure we cleanup properly
try
{
// Iterate resources
QString result;
peparse::IterRsrc(peptr, extractVersionFromResourceCallback, &result);
DestructParsedPE(peptr);
return result;
}
catch (...)
{
DestructParsedPE(peptr);
throw;
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the failures with the attached pe-parse.zip and trace ParsePEFromPointer, getDebugDir, and IterRsrc for System.Text.Json.dll and ConfKarat.exe. Compare the resource data supplied to the callback with the version resource visible in the files; done means both executables parse without the reported failure and the expected version resource is exposed correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- operating-systems, reverse-engineering
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100