现在我们已经学完了PE文件格式,但是尚还停留在纸上谈兵的阶段,作为Windows系统上的可执行文件格式,PE文件结构总是和结构体,指针等紧密联系在一起的。理解它的最好方法就是通过写一个类似LordPE的程序来帮助我们理解PE文件结构的底层实现逻辑。计算机到底是如何实现对于PE文件结构的读取和分析的,到底是怎么找到每一个数据的地址的,这是为我们今天研究的关键。

问题关键

1.如何读取导入文件

2.如何找到每个结构体的地址

3.熟悉PE文件结构对应的结构体(参考PE文件结构1)

一. 如何读取文件

首先通过CreatFileA函数打开文件;然后通过HeapAlloc函数分配空间;最后经过ReadFile函数读取文件内容至指定空间。这几个与文件有关的WindowsAPI函数是我们处理PE文件的关键。

二. 找到每个关键结构体的指针

在PE文件结构1当中已经介绍了,PE文件结构的每个组成部分都有其对应的结构体,那么只要我们熟悉了结构体的组成然后找到每个结构体对应的指针,那么问题也就解决了。

现在依次介绍每个部分对应指针应该如何寻址:

DOS首部:dosHeader = (PIMAGE_DOS_HEADER)lpBuffer;这里的lpBuffer其实就是文件的起始句柄了,PE文件是从DOS首部开始的,所以只要将起始句柄类型转化一下为对应的指针即可。

PE文件首部:ntHeader = (PIMAGE_NT_HEADERS)(lpBuffer + dosHeader->e_lfanew);这里就是一个RVA和VA的概念了,相对于文件起始地址为RVA也就是dosHeader->e_lfanew,加上文件的起始地址后才是我们可以用来寻址的指针。

ntHeader->FileHeader.Machine;
ntHeader->OptionalHeader.Magic;

由于PE文件首部内部还包含了两个结构体,这里举两个例子。

区块首部:imageSectionHeaderStruct = (PIMAGE_SECTION_HEADER)((DWORD)lpBuffer + dosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32));要找到区块表的首部地址就需要先找到PE文件首部地址再加上PE文件首部大小,即为对应的区块首部地址。

由于节块的数目是不一定的,需要通过循环将其依次打印。

for (int i = 0; i < numSections; i++)
{
printf("SECTION HEADER #%d\n", i);
printf("\t%s\n", imageSectionHeaderStruct->Name);
printf("\t\tVirtual Size: 0x%x\n", imageSectionHeaderStruct->Misc.VirtualSize);
printf("\t\tVirtual Address: 0x%x\n", imageSectionHeaderStruct->VirtualAddress);
printf("\t\tRaw Size: 0x%x\n", imageSectionHeaderStruct->SizeOfRawData);
printf("\t\tRaw Address: 0x%x\n", imageSectionHeaderStruct->PointerToRawData);
printf("\t\tReloc Address: 0x%x\n", imageSectionHeaderStruct->PointerToRelocations);
printf("\t\tRelocations Number: 0x%x\n", imageSectionHeaderStruct->NumberOfRelocations);
printf("\t\tLine Numbers: 0x%x\n", imageSectionHeaderStruct->NumberOfLinenumbers);
printf("\t\tCharacteristics: 0x%x\n", imageSectionHeaderStruct->Characteristics);
imageSectionHeaderStruct++;
}

三. 导入表等的打印

导入表,导出表和资源表相对来说就比较麻烦一点,需要先在数据目录表当中寻找对应地址,然后再去数据段找到相应数据打印。

这里以导入表为例:

IMAGE_IMPORT_DESCRIPTOR* ImportTables = (IMAGE_IMPORT_DESCRIPTOR)(RTF(rvaaddr) + pBegin); 这里我们先找到导入表的数据目录表对应的地址。 2. 然后找到对应的IAT地址,即int firstthunk = (int)ImportTables2->FirstThunkl;```这就是我们需要找的地址,之后依次打印即可。

感兴趣的可以查看https://github.com/FULLSHADE/pe-Parser。

PE文件结构2(实现PE文件载入)的更多相关文章

  1. PE文件结构详解(一)基本概念

    PE(Portable Execute) 文件是Windows下可执行文件的总称,常见的有DLL,EXE,OCX,SYS等,事实上,一个文件是否是PE文件与其扩展名无关,PE文件可以是任 何扩展名.那 ...

  2. 再探.NET的PE文件结构(安全篇)

    一.开篇 首先写在前面,这篇文章源于个人的研究和探索,由于.NET有自己的反射机制,可以清楚的将源码反射出来,这样你的软件就很容易被破解,当然这篇文章不会说怎么样保护你的软件不被破解,相反是借用一个软 ...

  3. PE文件结构(四) 输出表

    PE文件结构(四) 參考 书:<加密与解密> 视频:小甲鱼 解密系列 视频 输出表 一般来说输出表存在于dll中.输出表提供了 文件里函数的名字跟这些函数的地址, PE装载器通过输出表来改 ...

  4. PE文件结构(五岁以下儿童)基地搬迁

    PE文件结构(五岁以下儿童) 參考 书:<加密与解密> 视频:小甲鱼 解密系列 视频 基址重定位 链接器生成一个PE文件时,它会如果程序被装入时使用的默认ImageBase基地址(VC默认 ...

  5. COFF/PE文件结构

    COFF/PE文件结构 原创 C++应用程序在Windows下的编译.链接(二)COFF/PE文件结构 2.1概述 在windows操作系统下,可执行文件的存储格式是PE格式:在Linux操作系统下, ...

  6. PE文件结构及其加载机制

    一.PE文件结构 PE即Portable Executable,是win32环境自身所带的执行体文件格式,其部分特性继承自Unix的COFF(Common Object File Format)文件格 ...

  7. PE文件结构(三) 输入表

    PE文件结构(三) 參考 书:<加密与解密> 视频:小甲鱼 解密系列 视频 输入表 输入函数,表示被程序调用可是它的代码不在程序代码中的,而在dll中的函数.对于这些函数.磁盘上的可执行文 ...

  8. 原创 C++应用程序在Windows下的编译、链接:第二部分COFF/PE文件结构

    2.1概述 在windows操作系统下,可执行文件的存储格式是PE格式:在Linux操作系统下,可执行文件的存储格式的WLF格式.它们都是COFF格式文件的变种,都是从COFF格式的文件演化而来的. ...

  9. PE文件结构学习

    PE:Portable Executable File Format(可移植的执行体).Windows平台主流可执行文件格式..exe与.dll文件都是PE格式.32位的叫做PE32,64位的叫做PE ...

  10. PE文件结构详解(六)重定位

    前面两篇 PE文件结构详解(四)PE导入表 和 PE文件结构详解(五)延迟导入表 介绍了PE文件中比较常用的两种导入方式,不知道大家有没有注意到,在调用导入函数时系统生成的代码是像下面这样的: 在这里 ...

随机推荐

  1. 2021-09-26:搜索旋转排序数组。整数数组 nums 按升序排列,数组中的值 互不相同 。在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了

    2021-09-26:搜索旋转排序数组.整数数组 nums 按升序排列,数组中的值 互不相同 .在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.lengt ...

  2. docker安装rabbitmq:management

    1.拉取镜像 docker pull rabbitmq:management 2.安装 docker run -dit --name rabitmq -e RABBITMQ_DEFAULT_USER= ...

  3. Spring源码:Bean生命周期(终章)

    前言 本系列前面讲解了Spring的bean定义.bean实例化.bean初始化等生命周期.这些步骤使我们能够了解bean从创建到准备好使用所经历的过程.但是,除了这些步骤,bean的销毁也是非常重要 ...

  4. 【QCustomPlot】性能提升之修改源码(版本 V2.x.x)

    说明 使用 QCustomPlot 绘图库的过程中,有时候觉得原生的功能不太够用,比如它没有曲线平滑功能:有时候又觉得更新绘图数据时逐个赋值效率太低,如果能直接操作内存就好了:还有时候希望减轻 CPU ...

  5. jQuery 添加水印

    jQuery 添加水印 <script src="../../../../AJs/jquery.min.js"></script> <script t ...

  6. delving into deep imbalanced regression翻译

    非对照翻译,有所简略.翻译不对,尽情谅解,可留言 作者解释 and paper 笔记 Abstract   Real-world data often exhibit imbalanced distr ...

  7. 5个 Istio 访问外部服务流量控制最常用的例子,你知道几个?

    5 个 Istio 访问外部服务的流量控制常用例子,强烈建议收藏起来,以备不时之需. 环境准备 部署 sleep 服务,作为发送请求的测试源: kubectl apply -f samples/sle ...

  8. Swift4 入门到精通(第二章基本数据类型与量值)

    第二章 量值和基本数据类型 Swift 支持的基本数据类型, 整型,浮点型,布尔型,元组,可选类型. 学习的目标: 常量与变量的意义.声明.命名规范.类型 数据进制与计算机存储原理 整型数据.浮点型数 ...

  9. JIRA安装

    JIRA安装 操作系统: 阿里云centos6.8 域名: yan.jzhsc.com 1.安装与配置JAVA sudo -u root -H bash # 在oracle官网下载JDK,安装并配置环 ...

  10. 【AI在网络安全中的应用:趋势和未来】展望

    目录 [AI在网络安全中的应用:趋势和未来]- 展望 随着数字化和智能化的不断深入,网络安全问题越来越受到人们的关注.其中,人工智能技术在网络安全领域中的应用已成为当前研究的热点之一.本文将探讨AI在 ...