PE文件和COFF文件格式分析——RVA和RA相互计算
之前几节一直是理论性质的东西非常多。本文将会讲到利用之前的知识得出一个一个非常有用的一个应用。(转载请指明来源于breaksoftware的csdn博客)
首先我们说下磁盘上A.exe文件和正在内存中运行的A.xe之间的关系。当我们双击A.exe后,A.exe会运行起来。我们在任务管理器中可以看到A.exe。这个过程很简单,但是双击A.exe之后系统做了什么?这个过程你是否思考过?我不准备在此处详细说这个过程,因为这个过程比较复杂。我只讲一个过程——载入。
磁盘上A.exe在硬盘上,运行时的A.exe的执行体是在内存中。从磁盘到内存,这是个载入的过程。我们查看下A.exe占用的内存和A.exe这个文件的大小,会发现,这两个大小之间不存在任何关系。一则是因为A.exe运行时会载入部分DLL导致内存变大,其次可能是A.exe运行时申请了大量的空间。还有个原因很容易被忽略掉,就是系统在加载这个A.exe时,它是分段读取该文件,分段加载的。比如文件中一个信息是1byte,系统读取该信息后出于内存对齐考虑,可能会给这个信息分配4bytes的空间。是不是感觉我们A.exe被系统加载后,数据的连续性等被破坏了?如图
是的,原来的结构是被打乱的。是不是感觉恐慌?其实不用,这种映射必定存在一定的算法。我们本文就是讨论这种算法的。
讨论这个算法前,我们先说个概念——位置。现在有GPS功能的设备越来越多,玩这个功能的人是否考虑过其中的简单的原理呢?我没有研究过它,但是我想这是天上的卫星和地上(或者空间)一些设备合作计算出来的。比如我们地上有些基站,卫星知道它们的坐标,然后通过一些数据,比如我们“相对‘A基站的距离,“相对‘B基站的距离,从而计算出我们GPS设备和这些坐标的关系,从而得出我们所在的坐标,从而知道我们的位置。可以见得计算我们位置的过程涉及到“相对”这个概念。
文件中数据位置的描述也是使用”相对“来定位的,正在运行的程序中的数据的定位也是通过”相对“来定位的。一个数据位置相对于文件头(第一个字节)的偏移我们称为相对地址(RA),内存中一个数据相对于程序开始处的偏移我们称为相对虚拟地址(RVA)。这两个概念非常重要。
那我们PE文件中对数据的表述是使用RA还是RVA呢?大体可以总结如下:如果要在内存中运行和使用的数据大部分是使用RVA描述的。如果只是文件信息,程序运行时不关心的数据使用RA描述的。我在《PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头2》最后部分,说了一句话“DataDirectory保存了指向“块信息”的目录信息,其中包括偏移(除了IMAGE_DIRECTORY_ENTRY_SECURITY元素是相对文件偏移RA,其他都是相对虚拟首地址偏移RVA)和大小。”IMAGE_DIRECTORY_ENTRY_SECURITY区块保存的是文件的签名信息,在运行程序前,系统加载文件的过程是不会把这块信息加载到内存中的。还有《PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头1》中介绍的IMAGE_FILE_HEADER::PointerToSymbolTable,它指向的数据是符号表,该信息也是程序运行时不关心的,所以它也是RA。程序运行时需要使用的信息的数据地址就要使用RVA来表示了,试想如果这些数据用RA表示,则程序在运行前要根据加载的情况把这些数据在内存中的RVA再算出来,这个工作量是非常大的,是非常不科学的。
在我分析PE文件时,遇到的大部分信息是RVA。于是我想查看该位置的信息,就要通过RVA计算出RA。一般来说文件的结构是比较紧凑的,这样是为了方便文件传输(想想在那个网络非常慢,硬盘那么贵的年代)。而程序的内存中的结构则相对松散些,这个并不是因为内存不值钱,而是为了执行效率,而且一般没谁会把电脑上所有保存的程序都跑起来执行吧?
一般来说,系统加载PE文件时,会先读取文件头信息,查看该文件是否可以重定向(通过判断IMAGE_FILE_HEADER::Characteristics是否包含IMAGE_FILE_RELOCS_STRIPPED)啊。如果不可以,则查看它想加载的位置(IMAGE_OPTIONAL_HEADER32(64)::ImageBase)是否被占用了,如果没有占用,或者即使被占用了但是其允许重定位,就继续读取”节信息“。关于节信息,我在《PE文件和COFF文件格式分析——节信息》中有说明。这儿我们再看下节头信息数据结构
#define IMAGE_SIZEOF_SHORT_NAME 8typedef struct _IMAGE_SECTION_HEADER {BYTE Name[IMAGE_SIZEOF_SHORT_NAME];union {DWORD PhysicalAddress;DWORD VirtualSize;} Misc;DWORD VirtualAddress;DWORD SizeOfRawData;DWORD PointerToRawData;DWORD PointerToRelocations;DWORD PointerToLinenumbers;WORD NumberOfRelocations;WORD NumberOfLinenumbers;DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
VirtualAddress保存的是映像文件中该节被加载进内存时,第一个字节相对于映像基址的偏移量。VirtualSize保存的是内存中该节的大小。这组数据和RVA关系很大。
PoiterToRawData保存的是该节第一个字节在文件中相对于文件第一个字节的偏移量。SizeOfRawData保存的是该节在文件中的大小。这组数据和RA关系很大。
那么系统加载这些节可以用下图说明
是不是还是感觉比较乱?但是注意一个现象,看线1、2是平行的,线3、4是平行的,线5、6是平行的。为什么是平行的?在《PE文件和COFF文件格式分析——节信息》一文中我介绍VirtualSize属性时这么说的“VirtualSize属性是节加载进入内存后,节在内存中的大小。如果它比SizeOfRawData大,则多余的部分是用0x00填充的。”
那么这个平行这意味着什么?这意味着如果我们可以利用”相对“这个概念。因为平行就是相对的,如1和2平行而和3不平行。现在假如RVA落在内存的SectionBStart和SectionBEnd之间,则我们可以计算出RVA于SectionBStart的偏移OffsetBSection。然后我们通过节信息找到SectionBStart在文件中的相对地址RA,最后,我们让SectionBstart+OffsetBSection就得到RVA对应的RA了。是的!算法就是如此简单
for ( VecSectionHeaderIter it = m_vecSectionHeaders.begin(); it != m_vecSectionHeaders.end(); it++ ){if ( dwRVA >= it->VirtualAddress && dwRVA < it->VirtualAddress + it->Misc.VirtualSize ) { if ( 0 == it->SizeOfRawData ) {break;}dwRA = dwRVA - it->VirtualAddress + it->PointerToRawData;bSuc = TRUE;break;}}
这儿还要说一种场景:有些PE文件坏坏的让VirtualSize为0,而实际该大小确实存在的,这个时候我们就要修正VirtualSize之后再判断了。
for ( VecSectionHeaderIter it = m_vecSectionHeaders.begin(); it != m_vecSectionHeaders.end(); it++ ){if ( dwRVA >= it->VirtualAddress && 0 == it->Misc.VirtualSize ) { // 校正虚拟大小DWORD dwSectionAlignment = ( EOp32 == m_eFileOpType ) ? m_OptionalHeader32.SectionAlignment : m_OptionalHeader64.SectionAlignment;DWORD dwVirtualSize = ( it->SizeOfRawData + (dwSectionAlignment - 1) ) &~(dwSectionAlignment - 1);it->Misc.VirtualSize = dwVirtualSize;if ( dwRVA < it->VirtualAddress + dwVirtualSize ) {dwRA = dwRVA - it->VirtualAddress + it->PointerToRawData;bSuc = TRUE;break; }}}
以上算法是讨论了从RVA计算出RA的过程,而通过RA计算出RVA只是这样一个逆向过程。我想如果看懂了以上的原理,那么这个算法是很容易写出来的。
刚接触这块的同学可能会存在一个误区:比如他知道RVA=0x00002100,还知道这个RVA对应的RA=0x00002200。于是可能会想当然的认为该文件的RA = RVA + 0x100。于是他下次遇到RVA=0x00008000时就认为其对应的RA=RVA+0x100=0x00008100!!这个是不对的,就像0x00002200落在上图的SectionAStart和SectionAEnd之间,而0x00008000落在上图的SectionBStart和SectionBEnd之间,线1和3不是平行的,即差值是不同的,不能这么算的。
相关文章:

《评人工智能如何走向新阶段》后记(再续9)
由AI科技大本营下载自视觉中国2019.12.16 96. 近日《Nature》杂志推荐2019年度10大科学进展的杰出论文,其中一篇是有关人工智能的,谈采用深度学习/强化学习算法来训练四足机器狗ANYmal,使它能快速爬起来。该文谈到,在反复训练下&…

RTX组织架构刷新出现了问题
今天发现RTX的组织架构刷新出现了问题。按照网络上的方法什么的把什么配置文件的IP地址改啊改啊。还是没有用。也TELNET了8010端口,也没有用。其实这样的方法之前把服务程序装在另一台机器上倒是可以的。有点麻烦的了。呵呵不知道各位博友有没有解决的好方法啊。呵呵…
一个最简单的通过WireShark破解SSL加密网络数据包的方法
原文地址: http://article.yeeyan.org/view/530101/444688 一般来说,我们用WireShark来抓取包进行分析是没有多大问题的。但这里有个问题是,如果你碰到的是用SSL/TLS等加密手段加密过的网络数据的时候,往往我们只能束手无策。在过…

PE文件和COFF文件格式分析——导出表
在之前的《PE可选文件头》相关博文中我们介绍了可选文件头中很多重要的属性,而其中一个非常重要的属性是(转载请指明来源于breaksoftware的CSDN博客) IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 该数组保存了…
将Quartz.NET集成到 Castle中
Castle是针对.NET平台的一个开源项目,从数据访问框架ORM到IOC容器,再到WEB层的MVC框架、AOP,基本包括了整个开发过程中的所有东西,为我们快速的构建企业级的应用程序提供了很好的服务.具体可参看TerryLee的Castle 开发系列文章。 …

《评人工智能如何走向新阶段》后记(再续10)
本文由AI科技大本营下载自视觉中国106.百度自研的飞桨(Paddle paddle)框架是中国自研的首个开源产业极人工智能深度学习框架,目前飞桨已累计服务150多万开发者,在定制化训练平台上企业用户超过6.5万,发布了16.9万模型&…

水管工游戏 (深搜)
水管工游戏 本题依然是采用搜索,深搜,广搜都可以,本代码采用深搜,此题在搜索时需要增加一些判断条件以及下一步要搜索的位置即可。 代码如下: #include<stdio.h> int a[51][51]; int book[51][51],n,m,flag0,top…

PE文件和COFF文件格式分析——导出表的应用——一种插件模型
可能在很多人想想中,只有DLL才有导出表,而Exe不应该有导出表。而在《PE文件和COFF文件格式分析——导出表》中,我却避开了这个话题。我就是想在本文中讨论下载Exe中存在导出表的场景。(转载请指明出于breaksoftware的csdn博客&…

IBatis.Net学习笔记九--动态选择Dao的设计分析
在IBatis.Net中可以通过配置文件动态选择数据库、动态选择Dao对象。Dao对象也就是操作数据库的类,通过配置文件我们可以选择DataMapper的方式、Ado的方式、NHibernet的方式以前其他第三方的方式来操作数据库。有利于系统的灵活性和可扩展性。通过分析动态选择Dao的设…
Pytorch和Tensorflow,谁会笑到最后?
作者 | 土豆变成泥来源 | 知秋路(ID:gh_4a538bd95663)【导读】作为谷歌tensorflow某项目的Contributor,已经迅速弃坑转向Pytorch。目前Tensorflow还没有被Pytorch比下去,但之后极大概率被比下去。01 在学术界Pytorch已经超越Tenso…

HTTP请求的过程
HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤: 1. 建立TCP连接在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同…

JSTL+EL表达式方法获取Oracle的Clob字段内容
我们在页面获得数据的时候一般的类型还是很好获得的,但是一遇到Clob类型就比较麻烦,最常用的方法是用一个流将其读取出来.使用MVC框架的时候这些都是无所谓的事情,因为反正是写在java类中怎么写都行,可是不使用MVC框架,使用jsp页面JSTL的sql标签去读取数据库的数据这种方式就麻…
通向人工智能产业落地化的道路在哪?
整理 | 夕颜出品 | AI科技大本营(ID:rgznai100)世事浮云,白云苍狗,转眼间关于人工智能的研究已历经两个世纪。在研究者和践行者的不懈努力之下,如今人工智能应用已遍地可见,无论是繁华都市还是偏远小镇&…

PE文件和COFF文件格式分析——导出表的应用——通过导出表隐性加载DLL
通过导出表隐性加载DLL?导出表?加载DLL?还隐性?是的。如果觉得不可思议,可以先看《PE文件和COFF文件格式分析——导出表》中关于“导出地址表”的详细介绍。(转载请指明出于breaksoftware的csdn博客&#x…

系统启动时,spring配置文件解析失败,报”cvc-elt.1: 找不到元素 'beans' 的声明“异常...
现象:spring加载配置文件applicationContext.xml出错,抛出nested exception is og.xml.sax.SAXParseException; lineNumber: 12; columnNumber: 47; cvc-elt.1: 找不到元素 beans 的声明r的异常信息。 造成该异常原因有两种:第一,配置文件头部配置的xsd版…
DllMain中不当操作导致死锁问题的分析--死锁介绍
最近在网上看到一些关于在DllMain中不当操作导致死锁的问题,也没找到比较确切的解答,这极大吸引了我研究这个问题的兴趣。我花了一点时间研究了下,正好也趁机研究了下进程对DllMain的调用规律。因为整个研究篇幅比较长,我觉得还是…
XGBoost缺失值引发的问题及其深度分析 | CSDN博文精选
作者 | 兆军(美团配送事业部算法平台团队技术专家)来源 | 美团技术团队(*点击阅读原文,查看美团技术团队更多文章)背景XGBoost模型作为机器学习中的一大“杀器”,被广泛应用于数据科学竞赛和工业领域&#…

什么是CPI指数和GDP
即消费者物价指数(Consumer Price Index),英文缩写为CPI,是反映与居民生活有关的产品及劳务价格统计出来的物价变动指标,通常作为观察通货膨胀水平的重要指标。如果消费者物价指数升幅过大,表明通胀已经成为经济不稳定因素&#x…

The Ultimate Guide To iPhone Resolutions
2019独角兽企业重金招聘Python工程师标准>>> ios 屏幕尺寸 像素 等说明 转载于:https://my.oschina.net/starmier/blog/467271
DllMain中不当操作导致死锁问题的分析--进程对DllMain函数的调用规律的研究和分析
不知道大家是否思考过一个过程:系统试图运行我们写的程序,它是怎么知道程序起始位置的?很多同学想到,我们在编写程序时有个函数,类似Main这样的名字。是的!这就是系统给我们提供的控制程序最开始的地方&…
力挺Python!同是程序员,为啥同事年前就实现了财务自由?
人红是非多,最近Python就遇到了这样的问题。与技术社区上一片「形势大好」对比鲜明的是,国内技术圈却一直存在对Python,「力挺」和「吃瓜」两派阵营,针锋相对,那么,Python到底有没有用,真相究竟…

C# 判断远程文件是否存在
#region 判断远程文件是否存在/// <summary>/// 判断远程文件是否存在/// </summary>/// <param name"fileUrl"></param>/// <returns></returns>public static bool RemoteFileExists(string fileUrl){HttpWebRequest re null…

DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子
有了前面两节的基础,我们现在切入正题:研究下DllMain为什么会因为不当操作导致死锁的问题。首先我们看一段比较经典的“DllMain中死锁”代码。(转载请指明出于breaksoftware的csdn博客) //主线程中 HMODULE h LoadLibraryA(strD…
性能超FPN!北大、阿里等提多层特征金字塔网络
作者 | Qijie Zhao等编译 | 李杰出品 | AI科技大本营(ID:rgznai100)特征金字塔网络具有处理不同物体尺度变化的能力,因此被广泛应用到one-stage目标检测网络(如DSSD,RetinaNet,RefineDet)和two-…

什么是WIFI
WIFI全称Wireless Fidelity,又称802.11b标准,它的最大优点就是传输速度较高,可以达到11Mbps,另外它的有效距离也很长,同时也与已有的各种802.11DSSS设备兼容。 WIFI是由AP(Access Point)和无线网卡组成的无线网络。…
Android入门——电话拨号器和4种点击事件
关于HelloWorld为,电话拨号程序还AndroidA入门demo,从这个样例我们要理清楚做安卓项目的思路。大体分为三步: 1.理解需求,理清思路 2.设计UI 3.代码实现 电话拨号器 1. 理解需求: *一个文本框——用来接收电话号码 *一个button——用来触发事…

DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子2
本文介绍使用Windbg去验证《DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子》中的结论,调试对象是文中刚开始那个例子。(转载请指明出于breaksoftware的csdn博客) 1 g 让程序运行起来 2 ctrlbreak 中断程序 3 ~ 查看…
从入门到深入:移动平台模型裁剪与优化的技术探索与工程实践
可以看到,通过机器学习技术,软件或服务的功能和体验得到了质的提升。比如,我们甚至可以通过启发式引擎智能地预测并调节云计算分布式系统的节点压力,以此改善服务的弹性和稳定性,这是多么美妙。而对移动平台来说&#…

我在不炎熱也不抑鬱的秋天,依然不抽煙
写过几次电影的观后感,挺过瘾.最近看到my little airport的那张新唱片,再也没有办法保持沉默了 为什么人家的唱片名都起的和小说一样,难得是为了证明听歌的人们都不喜欢动笔吗? 于是,我建了个类别,叫 我也会听歌.很明显,这里面会塞一些和歌相关的东西 这是第一篇

ubuntu安装redis的方法以及PHP安装redis扩展、CI框架sess使用redis的方法
为什么80%的码农都做不了架构师?>>> 再一次被网上那些教程误导后决定自己写一个。真心被那些奇怪的教程误导了好几次,之前研究其它东西的时候也是。蛋疼啊。 安装redis 直接用apt-get命令即可 sudo apt-get install redis-server 安装的时候…