2

PE ファイルを解析しようとしています。それをメモリにロードし、WinNT 構造ポインタを適切なアドレスに設定します。しかし、DOS ヘッダーからのオフセットが間違っている (1 バイトが多すぎる) ため、PE\0\0 署名の愚かなチェックを行うことができません。したがって、IMAGE_NT_HEADERS.Signature を確認すると、「E」から始まる 4 バイトを受け取ります。

#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");

DEBUG スニペットの結果は次のとおりです。

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

pedump.meで確認したところm_DOSHeader->e_lfanew = 0xf0でOK。実際に正しい署名を取得するためにこのオフセットを減らす必要があるのは何ですか?

64 ビット Windows 8.1 で VS2013 RC を使用していますが、_WIN32 定義が設定されていることを確認しました。このエラーは、32 ビットと 64 ビットの両方の exe ファイルで発生します。

4

1 に答える 1