MAGE_NT_HEADERS STRUCT结构

12 篇文章 0 订阅

MAGE_NT_HEADERS STRUCT结构体包含了两个子结构体

typedef struct _IMAGE_NT_HEADERS 
{ 
+00h DWORD Signature 
+04h IMAGE_FILE_HEADER FileHeader 
+18h IMAGE_OPTIONAL_HEADER32 OptionalHeader 
} IMAGE_NT_HEADERS ENDS, *PIMAGE_NT_HEADERS32;

1.Signature 字段:
在一个有效的 PE 文件里,Signature 字段被设置为00004550h, ASCII 码字符是“PE00”。标志这 PE 文件头的开始。“PE00” 字符串是 PE 文件头的开始,DOS 头部的 e_lfanew 字段正是指向这里


2.子结构体一:
IMAGE_FILE_HEADER结构体

复制代码
typedef struct _IMAGE_FILE_HEADER 
{ 
+04h WORD Machine; // 运行平台 
+06h WORD NumberOfSections; // 文件的区块数目 
+08h DWORD TimeDateStamp; // 文件创建日期和时间 
+0Ch DWORD PointerToSymbolTable; // 指向COFF符号表(主要用于调试) 
+10h DWORD NumberOfSymbols; // COFF符号表中符号个数(同上) 
+14h WORD SizeOfOptionalHeader; // IMAGE_OPTIONAL_HEADER32 结构大小 
+16h WORD Characteristics; // 文件属性 
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
复制代码



(1)Machine:可执行文件的目标CPU类型。

ValueMeaning
IMAGE_FILE_MACHINE_I386 0x014c

x86

IMAGE_FILE_MACHINE_IA64 0x0200

Intel Itanium

IMAGE_FILE_MACHINE_AMD64 0x8664

x64


(2)NumberOfSection: 区块的数目。(注:区块表是紧跟在 IMAGE_NT_HEADERS 后边的)
(3)TimeDataStamp: 表明文件是何时被创建的。

这个值是自1970年1月1日以来用格林威治时间(GMT)计算的秒数,这个值是比文件系统(FILESYSTEM)的日期时间更加精确的指示器。

提示:VC的话可以用_ctime 函数或者 gmtime 函数。
(4)PointerToSymbolTable: COFF 符号表的文件偏移位置,现在基本没用了。
(5)NumberOfSymbols: 如果有COFF 符号表,它代表其中的符号数目,COFF符号是一个大小固定的结构,如果想找到COFF 符号表的结束位置,则需要这个变量。

(6)SizeOfOptionalHeader: 紧跟着IMAGE_FILE_HEADER 后边的数据结构(IMAGE_OPTIONAL_HEADER)的大小。(对于32位PE文件,这个值通常是00E0h;对于64位PE32+文件,这个值是00F0h )。
(7)Characteristics: 文件属性,有选择的通过几个值可以运算得到。( 这些标志的有效值是定义于 winnt.h 内的 IMAGE_FILE_** 的值,具体含义见下表。普通的EXE文件这个字段的值一般是 0100h,DLL文件这个字段的值一般是 210Eh。)小甲鱼温馨提示:多种属性可以通过 “或运算” 使得同时拥有!

ValueMeaning
IMAGE_FILE_RELOCS_STRIPPED 0x0001

Relocation information was stripped from the file. The file must be loaded at its preferred base address. If the base address is not available, the loader reports an error.

IMAGE_FILE_EXECUTABLE_IMAGE 0x0002

The file is executable (there are no unresolved external references).

IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004

COFF line numbers were stripped from the file.

IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008

COFF symbol table entries were stripped from file.

IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010

Aggressively trim the working set. This value is obsolete.

IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020

The application can handle addresses larger than 2 GB.

IMAGE_FILE_BYTES_REVERSED_LO 0x0080

The bytes of the word are reversed. This flag is obsolete.

IMAGE_FILE_32BIT_MACHINE 0x0100

The computer supports 32-bit words.

IMAGE_FILE_DEBUG_STRIPPED 0x0200

Debugging information was removed and stored separately in another file.

IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400

If the image is on removable media, copy it to and run it from the swap file.

IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800

If the image is on the network, copy it to and run it from the swap file.

IMAGE_FILE_SYSTEM 0x1000

The image is a system file.

IMAGE_FILE_DLL 0x2000

The image is a DLL file. While it is an executable file, it cannot be run directly.

IMAGE_FILE_UP_SYSTEM_ONLY 0x4000

The file should be run only on a uniprocessor computer.

IMAGE_FILE_BYTES_REVERSED_HI 0x8000

The bytes of the word are reversed. This flag is obsolete.


3.子结构体二:

IMAGE_OPTIONAL_HEADER 结构

复制代码
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;
复制代码

●AddressOfEntryPoint字段
  指出文件被执行时的入口地址,这是一个RVA地址(RVA的含义在下一节中详细介绍)。如果在一个可执行文件上附加了一段代码并想让这段代码首先被执行,那么只需要将这个入口地址指向附加的代码就可以了。

●ImageBase字段
  指出文件的优先装入地址。也就是说当文件被执行时,如果可能的话,Windows优先将文件装入到由ImageBase字段指定的地址中,只有指定的地址已经被**模块使用时,文件才被装入到**地址中。链接器产生可执行文件的时候对应这个地址来生成机器码,所以当文件被装入这个地址时不需要进行重定位操作,装入的速度最快,如果文件被装载到**地址的话,将不得不进行重定位操作,这样就要慢一点。


  对于EXE文件来说,由于每个文件总是使用独立的虚拟地址空间,优先装入地址不可能被**模块占据,所以EXE总是能够按照这个地址装入,这也意味着EXE文件不再需要重定位信息。对于DLL文件来说,由于多个DLL文件全部使用宿主EXE文件的地址空间,不能保证优先装入地址没有被**的DLL使用,所以DLL文件中必须包含重定位信息以防万一。因此,在前面介绍的 IMAGE_FILE_HEADER 结构的 Characteristics 字段中,DLL 文件对应的 IMAGE_FILE_RELOCS_STRIPPED 位总是为0,而EXE文件的这个标志位总是为1。

  在链接的时候,可以通过对link.exe指定/base:address选项来自定义优先装入地址,如果不指定这个选项的话,一般EXE文件的默认优先装入地址被定为00400000h,而DLL文件的默认优先装入地址被定为10000000h。

●SectionAlignment 字段和 FileAlignment字段
  SectionAlignment字段指定了节被装入内存后的对齐单位。也就是说,每个节被装入的地址必定是本字段指定数值的整数倍。而FileAlignment字段指定了节存储在磁盘文件中时的对齐单位。

●Subsystem字段
  指定使用界面的子系统,它的取值如表17.3所示。这个字段决定了系统如何为程序建立初始的界面,链接时的/subsystem:**选项指定的就是这个字段的值,在前面章节的编程中我们早已知道:如果将子系统指定为Windows CUI,那么系统会自动为程序建立一个控制台窗口,而指定为Windows GUI的话,窗口必须由程序自己建立。

界面子系统的取值和含义

取   值

Windows.inc中的预定义值

含   义

0

IMAGE_SUBSYSTEM_UNKNOWN

未知的子系统

1

IMAGE_SUBSYSTEM_NATIVE

不需要子系统(如驱动程序)

2

IMAGE_SUBSYSTEM_WINDOWS_GUI

Windows图形界面

3

IMAGE_SUBSYSTEM_WINDOWS_CUI

Windows控制台界面

5

IMAGE_SUBSYSTEM_OS2_CUI

OS2控制台界面

7

IMAGE_SUBSYSTEM_POSIX_CUI

POSIX控制台界面

8

IMAGE_SUBSYSTEM_NATIVE_WINDOWS

不需要子系统

9

IMAGE_SUBSYSTEM_WINDOWS_CE_GUI

Windows CE图形界面

 



●DataDirectory字段
   这个字段可以说是最重要的字段之一,它由16个相同的 IMAGE_DATA_DIRECTORY结构组成,虽然PE文件中的数据是按照装入内存后的页属性归类而被放在不同的节中的,但是这些处于各个节中的数据按照用途可以被分为导出表、导入表、资源、重定位表等数据块,这16个IMAGE_DATA_DIRECTORY结构就是用来定义多种不同用途的数据块的(如表17.4所示)。IMAGE_DATA_DIRECTORY结构的定义很简单,它仅仅指出了某种数据块的位置和长度。

IMAGE_DATA_DIRECTORY STRUCT
VirtualAddress DWORD ? ; //数据的起始RVA
isize DWORD ? ; //数据块的长度
IMAGE_DATA_DIRECTORY ENDS

 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  在 PE文件中寻找特定的数据时就是从这些IMAGE_DATA_DIRECTORY结构开始的,比如要存取资源,那么必须从第3个 IMAGE_DATA_DIRECTORY结构(索引为2)中得到资源数据块的大小和位置;同理,如果要查看PE文件导入了哪些DLL文件的哪些API函数,那就必须首先从第2个IMAGE_DATA_DIRECTORY结构得到导入表的位置和大小

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值