| 关键词: nbsp IMAGE define 文件 file 一个 DIRECTORY Machine WORD 结构 |
信息来源:邪恶八进制信息安全团队(www.eviloctal.com)因为PE结构是一个很复杂的结构,所以下面我们在讨论PE时把它分为PE头标、表节、文件导入/导出、资源分别介绍。如果你只对某部分内容感兴趣,可以直接跳到此节阅读。PE头标 PE 的意思就是 Portable Executable(可移植的执行体)。它是 Win32环境自身所带的执行体文件格式。它的一些特性继承自 Unix的 Coff (common object file format)文件格式。“Portable Executable”(可移植的执行体)意味着此文件格式是跨Win32平台的:即使Windows运行在非Intel的CPU上,任何win32平台的PE装载器都能识别和使用该文件格式。当然,移植到不同的CPU上的PE执行体必然得有一些改变。所有Win32执行体(除了VxD和16位的DLL)都使用PE文件格式,包括NT的内核模式驱动程序(Kernel Mode Drivers)。我们在PE结构中最先看见的PE格式中的是PE结构的头标。像所有其他微软可执行文件格式一样,PE文件在一个已知(或容易找到的)位置上,有一系列域来定义该文件其余部分看起来像什么。PE头标包含了至关重要的一些信息,诸如代码和数据区的位置和大小、该文件要用什么操作系统以及初始的堆栈大小。我们在学习PE结构时最好用PEDUMP来DUMP一个EXE或DLL文件比较好学习点(PEDUMP可以在X:Msvc\COMMON\TOOLS找到,X为VC的安装目录)。1. DOS头与其他微软的可执行格式相似的是,在PE头标前面还有一个百多个字节的DOS头。这个DOS区域是一小段DOS程序。这一段程序只有几行简单的汇编程序,在Windows 3.1中可以自己定义。把一个很大的DOS程序当成PE结构的头也是可以的,例如说做一个从DOS下启动的游戏,就可以把DOS启动的内容放在前面。到了Windows 9x中的PE结构,在VC 4.0以后,DOS头就不可定义了。现在,它的作用是如果此程序在DOS平台运行时,它将打印出“该程序不能在DOS模式下运行”之类的信息。这样就能提示程序的用户到Windows平台去运行此程序。下图是PE结构图。 PE文件的所有结构都能在WINNT.H文件中找到,其结构如下: 复制内容到剪贴板 代码:typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header WORD e_magic; // Magic number WORD e_cblp; // Bytes on last page of file WORD e_cp; // Pages in file WORD e_crlc; // Relocations WORD e_cparhdr; // Size of header in paragraphs WORD e_minalloc; // Minimum extra //paragraphs needed WORD e_maxalloc; // Maximum extra //paragraphs needed WORD e_ss; // Initial (relative) SS value WORD e_sp; // Initial SP value WORD e_csum; // Checksum WORD e_ip; // Initial IP value WORD e_cs; // Initial (relative) CS value WORD e_lfarlc; // File address of relocation table WORD e_ovno; // Overlay number WORD e_res[4]; // Reserved words WORD e_oemid; // OEM identifier (for e_oeminfo) WORD e_oeminfo; // OEM information; //e_oemid specific WORD e_res2[10]; // Reserved words LONG e_lfanew; // File address of new exe header } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;e_lfanew是相对实际PE头标的相对偏移量(或RVA)。要得到内存中一个指向PE头标的指针,只需将该域的值与映像的基相加: 复制内容到剪贴板 代码: //Ignoring typecasts and pointer conversion issues for clarity… pNTHeader= dosHeader + dosHeader->e_lfanew;其他字段的意义是和DOS头有关的字节,这里没有什么大的作用,就不做介绍了。2. IMAGE_NT_HEADERS主PE头标是一个IMAGE_NT_HEADERS类型的结构,该类型在WINNT.H中定义。在内存中,Windows中把IMAGE_NT_HEADERS结构作为它内存中的模块数据库。在Windows中,每个被装入的EXE或DLL都用一个IMAGE_NT_HEADERS结构来说明。其结构如下: 复制内容到剪贴板 代码:typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader;} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;Signature表示此文件所表示的类型,其意义定义如下: 复制内容到剪贴板 代码:#define IMAGE_DOS_SIGNATURE 0x4D5A // MZ#define IMAGE_OS2_SIGNATURE 0x4E45 // NE#define IMAGE_OS2_SIGNATURE_LE 0x4C45 // LE#define IMAGE_NT_SIGNATURE 0x50450000 // PE00如果是PE格式,则Signature为PE\0\0(PE后跟两个0)。3. IMAGE_FILE_HEADERPE头标中紧随PE的WORD记号的是一个IMAGE_FILE_HEADER类型的结构,如下所示: 复制内容到剪贴板 代码:typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics;} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;这个结构的域只包含了关于文件的最基本的信息。Machine表示该文件运行所要求的CPU,有如下的CPU ID定义: 复制内容到剪贴板 代码:#define IMAGE_FILE_MACHINE_UNKNOWN 0#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian#define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian#define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian#define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian#define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian#define IMAGE_FILE_MACHINE_THUMB 0x01c2#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64#define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64#define IMAGE_FILE_MACHINE_AXP64 //IMAGE_FILE_MACHINE_ALPHA64NumberOfSection表示在EXE或OBJ中的节数。这个很重要,因为它直接表示节表数组的大小。TimeDateStamp表示连接器生成该文件的时间。该值是指从1969年12月31日下午4点整开始至文件生成时之间的秒数。PointerToSymbolTable表示文件的COFF符号表的偏移量。该域只用在OBJ文件和带有COFF调试信息的PE文件中,此信息只在调试文件中有用。NumberOfSymbols表示在COFF符号表中的符号数目,参见前一个域,此信息只在调试文件中有用。SizeOfOptionalHeader表示紧跟该结构之后的一个可选头标的大小。在可执行文件中,它是紧随该结构的image_file_header结构的大小。这个值必须有效。Characteristics表示文件的信息化标记。一些重要的域描述如下: 复制内容到剪贴板 代码:// Relocation info stripped from file.#define IMAGE_FILE_RELOCS_STRIPPED 0x0001// File is executable (i.e. no unresolved external references).#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002// Line nunbers stripped from file.#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004// Local symbols stripped from file.#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008// Agressively trim working set#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010// App can handle >2gb addresses#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020// Bytes of machine word are reversed.#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080// 32 bit word machine.#define IMAGE_FILE_32BIT_MACHINE 0x0100// Debugging info stripped from file in .DBG file#define IMAGE_FILE_DEBUG_STRIPPED 0x0200// If Image is on removable media, copy and run from the swap file.#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400// If Image is on Net, copy and run from the swap file.#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800// System File.#define IMAGE_FILE_SYSTEM 0x1000// File is a DLL.#define IMAGE_FILE_DLL 0x2000// File should only be run on a UP machine#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000// Bytes of machine word are reversed.#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000我们常见的意义如下。>> 0x0001:该文件中没有重定位。>> 0x0002:文件是一个可执行的映像(即不是一个OBJ或LIB)。>> 0x2000:文件是一个动态连接库,不是一个程序。4. IMAGE_OPTIONAL_HEADERPE头标的第三部分是一个IMAGE_OPTIONAL_HEADER类型结构。对于PE文件,这部分是必要的。除了标准的IMAGE_FILE_HEADER外,COFF格式还允许单独定义一个附加信息结构。IMAGE_OPTIONAL_HEADER分为两种,一种是32位的,一种是64位的,我们可以在WINNT.H中找到对应的结构,其名分别为:IMAGE_OPTIONAL_HEADER32各IMAGE_OPTIONAL_HEADER64。我们在这里只对32位进行介绍,其结构如下: 复制内容到剪贴板 代码:typedef struct _IMAGE_OPTIONAL_HEADER { // // Standard fields. // WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; // // NT additional fields. // DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;Magic表示标志映像文件状态的一个WORD记号。值定义如下: 复制内容到剪贴板 代码:#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107>> 0x0107:一个ROM映像。>> 0x010B:一个普通的可执行映像(大多数文件含此值)。MajorLinkerVersion和MinorLinkerVersion表示生成该文件的连接器版本号。该数字以十进制形式显示,而不是十六进制,一个典型的连接器版本号是2.23。SizeOfCode表示所有代码段组合聚集在一起的尺寸大小,内存中整个PE映像体的尺寸。它是所有头和节经过节对齐处理后的大小。SizeOfInitializedData表示由初始化的数据(不包括代码段)组成的所有节的总尺寸。SizeOfUninitializedData表示初始化的数据的大小。未初始化的数据通常被归入称为.bss的一节中。AddressOfEntryPoint表示映像开始执行位置的地址。PE装载器准备运行的PE文件的第一个指令的RVA。若您要改变整个执行的流程,可以将该值指定到新的RVA,这样,新RVA处的指令首先被执行。BaseOfCode表示文件代码节开始处的RVA。典型情况下,代码节在PE头标之后,并在数据节之前进入内存。在微软生成的EXE文件中,该RVA通常是0x1000。BaseOfData表示文件的数据节开始处的RVA。典型情况下,数据节最后进入内存,排在PE头标和代码节后面。ImageBase表示当连接器创建一个可执行文件时,它假设该文件将被内存映射到内存中的一个指定位置上。也就是PE文件的优先装载程序的地址。因为在Windows操作系统中,总是把可执行程序安装到虚拟空间中去,每个虚拟空间在逻辑上都是相对独立的,不相干的。此值就是表示程序装在虚拟空间的什么地方开始。SectionAlignment表示内存中节对齐的粒度。例如,如果该值是4096 (1000h),那么每节的起始地址必须是4096的倍数。若第一节从401000h开始且大小是10个字节,则下一节必定从402000h开始,即使401000h和402000h之间还有很多空间没被使用。FileAlignment表示文件中节对齐的粒度。例如,如果该值是(200h),,那么每节的起始地址必须是512的倍数。若第一节从文件偏移量200h开始且大小是10个字节,则下一节必定位于偏移量400h: 即使偏移量512和1024之间还有很多空间没被使用/定义。MajorOperatingSystemVersion和MinorOperatingSystemVersion表示使用该可执行文件所要求的操作系统最小版本。该域含义有点模棱两可,因为subsystem域(后面的一些域)页体现类似的目的。在大多数Win32文件中,该域为版本1.0。MajorImageVersion和MinorImageVersion表示一个用户自定义域。该域允许你具有一个EXE或一个DLL的不同版本。可用连接器的/VERSION开关来置该域的值,如LINK/VERSION:2.0 myobj.obj。MajorSuvsystemVersion和MinorSubsystemVersion表示运行该可执行文件所要求的最小子系统版本。该域的一个典型值是4.0(意为Windows 4.0,即Windows 95)。Reserved1一般总为0。SizeOfImage一般是装载器不得不关心的映像部分的总尺寸。它是从映像基地址开始直到最后一节的尾端这个范围的长度。最后一节的尾端是被调整为最接近节对齐值的倍数的。SizeOfHeaders表示PE头标和节(对象)表的尺寸。这些节的生数据直接跟在所有头标部分之后。SizeOfHeaders =所有头+节表的大小也就等于文件尺寸减去文件中所有节的尺寸。CheckSum总是值0。 Subsystem表示该可执行文件为它用户接口而使用的子系统类型。WINNT.H定义了如下值: 复制内容到剪贴板 代码:// Unknown subsystem.#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Image doesn't require a subsystem.#define IMAGE_SUBSYSTEM_NATIVE 1 // Image runs in the Windows GUI subsystem.#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows character subsystem.#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // image runs in the OS/2 character subsystem.#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the Posix character subsystem.#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image is a native Win9x driver.#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 // Image runs in the Windows CE subsystem.#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9表示的意义如下。>> native=1:不需要子系统(例如,一个设备驱动器)>> WINDOWS_GUI=2:在Windows GUI子系统中运行>> WINDOWS_GUI=3:在Windows字符子系统中运行(一个控制台应用程序)>> OS2_GUI=5:在OS/2字符子系统中运行(只对OS/2 1.x的应用程序)>> POSIX_CUI=7:在Posix字符子系统中运行DllCharacteristics (在NT 3.5中标为obsolete)指示什么情况下一个DLL的初始化函数,例如DllMain()要被调用的标志集合。该值看起来总被置为0,然而操作系统仍为4个事件调用了DLL初始化函数。被定义的值如下。>> 1:当DLL第一次被装入一个进程的地址空间时调用;>> 2:当一个线程中止时调用;>> 4:当一个线程启动时调用;>> 8:当DLL退出时调用。SizeOfStakeReserve表示为初始线程栈保留的虚拟内存量。然而,这些内存不是都要交付的(见后一个域)。该域默认为0x100000(1MB)。如果你对CreateThread()指定一个0作为栈的大小,结果线程仍是得到一个域默认值相同的栈。SizeOfStackCommit表示为初始线程栈首先交付的内存量。在微软连接器中,该域默认值是0x1000字节(1页),而TLINK默认为0x2000字节(2页)。SizeOfHeapReserve表示为初始进程堆保留的虚拟内存量。该堆句柄可通过调用GetProcessHeap()来获得。这些内存也不是都要交付的(见下一个域)。SizeOfHeapCommit表示在进程堆中初始交付的内存量。连接器在该域的默认值是0x1000字节。Loaderflags(在NT 3.5中标记为obsolete)它们一般是与调试支持有关的域。NumberOfRvaAndSizes表示在DataDiretory数组中项的数目。目前的工具总把该域的值置为16。DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]是一个IMAGE_DATA_DIRECTORY结构数组。数组中前面的元素包含了该可执行文件重要部分的起始RVA和尺寸。数组尾端的元素目前还未用到。数组的第一个元素总是引出函数表(如果有的话)的地址和尺寸。第二个数组项是引入函数表的地址和尺寸,如此等等。对于一个完整的数组项的定义列表,在WINNT.H中的IMAGE_DIRECTORY_ENTRY_xxx #defin’s中有如下的几项: 复制内容到剪贴板 代码:// Export Directory#define IMAGE_DIRECTORY_ENTRY_EXPORT 0// Import Directory#define IMAGE_DIRECTORY_ENTRY_IMPORT 1// Resource Directory#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2// Exception Directory#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3// Security Directory#define IMAGE_DIRECTORY_ENTRY_SECURITY 4// Base Relocation Table#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5// Debug Directory#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Architecture Specific Data#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // RVA of GP#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // TLS Directory#define IMAGE_DIRECTORY_ENTRY_TLS 9 // Load Configuration Directory#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Bound Import Directory in headers#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Import Address Table#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Delay Load Import Descriptors#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // COM Runtime descriptor#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14该数组的目的是允许装载器可迅速地找到一个映像的特定节(例如引入函数表),而不必遍历映像的每一个节并逐一比较它们的名字。数组的大多数项描述了一个完整的节的数据。然而,IMAGE_DIRECTORY_ENTRY_ DEBUG元素只含了.rdata节中一小部分字节。 var tagarray = ['A1Pass','免杀','逆向工程','杀毒软件原理','三步走','EXP','ms08-067','讨论','内网','架构','感染','资源','捆绑','XSS','误区','ms08067','核心溢出','UTF-8','Tomcat','Apache','西天','唐僧','灌水','取经','MyCcl','密码效验和','ratproxy','90hackit','rsa','EasyRecovery','DataExplorer','Serv-U','Buffer','Office','WPS','Overflow','Microsoft','内核编程','DDoS','Ghost','数据恢复','手机号','收集','源代码','隐藏驱动','百度','驱动编程','机器狗','Oracle','招聘','猎头','属主','IIS'];var tagencarray = ['A1Pass','%E5%85%8D%E6%9D%80','%E9%80%86%E5%90%91%E5%B7%A5%E7%A8%8B','%E6%9D%80%E6%AF%92%E8%BD%AF%E4%BB%B6%E5%8E%9F%E7%90%86','%E4%B8%89%E6%AD%A5%E8%B5%B0','EXP','ms08-067','%E8%AE%A8%E8%AE%BA','%E5%86%85%E7%BD%91','%E6%9E%B6%E6%9E%84','%E6%84%9F%E6%9F%93','%E8%B5%84%E6%BA%90','%E6%8D%86%E7%BB%91','XSS','%E8%AF%AF%E5%8C%BA','ms08067','%E6%A0%B8%E5%BF%83%E6%BA%A2%E5%87%BA','UTF-8','Tomcat','Apache','%E8%A5%BF%E5%A4%A9','%E5%94%90%E5%83%A7','%E7%81%8C%E6%B0%B4','%E5%8F%96%E7%BB%8F','MyCcl','%E5%AF%86%E7%A0%81%E6%95%88%E9%AA%8C%E5%92%8C','ratproxy','90hackit','rsa','EasyRecovery','DataExplorer','Serv-U','Buffer','Office','WPS','Overflow','Microsoft','%E5%86%85%E6%A0%B8%E7%BC%96%E7%A8%8B','DDoS','Ghost','%E6%95%B0%E6%8D%AE%E6%81%A2%E5%A4%8D','%E6%89%8B%E6%9C%BA%E5%8F%B7','%E6%94%B6%E9%9B%86','%E6%BA%90%E4%BB%A3%E7%A0%81','%E9%9A%90%E8%97%8F%E9%A9%B1%E5%8A%A8','%E7%99%BE%E5%BA%A6','%E9%A9%B1%E5%8A%A8%E7%BC%96%E7%A8%8B','%E6%9C%BA%E5%99%A8%E7%8B%97','Oracle','%E6%8B%9B%E8%81%98','%E7%8C%8E%E5%A4%B4','%E5%B1%9E%E4%B8%BB','IIS'];parsetag(); |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|