工控编程吧
标题:
PE文件结构之标准PE头介绍及编程读取
[打印本页]
作者:
qq263946146
时间:
2019-12-17 18:52
标题:
PE文件结构之标准PE头介绍及编程读取
上一帖子介绍PE文件大体由PE文件头与节表组成,
PE文件头由DOS头+pe标识+标准PE头+可选PE头+节表+节内容组成。
这帖子在前面帖子代码基础上编写标准PE头方读取,并介绍标准PE文件头结构成员含义。
例程界面如下:
(, 下载次数: 3)
上传
点击文件名下载附件
通过界面按钮打开一个可执行文件后,可以点击标准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头成员显示函数:
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
{
}
}
复制代码
主要还是结构体IMAGE_FILE_HEADER成员的含义理解:
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文件运行平台。有哪些平台可支持,或有哪些值可供使用?
例程对应代码如下:
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");
复制代码
例如选择
"IMAGE_FILE_MACHINE_I386 |0x014c",
例程会提取数值0X014C赋值给
IMAGE_FILE_HEADER的成员变量Machine。
那么这些如
IMAGE_FILE_MACHINE_I386的含义是什么,表示什么处理器呢?
下面截图于一PDF文件,这里就不码字了:
(, 下载次数: 1)
上传
点击文件名下载附件
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个进进制位,每个位的含义是什么呢?
可以参考下面图片。
(, 下载次数: 2)
上传
点击文件名下载附件
例程中有实现对每个位的读取与设置,
可以下载例程来参考使用。
(, 下载次数: 1)
上传
点击文件名下载附件
以上就是标准PE头结果成员 的含义与读取的关键代码。
自己编写代码来读取一个可执行文件的每个部分是最好的学习PE文件。
例程下载地址:
(, 下载次数: 0)
上传
点击文件名下载附件
下一帖子会介绍可选PE头的读取与成员变量的含义。
欢迎光临 工控编程吧 (https://www.gkbc8.com/)
Powered by Discuz! X3.4