相对虚拟地址解释,二进制文件概述

2019-11-14 16:16栏目:网络系统
TAG:

PE文件与虚拟内存之间的映射

ImageBase = 00400000 (基地址)

typedef struct _IMAGE_NT_HEADERS {
  DWORD                 Signature;
  IMAGE_FILE_HEADER     FileHeader;
  IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

        VA = Image Base + RVA;

如VA = 00401325,则:

  PE相关结构NT映像头(IMAGE_NT_HEADER)由三个字段字组成:

PE文件:

|  .rdata  00002000   000000F6  00000600  00000200  40000040|

最后的数据目录表的结构有很多,比较重要的有输入表、输出表、资源等。

  Windows内存:1.物理内存层面;2.虚拟内存层面。

2、汇编中虚拟地址(VRA)与文件偏移地址(FileOffset)的相互转换:

在同一区块中,各地址的偏移量是相等的,但不同区块在磁盘和内存中的差值不一样。

  运行时操作系统会按PE文件的约定定位资源并装载入内存。可执行文件 ——>拆分——>若干数据节<——不同的资源。

如FileOffset = 435(文件偏移地址)

其中,IMAGE_OPTIONAL_HEADER 结构如下:

 

RVA是相对虚拟地址(Relative Virtual Address)的缩写,顾名思义,它是一个“相对”地址,也可以说是“偏移量”,PE文件的各种数据结构中涉及到地址的字段大部分都是以RVA表示的。

 

  可理解为: 实际 = 基点 + 位移.

PE文件中出现RVA的 概念是因为PE的内存映像和磁盘文件映像是不同的,同一数据相对于文件头的偏移量在内存中和在磁盘文件中可能是不同的,为了提高效率,PE文件头中使用的 都是内存映像中的偏移量,也就是RVA。从图17.3中也可以得到另一个结论,那就是RVA仅仅是对于处于节中的数据而言的,对于文件头和节表来说无所谓 RVA和文件偏移,因为它们在被映射到内存中后不管是大小还是偏移都不会有任何改变。

区块映射到内存后,其偏移位置就发生变化了。文件偏移地址与虚拟地址关系如下:

图片 1

|  .text   00001000   00000092  00000400  00000200  60000020|

  以下内容摘录自《加密与解密》:

  在PE文件中,以磁盘数据标准存放(我们知道硬盘以一个section为基本单位,即512byte),0x200字节,当一个数据节不足0x200字节时填充0x00;

VRk = VOffset - ROffset = 00001000 - 00000400 = C00 (得出文件虚拟地址和文件物理址之间的VRk值)

 

  在进行File Offset和VA换算时,会由存储单位引起节基址差称为节偏移。比如:

 

  PE装载器将从IMAGE_DOS_HEADER结构中的e_lfanew字段里找到PE Header的起始偏移量,加上基址得到PE头的指针。

图片 2

 

typedef struct _IMAGE_OPTIONAL_HEADER
{
//
// Standard fields.
//
+18h WORD Magic; // 标志字, ROM 映像(0107h),普通可执行文件(010Bh)
+1Ah BYTE MajorLinkerVersion; // 链接程序的主版本号
+1Bh BYTE MinorLinkerVersion; // 链接程序的次版本号
+1Ch DWORD SizeOfCode; // 所有含代码的节的总大小
+20h DWORD SizeOfInitializedData; // 所有含已初始化数据的节的总大小
+24h DWORD SizeOfUninitializedData; // 所有含未初始化数据的节的大小
+28h DWORD AddressOfEntryPoint; // 程序执行入口RVA
+2Ch DWORD BaseOfCode; // 代码的区块的起始RVA
+30h DWORD BaseOfData; // 数据的区块的起始RVA
//
// NT additional fields. 以下是属于NT结构增加的领域。
//
+34h DWORD ImageBase; // 程序的首选装载地址
+38h DWORD SectionAlignment; // 内存中的区块的对齐大小
+3Ch DWORD FileAlignment; // 文件中的区块的对齐大小
+40h WORD MajorOperatingSystemVersion; // 要求操作系统最低版本号的主版本号
+42h WORD MinorOperatingSystemVersion; // 要求操作系统最低版本号的副版本号
+44h WORD MajorImageVersion; // 可运行于操作系统的主版本号
+46h WORD MinorImageVersion; // 可运行于操作系统的次版本号
+48h WORD MajorSubsystemVersion; // 要求最低子系统版本的主版本号
+4Ah WORD MinorSubsystemVersion; // 要求最低子系统版本的次版本号
+4Ch DWORD Win32VersionValue; // 莫须有字段,不被病毒利用的话一般为0
+50h DWORD SizeOfImage; // 映像装入内存后的总尺寸
+54h DWORD SizeOfHeaders; // 所有头 + 区块表的尺寸大小
+58h DWORD CheckSum; // 映像的校检和
+5Ch WORD Subsystem; // 可执行文件期望的子系统
+5Eh WORD DllCharacteristics; // DllMain()函数何时被调用,默认为 0
+60h DWORD SizeOfStackReserve; // 初始化时的栈大小
+64h DWORD SizeOfStackCommit; // 初始化时实际提交的栈大小
+68h DWORD SizeOfHeapReserve; // 初始化时保留的堆大小
+6Ch DWORD SizeOfHeapCommit; // 初始化时实际提交的堆大小
+70h DWORD LoaderFlags; // 与调试有关,默认为 0
+74h DWORD NumberOfRvaAndSizes; // 下边数据目录的项数,这个字段自Windows NT 发布以来 // 一直是16
+78h IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
// 数据目录表
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

      文件偏移量 = 0x00404141 - 0x00400000(默认的Image Base)-(0x1000 - 0x400)(代码存于.text文件中) = 0x3541

+---------+---------+---------+---------+---------+---------+

File Offset = RVA - △k

  则有:

 

  例如,假设一个EXE文件从地址400000h处装入,并且它的代码区块开始于401000h,代码区块的RVA将是401000h-400000h=RVA1000h。

  典型PE文件通常包含:.text(编译器产生,存放二进制代码, 反汇编和调试的对象)、.data(初始化数据块)、.idata(使用的外来函数如动态链接库与文件信息)、.rsrc(存放程序资源),还包括其他如.reloc、.edata、.tls、.rdata等。

+---------+---------+---------+---------+---------+---------+

  为了在PE文件中避免有确定的内存地址,出现了相对虚拟地址(RVA)的概念。RVA只是内存中的一个简单的相对于PE文件装入地址的偏移位置。它是一个“相对”地址,或称为“偏移量”。

  默认情况下:一般PE文件的0字节 =》虚拟内存0x00400000位置,即所谓的装载地址。

|  Name     VOffset    VSize    ROffset    RSize      Flags |

 

  那么就可以计算出:

准 确地说,RVA就是当PE文件被装载到内存中后,某个数据的位置相对于文件头的偏移量。举个例子,如果Windows装载器将一个PE文件装入 00400000h处的内存中,而某个节中的某个数据被装入0040xxxxh处,那么这个数据的RVA就是(0040xxxxh- 00400000h)=xxxxh,反过来说,将RVA的值加上文件被装载的基地址,就可以找到数据在内存中的实际地址。

图片 3

FileOffset = VA - ImageBase - VRk = 00401000 - 00400000 - C00 = 400(文件物理地址的偏移地址)

  VA、Image Base、RVA之间关系:

|  段名称   虚拟地址  虚拟大小  物理地址  物理大小   标志   |

 =_=..

 

  那万一有用户需要取出超出实际金额数怎么办,操作系统原理中有“虚拟内存”概念, 即在这种情况下有时会将“部分硬盘空间”暂时作为内存使用。(两者“虚拟内存“概念对象不一,不宜混淆)

文件虚拟偏移地址和文件物理偏移地址的计算公式如下:

  (2).装载基址(Image Base):PE装入内存时的基地址。默认EXE文件在内存中的基地址为0x00400000,DLL为0x10000000。当然位置可由编译选项更改。

+---------+---------+---------+---------+---------+---------+

  内存管理器可以使进程在实际只有512MB物理内存的情况下使进程“认为”自己拥有4GB内存(其中包括代码, 栈空间,资源区,动态链接库等)。

>>>>>>FileOffsetToVa( 文件偏移地址转虚拟地址)

  而在内存中,则以0x1000字节(4byte)为基本单位进行组织,其他与前者类似。

源文档 <>

  这种情况和实际生活中银行相似,你需要用的钱其实并不等于你拥有的财富,银行实际存有的金额数小于所有储户的财富和。

如VA = 00401000 (虚拟地址)

虚拟内存:

 

        = VA - Image Base - (相对虚拟偏移量 - 文件偏移量)

VA = FileOffset + ImageBase + VRk = 435 + 00400000 + C00 = 00401035(虚拟地址)

  PE(Portable Executable)是win32平台下可执行遵守的数据格式。平时常见的比如*.exe和*.dll都是PE文件。

>>>>>>>VaToFileOffset( 虚拟地址转文件偏移地址)

  按上表,比如计算虚拟内存中0x00404141处的一条指令,要换算出该指令在文件中的偏移量:

|  .data   00003000   0000018E  00000800  00000200  C0000040|

  装载PE文件时,文件偏移地址(磁盘上)与RVA(内存上)有很大一致性(操作系统会尽量保持PE中各数据结构),那同样会有细微差异,由文件数据和内存数据的存放单位不同造成。

|  .rsrc   00004000   000003A0  00000A00  00000400  C0000040|

  (1).文件偏移地址(File Offset):数据在PE文件中的地址,在磁盘上存放时相对于文件开头的偏移。

FileOffset = VA - ImageBase - VRk = 00401325 - 00400000 - C00 = 725

  (3).虚拟内存地址(Virtual Address,VA):PE文件中的指令被装入内存后的地址。

+---------+---------+---------+---------+---------+---------+

  一些PE工具也提供这类地址转化:Lord PE.

 

  (4).相对虚拟地址(Relative Virtual Address,RVA):内存地址相对于映射基址(即装载基址)的偏移量。

  可执行文件:包含二进制代码,字符串,菜单,图标,位图字体等。

  物理内存通常内核级别ring0才能看到;通常用户模式下看见的为Windows用户态内存映射机制下的虚拟内存。

  FileOffset = VA - Image Base -节偏移

 

 

《软件漏洞分析技术》笔记

版权声明:本文由澳门新葡亰平台游戏发布于网络系统,转载请注明出处:相对虚拟地址解释,二进制文件概述