本文转自小甲鱼的PE文件详解系列原文传送门

到此为止,小甲鱼和大家已经学了许多关于 DOS header 和 PE header 的知识。接下来就该轮到SectionTable (区块表,也成节表)。

越学越多的结构,大家可能觉得PE挺乱挺杂的哈,所以这里插播下一下必要知识的详细注释,大伙可以按需要看。

PE文件中所有节的属性都被定义在节表中,节表由一系列的IMAGE_SECTION_HEADER结构排列而成,每个结构用来描述一个节,结构的排列顺序和它们描述的节在文件中的排列顺序是一致的。

全部有效结构的最后以一个空的IMAGE_SECTION_HEADER结构作为结束,所以节表中总的IMAGE_SECTION_HEADER结构数量等于节的数量加一。

节表总是被存放在紧接在PE文件头的地方。

另外,节表中 IMAGE_SECTION_HEADER 结构的总数总是由PE文件头 IMAGE_NT_HEADERS 结构中的 FileHeader.NumberOfSections 字段来指定的。

typedef struct _IMAGE_SECTION_HEADER
{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 节表名称,如“.text”
//IMAGE_SIZEOF_SHORT_NAME=8
union
{
DWORD PhysicalAddress; // 物理地址
DWORD VirtualSize; // 真实长度,这两个值是一个联合结构,可以使用其中的任何一个,一般是取后一个
} Misc;
DWORD VirtualAddress; // 节区的 RVA 地址
DWORD SizeOfRawData; // 在文件中对齐后的尺寸
DWORD PointerToRawData; // 在文件中的偏移量
DWORD PointerToRelocations; // 在OBJ文件中使用,重定位的偏移
DWORD PointerToLinenumbers; // 行号表的偏移(供调试使用地)
WORD NumberOfRelocations; // 在OBJ文件中使用,重定位项数目
WORD NumberOfLinenumbers; // 行号表中行号的数目
DWORD Characteristics; // 节属性如可读,可写,可执行等
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

Name:

区块名。这是一个由8位的ASCII 码名,用来定义区块的名称。

多数区块名都习惯性以一个“.”作为开头(例如:.text),这个“.” 实际上是不是必须的。

值得我们注意的是,如果区块名超过 8 个字节,则没有最后的终止标志“NULL” 字节。

并且前边带有一个“”的区块名字会从连接器那里得到特殊的待遇,前边带有“” 的相同名字的区块在载入时候将会被合并,在合并之后的区块中,他们是按照“$” 后边的字符的字母顺序进行合并的。

另外小甲鱼童鞋要跟大家啰嗦一下的是:每个区块的名称都是唯一的,不能有同名的两个区块。

但事实上节的名称不代表任何含义,他的存在仅仅是为了正规统一编程的时候方便程序员查看方便而设置的一个标记而已。

所以将包含代码的区块命名为“.Data” 或者说将包含数据的区块命名为“.Code” 都是合法的。

因此,小甲鱼建议大家:当我们要从PE 文件中读取需要的区块时候,不能以区块的名称作为定位的标准和依据。

正确的方法是按照 IMAGE_OPTIONAL_HEADER32 结构中的数据目录字段结合进行定位。

Virtual Size:

对应的区块的大小,这是区块的数据在没有进行对齐处理前的实际大小。

Virtual Address:

该区块装载到内存中的RVA 地址。这个地址是按照内存页来对齐的,因此它的数值总是 SectionAlignment 的值的整数倍。

在Microsoft 工具中,第一个块的默认 RVA 总为1000h。在OBJ 中,该字段没有意义地,并被设为0。

SizeOfRawData:

该区块在磁盘中所占的大小。在可执行文件中,该字段是已经被FileAlignment 潜规则处理过的长度。

PointerToRawData:

该区块在磁盘中的偏移。这个数值是从文件头开始算起的偏移量哦。

PointerToRelocations:

这哥们在EXE文件中没有意义,在OBJ 文件中,表示本区块重定位信息的偏移值。

(在OBJ 文件中如果不是零,它会指向一个IMAGE_RELOCATION 结构的数组)

PointerToLinenumbers:

行号表在文件中的偏移值,文件的调试信息,于我们没用,鸡肋。

NumberOfRelocations:

这哥们在EXE文件中也没有意义,在OBJ 文件中,是本区块在重定位表中的重定位数目来着。

NumberOfLinenumbers:

该区块在行号表中的行号数目,鸡肋。

Characteristics:

该区块的属性。该字段是按位来指出区块的属性(如代码/数据/可读/可写等)的标志。

具体内容可以参考MSDN在线文档:传送门

下面通过一个例子来详细朔门这些内容:还是以上次那个为例

根据以前的内容可以知道这个文件PE头在0xf0的位置,上一次是通过各个结构体大小来找到PE头中这个OptionalHeader结构的地址,但是当时我忘记了,在FileHeader 这个结构中有一个SizeOfOptionalHeader这个域专门用来记录OptionalHeader结构的大小,它在PE头的偏移为0x14也就是在0xf0 + 0x14 = 0x104的位置



查看文件得知这个值为0xe0, OptionalHeader偏移0x18 + 大小0xe0 + pe头的偏移0xf0 = 0x1e8



根据这个结构中的成员很容易计算出来,这个结构占0x28个字节,这样根据上一个的起始地址 + 0x28就可以得到下一个的地址,这样可以陆陆续续找到所有的节



节表中的最后一个为全0,这样这个PE文件中总共有.textbss、.text、.radta、.data、.idata、.rsrc、.reloc这样几个节。

接下来读取各个部分的内容,比如说在text节中,

VirtualSize = 0x00014360

PointerToRawData = 0x000400

VirtualAddress = 0x00011000

SizeOfRawData = 0x00014400

Characteristics = 0x60000020

这些节区都是按照文件中的某个值对齐,然后在紧密排列的,所以根据它在文件中的偏移 + 对齐后的值可以得到下一个节在文件中的偏移地址,根据这点在text节中

PointerToRawData + SizeOfRawData = 0x000400 + 0x00014400 = 0x00014800,而下一个的文件偏移地址正好是这个,这个根据在PE中查找到的数据,发现下一个确实是这个值

PE文件详解(四)的更多相关文章

  1. PE文件详解(八)

    本文转载自小甲鱼PE文件详解系列教程原文传送门 当应用程序需要调用DLL中的函数时,会由系统将DLL中的函数映射到程序的虚拟内存中,dll中本身没有自己的栈,它是借用的应用程序的栈,这样当dll中出现 ...

  2. PE文件详解(六)

    这篇文章转载自小甲鱼的PE文件详解系列原文传送门 之前简单提了一下节表和数据目录表,那么他们有什么区别? 其实这些东西都是人为规定的,一个数据在文件中或者在内存中的位置基本是固定的,通过数据目录表进行 ...

  3. PE文件详解(三)

    本文转自小甲鱼的PE文件详解系列传送门 PE文件到内存的映射 在执行一个PE文件的时候,windows 并不在一开始就将整个文件读入内存的,二十采用与内存映射文件类似的机制. 也就是说,windows ...

  4. PE文件详解(九)

    本篇文章转载自小甲鱼的一篇日志,原文地址 我们知道,Windows 将程序的各种界面定义为资源,包括加速键(Accelerator).位图(Bitmap).光标(Cursor).对话框(Dialog ...

  5. PE文件详解(七)

    本文转载自小甲鱼PE文件讲解系列原文传送门 这次主要说明导出表,导出表一般记录着文件中函数的地址等相关信息,供其他程序调用,常见的.exe文件中一般不存在导出表,导出表更多的是存在于dll文件中.一般 ...

  6. PE文件详解(五)

    在前面几节中经常提到相对虚拟地址RVA,在这篇博客中主要说明这个概念.本来是想接着转载小甲鱼的,但是我自己根据这篇文章和他的视频来学习的时候,发现在RVA与文件的相对偏移地址进行转化的时候,那块我看不 ...

  7. PE文件详解二

    本文转自小甲鱼的PE文件相关教程,原文传送门 咱接着往下讲解IMAGE_OPTIONAL_HEADER32 结构定义即各个属性的作用! 接着我们来谈谈 IMAGE_OPTIONAL_HEADER 结构 ...

  8. MyBatis之Mapper XML 文件详解(四)-JDBC 类型和嵌套查询

    支持的 JDBC 类型为了未来的参考,MyBatis 通过包含的 jdbcType 枚举型,支持下面的 JDBC 类型. BITFLOATCHARTIMESTAMPOTHERUNDEFINEDTINY ...

  9. PE文件结构详解(四)PE导入表

    PE文件结构详解(二)可执行文件头的最后展示了一个数组,PE文件结构详解(三)PE导出表中解释了其中第一项的格式,本篇文章来揭示这个数组中的第二项:IMAGE_DIRECTORY_ENTRY_IMPO ...

随机推荐

  1. Java中string 创建对象时 “”和null的差别

    null和""的差别 问题一: null和""的差别 String s=null; string.trim()就会抛出为空的exception String s ...

  2. Django项目实践4 - Django网站管理(后台管理员)

    http://blog.csdn.net/pipisorry/article/details/45079751 上篇:Django项目实践3 - Django模型 Introduction 对于某一类 ...

  3. Spring基础知识之依赖注入

    Spring框架的四大原则: 1)使用POJO进行轻量级和最小侵入式的开发. 2)通过依赖注入和基于接口编程实现松耦合. 3)通过AOP和默认习惯进行声明式编程. 4)使用AOP和模板(templat ...

  4. 在Visual Studio Code中开发Office Add-in

    作者:陈希章 发表于 2017年7月13日 上一篇 我介绍了如何在Visual Studio中开发Office Add-in,因为有标准的项目模板,一系列配套的工具,尤其是自带的一键调试功能,可以让开 ...

  5. Ajax顺序执行

    循环中的Ajax 在前后端分离的项目中,Ajax是连接前后端的枢纽. 需求:有一个需要循环发起n次的请求,但是n次循环传参不同,我并不知道n是多少,并且要求能够保证返回顺序.JSONP用同步锁无效 示 ...

  6. 在用python操作mysql时报错:ModuleNotFoundError: No module named 'MySQLdb'

    用Flask+python+mysql写一个小项目 系统 win10 py版本:3.6.1 在配置数据库时报错ModuleNotFoundError: No module named 'MySQLdb ...

  7. CSS小全

    CSS 的使用 内联(inline style attribute) 完全不应该这样做 <head> 标签内的 <style> 标签 偶尔可以用 <link> 标签 ...

  8. redis的list类型

    1.简单介绍 redis的list类型其实就是一个每个元素都是string类型的双向链表.所以lpush.rpush.lpop和rpop命令的时间复杂度是O(1),list会记录链表的长度,所以lle ...

  9. Intellij 如何在新窗口中打开项目

    好多程序员都使用intelliJ idea开发项目,由于不小心设置了不在提示打开项目项目方式,所以只能打开一个窗口,而且只能同时打开一个项目,特别郁闷,分享下设置后的效果 工具/原料   Intell ...

  10. C#:MVC引用Log4Net生成错误日志

    第一步:引用log4net配置文件 第二步:在自己项目下新建文件夹LogNet,再在里面建立类Log.cs log.cs内容如下: 第三步:在自己项目下新建Log4Net.config Log4Net ...