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

具有相同属性的数据被安排到同一个区块中。

区块表的结构为IMAGE_SECTION_HEADER,在PE文件中存在一个该结构的数组,用来保存各个区块的信息,这个数组的大小在PE头的结构 IMAGE_NT_HEADERS 的成员NumberOfSections描述。

区块表结构IMAGE_SECTION_HEADER结构如下:

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;

在程序中我们主要列出了,区块名称、RVA、在进行内存对齐后的尺寸,在磁盘中的大小,在文件中的偏移,节属性。

在界面中,定义了一个listctrl来显示这些信息。

在CPeFileInfo类中定义了一个vector m_SectionTable;专门用来存储区块表的属性信息。获取这个信息。

在这个类中与区块表有关的函数主要有两个:

GetSectionHeader : 用来获取指向表的指针

InitSectionTable:初始化上面定义的结构

下面来一一说明这两个函数

PIMAGE_SECTION_HEADER CPeFileInfo::GetSectionHeader()
{
PIMAGE_FILE_HEADER pFileHeader = GetFileHeader();
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
if (NULL == pFileHeader)
{
return NULL;
}
PIMAGE_OPTIONAL_HEADER pOptionHeader = GetOptionalHeader();
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)(pOptionHeader) + pFileHeader->SizeOfOptionalHeader);
return pSectionHeader; // PIMAGE_NT_HEADERS pNtHeader = GetNtHeaders();
// return (PIMAGE_SECTION_HEADER)((DWORD)pNtHeader + sizeof(IMAGE_NT_HEADERS));
}

在PE文件中区块表的属性信息是紧密排列在PE头结构后面的,所以我们只要知道OptionHeader结构的指针,然后加上这个结构的大小就可以获取到区块表的地址,上面的代码也是这样做的,首先获取了FileHeader的指针,这个结构中的SizeOfOptionalHeader定义了OptionHeader这个结构的大小,我们利用FileHeader + SizeOfOptionalHeader这样就偏移到了区块表所在的位置。

或者更简单的方式是利用PE文件头的地址 + 文件头的大小也一样可以获取到区块表的地址

void CPeFileInfo::InitSectionTable()
{
if (!m_SectionTable.empty())
{
return ;
}
PIMAGE_SECTION_HEADER pSectionHeader = GetSectionHeader();
PIMAGE_FILE_HEADER pFileHeader = GetFileHeader();
if (NULL != pSectionHeader && NULL != pFileHeader)
{
DWORD dwCountOfSection = pFileHeader->NumberOfSections;
int nCount = 0;
while (nCount < dwCountOfSection)
{
IMAGE_SECTION_HEADER ImageSec = pSectionHeader[nCount];
m_SectionTable.push_back(ImageSec);
nCount++;
}
}
}

后面就是循环遍历将所有信息写入m_SectionTable这个动态数组中。在这份代码中我们首先利用FileHeader的NumberOfSections成员获取区块表的个数,然后在循环中以这个个数作为条件,以此往后寻址,将信息写入到对应的数组中,最后在输出的时候只需要根据需求输出我们感兴趣的内容即可

PE解析器的编写(三)——区块表的解析的更多相关文章

  1. PE解析器的编写(四)——数据目录表的解析

    在PE结构中最重要的就是区块表和数据目录表,上节已经说明了如何解析区块表,下面就是数据目录表,在数据目录表中一般只关心导入表,导出表和资源这几个部分,但是资源实在是太复杂了,而且在一般的病毒木马中也不 ...

  2. PE解析器的编写(一)——总体说明

    之前自己学习了PE文件的格式,后来自己写了个PE文件的解析器,这段时间工作上刚好要用到它,老板需要能查看某个exe中加载的dll的一个工具,我在使用之前自己写的这个东西的时候,发现很多东西都忘记了,所 ...

  3. 非标准的xml解析器的C++实现:二、解析器的基本构造:语法表

    解析器的目的:一次从头到尾的文本遍历,文本数据 转换为 xml节点数据. 这其实是全世界所有编程语言编译或者转换为虚拟代码的基础,学会这种方法,发明一种编程语言其实只是时间问题,当然了,时间也是世界上 ...

  4. springMVC源码解析--ViewResolver视图解析器执行(三)

    之前两篇博客springMVC源码分析--ViewResolver视图解析器(一)和springMVC源码解析--ViewResolverComposite视图解析器集合(二)中我们已经简单介绍了一些 ...

  5. Python 之父的解析器系列之三:生成一个 PEG 解析器

    原题 | Generating a PEG Parser 作者 | Guido van Rossum(Python之父) 译者 | 豌豆花下猫("Python猫"公众号作者) 声明 ...

  6. PE文件解析器的编写(二)——PE文件头的解析

    之前在学习PE文件格式的时候,是通过自己查看各个结构,自己一步步计算各个成员在结构中的偏移,然后在计算出其在文件中的偏移,从而找到各个结构的值,但是在使用C语言编写这个工具的时候,就比这个方便的多,只 ...

  7. Spring MVC-视图解析器(View Resolverr)-XML视图解析器(Xml View Resolver)示例(转载实践)

    以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_xmlviewresolver.htm 说明:示例基于Spring MVC 4.1 ...

  8. SpringMVC 视图和视图解析器&表单标签

    视图和视图解析器 请求处理方法执行完成后,最终返回一个 ModelAndView 对象.对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它 ...

  9. 邵国际: C 语言对象化设计实例 —— 命令解析器

    本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者: 邵国际 来源: 微信公众号linux阅码场(id: linuxdev) 内容简介 单片机工程师常常疑惑为什么 ...

随机推荐

  1. Lucene41PostingWriter源代码分析

    原来看lucene4.0的posting格式(http://blog.csdn.net/jollyjumper/article/details/30017581),发现这还是比較简单的VInt格式,据 ...

  2. 《RabbitMQ Tutorial》译文 第 6 章 远程过程调用(RPC)

    原文来自 RabbitMQ 英文官网的教程(6.Remote procedure call - RPC),其示例代码采用了 .NET C# 语言. In the second tutorial we ...

  3. Softmax多分类算法

    List<double[]> inputs_x = new List<double[]>(); inputs_x.Add(new double[] { 0.2, 0.3 }); ...

  4. spring boot + druid + 封装JdbcTemplate

    本源码内容如下: spring boot项目 用的druid连接池 druid监控页面配置 数据操作用spring jdbctemplate 进一步封装spring jdbctemplate支持用对象 ...

  5. 写给自己的web总结——css篇(1)

    上一篇写了关于html的知识,算是小试牛刀,这次来尝试写一下css. 初步了解css css的全称为cascading style sheet-- 层叠样式表,通过编入代码来对html里的标签做出各种 ...

  6. JMeter接口返回数组键值对校验方法

    $.data.tourRecommend[?(@.title=="产品特色")].type

  7. iOS 5个Xcode开发调试技巧

    转自Joywii的博客,原文:Four Tips for Debugging in XCode Like a Bro    1.Enable NSZombie Objects(开启僵尸对象) Enab ...

  8. iOS 获取当前应用的信息以及用户信息:版本号手机号手机型号

    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; CFShow(infoDictionary); // ap ...

  9. scala-Future和Promise

    首先说明同步与异步,阻塞与非阻塞的问题: Asynchronous vs. Synchronous A method call is considered synchronous if the cal ...

  10. ReactNative布局样式总结

    flex number 用于设置或检索弹性盒模型对象的子元素如何分配空间 flexDirection enum('row', 'row-reverse' ,'column','column-rever ...