最近在看Iczelion的PE教程,整理一个简单的C/C++代码。目标是最终写一个PEViewer。

本篇为判断文件是否是PE文件。具体思路是判断IMAGE_DOS_HEADER和IMAGE_NT_HEADERS中的SIGNATURE,也就是著名的“MZ”和“PE\0\0"。简单类代码如下:

#include <iostream>
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
using namespace std;
class PEfileOper
{
#define IF_INVALID_POINTER(p) if((p)==NULL)
private:
    char* _fileName;
    bool _valid ;
    FILE* _pf ;
    IMAGE_DOS_HEADER _dosHeader;
    IMAGE_NT_HEADERS _ntHeader;
public:
    PEfileOper(char* fName)
    {
        _pf = NULL;
        _valid = false;
        if(fName == NULL)
            _fileName = NULL ;
        else
        {
            int len = strlen(fName) ;
            _fileName = new char[len+1] ;
            strcpy(_fileName, fName) ;
        }
        initPE();
    }
    bool isValidPE()
    {
        bool dos = loadDosHeader();
        if(dos)
        {
            bool nt = loadNTHeader();
            if(nt)
                return true;
        }
        return false;
    }
    ~PEfileOper()
    {
        if(_fileName != NULL)
        {
            delete _fileName ;
            _fileName = NULL;
        }
        if(_pf != NULL)
        {
            fclose(_pf);
            _pf = NULL;
        }
    }
private:
    bool initPE()
    {
        if(_fileName == NULL) return false;
        _pf = fopen(_fileName, "rb");
        IF_INVALID_POINTER(_pf)
            return false;
        return true;
    }
    bool loadDosHeader()
    {
        size_t dos_head_size = fread(&_dosHeader, sizeof(char), sizeof(IMAGE_DOS_HEADER), _pf);
        assert(dos_head_size > 0);
        if(_dosHeader.e_magic == IMAGE_DOS_SIGNATURE)
            return true ;
        else
            return false;
    }
    bool loadNTHeader()
    {
        fseek(_pf, _dosHeader.e_lfanew, SEEK_SET);
        size_t nt_header_size = fread(&_ntHeader, sizeof(char), sizeof(IMAGE_NT_HEADERS), _pf);
        assert(nt_header_size > 0);
        if(_ntHeader.Signature == IMAGE_NT_SIGNATURE)
            return true;
        else
            return false;
    }
};