所谓PE文件就是可执行文件在硬盘中存储是的文件表示,Windows中可执行文件的文件表示的发展途径为com->LE(Linerar executable)->PE(Portable Executable File Formate)。在程序运行的时候PE文件中的部分内容被载入内存(各种节),这些内容提供了程序运行所需的所有信息,下图展示了PE文件到内存的映射:

文章目录

  • PE文件结构
    • IMAGE_DOS_HEADER
    • DOS Stub
    • IMAGE_NT_HEADERS
      • IMAGE_FILE_HEADER
      • IMAGE_OPTIONAL_HEADER32
    • IMAGE_SECTION_HEADER
  • 功能数据介绍
    • 导入表
    • 导出表
    • 资源
    • 重定位表
    • 总结

PE文件结构

下图展示了PE文件的总体结构,在下面小节中将对各个结构进行详细的说明。

IMAGE_DOS_HEADER

DOS部分是为了兼容DOS系统程序,此部分包括Header和stub两部分,前者是对DOS程序的描述,后者包含了DOS可执行程序,Header头部如下所示:

IMAGE_DOS_HEADER STRUCTe_magic       WORD    ;DOS可执行文件标记e_cblp       WORD    e_cp         WORDe_crlc       WORDe_cparhdr    WORDe_minalloc   WORDe_maxalloc   WORDe_ss         WORD   ;代码的初始化堆栈段基址e_sp         WORD   ;代码的堆栈段偏移指针e_csum       WORDe_ip         WORD   ;DOS代码段偏移指针e_cs         WORD   ;DOS代码段基址e_lfarlc     WORDe_ovno       WORD   ;DOS文件头部到此为此,下述字段为了对其他可执行文件进行扩充,DOS系统对下述字段不解释e_res        WORDe_oemid      WORDe_oeminfo    WORDe_res2       WORDe_lfanew     DWORD  ;指向PE文件头部(或者LE,LX其他可执行文件头部)
IMAGE_DOS_HEADER ENDS

通过Lord PE工具可以查看程序的IMAGE_DOS_HEADER信息:

DOM可执行文件的识别标志为MZ

DOS Stub

DOS系统下可执行的代码,默认情况下这段代码只会简单的显示一个“This program cannot be run in DOS mode”然后就退出了,具体代码如下图黄框所示(Study PE工具截图)

上述黄框中部分机器码内容如下:

0E                PUSH    cs
1F                POP     ds
BA0E00            MOV     dx,  0x000E    ;串地址(即This program cannot.....的地址)
B409              MOV     ah, 0x09       ;显示字符串
CD21              INT     0x21           ;中断调用
B8014C            MOV     ax,0x4c01      ;带返回码结束,返回码为1
CD21              INT     0x21

可以使用链接器(link.exe)的/stud参数在链接时指定其他的DOM程序来代替上述提示程序

IMAGE_NT_HEADERS

IMAGE_NT_HEADERS是正式的PE文件头,本部分以8字节为单位对其,详细结构如下所示:

IMAGE_NT_HEADERS STRUCTSignature     DWORD                    ;PE文件标识FileHeader       IMAGE_FILE_HEADEROptionalHeader   IMAGE_OPTIONAL_HEADER32
IMAGE_NT_HEADERS ENDS

其中Signature的值为0x00004550也就是PE\0\0

IMAGE_FILE_HEADER

IMAGE_FILE_HEADER STRUCTMachine                WORD     ;运行平台NumberOfSections       WORD     ;文件的节数TimeDateStamp          DWORD    ;文件创建日期和时间PointerToSymbolTable   DWORD    ;符号表指针(调试用)NumberOfSymbols        DWORD    ;符号表中的符号数量(调试用)SizeOfOptionalHeader   WORD     ;IMAGE_OPTIONAN_HEADER32结构的长度Characteristics        WORD     ;文件属性
IMAGE_FILE_HEADER ENDS

下图是Lord PE软件载入某执行文件后上述结构体的值:

  • Machine:表示运行平台
  • TimeDateStamp:自1969年12月31日下午4点到文件创建时的秒数
  • SizeOfOptionalHeader:这个值为00e0h
  • Characteristics:这个字段16位(WORD),每一位描述着不同的文件属性

IMAGE_OPTIONAL_HEADER32

此结构体本意是让开发者能够在PE文件头中使用自定义数据,这个结构体弥补了IMAGE_FILE_HEADER不能够充分描述PE文件属性的不足

IMAGE_OPTIONAL_HEADER32 STRUCT:Magic                         WORD                       ;MajorLinkerVersion            BYTE                       ;连接器版本号MinorLinkerVersion            BYTE                       ;SizeOfCode                    DWORD                      ;所有包含代码的节的总大小SizeOfInitializedData         DWORD                      ;所有包含已初始化数据的节的总大小SizeOfUninitializedData       DWORD                      ;所有包含未初始化数据的节的总大小AddressOfEntryPoint           DWORD                      ;程序执行的入口偏移虚拟地址(RVA)BaseOfCode                    DWORD                      ;代码节的起始偏移虚拟地址(RVA)BaseOfData                    DWORD                      ;数据节的起始偏移虚拟地址(RVA)ImageBase                     DWORD                      ;程序建议装载地址SectionAlignment              DWORD                      ;内存中的节的对齐粒度FileAlignment                 DWORD                      ;文件中的节的对其粒度MajorOperatingSystemVersion   WORD                       ;操作系统的主版本号MinorOperatingSystemVersion   WORD                       ;操作系统中副版本号MajorImageVersion             WORD                       ;可运行于操作系统的最小版本号MinorImageVersion             WORD                       ;MajorSubsystemVersion         WORD                       ;可运行于操作系统的最小子版本号MinorSubsystemVersion         WORD                       ;Win32VersionValue             DWORD                      ;未用SizeOfImage                   DWORD                      ;内存中整个PE映像的尺寸SizeOfHeaders                 DWORD                      ;所有头+节表的大小CheckSum                      WORD                       ;Subsystem                     WORD                       ;文件的子系统DllCharacteristics            DWORD                      ;SizeOfStackReserve            DWORD                      ;初始化时堆栈大小SizeOfStackCommit             DWORD                      ;初始化时实际提交的堆栈大小SizeOfHeapReserve             DWORD                      ;初始化时保留的堆的大小SizeOfHeapCommit              DWORD                      ;初始化时实际提交的堆的大小LoaderFlags                   DWORD                      ;未用NumberOfRvaAndSizes           DWORD                      ;下面的数据目录结构的数量DataDirectory                 IMAGE_DATA_DIRECTORY 16 dup;
IMAGE_OPTIONAL_HEADER32 ENDS

下图展示了某程序的IMAGE_OPTIONAL_HEADER32 :

  • AddressOfEntryPoint:指出文件被执行时的入口地址,这是一个虚拟偏移地址(RVA)
  • ImageBase:指出程序有限装入的地址,也就是在文件执行时,WIndows优先将程序装入到ImageBase指定的地址中,如果执行地址已被占用,此时文件将会被装入其他地址
    1. EXE文件装入内存的基址为0x00400000DLL文件转入内存的基址为0x10000000,可以通过链接器(link.exe)的/base:address选项自定义优先转入的地址。
    2. EXE文件装入内存时常能如愿的加载到ImageBase指定的地址,因为每个EXE文件都有独立的虚拟地址空间,这也是EXE文件的IMAGE_FILE_HEADER结构的IMAGE_FILE_RELOCS_STRIPPED为常为1的原因;而DLL文件常常不能加载到指定内存,因为一个EXE通常会加载多个DLL,为此只有先加载的DLL才能遂愿,大部分的都不遂愿,这也是DLL文件的IMAGE_FILE_HEADER结构的IMAGE_FILE_RELOCS_STRIPPED为常为0的原因。
    3. 需要重定位的程序往往会比不需要重定位的程序慢的多,因为不需要重定位的程序在生成机器码时相对地址可以事先计算好,而需要重定位的程序不能这样做只有在程序转入运行时才能计算地址。
  • SectionAlignment和FileAlignment
    由于硬盘文件存储时存储的基本单位可能会与内存存储时基本的存储单位不同而导致节偏移的情况,为此:
    文件偏移地址=虚拟内存地址-装载基址-节偏移=RVA(相对虚拟内存偏移地址)-节偏移
  • Subsystem:此字段指定程序使用的界面子系统,这个字段决定程序如何建立初始界面
    可以通过链接器(link.exe)的/subsystem:xxx选项指定这个字段的值。
    下图是Lord PE工具所能识别的子系统列表:
  • DataDirectory: 最重要字段之一,由16个(NumberOfRvaAndSizes字段的值)IMAGE_DATA_DIRECTORY结构组成
    PE文件再装入内存后的页属性而被归类到不同的节中,但是这些处于不同节中的数据还可以按照用途被分类为导出表、导入表、资源、重定位表等数据块,这16个IMAGE_DATA_DIRECTORY就是用来定义多种不同用途的数据块的。也就是说节是按照页属性划分的,而DataDirectory是按照功能用途来划分的,但DataDirectory所指向的数据还是位与节中。
    IMAGE_DATA_DIRECTORY结构如下:
IMAGE_DATA_DIRECTORY STRUCTVirtualAddress DWORD     ;数据的起始RVAisize          DWORD     ;数据块的长度
IMAGE_DATA_DIRECTORY ENDS

下图展示了这16个IMAGE_DATA_DIRECTORY结构的用途:
下图是通过Lord PE软件查看的某个EXE文件的DataDirectory列表:

IMAGE_SECTION_HEADER

在PE文件装入时Windows装载器在装载DOS部分、PE文件头部分和节表部分时不进行任何处理,而在装载节的时候会根据节的属性做不同的处理,一般需要处理以下几个方面内容:

  • 内存页的属性:与节对应的内存页的属性也要按照节的属性来设置,所以同属于一个模块的内存页中,从不同节映射过来的内存页的属性也是不同的。
  • 节的偏移地址:节在磁盘中的对其单位是IMAGE_OPTIONAL_HEADER32结构中FileAlignment指定的,而在内存中对其单位是SectionAlignment字段指定的,二者可能不同。因为内存页的属性是对应于节属性设置的,而Windows系统对内存属性的设定单位为页,为此节的最小对其单位对应于Windows系统内存页的大小,而在磁盘中为了减小文件存储时所占用的空间从而降低了其磁盘中的对齐单位。
  • 节的尺寸
    在节由磁盘转入内存的过程中主要有两个原因影响节的尺寸,其一就是上面提到的由于对齐方式不同可能需要填充从而导致节的尺寸变大,其次就是对于包含未初始化数据的节在磁盘中存储时其尺寸为0,载入内从后Windows装载器根据额外信息将这些节装载到指定内存地址并开辟指定的空间。
  • 不进行映射的节
    有些节包含的数据仅在装载时使用,比如像包含重定向数据的节(.reloc),这些节在装载完成后就没有装入到内存中的价值了,为此这些节仅存在与磁盘文件中而不会被映射到内存页

PE文件所有节的属性均被定义在节表中,节表由一些列(IMAGE_NT_HEADERS.FileHeader.NumberOfSecitons字段指定节表长度)的IMAGE_SECTION_HEADER结构组成,这些结构的排列顺序与他们所描述节的排列顺序一致,节表起始地址位于距离PE文件头(不是文件头)00f8h偏移的位置,IMAGE_SECTION_HEADER结构如下所示:

IMAGE_SCETION_HEADER STRUCTName1 db IMAGE_SIZEOF_SHORT_NAME dup(?)        ;8个字节的节区名称union MiscPhysicalAddress              dd               ;VirtualSize                  dd            ;节的尺寸endsVirtualAddress                   dd            ;节区的RVASizeofRawData                    dd            ;在文件中对齐后的尺寸PointerToRawData                 dd            ;在文件中的偏移PointerToRelocations             dd            ;在OBJ文件中使用PoninterToLinenumbers            dd            ;行号表的位置(供调试用)NumberOfRelocations              dw            ;在OBJ文件中使用NumberOfLinenumbers              dw            ;行号表中行号的数量Characteristics                  dd            ;节的属性
IMAGE_SCETION_HEADER ENDS

上面有些字段是供COFF格式的OBJ文件使用的,对于可执行文件来说不代表任何意义

  • Name1:此字段由8个字节组成,用于定义节的名称,不要求以0结束,节的名称仅为标识不具有特殊意义
  • VirtualAddress:指定节被装入内存后的偏移地址(RVA)
  • VirtualSize:代表节在没有进行对齐处理前的实际的大小
  • PointerToRawData:指定节在磁盘文件中所处的位置,是相对于文件头的偏移量
  • SizeOfRawData:指出节在磁盘文件中所占空间的大小
  • Characteristics:节的属性标志字段,其不同数据位代表着不同的属性
    下表展示了不同的位所表示的不同属性:
    下图展示了某EXE文件.rdada节的属性:
    下图是某程序的节表:

功能数据介绍

前面已经提及过节是按照数据属性进行的分类,DataDirectory是按照数据功能进行的分类。本节中介绍导入表,导出表,资源,重定位表四个重要的DataDirectory。

导入表

导入表中保存了导入函数的相关信息(导入函数名,其驻留的DLL),所谓导入函数就是代码中调用了这些函数而这些函数并没有在本代码中定义而是从一个或多个DLL中导入进来的函数。当PE文件位与磁盘上时无法得知导入函数会位与内存的哪个位置,只有PE文件被装入内存时,Windows转载器才会将DLL装入并将导入函数的指令与函数实际所处的地址联系起来,这就是动态链接的概念。
导入表由一系列的IMAGE_IMPORT_DESCRIPTOR结构组成,这个结构与导入的DLL文件一 一对应,最后需要一个内容全为0的IMAGE_IMPORT_DESCRIPTOR结构作为结束

IMAGE_IMPORT_DESCRIPTOR STRUCTunionCharacteristics       dd         OriginalFirstThunk    ddendsTimeDateStamp             ddForwarderChain            ddName1                     dd       ;指向DLL文件名称的RVAFirstThunk                dd
IMAGE_IMPORT_DESCRIPTOR ENDS

OriginalFirstThunk和FirstThunk字段含义均指向一个包含一系列IMAGE_THUNK_DATA结构的数据,每个IMAGE_THUNK_DATA结构对应于一个导入函数信息,数组最后由一个全0的IMAGE_THUNK_DATA结构收尾,此结构(双字大小)具体如下:

IMAGE_THUNK_DATA STRUCTunion u1ForwarderString   ddFunction          ddOrdinal           ddAddressOfData     ddends
IMAGE_THUNK_DATA ENDS

由于上述结构采用union结构所以其实其就是一个双字类型,当这个双字表示了函数的导入方式:

  • 最高位为1,表明以序号方式导入,双字其余低位就表示者函数的序号
  • 最高位为0,表示以函数名方式导入,此时双字的值是一个RVA,其指向一个用来定义导入函数名称的IMAGE_IMPORT_BY_NAME结构,此结构的定义如下:
IMAGE_IMPORT_BY_NAME STRUCTHint            dw           ;表示函数序号,此字段可选Name1           db            ;定义了导入函数的名称字符串,以0结尾的字符串
IMAGE_IMPORT_BY_NAME ENDS

下图展示了装入内存前PE文件中的导入表,此表表示从Kernel32.dll导入四个函数(前三个以函数名方式导入,最后那个以序号方式导入):

下图展示了装载进内存后上述导入表的状况:
导入内存后FirstThunk指向的那个数组中的每个双字均被替换为真正的函数地址,OriginalFirstThunk与FirstThunk对照使用可以由地址得知函数名称,也可以由函数名或者序号查询函数在内存中的地址。
之前说个IMAGE_IMPORT_DESCRIPTOR结构与DLL文件一一对应,这些结构中FirstThunk指向的地址数组在内存中是被排列在一起的,这一内存块称之为导入地址表(Import Address Table,IAT),导入表中第一个IMAGE_IMPORT_DESCRIPTOR结构的FirstThunk字段指向了IAT的起始地址,除此之外DataDirectory结构中第13项IMAGE_DATA_DIRECTORY 结构也指向了IAT的起始地址。

导出表

除了导入表还有导出表,导入表指的是程序运行时要从DLL中导入的函数信息,而导出表则表示着DLL文件中函数的导出信息,主要用于修正IAT,导出表包含了函数的名称、序号以及入口地址等信息。EXE文件一般不存在导出表,大部分的DLL文件都包含导出表,通过导出表可以看DLL中包含那些函数。下图展示了一个DLL文件的导入与导出函数信息:

导出表中为每个导出函数定义了导出序号,但是函数名的定义是可选的,导出表只有一个IMAGE_EXPORT_DIRECTORY结构,此结构定义如下:

IMAGE_EXPORT_DIRECTORY STRUCTCharacteristics               DWORD           ;未使用,总是为0TimeDateStamp                 DWORD           ;文件的创建时间MajorVersion                  WORD            ;未使用,总是为0MinorVersion                  WORD            ;未使用,总是为0nName                         DWORD           ;指向文件名的RVAnBase                         DWORD           ;导出函数的起始序号NumberOfFunctions             DWORD           ;导出函数的总数NumberOfNames                 DWORD           ;有名称的导出函数总数AddressOfFunctions            DWORD           ;指向导出函数地址表的RVAAddressofNames                DWORD           ;指向函数名地址表的RVAAddressOfNameOrdinals         DWORD           ;指向函数名序号表的RVA
IMAGE_EXPORT_DIRECTORY ENDS

下图展示了导出表及相关数据的结构及关系(nBase:x):
不明白的是函数的入口RVA在载入内存之前的磁盘文件中就存在了,为什么?RVA不是内存中才有的概念吗?难道是.text是第一个段所以其前面的头部载入时不会发生相对偏移?

资源

  • PE文件中的资源如上图所示按目录结构组织,所有的目录结构及资源数据都几种的放在一个资源数据块中
  • 这个数据块的RVA由IMAGE_OPTIONAL_HEADER32.DataDirectory.Resource.VitrualAddress指定,而这个起始地址也对应着上图中的更目录首地址,依此就可以一层层的访问资源
  • 需要注意的是尽管资源一般情况下在**.rsrc**节中但并非必然,为此不可以通过这个节来对资源进行访问

接下来对资源涉及到的几种数据结构进行介绍,首先介绍IMAGE_RESOURCE_DIRECTORY,此结构包含了本目录的各种属性信息,具体结构如下:

IMAGE_RESOURCE_DIRECOTRY STRUCTCharacteristics      dd                 ; 理论上为资源的属性,不过通常总是为0TimeDateStamp        dd                 ; 资源的产生时刻MajorVersion         dw                 ; 理论上为资源的版本,不过事实上总是为0MinerVersion         dw                 ;NumberOfNameEntries  dw                 ; 以名称命名的入口数量NumberOfIdEntries    dw                 ; 以ID命名的入口数量
IMAGE_RESOURCE_DIRECTORY ENDS

上述结构中后两项说明了本目录中目录项的数量,这两者相加是本目录下目录项的总和,接下来了解下IMAGE_RESOURCE_DIRECTORY_ENTRY结构:

IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCTName1           dd         ; OffsetToData    dd         ;
IMAGE_RESOURCE_DIRECTORY_ENTRY ENDS

Name1字段字段在不同情况下有不同的含义,具体如下所示:

  • 资源类型:处于上图第一层目录时,31位为0时低位表示ID类型资源,系统预定义资源的ID表如下图所示,当ID值大于16时为用户自定义的ID资源
  • 指向目录项名称的指针或者目录项ID:处于上图第二层目录。第31位为0时低位表示ID;第31位为1时,低位为指针其所指的并不是字符串(因为项目名称是Unicode编码)而是指向一个IMAGE_RESOURCE_DIR_STRING_U结构体
IMAGE_RESOURCE_DIR_STRING_U STRUCTLength1        dw                 ;字符串长度NameString     dw     dup(?)      ;dup(?)代表重复?次,因为Unicode字符串长度不固定
IMAGE_RESOURCE_DIR_STRING_U ENDSUnicode字符串
  • 代码编号:处于上图第三层目录时

OffsetToData字段在不同情况下有不同的含义,具体如下所示:

  • 目录项指针:处于一二层目录结构时,此项高位为1,低位指向一个IMAGE_RESOURCE_DIRECTORY结构
  • 资源项指针:处于第三层是此项高位为0,低位指向一个IMAGE_RESOURCE_DATA_ENTRY结构
IMAGE_RESOURCE_DATA_ENTRY STRUCTOffsetToData            dd              ;资源数据的RVASize1                   dd              ;资源数据的长度CodePage                dd              ;代码页,实际之中好像未被使用,总是为0Reserved                dd              ;保留字段
IMAGE_RESOURCE_DATA_ENTRY ENDS

需要注意的是上述结构中的指针含义均是相对于资源根目录起始地址的偏移量
下面结合Winhex与stud_PE分析下某程序的资源信息:

  • 首先使用Stud_PE工具在DataDirectory找到Resource的RVA,如下图所示:
  • 接下来观察更具节信息将RVA转化为磁盘中的偏移地址,转化的算法大概如下伪代码所示:
for i in 节表:if RVA>i.VirtualAddress and RVA < i.VirtualAddress+i.sizeOfRawData:文件偏移 = i.PointerToRawData+(RVA-i.VirtualAddress)

节信息如下,按上述算法资源处于.rsrc节中且资源的起始地址刚好是这个节的起始地址,为此可以判断出资源在文件中的偏移为0x000FE000

  • 使用WinHex打开此程序并定位到0x000FE000的位置,如下图所示:
    上图中资源信息IMAGE_RESOURCE_DATA_ENTRY.CodePage并不为0与之前介绍的有出入

重定位表

上述代码中第5行使用了直接寻址的方式,在此应用程序装入预设的0x0040000地址时这中寻址方式直接出现在代码中没有问题,如果程序没有载入预设地址那怎么办呢?重定位就是来解决这个问题的,32位的代码中涉及直接寻址的指令都是需要重定位的,16的DOS中只有涉及段操作的指令才需要重定位,重定位信息是在编译时有编译器生成并保存在可执行文件中的。重定位具体操作如下:
重定位后地址 = 代码中出现的直接寻址地址-预装地址(0x00400000)+代码实际装入地址
上述三个操作数中预装地址已经在IMAGE_OPTIONAL_HEADER32.ImageBase字段定义了,而代码的实际装入地址也在代码装入是由Windows装载器确定,为此只需要将出现直接寻址地址的代码地址放入重定向表中就能够准确的进行代码重定向操作了。通过DataDirectory中的第六项可以定位重定位表的位置,重定位表通常保存在**.reloc**节中但是在此强调一次,通常但不是必须为此还是通过DataDirectory来寻找重定位表的位置比较靠谱。还需要说明的是重定向表一般不会再程序运行时装入内存,其仅在程序装载时辅助装载器对程序进行重定位操作。为了节约存储空间,重定位表在保存时采用了这样的存储方式即按页保存重定位代码地址,首先保存一个4字节的内存页起始地址,再保存一个此页内重定位代码的项数,最后保存所有的需要重定位操作的代码地址相对于页起始地址的偏移(页内寻址为12位,这里扩展到16位)。这样存储一个页内的所有重定位代码信息就需要4+4+2n字节,这种存储方式在内存页内重定位项数多于4时优于直接存储每个需要重定位代码的地址(4n)。按照这个逻辑关系每个内存页对应着一个重定位块这个块以IMAGE_BASE_RELOCATION开头:

IMAGE_BASE_RELOCATION STRUCTVirtualAddress        dd          ;页起始RVASizeOfBlock           dd          ;重定位块的长度 4+4+2*n
IMAGE_BASE_RELOCATION ENDS

上面提到要把12位的页内地址扩展到16位,低12位是原来的地址,高四位也被赋予了具体的函数,如下表所示:

上述表中0和3是最为常见的情况,所有的重定位块终于一个VirtualAddress字段全0的IMAGE_BASE_RELOCATION结构,这时候问题来了,那么RVA为0的内存页中需要重定位的代码如何解决呢?为了解决这个问题所有的可执行文件的代码总是从装入地址的0x1000处开始定义,如下图所示:

下面结合Winhex与stud_PE分析下某DLL文件重定位表:

  • 首先使用Stud_PE工具在DataDirectory找到重定位表的RVA,如下图所示:
  • 接下来观察更具节信息将RVA转化为磁盘中的偏移地址
    为此可以确定重定位表在文件中的偏移地址为0x00191000
  • 使用WinHex打开此程序并定位到0x00191000的位置,如下图所示:

    按上图划线部分可以知6个需要重定向代码的RVA为0xC6000、0xC62A8、0xC646F、0xC64B0、0xC64CC、0xC64F2。可以将这些RVA转换为文件偏移去文件中寻找相应指令的机器码,但是不可以使用OD等动态分析工具将文件载入然后去相应的RVA位置查看指令,因为载入后已经完成重定向,里面的代码是重定向后的指令。

总结

  • PE文件中所有数据都存储的节表中,而这些节表中的数据由于功能不同还被划分到其他的逻辑结构比如DataDirectory。
  • RVA及物理内存通过节来转换,但是并非所有的RVA都能成功转化为文件偏移地址
for i in 节表:if RVA>i.VirtualAddress and RVA < i.VirtualAddress+i.sizeOfRawData:文件偏移 = i.PointerToRawData+(RVA-i.VirtualAddress)
  • 大小端是对于数据来说的,而不是指令
  • 操作系统识别可执行文件的方法是依赖于文件头而不是文件扩展名,如果当前文件格式不符合任何已定义文件头格式则将其按照COM文件格式装入即将整个文件的数据当做代码装入执行
  • 节是按照数据属性进行的分类,DataDirectory是按照数据功能进行的分类

二进制菜鸟之PE文件结构相关推荐

  1. PE文件结构与程序装载

    PE文件结构与程序装载是掌握Windows逆向.加壳.免杀等技术的基础,本文详细记录了PE文件的基本结构,用编辑器对文件结构进行分析,并介绍程序装载的相关概念和基本过程. 参考书籍:<逆向工程核 ...

  2. PE文件结构详解 --(完整版)

    From:https://blog.csdn.net/adam001521/article/details/84658708 PE结构详解:https://www.cnblogs.com/zheh/p ...

  3. 学PE文件结构之记笔记

    PE PE(protable executable) 可移植的可执行文件 EXE和DLL文件之间的区别是语义上的,他们使用完全相同的PE格式.唯一的区别:用一个字段标识出EXE或DLL. 64位Win ...

  4. 4.13~4.17(PE文件结构预习+hook+进程hellow)

    常见PE文件结构 常见的PE文件:exe.dll.sys Ag: exe就不用多说,就是可执行文件 dll动态链接库 对于 Windows 操作系统,操作系统的大部分功能都由 DLL 提供 (http ...

  5. PE文件结构 - 数据目录表学习

    数据目录表,是一个结构体数组.数组里的每个元素对应一个数据表.通常有16个. 数组每个元素都是一个结构体,结构体如下 typedef struct _IMAGE_DATA_DIRECTORY {    ...

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

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

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

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

  8. PE文件结构详解(五)延迟导入表

    by evil.eagle 转载请注明出处. http://blog.csdn.net/evileagle/article/details/12718845 PE文件结构详解(四)PE导入表讲了一般的 ...

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

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

最新文章

  1. java多态调用优先级_关于java的多态方法调用顺序的问题
  2. Element UI——滚动条组件(ElScrollBar)修改.el-scrollbar__wrap和el-scrollbar__view的CSS属性
  3. python学习笔记四——数据类型
  4. Struts2的Action编写
  5. delphi控件切图界面闪烁_先本设计教你跳过UI小程序的七个坑
  6. jmstudio 摄像头获取不到_什么是全景摄像头?
  7. Github上删除文件后与本地同步
  8. 敏捷开发中的MoSCoW优先级排序方法
  9. linux定时任务打印日志,Centos7(linux)使用crond服务定时执行js脚本并将脚本的输出内容记录日志文件的简单应用...
  10. 如何在虚拟机安装并使用NTFS for Mac 15
  11. 2010-10-08在浏览器中兼容+jQuery3
  12. 开发了一款开虚拟店通过百度网盘卖成千上万本电子书虚拟商品自动发货机器人软件助手
  13. python编辑函数求n阶乘fact_python中fact函数的用法
  14. 柠檬班python自动化百度云_柠檬班python
  15. 海洋磁力数据处理步骤
  16. lib与dll的关系(详解静态链接库和动态链接库)
  17. Bert超长文本分类、文本摘要
  18. Video.js使用教程(二)
  19. Android全屏显示
  20. 选择比努力更重要,这些微信号值得你细细品味

热门文章

  1. Zookeeper(超级无敌认真好用,万字收藏篇!!!!)
  2. DCloud-MUI:下拉刷新、上拉加载
  3. 把vim打造成牛逼的C++ IDE
  4. java时间戳与php时间戳_java 时间戳和PHP时间戳 的转换 php time()
  5. 7.3_时间轴扭曲函数
  6. 区块链游戏和传统游戏有什么区别?
  7. IoT黑板报:中移动净利润是电信联通总和6倍
  8. Amesim2021.1与Simulink联合仿真配置流程及经验总结
  9. ABP官方文档(四)【启动配置】
  10. linux中vi后如何退出命令,linux vi保存退出命令 (如何退出vi)