| 上一帖子介绍PE文件大体由PE文件头与节表组成, PE文件头由DOS头+pe标识+标准PE头+可选PE头+节表+节内容组成。
 这帖子在前面帖子代码基础上编写标准PE头方读取,并介绍标准PE文件头结构成员含义。
 例程界面如下:
 
 PE文件结构之标准PE头介绍及编程读取   通过界面按钮打开一个可执行文件后,可以点击标准PE头按钮,显示从PE文件的标准PE头读取的信息。
 标准PE头对应为一个结构体类型变量IMAGE_FILE_HEADER。
 在上一帖子介绍pe标识+标准PE头+可选PE头为PE头部分,对应结构体为IMAGE_NT_HEADERS。
 标准PE头在PE文件中,开始地址由DOS_MZ成员e_lfanew指定。
 那么PE头的定位代码,在例程中就可以这样写:
 PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG)pDosHeader+pDosHeader->e_lfanew);
 标准PE头成员变量就可以这样访问:
 pNtHeaders->FileHeader.Machine;
 pDosHeader为DOS头指针,在上一帖子中有介绍是在文件打开时获取。
 下面代码为标准PE头成员显示函数:
 
 主要还是结构体IMAGE_FILE_HEADER成员的含义理解:复制代码void CFileHeaderDlg::UpdateData(PIMAGE_DOS_HEADER pDosHeader,bool bSetGet)
{
        if(pDosHeader == NULL)
                return;
        PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG)pDosHeader+pDosHeader->e_lfanew);
        CString sText;
        if(bSetGet)
        {
                sText.Format("%04X",pNtHeaders->Signature);
                SetDlgItemText(IDC_EDIT11,sText);
                sText.Format("%04X",pNtHeaders->FileHeader.Machine);
                SetDlgItemText(IDC_EDIT1,sText);
                sText.Format("%04X",pNtHeaders->FileHeader.NumberOfSections);
                SetDlgItemText(IDC_EDIT2,sText);
                sText.Format("%08X",pNtHeaders->FileHeader.TimeDateStamp);
                SetDlgItemText(IDC_EDIT3,sText);
                sText.Format("%08X",pNtHeaders->FileHeader.PointerToSymbolTable);
                SetDlgItemText(IDC_EDIT4,sText);
                sText.Format("%08X",pNtHeaders->FileHeader.NumberOfSymbols);
                SetDlgItemText(IDC_EDIT5,sText);
                sText.Format("%04X",pNtHeaders->FileHeader.SizeOfOptionalHeader);
                SetDlgItemText(IDC_EDIT6,sText);
                sText.Format("%04X",pNtHeaders->FileHeader.Characteristics);
                SetDlgItemText(IDC_EDIT7,sText);
        }
        else
        {
        }
}
typedef struct _IMAGE_FILE_HEADER {
 WORD    Machine;
 WORD    NumberOfSections;
 DWORD   TimeDateStamp;
 DWORD   PointerToSymbolTable;
 DWORD   NumberOfSymbols;
 WORD    SizeOfOptionalHeader;
 WORD    Characteristics;
 } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
 
 
 1.Machine:
 单字长度, 用来指定PE文件运行平台。有哪些平台可支持,或有哪些值可供使用?
 例程对应代码如下:
 
 例如选择"IMAGE_FILE_MACHINE_I386 |0x014c",复制代码 m_Combox.AddString("IMAGE_FILE_MACHINE_UNKNOWN           |0X00");
        m_Combox.AddString("IMAGE_FILE_MACHINE_I386              |0x014c");
        m_Combox.AddString("IMAGE_FILE_MACHINE_R3000             |0x0162");
        m_Combox.AddString("IMAGE_FILE_MACHINE_R4000             |0x0166");
        m_Combox.AddString("IMAGE_FILE_MACHINE_R10000            |0x0168");
        m_Combox.AddString("IMAGE_FILE_MACHINE_WCEMIPSV2         |0x0169");
        m_Combox.AddString("IMAGE_FILE_MACHINE_ALPHA             |0x0184");
        m_Combox.AddString("IMAGE_FILE_MACHINE_SH3               |0x01a2");
        m_Combox.AddString("IMAGE_FILE_MACHINE_SH3DSP            |0x01a3");
        m_Combox.AddString("IMAGE_FILE_MACHINE_SH3E              |0x01a4");
        m_Combox.AddString("IMAGE_FILE_MACHINE_SH4               |0x01a6");
        m_Combox.AddString("IMAGE_FILE_MACHINE_SH5               |0x01a8");
        m_Combox.AddString("IMAGE_FILE_MACHINE_ARM               |0x01c0");
        m_Combox.AddString("IMAGE_FILE_MACHINE_THUMB             |0x01c2");
        m_Combox.AddString("IMAGE_FILE_MACHINE_AM33              |0x01d3");
        m_Combox.AddString("IMAGE_FILE_MACHINE_POWERPC           |0x01F0");
        m_Combox.AddString("IMAGE_FILE_MACHINE_POWERPCFP         |0x01f1");
        m_Combox.AddString("IMAGE_FILE_MACHINE_IA64              |0x0200");
        m_Combox.AddString("IMAGE_FILE_MACHINE_MIPS16            |0x0266");
        m_Combox.AddString("IMAGE_FILE_MACHINE_ALPHA64           |0x0284");
        m_Combox.AddString("IMAGE_FILE_MACHINE_MIPSFPU           |0x0366");
        m_Combox.AddString("IMAGE_FILE_MACHINE_MIPSFPU16         |0x0466");
        m_Combox.AddString("IMAGE_FILE_MACHINE_TRICORE           |0x0520");
        m_Combox.AddString("IMAGE_FILE_MACHINE_CEF               |0x0CEF");
        m_Combox.AddString("IMAGE_FILE_MACHINE_EBC               |0x0EBC");
        m_Combox.AddString("IMAGE_FILE_MACHINE_AMD64             |0x8664");
        m_Combox.AddString("IMAGE_FILE_MACHINE_M32R              |0x9041");
        m_Combox.AddString("IMAGE_FILE_MACHINE_CEE               |0xC0EE");
例程会提取数值0X014C赋值给IMAGE_FILE_HEADER的成员变量Machine。
 那么这些如IMAGE_FILE_MACHINE_I386的含义是什么,表示什么处理器呢?
 下面截图于一PDF文件,这里就不码字了:
 
 PE文件结构之标准PE头介绍及编程读取   
 2.NumberOfSections:
 PE文件中存在的节的个数,单字长度。
 在XP系统中,可以没有节,但数值不可小于1,或大于96。
 仅能等于内存中存在的节个数,不然系统装载PE文件时会提示错误。
 如果我们想在PE文件增,删节,得记得对应修改一下此数值。
 
 3.TimeDateStamp:
 双字长度,编译器在创建此文件时填写的时间戳,表示从1970年,1月1日,0时,0分,0秒开始,到文件创建时的总的秒数。
 此数值无意义,可任意修改。要注意的是此值与文件属性:创建时间,修改时间,访问时间无关。
 如果想知道时间戳与年月日,时分秒间如何相互转换,可以下载与参考例程源代码。
 如上面第一图片,点击界面两个按钮,可以进行相互间转换。
 
 4.PointerToSymbolTable,NumberOfSymbols:
 PointerToSymbolTable双字长度,COFF符号表文件偏移,如无COFF符号表,此值为0。
 对于映像文件,此值为0,微软已不建议使用。
 NumberOfSymbols双字长度,符号表中元数数目。
 这两成员已无用,主要用于调试,可不用关注。
 COFF:Common Object File Format标准通用文件对象,记录了PE文件的全局属性。
 
 5.SizeOfOptionalHeader:
 单字,指定可选PE头(对应结构体IMAGE_OPTIONAL_HEADER32)的长度。
 默认值为0X00E0,如果是64位PE文件,默认值则为0x00f0.
 可以修改此值,但要自行保证文件中IMAGE_OPTIONAL_HEADER32大小与此值相同。
 以及满足PE文件对齐特征。
 
 6.Characteristics:
 单字长度,表示文件属性标识字段。以二进制位的形式来使用,共16个属性。
 这是一个很重要的字段,系统会根据此值来决定对文件的装载方式。
 对于一般可执行文件,此值一般是0x10f,
 对于DLL文件,一般是0x210e.
 那么这16个进进制位,每个位的含义是什么呢?
 可以参考下面图片。
 
 PE文件结构之标准PE头介绍及编程读取   例程中有实现对每个位的读取与设置,
 可以下载例程来参考使用。
 
 PE文件结构之标准PE头介绍及编程读取   以上就是标准PE头结果成员 的含义与读取的关键代码。
 自己编写代码来读取一个可执行文件的每个部分是最好的学习PE文件。
 例程下载地址:
 
 
 下一帖子会介绍可选PE头的读取与成员变量的含义。
 
 
 |