PE知识学习,连载----------------------3,4

导读:
  pe知识学习(三)
  前两个贴子我们已经介绍了pe文件的两个结构,希望还没有让你看晕.下面我把pe文件的结构列出来,让我们有个全局的印象.
  _______________________________
  | IMAGE_DOS_HEADER | <-- Dos部首
  -------------------------------
  | 'PE',0,0 | <-- PE文件标志
  -------------------------------
  | IMAGE_FILE_HEADER | <-- 映像文件头
  -------------------------------
  | IMAGE_OPTIONAL_HEADER32 | <-- 映像可选头
  -------------------------------
  | Section Table | <-- 节表
  -------------------------------
  | .text | <-- 代码区段
  -------------------------------
  | .data | <-- 数据区段
  -------------------------------
  | .idata | <-- 输入表
  -------------------------------
  | .edata | <-- 输出表
  -------------------------------
  | .reloc | <-- 重定位表区段
  -------------------------------
  | .... |
  -------------------------------
  | 调试信息 |
  -------------------------------
  好了,我们接着看看IMAGE_OPTIONAL_HEADER32结构.这个结构的域比较多,但是和后面要讲到的节表一样,非常重要.希望你能够用心体会,并动手实践一下.
  IMAGE_OPTIONAL_HEADER32的结构定义如下:
  typedef struct _IMAGE_OPTIONAL_HEADER {
  //
  // Standard fields.
  //
  00h WORD Magic; //幻数,32位pe文件总为010bh
  02h BYTE MajorLinkerVersion; //连接器主版本号
  03h BYTE MinorLinkerVersion; //连接器副版本号
  04h DWORD SizeOfCode; //代码段总大小
  08h DWORD SizeOfInitializedData; //已初始化数据段总大小
  0ch DWORD SizeOfUninitializedData; //未初始化数据段总大小
  10h DWORD AddressOfEntryPoint; //程序执行入口地址(RVA)
  14h DWORD BaseOfCode; //代码段起始地址(RVA)
  18h DWORD BaseOfData; //数据段起始地址(RVA)
  //
  // NT additional fields.
  //
  1ch DWORD ImageBase; //程序默认的装入起始地址
  20h DWORD SectionAlignment; //内存中区块的对齐单位
  24h DWORD FileAlignment; //文件中区块的对齐单位
  28h WORD MajorOperatingSystemVersion; //所需操作系统主版本号
  2ah WORD MinorOperatingSystemVersion; //所需操作系统副版本号
  2ch WORD MajorImageVersion; //自定义主版本号
  2eh WORD MinorImageVersion; //自定义副版本号
  30h WORD MajorSubsystemVersion; //所需子系统主版本号
  32h WORD MinorSubsystemVersion; //所需子系统副版本号
  34h DWORD Win32VersionValue; //总是0
  38h DWORD SizeOfImage; //pe文件在内存中的映像总大小
  3ch DWORD SizeOfHeaders; //从pe文件开始到节表(包含节表)的总大小
  40h DWORD CheckSum; //pe文件CRC校验和
  44h WORD Subsystem; //用户界面使用的子系统类型
  46h WORD DllCharacteristics; //为0
  48h DWORD SizeOfStackReserve; //为线程的栈初始保留的虚拟内存的默认值
  4ch DWORD SizeOfStackCommit; //为线程的栈初始提交的虚拟内存的大小
  50h DWORD SizeOfHeapReserve; //为进程的堆保留的虚拟内存的大小
  54h DWORD SizeOfHeapCommit; //为进程的堆初始提交的虚拟内存的大小
  58h DWORD LoaderFlags; //为0
  5ch DWORD NumberOfRvaAndSizes; //数据目录结构数组的项数,总为 00000010h
  60h IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
  //数据目录结构数组
  } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
  下面再具体解释一下各个域的含义.不要闲罗嗦,后面这些知识实在是太重要了.
  1)Magic 幻数,32位pe文件总为010bh
  这个常数的定义如下:
  #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
  #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
  #define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
  2)MajorLinkerVersion 连接程序的主版本号 如vc6.0的为06h
  3)MinorLinkerVersion 连接程序的次版本号 如vc6.0的为00h
  4)SizeOfCode pe文件代码段的大小.是FileAlignment的整数倍.
  5)SizeOfInitializedData 所有含已初始化数据的块的大小,一般在.data段中.
  6)SizeOfUninitializedData 所有含未初始化数据的块的大小,一般在.bss段中.
  7)AddressOfEntryPoint 程序开始执行的地址,这是一个RVA(相对虚拟地址).对于exe文件,这里是启动代码;对于dll文件,这里是libMain()的地址.
  在脱壳时第一件事就是找入口点,指的就是这个值.
  8)BaseOfCode 代码段基地址,微软的连接程序生成的程序一般把这个值置为1000h,
  9)BaseOfData 数据段基地址
  10)ImageBase pe文件默认的装入地址.windows9x中exe文件为400000h,dll文件为10000000h.
  11)SectionAlignment 内存中区块的对齐单位.区块总是对齐到这个值的整数倍.x86的32位系统上默认值位1000h
  12)FileAlignment pe文件中区块的对齐单位.pe文件中默认值为 200h.
  13)MajorOperatingSystemVersion
  14)MinorOperatingSystemVersion
  上面两个域是指运行这个pe文件所需的操作系统的最低版本号.windows95/98和windows nt 4.0 的内部版本号都是 4.0 ,而windows2000的内部版本号是5.0
  15)MajorImageVersion
  16)MinorImageVersion
  上面两个域是指用户自定义的pe文件的版本号.可以通过连接程序来设置,如: LINK /VERSION:2.0 MyApp.obj一般在升级时使用.
  17)MajorSubsystemVersion
  18)MinorSubsystemVersion
  上面两个域是指运行这个pe文件所要求的子系统的版本号.
  19)Win32VersionValue 总是0
  20)SizeOfImage pe文件装入内存后映像的总大小.如果SectionAlignment域和FileAlignment域相等,那么这个值也是pe文件在硬盘上的大小.
  21)SizeOfHeaders 从文件开始到节表(包含节表)的总大小.其后是各个区段的数据.
  22)CheckSum pe文件的CRC校验和.
  23)Subsystem pe文件的用户界面使用的子系统类型.定义如下:
  #define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem.
  #define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem.
  #define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
  #define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
  #define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem.
  #define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image runs in the Posix character subsystem.
  #define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 // image is a native Win9x driver.
  #define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 // Image runs in the Windows CE subsystem.
  24)DllCharacteristics 总为0
  25)SizeOfStackReserve 为线程的栈初始保留的虚拟内存的大小,默认为00100000h.如果在调用CreateThread函数时指定堆栈的大小为0,被创建的线程的堆栈的初始大小就与这个值相同.
  26)SizeOfStackCommit 为线程的栈初始提交的虚拟内存的大小.微软的连接程序把这个值置为 1000h.
  27)SizeOfHeapReserve 为进程的堆保留的虚拟内存的大小.默认值为 00100000h.
  28)SizeOfHeapCommit 为进程的堆初始提交的虚拟内存的大小.微软的连接程序把这个值置为1000h.
  29)LoaderFlags 通常为0
  30)NumberOfRvaAndSizes 数据目录结构数组的项数,总为 00000010h
  这个值定义如下:
  #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
  31)IMAGE_DATA_DIRECTORY DataDirectory[0x10] 数据目录结构数组
  IMAGE_DATA_DIRECTORY结构定义如下:
  typedef struct _IMAGE_DATA_DIRECTORY {
  DWORD VirtualAddress; 相对虚拟地址
  DWORD Size; 大小
  } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
  这个结构包含了pe文件中重要部分的RVA地址和大小.这个数组使操作系统的加载程序能够快速定位特定的区段.具体定义如下:
  #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory
  #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory
  #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory
  #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory
  #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory
  #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table
  #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory
  // IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage)
  #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data
  #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP
  #define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory
  #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory
  #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers
  #define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table
  #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors
  #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor
  作者: sdlj8051 发布日期: 2006-8-26
  pe知识学习(四)
  下面我们要学习的可以说是pe文件的核心内容了.即块表(section table)和各种块(区段)的结构.这些内容比较多且长.因此我会把写完的先发出来,然后在慢慢的续完.希望你有耐心看下去.学习有时是很枯燥的.因此在适当的时候我也会给出点应用的实例.
  你可能还记得,区块的数量在IMAGE_FILE_HEADER结构的NumberOfSections域定义.好了,我们看看和区块密切相关的块表的结构定义.
  块表结构的定义如下:
  #define IMAGE_SIZEOF_SHORT_NAME 8
  typedef struct _IMAGE_SECTION_HEADER {
  00h BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //块名,8个字节长
  08h union {
  DWORD PhysicalAddress; //obj文件中,区段的实际地址
  DWORD VirtualSize; //exe和dll文件中区段在文件中对齐前的大小
  } Misc;
  0ch DWORD VirtualAddress; //块的RVA(相对虚拟地址)
  10h DWORD SizeOfRawData; //在文件中对齐后的大小
  14h DWORD PointerToRawData; //在文件中的偏移
  18h DWORD PointerToRelocations; //重定位的偏移(obj文件中使用)
  1ch DWORD PointerToLinenumbers; //行号表的偏移(调试用)
  1eh WORD NumberOfRelocations; //重定位项数目(obj文件中使用)
  20h WORD NumberOfLinenumbers; //行号表中行号的数目
  24h DWORD Characteristics; //块属性
  } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
  块表结构描述了区段的一些重要的属性,下面具体解释一下各个域的含义.
  1)Name[8] 8个字节的区段名,不足8个后面用0补齐.
  2)VirtualSize 在exe和dll文件中这个域包含的是区段还没有按FileAlignment域对齐前的大小.如果这个结构描述的是代码段,那么这个域的值就是实际的代码量的大小.在pe文件的diy时,这个域很有用.它指出了区段中有多少没有使用的空间.我们可以在没有使用的空间里插入自己的代码.好多病毒也是把代码插入剩余的空间里.(呵呵,不要学坏.)
  3)VirtualAddress 在exe文件中,这个域是pe文件映射到虚拟内存后该区段的RVA地址.这个值加上基地址(IMAGE_OPTIONAL_HEADER32.ImageBase)后,就得到了该区段在内存中的实际起始地址.
  4)SizeOfRawData 这个域是它描述的区段按IMAGE_OPTIONAL_HEADER32.FileAlignment域对齐后在文件中的大小.如果FileAlignment为 0200h,VirtualSize为035Ah,则这个值为 0400h.
  5)PointerToRawData 它描述的区段的起始地址在pe文件中的偏移.
  6)PointerToRelocations
  7)PointerToLinenumbers
  8)NumberOfRelocations
  9)NumberOfLinenumbers
  上面这四个域在发行版本的程序里都是0.
  10)Characteristics 该区段的属性信息.用于表示这个区段是代码、数据、可读、可写等等.
  这个域定义如下(重要的已经做了中文注释):
  // IMAGE_SCN_TYPE_REG 0x00000000 // Reserved.
  // IMAGE_SCN_TYPE_DSECT 0x00000001 // Reserved.
  // IMAGE_SCN_TYPE_NOLOAD 0x00000002 // Reserved.
  // IMAGE_SCN_TYPE_GROUP 0x00000004 // Reserved.
  #define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.
  // IMAGE_SCN_TYPE_COPY 0x00000010 // Reserved.
  #define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code.
  //区段包含代码
  #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data.
  //区段包含已初始化数据
  #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data.
  //区段包含未初始化数据
  #define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.
  #define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments
  // or some other type of information.
  // IMAGE_SCN_TYPE_OVER 0x00000400 // Reserved.
  #define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.
  #define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat.
  // 0x00002000 // Reserved.
  // IMAGE_SCN_MEM_PROTECTED - Obsolete 0x00004000
  #define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 // Reset speculative exceptions handling bits
  // in the TLB entries for this section.
  #define IMAGE_SCN_GPREL 0x00008000 // Section content can be accessed relative to GP
  #define IMAGE_SCN_MEM_FARDATA 0x00008000
  // IMAGE_SCN_MEM_SYSHEAP - Obsolete 0x00010000
  #define IMAGE_SCN_MEM_PURGEABLE 0x00020000
  #define IMAGE_SCN_MEM_16BIT 0x00020000
  #define IMAGE_SCN_MEM_LOCKED 0x00040000
  #define IMAGE_SCN_MEM_PRELOAD 0x00080000
  #define IMAGE_SCN_ALIGN_1BYTES 0x00100000 //
  #define IMAGE_SCN_ALIGN_2BYTES 0x00200000 //
  #define IMAGE_SCN_ALIGN_4BYTES 0x00300000 //
  #define IMAGE_SCN_ALIGN_8BYTES 0x00400000 //
  #define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified.
  #define IMAGE_SCN_ALIGN_32BYTES 0x00600000 //
  #define IMAGE_SCN_ALIGN_64BYTES 0x00700000 //
  #define IMAGE_SCN_ALIGN_128BYTES 0x00800000 //
  #define IMAGE_SCN_ALIGN_256BYTES 0x00900000 //
  #define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 //
  #define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 //
  #define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 //
  #define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 //
  #define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 //
  // Unused 0x00F00000
  #define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // Section contains extended relocations.
  #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded.
  //该区段可丢弃
  #define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable.
  #define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable.
  #define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable.
  //该区段可共享
  #define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable.
  //该区段可执行
  #define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable.
  //该区段可读
  #define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable.
  //该区段可写
  下面我们看一下pe文件里常用的一下区段:
  1).text
  code
  这里一般放的是代码.
  2).data
  这里一般放的是已初始化的数据.
  3).idata
  这里一般放的是输入表.这个后面还要详细讲.
  4).rsrc
  这里一般放的是资源.
  5).reloc
  这里一般放的是基地址重定位表.
  6).edata
  这里一般放的是输出表.
  7).tls
  这里一般是线程局部存储数据.
  8).bbs
  这里一般放的是未初始化的数据.

本文转自
http://hi.baidu.com/19chang19/blog/item/59390b4e6013e6c9d1c86a27.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值