Question

I am trying to parse PE file, I load it into memory and I set WinNT structures pointer to appopriate addresses. However, I'm not able to do stupid checking for PE\0\0 signature, because I have wrong offset from DOS header (one byte too much). So when I check IMAGE_NT_HEADERS.Signature I receive 4 bytes starting from 'E'.

#define SHOW_VAR(x)  std::cout << #x << " = " << x << std::endl
#define SHOW_HEX(x)  std::cout << std::showbase << std::hex << #x << " = " << x << std::endl; std::cout << std::dec

uintmax_t fileSize = boost::filesystem::file_size(m_filePath);
m_image.reset(new char[fileSize]);

boost::filesystem::ifstream file;
file.open(m_filePath, std::ios::in);
file.read(m_image.get(), fileSize);
file.close();

m_DOSHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(m_image.get());
// --m_DOSHeader->e_lfanew; <---- THIS SOLVES THE PROBLEM BUT WHY?
m_NTHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(m_image.get() + m_DOSHeader->e_lfanew);

// DEBUG
SHOW_HEX(m_DOSHeader->e_lfanew);
for(int i = m_DOSHeader->e_lfanew - 5; i < m_DOSHeader->e_lfanew + 5; ++i)
{
    if(i == m_DOSHeader->e_lfanew)
        std::cout << "---> ";
    SHOW_HEX(m_image[i]);
}

// check if MZ
if(m_DOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
    throw std::runtime_error("[PEFile] MZ signature not found");

// check if PE00
SHOW_VAR((char)m_NTHeaders->Signature);
if(m_NTHeaders->Signature != IMAGE_NT_SIGNATURE)
    throw std::runtime_error("[PEFile] PE00 signature not found");

The result of DEBUG snippet is:

m_DOSHeader->e_lfanew = 0xf0
m_image[i] =  
m_image[i] =  
m_image[i] =  
m_image[i] =  
m_image[i] = P
---> m_image[i] = E
m_image[i] =  
m_image[i] =  
m_image[i] = L
m_image[i] = 
(char)m_NTHeaders->Signature = E
[ERROR] [PEFile] PE00 signature not found

I checked it with pedump.me and m_DOSHeader->e_lfanew = 0xf0 is OK. What do I do wrong that I have to decrement this offset to get actually correct signature?

I'm using VS2013 RC on 64-bit Windows 8.1, but I checked that I have set _WIN32 define. And this error occures for both 32 and 64 bit exe files.

Was it helpful?

Solution

file.open(m_filepath, std::ios::in | std::ios::binary);

If you don't open in binary mode, then additional characters can be added or removed by std::fstream when processing input.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top