分享
 
 
 

PE文件格式详解(4)

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

PE文件段

PE文件规范由目前为止定义的那些头部以及一个名为“段”的一般对象组成。段包含了文件的内容,包括代码、数据、资源以及其它可执行信息,每个段都有一个头部和一个实体(原始数据)。我将在下面描述段头部的有关信息,但是段实体则缺少一个严格的文件结构。因此,它们几乎可以被链接器按任何的方法组织,只要它的头部填充了足够能够解释数据的信息。

段头部

PE文件格式中,所有的段头部位于可选头部之后。每个段头部为40个字节长,并且没有任何的填充信息。段头部被定义为以下的结构:

WINNT.H

#define IMAGE_SIZEOF_SHORT_NAME 8

typedef struct _IMAGE_SECTION_HEADER {

UCHAR Name[IMAGE_SIZEOF_SHORT_NAME];

union {

ULONG PhysicalAddress;

ULONG VirtualSize;

} Misc;

ULONG VirtualAddress;

ULONG SizeOfRawData;

ULONG PointerToRawData;

ULONG PointerToRelocations;

ULONG PointerToLinenumbers;

USHORT NumberOfRelocations;

USHORT NumberOfLinenumbers;

ULONG Characteristics;

} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

你如何才能获得一个特定段的段头部信息?既然段头部是被连续的组织起来的,而且没有一个特定的顺序,那么段头部必须由名称来定位。以下的函数示范了如何从一个给定了段名称的PE映像文件中获得一个段头部:

PEFILE.C

BOOL WINAPI GetSectionHdrByName(LPVOID lpFile,

IMAGE_SECTION_HEADER *sh, char *szSection)

{

PIMAGE_SECTION_HEADER psh;

int nSections = NumOfSections (lpFile);

int i;

if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET(lpFile))

!= NULL)

{

/* 由名称查找段 */

for (i = 0; i < nSections; i++)

{

if (!strcmp(psh->Name, szSection))

{

/* 向头部复制数据 */

CopyMemory((LPVOID)sh, (LPVOID)psh,

sizeof(IMAGE_SECTION_HEADER));

return TRUE;

}

else

psh++;

}

}

return FALSE;

}

这个函数通过SECHDROFFSET宏将第一个段头部定位,然后它开始在所有段中循环,并将要寻找的段名称和每个段的名称相比较,直到找到了正确的那一个为止。当找到了段的时候,函数将内存映像文件的数据复制到传入函数的结构中,然后IMAGE_SECTION_HEADER结构的各域就能够被直接存取了。

段头部的域

·Name。每个段都有一个8字符长的名称域,并且第一个字符必须是一个句点。

·PhysicalAddress或VirtualSize。第二个域是一个union域,现在已不使用了。

·VirtualAddress。这个域标识了进程地址空间中要装载这个段的虚拟地址。实际的地址由将这个域的值加上可选头部结构中的ImageBase虚拟地址得到。切记,如果这个映像文件是一个DLL,那么这个DLL就不一定会装载到ImageBase要求的位置。所以一旦这个文件被装载进入了一个进程,实际的ImageBase值应该通过使用GetModuleHandle来检验。

·SizeOfRawData。这个域表示了相对FileAlignment的段实体尺寸。文件中实际的段实体尺寸将少于或等于FileAlignment的整倍数。一旦映像被装载进入了一个进程的地址空间,段实体的尺寸将会变得少于或等于FileAlignment的整倍数。

·PointerToRawData。这是一个文件中段实体位置的偏移量。

·PointerToRelocations、PointerToLinenumbers、NumberOfRelocations、NumberOfLinenumbers。这些域在PE格式中不使用。

·Characteristics。定义了段的特征。这些值可以在WINNT.H及本光盘(译注:MSDN的光盘)的PE格式规范中找到。

定义

0x00000020

代码段

0x00000040

已初始化数据段

0x00000080

未初始化数据段

0x04000000

该段数据不能被缓存

0x08000000

该段不能被分页

0x10000000

共享段

0x20000000

可执行段

0x40000000

可读段

0x80000000

可写段

定位数据目录

数据目录存在于它们相应的数据段中。典型地来说,数据目录是段实体中的第一个结构,但不是必需的。由于这个缘故,如果你需要定位一个指定的数据目录的话,就需要从段头部和可选头部中获得信息。

为了让这个过程简单一点,我编写了以下的函数来定位任何一个在WINNT.H之中定义的数据目录。

PEFILE.C

LPVOID WINAPI ImageDirectoryOffset(LPVOID lpFile,

DWORD dwIMAGE_DIRECTORY)

{

PIMAGE_OPTIONAL_HEADER poh;

PIMAGE_SECTION_HEADER psh;

int nSections = NumOfSections(lpFile);

int i = 0;

LPVOID VAImageDir;

/* 必须为0到(NumberOfRvaAndSizes-1)之间 */

if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes)

return NULL;

/* 获得可选头部和段头部的偏移量 */

poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(lpFile);

psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET(lpFile);

/* 定位映像目录的相对虚拟地址 */

VAImageDir = (LPVOID)poh->DataDirectory

[dwIMAGE_DIRECTORY].VirtualAddress;

/* 定位包含映像目录的段 */

while (i++ < nSections)

{

if (psh->VirtualAddress <= (DWORD)VAImageDir &&

psh->VirtualAddress +

psh->SizeOfRawData > (DWORD)VAImageDir)

break;

psh++;

}

if (i > nSections)

return NULL;

/* 返回映像导入目录的偏移量 */

return (LPVOID)(((int)lpFile +

(int)VAImageDir. psh->VirtualAddress) +

(int)psh->PointerToRawData);

}

该函数首先确认被请求的数据目录入口数字,然后它分别获取指向可选头部和第一个段头部的两个指针。它从可选头部决定数据目录的虚拟地址,然后它使用这个值来决定数据目录定位在哪个段实体之中。如果适当的段实体已经被标识了,那么数据目录特定的位置就可以通过将它的相对虚拟地址转换为文件中地址的方法来找到。(未完待续)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有