文档库 最新最全的文档下载
当前位置:文档库 › pe文件剖析

pe文件剖析

pe文件剖析
pe文件剖析

pe文件

pe文件结构图

PE文件被称为可移植的执行体是Portable Execute的全称,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(可能是间接被执行,如DLL)

一个操作系统的可执行文件格式在很多方面是这个系统的一面镜子。虽然学习一个可执行文件格式通常不是一个程序员的首要任务,但是你可以从这其中学到大量的知识。在这篇文章中,我会给出MicroSoft 的所有基于win32系统(如winnt,win9x)的可移植可执行(PE)文件格式的详细介绍。在可预知的未来,包括Windows2000, PE 文件格式在MicroSoft 的操作系统中扮演一个重要的角色。如果你在使用Win32 或Winnt ,那么你已经在使用PE 文件了。甚至你只是在Windows3.1 下使用Visual C++ 编程,你使用的仍然是PE 文件(Visual C++ 的32 位MS-DOS 扩展组件用这个格式)。简而言之,PE 格式已经普遍应用,并且在不短的将来仍是不可避免的。现在是时候找出这种新的可执行文件格式为操作系统带来的东西了。

我最后不会让你盯住无穷无尽的十六进制Dump,也不会详细讨论页面的每一个单独的位的重要性。代替的,我会向你介绍包含在PE 文件中的概念,并且将他们和你每天都遇到的东西联系起来。比如,线程局部变量的概念,如下所述:

declspec(thread) int i;

我快要发疯了,直到我发现它在可执行文件中实现起来是如此的简单并且优雅。既然你们中的许多人都有使用16 Windows 的背景,我将把Win32 PE 文件的构造追溯到和它等价的16 位NE 文件。

除了一个不同的可执行文件格式,MicroSoft 还引入了一个用它的编译器和汇编器生成的新的目标模块格式。这个新的OBJ 文件格式有许多和PE 文件共同的东东。我做了许多无用功去查找这个新的OBJ 文件格式的文档。所以我以自己的理解对它进行解析,并且,在这里,除了PE 文件,我会描述它的一部分。

大家都知道,Windows NT 继承了VAX? VMS? 和UNIX? 的传统。许多Windows NT 的创始人在进入微软前都在这些平台上进行设计和编码。当他们开始设计Windows NT 时,很自然的,为了最小化项目启动时间,他们会使用以前写好的并且已经测试过的工具。用这些工具生成的并且工作的可执行和OBJ 文件格式叫做COFF (Common Object File Format 的首字母缩写)。COFF 的相对年龄可以用八进制的域来指定。COFF 本身是一个好的起点,但是需要扩展到一个现代操作系统如Windows 95 和Windows NT 的需要。这个更新的结果就是(PE格式)可移植可执行文件格式。它被称为"可移植的"是因为在所有平台(如x86,Alpha,MIPS等等)上实现的WindowsNT 都使用相同的可执行文件格式。当然了,也有许多不同的东西如二进制代码的CPU指令。重要的是操作系统的装入器和程序设计工具不需要为任何一种CPU完全重写就能达到目的。

MicroSoft 抛弃现存的32位工具和可执行文件格式的事实证实了他们想让WindowsNT 升级并且运行的更快的决心。为16位Windows编写的虚拟设备驱动程序用一种不同的32位文件布局--LE 文件格式--WindowsNT出现很早以前就存在了。比这更重要的是对OBJ 文件的替换!在WindowsNT 的 C 编译器以前,所有的微软编译器都用Intel 的OMF ( Object Module Format ) 规范。就像前面提到的,MicroSoft 的Win32 编译器生成COFF 格式的OBJ 文件。一些微软的竞争者,如Borland 和Symentec ,选择放弃了COFF 格式并坚持Intel 的OMF 文件格式。这样的结果是制作OBJ 和LIB 的公司为了使用多个不同的编译器,不得不为每个不同的编译器分发这些库的不同版本(如果他们不这么做)。

PE 文件格式在winnt.h 头文件中文档化了(用最不精确的语言)!大约在winnt.h 的中间部分标题为"Image Format"的一个快。在把MS-DOS 的MZ 文件头和NE 文件头移入新的PE文件头之前,这个块就开始于一个小栏。WINNT.H提供PE文件用到的生鲜数据结构的定义,但只有很少有助于理解这些数据结构和标志变量的注释。不管谁为PE文件格式写出这样的头文件都肯定是一个信徒无疑(突然持续地冒出Michael J. O'Leary的名字来)。描述名字,连同深嵌的结构体和宏。当你配套winnt.h进行编码时,类似下面这样的表达式并不鲜见:

pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]

.VirtualAddress;

为了有助于逻辑的理解这些winnt.h中的信息,阅读可移植可执行和公共对象文件格式的规格说明,这些在MSDN既看光盘中是可用的,一直包括到2001年8月。

现在让我们转换到COFF格式的OBJ文件的主体上来,WINNT.H包括COFF OBJ和LIB的结构化定义和类型定义。不幸的是,我还没有找到上面提到的可执行文件格式的类似文档。既然PE文件和COFF OBJ文件是如此的相似,我决定是时间把这些文件带到重点上来,并且把它们也文档化。仅仅读过了关于PE 文件的组成,你自己也想Dump一些PE文件来看这些概念。如果你用微软基于32位WINDOWS的开发工具,DUMPBIN 程序可以将PE文件和COFF OBJ/LI B文件转化为可读的形式。在所有的PEDump器中,DUMPBIN是最容易理解的。它恰好有一些很好的选项来反汇编它正解析的文件的代码块,Borland用户可以使用tdump来浏览PE文件,但tdump不能解析COFF OBJ/LIB 文件。这不是一个重要的东西因为Borland的编译器首先就不生成COFF 格式的OBJ文件。

我写了一个PE和COFF OBJ 文件的Dump程序--PEDUMP,我想提供一些比DUMPBIN更加可理解的输出。虽然它没有反汇编器以及和LIB库文件一起工作,它在其他方面和DUMPBIN是一样的,并且加入了一些新的特性来使它值得被认同。它的源代码在任何一个MSJ电子公报版上都可以找到,所有我不打算在这里把他全部列出。作为代替,我展示一些从PEDUMP得到的示例输出来阐明我为它们描述的概念。

译注:--说实话,我从这这份代码中几乎唯一学到的东西就是"如何处理命令行",其它的都没学到。

表 1 PEDUMP.C

file://--------------------/

// PROGRAM: PEDUMP

// FILE: PEDUMP.C

// AUTHOR: Matt Pietrek - 1993

file://--------------------/

#include

#include

#include "objdump.h"

#include "exedump.h"

#include "extrnvar.h"

// Global variables set here, and used in EXEDUMP.C and OBJDUMP.C

BOOL fShowRelocations = FALSE;

BOOL fShowRawSectionData = FALSE;

BOOL fShowSymbolTable = FALSE;

BOOL fShowLineNumbers = FALSE;

char HelpText[] =

"PEDUMP - Win32/COFF .EXE/.OBJ file dumper - 1993 Matt Pietrek\n\n"

"Syntax: PEDUMP [switches] filename\n\n"

" /A include everything in dump\n"

" /H include hex dump of sections\n"

" /L include line number information\n"

" /R show base relocations\n"

" /S show symbol table\n";

// Open up a file, memory map it, and call the appropriate dumping routine

void DumpFile(LPSTR filename)

HANDLE hFile;

HANDLE hFileMapping;

LPVOID lpFileBase;

PIMAGE_DOS_HEADER dosHeader;

hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,

OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

if ( hFile = = INVALID_HANDLE_VALUE )

{ printf("Couldn't open file with CreateFile()\n");

return; }

hFileMapping = CreateFileMapping(hFile, NULL,

PAGE_READONLY, 0, 0, NULL);

if ( hFileMapping = = 0 )

{

CloseHandle(hFile);

printf("Couldn't open file mapping with CreateFileMapping()\n");

return;

lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); if ( lpFileBase = = 0 )

CloseHandle(hFileMapping);

CloseHandle(hFile);

printf("Couldn't map view of file with MapViewOfFile()\n");

return;

printf("Dump of file %s\n\n", filename);

dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;

if ( dosHeader->e_magic = = IMAGE_DOS_SIGNATURE )

{ DumpExeFile( dosHeader ); }

else if ( (dosHeader->e_magic = = 0x014C) // Does it look like a i386 && (dosHeader->e_sp = = 0) ) // COFF OBJ file???

// The two tests above aren't what they look like. They're

// really checking for IMAGE_FILE_HEADER.Machine = = i386 (0x14C) // and IMAGE_FILE_HEADER.SizeOfOptionalHeader = = 0; DumpObjFile( (PIMAGE_FILE_HEADER)lpFileBase );

else

printf("unrecognized file format\n");

UnmapViewOfFile(lpFileBase);

CloseHandle(hFileMapping);

CloseHandle(hFile);

// process all the command line arguments and return a pointer to

// the filename argument.

PSTR ProcessCommandLine(int argc, char *argv[])

int i;

for ( i=1; i < argc; i++ )

strupr(argv);

// Is it a switch character?

if ( (argv[0] = = '-') || (argv[0] = = '/') )

if ( argv[1] = = 'A' )

{ fShowRelocations = TRUE;

fShowRawSectionData = TRUE;

fShowSymbolTable = TRUE;

fShowLineNumbers = TRUE; }

else if ( argv[1] = = 'H' )

fShowRawSectionData = TRUE;

else if ( argv[1] = = 'L' )

fShowLineNumbers = TRUE;

else if ( argv[1] = = 'R' )

fShowRelocations = TRUE;

else if ( argv[1] = = 'S' )

fShowSymbolTable = TRUE;

else // Not a switch character. Must be the filename

{ return argv; }

int main(int argc, char *argv[])

PSTR filename;

if ( argc = = 1 )

{ printf( HelpText );

return 1; }

filename = ProcessCommandLine(argc, argv);

if ( filename )

DumpFile( filename );

return 0;

}

1 WIN3

2 与PE 基本概念

让我们复习一下几个透过PE文件的设计了解到的基本概念。我用术语"MODULE"来表示一个可执行文件或一个DLL载入内存的代码(CODE)、数据(DA TA)、资源(RESOURCES),除了代码和数据是你的程序直接使用的,一个模块还可以由WINDOWS用来确定数据和代码载入的位置的支撑数据结构组成。在16位WINDOWS中,这些支撑数据结构在模块数据库(用一个HMODULE来指示的段)中。在WIN32里面,这些数据结构在PE文件头中,这些我将会简要地解释一下。

PE文件略图

关于PE文件最重要的是,磁盘上的可执行文件和它被WINDOWS调入内存之后是非常相像的。WINDOWS载入器不必为从磁盘上载入一个文件而辛辛苦苦创建一个进程。载入器使用内存映射文件机制来把文件中相似的块映射到虚拟空间中。用一个构造式的分析模型,一个PE文件类似一个预制的屋子。它本质上开始于这样一个空间,这个空间后面有几个把它连到其余空间的机件(就是说,把它联系到它的DLL上,等等)。这对PE格式的DLL是一样容易应用的。一旦这个模块被载入,Windows 就可以有效的把它和其它内存映射文件同等对待。

和16位Windows不同的是。16位NE文件的载入器读取文件的一部分并且创建完全不同的数据结构在内存中表示模块。当数据段或者代码段需要载入时,载入器必须从全局堆中新申请一个段,从可执行文件中找出生鲜数据,转到这个位置,读入这些生鲜数据,并且要进行适当的修正。除此而外,每个16位模块都有责任记住当前它使用的所有段选择器,而不管这个段是否被丢弃了,如此等等。

对Win32来讲,模块所使用的所有代码,数据,资源,导入表,和其它需要的模块数据结构都在一个连续的内存块中。在这种形势下,你只需要知道载入器把可执行文件映射到了什么地方。通过作为映像的一部分的指针,你可以很容易的找到这个模块所有不同的块。

另一个你需要知道的概念是相对虚拟地址(RVA)。PE文件中的许多域都用术语RVA来指定。一个RVA只是一些项目相对于文件映射到内存的偏移。比如说,载入器把一个文件映射到虚拟地址0x10000开始的内存块。如果一个映像中的实际的表的首址是0x10464,那么它的RVA就是0x464。

(虚拟地址0x10464)-(基地址0x10000)=RVA 0x00464

为了把一个RVA转化成一个有用的指针,只需要把RVA值加到模块的基地址上即可。基地址是内存映射EXE和DLL文件的首址,在Win32中这是一个很重要的概念。为了方便起见,WindowsNT 和Windows9x用模块的基地址作为这个模块的实例句柄(HINSTANCE)。在Win32中,把模块的基地址叫做HINS TANCE可能导致混淆,因为术语"实例句柄"来自16位Windows。一个程序在16位Windows中的每个拷贝得到它自己分开的数据段(和一个联系起来的全局句柄)来把它和这个程序其它的拷贝分别开来,就形成了术语"实例句柄"。在Win32中,每个程序不必和其它程序区别开来,因为他们不共享相同的地址空间。术语INSTANCE仍然保持16位windows和32位Windows之间的连续性。在Win32中重要的是你可以对任何DLL调用GetModuleHandle()得到一个指针去访问它的组件(译注)。

译注:如果dllname 为NULL,则得到执行体自己的模块句柄。这是非常有用的,如通常编译器产生的启动代码将取得这个句柄并将它作为一个参数hInst ance传给WinMain !

你最终需要理解的PE文件的概念是"块(Section)"。PE文件中的一个块和NE文件中的一个段或者资源等价。块可以包含代码或者数据。和段不同的是,块是内存中连续的空间,而没有尺寸限制。当你的连接器和库为你建立,并且包含对操作系统非常重要的信息的其它的数据块时,这些块包含你的程序直接声明和使用的代码或数据。在一些PE格式的描述中,块也叫做对象。术语对象有如此多的涵义,以至于只能把代码和数据叫做"块"。

2 PE首部

和其它可执行文件格式一样,PE文件在众所周知的地方有一些定义文件其余部分面貌的域。首部就包含这样象代码和数据的位置和尺寸的地方,操作系统要对它进行干预,比如初始堆栈大小,和其它重要的块的信息,我将要简短的介绍一下。和微软其它可执行格式相比,主要的首部不是在文件的最开始。典型的PE 文件最开始的数百个字节被DOS残留部分占用。这个残留部分是一个可以打印如"这个程序不能在DOS下运行!"这类信息的小程序。所以,你在一个不支持Wi n32的系统中运行这个程序,便可以得到这类错误信息。当载入器把一个Win32程序映射到内存,这个映射文件的第一个字节对应于DOS残留部分的第一个字节。那是无疑的。和你启动的任一个基于Win32 的程序一起,都有一个基于DOS的程序连带被载入。

和微软的其它可执行格式一样,你可以通过查找它的起始偏移来得到真实首部,这个偏移放在DOS残留首部中。WINNT.H头文件包含了DOS残留程序的数据结构定义,使得很容易找到PE首部的起始位置。e_lfanew 域是PE真实首部的偏移。为了得到PE首部在内存中的指针,只需要把这个值加到映像的基址上即可。

file://忽/略类型转化和指针转化...

pNTHeader = dosHeader + dosHeader->e_lfanew;

一旦你有了PE主首部的指针,游戏就可以开始了!PE主首部是一个IMAGE_NT_HEADERS的结构,在WINNT.H中定义。这个结构由一个双字(DWORD)和两个子结构组成,布局如下:

DWORD Signature;

IMAGE_FILE_HEADER FileHeader;

IMAGE_OPTIONAL_HEADER OptionalHeader;

标志域用ASCII表示就是"PE"。如果在DOS首部中用了e_lfanew域,你得到一个NE标志而不是PE,那么这是16位NE文件。同样的,在标志域中的LE 表示这是一个Windows3.x 的虚拟设备驱动程序(VxD)。LX表示这个文件是OS/2 2.0文件。

PE DWORD标志后的是结构IMAGE_FILE_HEADER 。这个域只包含这个文件最基本的信息。这个结构表现为并未从它的原始COFF实现更改过。除了是PE首部的一部分,它还表现在微软Win32编译器生成的COFF OBJ 文件的最开始部分。IMAGE_FILE_HEADER的这个域显示在下面:表2 IMAGE_FILE_HEADER Fields

WORD Machine

表示CPU的类型,下面定义了一些CPU的ID

0x14d Intel i860

0x14c Intel I386 (same ID used for 486 and 586)

0x162 MIPS R3000

0x166 MIPS R4000

0x183 DEC Alpha AXP

WORD NumberOfSections

这个文件中的块数目。

DWORD TimeDateStamp

连接器产生这个文件的日期(对OBJ文件是编译器),这个域保存的数是从1969年12月下午4:00开始到现在经过的秒数。

DWORD PointerToSymbolTable

COFF符号表的文件偏移量。这个域只用于有COFF调试信息的OBJ文件和PE文件,PE文件支持多种调试信息格式,所以调试器应该指向数据目录的IM AGE_DIRECTORY_ENTRY_DEBUG条目。

DWORD NumberOfSymbols

COFF符号表的符号数目。见上面。

WORD SizeOfOptionalHeader

这个结构后面的可选首部的尺寸。在OBJ文件中,这个域是0。在可执行文件中,这是跟在这个结构后的IMAGE_OPTIONAL_HEADER结构的尺寸。

WORD Characteristics

关于这个文件信息的标志。一些重要的域如下:

0x0001 这个文件中没有重定位信息

0x0002 可执行文件映像(不是OBJ或LIB文件)

0x2000 文件是动态连接库,而非程序

其它域定义在WINNT.H中。

PE首部的第三个组成部分是一个IMAGE_OPTIONAL_HEADER型的结构。对PE文件,这一部分当然不是"可选的"。COFF格式允许单独实现来定义一个超出标准IMAGE_FILE_HEADER附加信息的结构。IMAGE_OPTIONAL_HEADER里面的域是PE的实现者感到超出IMAGE_FILE_HEADER基本信息以外非常关键的信息。

并非IMAGE_OPTIONAL_HEADER 的所有域都是重要的(见图4)。比较重要,需要知道的是ImageBase 和SubSystem 域。你可以忽略其它域的描述。

表3 IMAGE_FILE_HEADER 的域:

WORD Magic

表现为一些类别的标志字,通常是0X010B 。

BYTE MajorLinkerVersion

BYTE MinorLinkerVersion

生成这个文件的连接器的版本。这个数字以十进制显示比用十六进制好。一个典型的连接器版本是2.23。

DWORD SizeOfCode

所有代码块的进位尺寸。通常大多数文件只有一个代码块,所以这个域和.TEXT 块匹配。

DWORD SizeOfInitializedData

已初始化的数据组成的块的大小(不包括代码段)。然而,和它在文件中的表现形式并不一致。

DWORD SizeOfUninitializedData

载入器在虚拟内存中申请空间,但在磁盘上的文件中并不占用空间的块的尺寸。这些块在程序启动时不需要指定初值,因此术语名就是"未初始化的数据"。未初始化的数据通常在一个名叫.bss 的块中。

DWORD AddressOfEntryPoint

载入器开始执行这个程序的地址,即这个PE文件的入口地址。这是一个RVA,通常在.text 块中。

DWORD BaseOfCode

代码块起始地址的RVA 。在内存中,代码块通常在PE首部之后,数据块之前。在微软的连接器产生的EXE文件中,这个值通常是0x1000 。Borland 的连接器TLINK32 也一样,把映像第一个代码块的RVA和映像基址相加,填入这个域。

译注:这个域好像一直没有什么用

DWORD BaseOfData

数据块起始地址的RVA 。在内存中,数据块经常在最后,在PE首部和代码块之后。

译注:这个域好像也一直没有什么用

DWORD ImageBase

连接器创建一个可执行文件时,它假定这个文件被映射到内存中的一个指定的地方,这个地址就存在这个域中,假定一个载入地址可以使连接器优化以便节省空间。如果载入器真的把这个文件映射到了这个地方,在运行之前代码不需要任何改变。在为WindowsNT 创建的可执行文件中,默认的ImageBase 是0x10 000。对DLL,默认是0x40000。在Window95中,地址0x10000不能用来载入32位EXE文件,因为这个区域在一个被所有进程共享的线性地址空间中。因此,微软把Win32可执行文件的默认基址改为0x40000,假定基址为0x10000 的老程序坐在Windows95 中需要更长的载入时间,这是因为载入器需要重定位基址。

译注:这个域即"Prefered Load Address",如果没有什么意外,这就是该PE文件载入内存后的地址。

DWORD SectionAlignment

映射到内存中时,每个块都必须保证开始于这个值的整数倍。为了分页的目的,默认的SectionAlignment 是0x1000。

DWORD FileAlignment

在PE文件中,组成每个块的生鲜数据必须保证开始于这个值的整数倍。默认值是0x200 字节,也许是为了保证块都开始于一个磁盘扇区(一个扇区通常是512 字节)。这个域和NE文件中的段/资源对齐(segment/resource alignment)尺寸是等价的。和NE文件不同的是,PE文件通常没有数百个的块,所以,为了对齐而浪费的通常空间很少。

WORD MajorOperatingSystemVersion

WORD MinorOperatingSystemVersion

这个程序运行需要的操作系统的最小版本号。这个域有点含糊,因为Subsystem 域(后面将会说到)可以提供类似的功能。这个域在到目前为止的Win32

中默认是1.0。

WORD MajorImageVersion

WORD MinorImageVersion

一个可由用户定义的域。这允许你有不同的EXE和DLL版本。你可以通过链接器的/version 选项设置这个域的值。例如:"link /version:2.0 myobj.obj"。

WORD MajorSubsystemVersion

WORD MinorSubsystemVersion

这个程序运行需要的最小子系统版本号。这个域的一个典型值是3.10 (表示WindowsNT 3.1)。

DWORD Reserved1

通常是0 。

DWORD SizeOfImage

载入器必须关心的这个映像所有部分的大小总和。是从映像的开始到最后一个块结尾这段区域的大小。最后一个块结尾按SectionAlignment进位。

译注:这个很重要,可以大,但不可以小!

DWORD SizeOfHeaders

PE首部和块表的大小。块的实际数据紧跟在所有首部组件之后。

DWORD CheckSum

这个文件的CRC校验和。在微软可执行格式中,这个域被忽略并且置为0 。这个规则的一个例外情况是信任服务,这类EXE文件必须有一个合法的校验和。

WORD Subsystem

可执行文件的用户界面使用的子系统类型。WINNT.H 定义了下面这些值:

NATIVE 1 不需要子系统(比如设备驱动)

WINDOWS_GUI 2 在Windows图形用户界面子系统下运行

WINDOWS_CUI 3 在Windows字符子系统下运行(控制台程序)

OS2_CUI 5 在OS/2字符子系统下运行(仅对OS/2 1.x)

POSIX_CUI 7 在Posix 字符子系统下运行

WORD DllCharacteristics

指定在何种环境下一个DLL的初始化函数(比如DllMain)将被调用的标志变量。这个值经常被置为0 。但是操作系统在下面四种情况下仍然调用DLL的初始化函数。

下面的值定义为:

1 DLL第一次载入到进程中的地址空间中时调用

2 一个线程结束时调用

4 一个线程开始时调用

8 退出DLL时调用

DWORD SizeOfStackReserve

为初始线程保留的虚拟内存总数。然而并不是所有这些内存都被提交(见下一个域)。这个域的默认值是0x100000(1Mbytes)。如果你在CreateThread 中把堆栈尺寸指定为0 ,结果将是用这个相同的值(0x10000)。

DWORD SizeOfStackCommit

开始提交的初始线程堆栈总数。对微软的连接器,这个域默认是0x1000字节(一页),TLINK32 是两页。

DWORD SizeOfHeapReserve

为初始进程的堆保留的虚拟内存总数。这个堆的句柄可以用GetPocessHeap 得到。并不是所有这些内存都被提交(见下一个域)。

DWORD SizeOfHeapCommit

开始为进程堆提交的内存总数。默认是一页。

PE文件格式

1.PE文件的含义

PE文件的意思是Portable Executable(可移植,可执行),它是win32可执行文件的标准格式.它的一些特性继承unix的COFF文件格式,同时保留了与旧版MS-DOS和WINDOWS的兼容.其可移植可执行意味着是跨win32平台的.

2.PE文件的层次结构

PE文件最前面紧随DOS MZ文件头的是一个DOS可执行文件(Stub).这使得PE文件成为一个合法的MS-DOS可执行文件.DOS MZ文件头后面是一个32位的PE文件标志0x50450000(IMAGE_NT_SIGNATURE),即PE00.接下来的是PE的映像文件头,包含的信息有该程序的运行平台,有多少个节,文件链接的时间,

文件的命名格式.后面还紧跟一个可选映像头,包含PE文件的逻辑分布信息,程序加载信息,开始地址,保留的堆栈数量,数据段大小等.可选头还有一个重要的域,称为:数据目录表"的数组,表的每一项都是指向某一节的指针.可选映像头后面紧跟的是节表和节.节通过节表来实现索引.实际上,节的内容才是真正执行的数据和程序.每一个节都有相关的标志.每一个节会被一个或多个目录表指向,目录表可通过可选头的"数据目录表"的入口找到.就像输出函数表或基址重定位表.也存在没有目录表指向的节.

3.PE文件层次解释

A.DOS STUB和DOS头

DOS插桩程序在大多数情况下由汇编器/编译器自动产生.通常它调用INT 21H服务9来显示上述字符串.可以通过IMAGE_DOS_HEADER结构来识别一个合法的DOS头.这个结构的头两个字节肯定是"MZ".可通过该结构的e_lfanew成员来找到PE文件的开始标志.MS-DOS头部占据了PE文件的头64个字节.在微软的WINNT.H中可以找到其内容结构的描述.

B.PE文件头

在DOS STUB后是PE文件头(PE header).PE文件头是PE相关结构IMGAE_NT_HEADERS的简称,即NT映像头,存放PE整个文件信息发布的重要字段,包含了PE装载器用到的重要域.执行体在操作系统中执行时,PE装载器将从DOS MZ头中找到PE头文件的起始偏移量e_lfanew,从而跳过DOS STUB直接定位真正的PE文件.它由3部分组成:

(1)PE文件标志(4H字节)

PE文件标志0x50450000即PE00,标志着NT映像头的开始,也是PE文件中与windows有关内容的开始.

(2)映像文件(14H字节)

是NT映像文件的主要部分,包含PE文件的基本信息

(3)可选映像头

包含PE文件的逻辑分布信息.

C.节表

节表其实是紧跟NT映像文件的一个结构数组.其成员数目由映像文件头结构NumberOFSectios域的值来决定.

D.节

PE文件的真正内容划分为块,称之为节.节的划分基于各组数据的共同属性.惟有节的属性设置决定了节的特性和功能.典型的windows NT应用程序可以具有9个节:.texr,.bss.rdata,.data,.rsrc,edata,idata,pdata,.debug

判断一个文件是否为PE文件

function TForm1.is_PE(FileName: string): boolean;

var //检测指定文件是否有效PE文件

PEDosHead: TImageDosHeader;

PENTHead: TImageNtHeaders;

m_file: integer;

begin

Result := False;

m_file := FileOpen(filename, fmOpenRead or fmShareDenyNone); //只读和其它任意

if m_File > 0 then

try

FileSeek(m_file, 0, soFromBeginning); //将指针挪至文件头

FileRead(m_file, PEDosHead, SizeOf(PEDosHead)); //读PEDosHead结构

FileSeek(m_file, PEDosHead._lfanew, soFromBeginning); //将指针挪至_lfanew

FileRead(m_file, PENTHead, SizeOf(PENTHead)); //读PENTHead结构

finally

FileClose(m_file);

end;

if (PENTHead.Signature = IMAGE_NT_SIGNATURE) then //检验文件头部第一个字的值是否等于IMAGE_DOS_SIGNATURE

Result := True;

end;

pe文件结构图

pe文件格式

PE文件格式详解(一)――基础知识 什么是PE文件格式: 我们知道所有文件都是一些连续(当然实际存储在磁盘上的时候不一定是连续的)的数据组织起来的,不同类型的文件肯定组织形式也各不相同;PE文件格式便是一种文件组织形式,它是32位Wind ow系统中的可执行文件EXE以及动态连接库文件DLL的组织形式。为什么我们双击一个EXE文件之后它就会被Window运行,而我们双击一个DOC文件就会被Word打开并显示其中的内容;这说明文件中肯定除了存在那些文件的主体内容(比如EXE文件中的代码,数据等,DOC文件中的文件内容等)之外还存在其他一些重要的信息。这些信息是给文件的使用者看的,比如说EXE文件的使用者就是Window,而DOC文件的使用者就是Word。Window可以根据这些信息知道把文件加载到地址空间的那个位置,知道从哪个地址开始执行;加载到内存后如何修正一些指令中的地址等等。那么PE文件中的这些重要信息都是由谁加入的呢?是由编译器和连接器完成的,针对不同的编译器和连接器通常会提供不同的选项让我们在编译和 联结生成PE文件的时候对其中的那些Window需要的信息进行设定;当然也可以按照默认的方式编译连接生成Window中默认的信息。例如:WindowNT默认的程序加载基址是0x40000;你可以在用VC连接生成EXE文件的时候使用选项更改这个地址值。在不同的操作系统中可执行文件的格式是不同的,比如在Linux上就有一种流行的ELF格式;当然它是由在Linux上的编译器和连接器生成的,

所以编译器、连接器是针对不同的CPU架构和不同的操作系统而涉及出来的。在嵌入式领域中我们经常提到交叉编译器一词,它的作用就是在一种平台下编译出能在另一个平台下运行的程序;例如,我们可以使用交叉编译器在跑Linux的X86机器上编译出能在Arm上运行的程序。 程序是如何运行起来的: 一个程序从编写出来到运行一共需要那些工具,他们都对程序作了些什么呢?里面都涉及哪些知识需要学习呢?先说工具:编辑器-》编译器-》连接器-》加载器;首先我们使用编辑器编辑源文件;然后使用编译器编译程目标文件OBJ,这里面涉及到编译原理的知识;连接器把OBJ文件和其他一些库文件和资源文件连接起来生成EXE文件,这里面涉及到不同的连接器的知识,连接器根据OS的需要生成EXE文件保存着磁盘上;当我们运行EXE文件的时候有W indow的加载器负责把EXE文件加载到线性地址空间,加载的时候便是根据上一节中说到的PE文件格式中的哪些重要信息。然后生成一个进程,如果进程中涉及到多个线程还要生成一个主线程;此后进程便开始运行;这里面涉及的东西很多,包括:PE文件格式的内容;内存管理(CPU内存管理的硬件环境以及在此基础上的OS内存管理方式);模块,进程,线程的知识;只有把这些都弄清楚之后才能比较清楚的了解这整个过程。下面就让我们先来学习PE文件格式吧。

PE格式基础及程序的装入

DOS MZ header部分是DOS时代遗留的产物,是PE文件的一个遗传基因,一个Win32程序如果在DOS下也是可以执行,只是提示:“This program cannot be run in DOS mode.”然后就结束执行,提示执行者,这个程序要在Win32系统下执行。 DOS stub 部分是DOS插桩代码,是DOS下的16位程序代码,只是为了显示上面的提示数据。这段代码是编译器在程序编译过程中自动添加的。 PE header 是真正的Win32程序的格式头部,其中包括了PE格式的各种信息,指导系统如何装载和执行此程序代码。 Section table部分是PE代码和数据的结构数据,指示装载系统代码段在哪里,数据段在哪里等。对于不同的PE文件,设计者可能要求该文件包括不同的数据的Section。所以有一个Section Table 作为索引。Section多少可以根据实际情况而不同。但至少要有一个Section。如果一个程序连代码都没有,那么他也不能称为可执行代码。在Section Table后,Section数目的多少是不定的。 二、程序的装入 当我们在explorer.exe(资源管理器)中双击某文件,执行一个可执行程序,系统会根据文件扩展名启动一个程序装载器,称之为Loader。Loader会首先检查DOS MZ Header,如果存在,就继续寻找PE header,如果这两项都不存在,就认为是DOS 16位代码,如果只存在DOS MZ Header,而其中又指示了而其中又指示了PE Header 的位置,那么Loader 就判定此文件不一个有效的PE文件,拒绝执行。 如果DOS Header 和PE Header都正常有效,那么Loader就会根据PE Header 及Section Table的指示,将相应的代码和数据映射到内存中,然后根据不同的Section进行数据的初始化,最后开始执行程序段代码。 三、PE格式高级分析 下面我们以一个真实的程序为例详细分析PE格式,分析PE格式最好有PE分析器,常用的软件是Lord PE,也有其它的分析工具和软件如PE Editor 、Stud PE等。 先分析一下磁盘文件的内容,这里我们使用UltraEdit32(UE)工具,这是一个实用的文件编辑器,可以编辑文本和二进制文件。

PE文件头解析大全

PE可选头部 PE可执行文件中接下来的224个字节组成了PE可选头部。虽然它的名字是“可选头部”,但是请确信:这个头部并非“可选”,而是“必需”的。OPTHDROFFSET宏可以获得指向可选头部的指针: PEFILE.H #define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \ ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ SIZE_OF_NT_SIGNATURE + \ sizeof(IMAGE_FILE_HEADER))) 可选头部包含了很多关于可执行映像的重要信息,例如初始的堆栈大小、程序入口点的位置、首选基地址、操作系统版本、段对齐的信息等等。IMAGE_OPTIONAL_HEADER结构如下: WINNT.H typedef struct _IMAGE_OPTIONAL_HEADER { // // 标准域 // USHORT Magic; UCHAR MajorLinkerVersion; UCHAR MinorLinkerVersion; ULONG SizeOfCode; ULONG SizeOfInitializedData; ULONG SizeOfUninitializedData; ULONG AddressOfEntryPoint; ULONG BaseOfCode; ULONG BaseOfData; // // NT附加域 // ULONG ImageBase; ULONG SectionAlignment;

ULONG FileAlignment; USHORT MajorOperatingSystemVersion; USHORT MinorOperatingSystemVersion; USHORT MajorImageVersion; USHORT MinorImageVersion; USHORT MajorSubsystemVersion; USHORT MinorSubsystemVersion; ULONG Reserved1; ULONG SizeOfImage; ULONG SizeOfHeaders; ULONG CheckSum; USHORT Subsystem; USHORT DllCharacteristics; ULONG SizeOfStackReserve; ULONG SizeOfStackCommit; ULONG SizeOfHeapReserve; ULONG SizeOfHeapCommit; ULONG LoaderFlags; ULONG NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; 如你所见,这个结构中所列出的域实在是冗长得过分。为了不让你对所有这些域感到厌烦,我会仅仅讨论有用的——就是说,对于探究PE文件格式而言有用的。 标准域 首先,请注意这个结构被划分为“标准域”和“NT附加域”。所谓标准域,就是和UNIX可执行文件的COFF 格式所公共的部分。虽然标准域保留了COFF中定义的名字,但是Windows NT仍然将它们用作了不同的目的——尽管换个名字更好一些。 ·Magic。我不知道这个域是干什么的,对于示例程序EXEVIEW.EXE示例程序而言,这个值是0x010B

PE文件结构

检验PE文件的有效性 <1>首先检验文件头部第一个字的值是否等于IMAGE_DOS_SIGNATURE,是则表示DOS MZ header有效 <2>一旦证明文件的Dos header 有效后,就可用e_lfanew来定位PE header <3>比较PE header 的第一个字的值是否等于IMAGE_NT_HEADER,如果前后两个值都匹配. PS.WinHex使用方法 1.Alt+G跳到指定位置 2.Ctrl+Shift+N放入新文件 3.大文件扩容,新建一个扩容大小+1的文件,把这个文件的数据复制后写入整个文件的尾地址. 4.文本搜索ctrl+F 5.十六进制搜索ctrl+alt+x 6.文本显示F7 7.打开内存alt+F9 8.进制转换器F8 9.分析选块F2 10.计算HASH ctrl+F2 11.收集文本信息ctrl+F10 12.编辑模式F6 一.IMAGE_DOS_HEADER <1>位置00H,WORD(2个字节)的e_magic为4D5A,即MZ <2>位置3CH,60,LONG(4个节节)的e_lfanew为64+112=176即B0H, 二.IMAGE_NT_HEADERS <1>位置B0H,DWORD(4个字节),PE开始标记,写入50450000,即PE <2>位置B4H,WORD,PE所要求的CPU,对于Intel平台,为4C01 <2>位置B6,WORD,PE中段总数,计划有3个段,.text代码段,.rdata只读数据段,.data全局变量数据段,所以值为0300, <3>位置C4,WORD,表示后面的PE文件可选头的占空间大小,即224字节(E0),值为E000 <4>位置C6,WORD,表示文件是EXE还是DLL,如果是可执行文件写0200,如果是dll,写0020, <5>位置C8,WORD,表示文件格式,如果是0B01表示.exe,如果是0701表示ROM映像

手工构造典型PE文件

2009-06-08 11:38:40 https://www.wendangku.net/doc/3010797920.html, 来源:黑客防线 一直以来都在学习PE文件结构,从不敢轻视,但是即使如此还是发现自己在这方面有所不足,于是便想到了用纯手工方式打造一个完整的可执行的PE文件。在这期间我也查了大量资料,但是这些资料都有一个通病就是不... 一直以来都在学习PE文件结构,从不敢轻视,但是即使如此还是发现自己在这方面有所不足,于是便想到了用纯手工方式打造一个完整的可执行的PE文件。在这期间我也查了大量资料,但是这些资料都有一个通病就是不完整,看雪得那个只翻译了一部分,加解密技术内幕介绍的更是笼统,而且是打造一个只有180字节的PE文件,是高手们茶余饭后的怡情小游戏。 鉴于此,心想为什么不自己摸索着手工打造一个完整些的呢?一是加强一下自己对于PE文件的了解,二是写出一篇参考性比较强的文章,给有志于在此发展的朋友们铺一铺路,也算是干了一件利国利民的好事。 对于手工打造PE文件,我个人认为至少要分为三篇文章来阐述,每篇相对独立,合起来形成一个相对的体系。第一篇文章(也就是本文)用来介绍怎样用手工打造一个最典型、最简单的PE文件,而后两篇文章的问世还要引用潘爱民先生的一句话“还需要时日与机缘”。 本文介绍的PE文件手工编辑方式,是本着以下三个原则所写的,望读者注意: 1、完整性:对于手工打造PE文件所不需注意的字段也进行了必要的介绍,因此整文可能显得非常臃肿。 2、典型性:完全按照典型的PE文件结构构造,因此对于某些不常见的PE文件结构有一定差距。 3、易学性:对于字段之间的逻辑关系进行了比较细致的介绍,因此对于一部分底子比较好的读者来说可能显得有些啰嗦。 为了方便各位阅读与查阅,我将文章分成了三各部分,以便各位读者各取所需,不用把宝贵的精力浪费在查找上。 1、PE文件整体信息,提供了一个剖析PE文件的图表,以便于读者对于PE文件有一个整体的了解,并监督自己的工作进度。 2、对于重点字段的介绍,以及字段之间的逻辑关系,建议首先从这里开始看。 3、手工构造PE文件字段清单,此清单包含构造一个完整PE文件的每一个字节,跟着这个清单走就可以构造一个PE文件。 对于第一次手工打造PE文件的朋友们来说,你们可以以“一、整体性息”为大纲,并参考第三部分一块一块的慢慢打造,如果有不懂的地方就去看第二部分。 选读:为什么要手工打造PE文件? 我们知道,往往从一个系统可执行文件结构上,就可以看整个操作系统的一些特性。也就是说PE里有Windows操作系统结构与运行机理的影子。由此可见,PE文件必然是一个非常庞杂且逻辑复杂的结构,那么为什么我们还要“自取其辱”来手工制造一个PE文件呢?这就要从PE文件的重要性说起了。 我们现今组成Windows大家庭的主要成员就是PE文件了,里面包括EXE、DLL、OCX、SYS等一切最有价值的文件都是PE文件格式,出于对版权的考虑或对某种技术的渴求,任何一种与Windows系统相关的行为最终都要归集到这里--PE文件。 特别是对于想学习加壳、破解、搞虚拟机的朋友们来说,熟知PE文件结构更是必不可少的基本功! 但也正是由于PE文件的复杂性,我们才要采取一些特别的办法来攻克它,其中手工打造PE文件就是一条捷径。 你可以想像一下,如果你都可以手工打造PE文件的话,那么对于PE文件的了解更是

pe文件结构 入门 教程

三年前,我曾经写了一个手工打造可执行程序的文章,可是因为时间关系,我的那篇文章还是有很多模糊的地方,我一直惦记着什么时候再写一篇完美的,没想到一等就等了三年。因为各种原因直到三年后的今天我终于完成了它。现在把它分享给大家,希望大家批评指正。 我们这里将不依赖任何编译器,仅仅使用一个十六进制编辑器逐个字节的手工编写一个可执行程序。以这种方式讲解PE结构,通过这个过程读者可以学习PE结构中的PE头、节表以及导入表相关方面的知识。为了简单而又令所有学习程序开发的人感到亲切,我们将完成一个Hello World! 程序。功能仅仅是运行后弹出一个消息框,消息框的内容是Hello World!。 首先了解一下Win32可执行程序的大体结构,就是通常所说的PE结构。 如图1所示PE结构示意图: 图1 标准PE结构图 由图中可以看出PE结构分为几个部分: MS-DOS MZ 头部:所有PE文件必须以一个简单的DOS MZ 头开始。有了它,一旦程序在DOS下执行,DOS就能识别出这是有效的执行体,然后运行紧随MZ header 之后的DOS程序。以此达到对Dos系统的兼容。(通常情况DOS MZ header总共占用64byte)。 MS-DOS 实模式残余程序:实际上是个有效的EXE,在不支持PE文件格式的操作系统中,它将简单显

示一个错误提示,大多数情况下它是由汇编编译器自动生成。通常,它简单调用中断21h,服务9来显示字符串"This program cannot run in DOS mode"。(在我们写的程序中,他不是必须的,可以不予以实现,但是要保留其大小,大小为112byte,为了简洁,可以使用00来填充。) PE文件标志:是PE文件结构的起始标志。(长度4byte, Windows程序此值必须为0x50450000) PE文件头:是PE相关结构 IMAGE_NT_HEADERS 的简称,其中包含了许多PE装载器用到的重要域。执行体在支持PE文件结构的操作系统中执行时,PE装载器将从DOS MZ header中找到PE header的起始偏移量,跳过了MS-DOS 实模式残余程序,直接定位到真正的文件头PE header,长度20byte。 PE文件可选头:虽然它的名字是“可选头部”,但是请确信:这个头部并非“可选”,而是“必需”的。(长度 224byte )。 各段头部:又称节头部,一个Windows NT的应用程序典型地拥有9个预定义段(节),它们是“.text”、“.bss”、“.rdata”、“.data”、“.rsrc”、“.edata”、“.idata”、“.pdata”和“.debug”。一些应用程序不需要所有的这些段,同样还有些应用程序为了自己特殊的需要而定义了更多的段。(每个段头部占40byte,我们这里也不需要所有的段,仅需3个段。) 通常我们是将PE整个结构分成四个部分,把MS-DOS MZ 头部和MS-DOS 实模式残余程序作为第一部分,可以称他为DOS部分,而PE文件标志、PE文件头、PE文件可选头三个部分作为第二部分,称之为PE头部分,因为这部分才是Windows下真正需要的部分,所以从PE文件标志开始才是真正的PE部分。各段头部是第三部分,称之为节表。它详细描述了PE文件中各个节的详细信息。最后就是各个节的实体部分了,称为节数据。 以上仅仅是对PE结构各部分的大体讲解。接下来再手写这个Hello World!程序过程中,我将详细介绍每个部分的含义。 首先准备一下工具,一个十六进制编辑器足以。我们这里使用VC++ 6.0所携带的十六进制编辑器,您也可以使用如WinHex等十六进制编辑工具。 打开VC,选择文件,新建菜单项,然后选择一个二进制文件,单击确定。一切就绪了,下面就开始手写可执行程序,如图2所示:

pe文件格式

pe文件格式:PE文件格式(1) 疯狂代码 https://www.wendangku.net/doc/3010797920.html,/ ?:http:/https://www.wendangku.net/doc/3010797920.html,/Waigua/Article60255.html 介绍说明:希望本文能够对初级入门CRACKER有定帮助翻译存在疏漏或者不准确希望来信指出感谢您指导!感谢看雪为我们提供这个交流平台让我们技术和时俱进!! 前言: PE("portableexecutable")文件格式是针对MSwindowsNT,windows95and win32s可执行 2进制代码(DLLsandprograms)在windowsNT内,驱动也是这个格式也可以用于对象文件和库 这个格式是Microsoft设计并在1993经过TIS(toolerfacestandard)委员会 (Microsoft,Intel,Borland,Watcom,IBM等)标准化了它基于在UNIX和VMS上运行对象文件和可执行文件COFF"commonobjectfileformat"格式 win32SDK包括个头文件包括对PE格式定义我将提及成员名和定义你也可能发现DLL文件"imagehelp.dll"非常有用它是NT部分但文档很少它些在"DeveloperNetwork"被描述 总览: 在PE文件开始我们可以发现MSDOS执行部分("stub");这使得任何个PE文件是有效DOS执行文件在DOS-stub的后是32位魔数0x00004550(IMAGE_NT_SIGNATURE).然后是个COFF格式文件头指明在何种机器上运行多少个节在里面连接时间是否是可执行文件或者DLL等DLL和可执行文件区别:DLL不能够启动只可以被其他可执行文件使用个可执行文件不能够连接到另个可执行文件 接着我们看到个可选文件头optionalheader(虽然叫“可选”它实际上直存在) COFF把可选文件头用于库不用于目标文件这里告诉我们文件如何被调入:起始地址预留堆栈数数据段尺寸 个有趣部分是尾巴上数据目录datadirectories这些目录包含指向节内数据指针例如如果文件有输出目录可以在成员IMAGE_DIRECTORY_ENTRY_EXPORT内发现个指针指向那个目录(目录描述结构->THUNKDATA结构->BYNAME结构)他将指向个节 在头后面是节头实际上节内容就是真正需要运行个所需要东西所有头和目录成员就是帮你找到它每个节有几个标志:对齐包含数据类型(化数据等)是否可以共享等及数据自身多数节含有个或多个通过“可选头”内数据目录项引用目录没有目录类型内容是化数据或者可执行代码(节是物理意义上内容组织目录是逻辑意义上内容

实验1《 PE文件剖析实验》

《PE文件剖析实验》报告 学院:计算机学院 日期: 2016年 4 月 25 日

目录 1. 实验目的 (2) 2. 实验过程 (2) 3. 实现结果 (2) 4. 遇到的问题及感想收获 (5)

1. 实验目的 熟悉各种PE编辑查看工具,详细了解PE文件格式,为后续计算机病毒学习打下基础,学会分析PE文件文件头、引入表、引出表以及资源表。 2. 实验过程 PE文件被称为可移植的执行体,是Portable Execute的简称,常见的EXE、DLL、OCX、SYS、COM等文件都是PE文件。 本次实验将综合运用Peview和LordPE,自由选择一款EXE文件或DLL文件,对其展开分析,找出文件的PE标志,入口地址、基址,节表个数及列出节表、输出表、输入表等信息。 3. 实现结果 ●自由选择一款EXE文件或DLL文件,对其展开分析,各项结果截图如下:●文件的PE标志

●入口地址 ●基址 ●节表个数及列出节表

●输出表 ●输入表

4. 遇到的问题及感想收获 本次实验时对PE文件格式进行分析,对PE文件有了一个大致的了解,如什么是PE文件的文件头,什么是区段,什么是数据目录。由于现阶段大都的病毒都是PE病毒,所以了解它们可以更好地知道PE病毒是如何感染PE文件的。不仅如此,对PE文件的修改加壳等操作也证实了PE文件并不是不可编辑的,也可以让我们更好地了解PE文件的内部结构。 这次实验主要使用了LoadPE和Peview软件对PE文件进行查看,提高了我们对PE文件结构的认识,帮助了我们吸收理论课上所学的知识,如基址与相对虚拟地址及其查看方法,PE文件首部,区段的含义等。这对我们以后的学习有很大的帮助,达到了预期的实验目的。 通过本次课程设计,我深刻认识到要掌握知识,不仅仅是要把书上的基本知识学好而且还要不断进行实践,将所学的跟实践操作结合起来才能更好地巩固所学,才能提高自己的实践能力。

PE结构4——区段与代码类型

甲壳虫免杀VIP教程 https://www.wendangku.net/doc/3010797920.html, 专业的免杀技术培训基地 我们的口号:绝对不一样的免杀教程!绝对不一样的实战体验!清晰的思路!细致全面的讲解!让你感到免杀原来可以这么简单! 动画教程只是起到技术交流作用.请大家不用利用此方法对国内的网络做破坏. 国人应该团结起来一致对外才是我们的责任.由此动画造成的任何后果和本站 无关. -------------------------------------------------------------------- 【免杀PE结构班】制作:Just41(carrieyz) 第四节【PE文件常见区段及其代码类型】 一、区段表的结构 PE文件格式中,所有的区段信息位于可选PE头之后。每个区段信息为40个字节长,并且没有任何填充信息。区段信息被定义为以下的结构: 学名:免杀技术说明大小LOADPE Name:区段名称,如".text" [8h] SizeOfRawData:RV A偏移大小[4h] VSize VirtualAddress:区段RV A起始地址[4h] VOffset PointerToRawData:区段物理偏移大小(偏移量)[4h] RSize PhysicalAddress:区段物理起始地址[4h] ROffset VirtualSize:真实长度[4h] PointerToRelocations:重定位的偏移[4h] PointerToLinenumbers:行号表的偏移[4h] NumberOfRelocations:重定位项数目[2h] NumberOfLinenumbers:行号表的数目[2h] Characteristics:区段属性[4h] 标志 计算方式: 区段表的文件偏移地址=PE头的文件偏移地址+14h+可选PE头大小+1 首先从0X3Ch处得到PE头的文件偏移地址,然后由PE头的文件偏移地址+14h得到可选PE头大小,再将上面三个数据相加再+1就得到区段表的文件偏移地址了。 VSize的大小只是效验下是否跨越下一个节了,或者是否超出了SizeOfImage,如果出现越界问题,提示非法32位应用程序,否则的话,它的值没有意义,节的大小不是由它决定的......对非最后一个节,按节间VOffset之差,最后一节用SizeOfImage-VOffset。

PE文件格式分析及修改

PE文件格式分析及修改(图) PE 的意思是 Portable Executable(可移植的执行体)。它是 Win32环境自身所带的执行文件格式。它的一些特性继承自Unix的Coff(common object file format)文件格式。“Portable Executable”(可移植的执行体)意味着此文件格式是跨Win32平台的;即使Windows运行在非Intel的CPU上,任何win32平台的PE装载器都能识别和使用该文件格式。 PE文件在文件系统中,与存贮在磁盘上的其它文件一样,都是二进制数据,对于操作系统来讲,可以认为是特定信息的一个载体,如果要让计算机系统执行某程序,则程序文件的载体必须符合某种特定的格式。要分析特定信息载体的格式,要求分析人员有数据分析、编码分析的能力。在Win32系统中,PE 文件可以认为.exe、.dll、.sys 、.scr类型的文件,这些文件在磁盘上存贮的格式都是有一定规律的。 一、PE格式基础 下表列出了PE的总体结构 一个完整的PE文件,前五项是必定要有的,如果缺少或者数据出错,系统会拒绝执行该文件如下图

DOS MZ header部分是DOS时代遗留的产物,是PE文件的一个遗传基因,一个Win32程序如果在DOS 下也是可以执行,只是提示:“This program cannot be run in DOS mode.”然后就结束执行,提示执行者,这个程序要在Win32系统下执行。 DOS stub 部分是DOS插桩代码,是DOS下的16位程序代码,只是为了显示上面的提示数据。这段代码是编译器在程序编译过程中自动添加的。 PE header 是真正的Win32程序的格式头部,其中包括了PE格式的各种信息,指导系统如何装载和执行此程序代码。 Section table部分是PE代码和数据的结构数据,指示装载系统代码段在哪里,数据段在哪里等。对于不同的PE文件,设计者可能要求该文件包括不同的数据的Section。所以有一个Section Table 作为索引。Section多少可以根据实际情况而不同。但至少要有一个Section。如果一个程序连代码都没有,那么他也不能称为可执行代码。在Section Table后,Section数目的多少是不定的。 二、程序的装入 当我们在explorer.exe(资源管理器)中双击某文件,执行一个可执行程序,系统会根据文件扩展名启动一个程序装载器,称之为Loader。Loader会首先检查DOS MZ Header,如果存在,就继续寻找PE header,如果这两项都不存在,就认为是DOS 16位代码,如果只存在DOS MZ Header,而其中又指示

【翻译】“PE文件格式”1.9版 完整译文(附注释)

标题:【翻译】“PE文件格式”1.9版完整译文(附注释) 作者:ah007 时间: 2006-02-28,13:32:12 链接: https://www.wendangku.net/doc/3010797920.html,/showthread.php?t=21932 $Id: pe.txt,v 1.9 1999/03/20 23:55:09 LUEVELSMEYER Exp $ PE文件格式系列译文之一---- 【翻译】“PE文件格式”1.9版完整译文(附注释) ========================================================= 原著:Bernd. Luevelsmeyer 翻译:ah007 [注意:本译文的所有大小标题序号都是译者添加,以方便大家阅读。圆圈内的数字是注释的编号,其中注释②译自微软的《PECOFF规范》,其它译自网络。----译者] 一、前言(Preface) ------------------ PE(“portable executable”,可移植的可执行文件)文件格式,是微软WindwosNT,Windows95和Win32子集①中的可执行的二进制文件的格式;在WindowsNT中,驱动程序也是这种格式。它还能被应用于各种目标文件②和库文件中。 这种文件格式是由微软设计的,并于1993年被TIS(tool interface standard,工具接口标准)委员会(由Microsoft,Intel,Borland,Watcom,IBM,等等组成)所批准,它明显的基于COFF文件格式的许多知识。COFF (“common object file fromat”,通用目标文件格式)是应用于好几种UNIX系统③和VMS④系统中的目标文件和可执行文件的格式。 Win32 SDK⑤中包含一个名叫的头文件,其中含有很多用于PE格式的#define和typedef定义。我将逐步地提到其中的很多结构成员名字和#define定义。 你也可能发现DLL文件“imagehelp.dll”很有用途,它是WindowNT的一部分,但其书面文件却很缺乏。它的一些功用在“Developer Network”(开发者网络)中有所描述。 二、总览(General Layout) ------------------------- 在一个PE文件的开始处,我们会看到一个MS-DOS可执行体(英语叫“stub”,意为“根,存根”);它使任何PE文件都是一个有效的MS-DOS可执行文件。 在DOS-根之后是一个32位的签名以及魔数0x00004550 (IMAGE_NT_SIGNATURE)(意为“NT签名”,也

PE文件结构与ELF文件结构

一、PE文件结构 PE文件被称为可移植的执行体是Portable Execute的全称,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(可能是间接被执行,如DLL),Portable 是指对于不同的Windows版本和不同的CPU类型上PE文件的格式是一样的,当然CPU不一样了,CPU指令的二进制编码是不一样的。只是文件中各种东西的布局是一样的。 在下面关于结构的定义中,WORD 表示变量大小为2个字节,DWORD表示变量大小是4个字节。 1.1 PE文件的结构 PE文件有着固定的结构,分为五个部分,如下: 1:DOS MZ Header(DOS文件头) 一个IMAGE_DOS_HEADER结构,大小为64字节。 2:DOS Stub(DOS加载模块) 没有固定大小。 3:PE Header(PE文件头)一个IMAGE_NT_HEADERS结构,大小为248字节。 4:Section Table(节表)一个IMAGE_SECTION_HEADER结构数组,数组大小依据节而定,如果PE文件有5个节,则数组大小为5。 5:Sections(节或段)没有固定大小,可以有多个节。 1.2 DOS文件头和DOS加载模块 PE文件的一二部分完全是为了程序能在DOS运行下时给出一个提示。 IMAGE_DOS_HEADER结构的定义如下: Typedef struct IMAGE_DOS_HEADER{ WORD e_magic; // 魔术数字 WORD e_cblp; // 文件最后页的字节数 WORD e_cp; // 文件页数 WORD e_crlc; // 重定义元素个数 WORD e_cparhdr; // 头部尺寸,以段落为单位 WORD e_minalloc; // 所需的最小附加段 WORD e_maxalloc; // 所需的最大附加段 WORD e_ss; // 初始的SS值(相对偏移量) WORD e_sp; // 初始的SP值 WORD e_csum; // 校验和 WORD e_ip; // 初始的IP值 WORD e_cs; // 初始的CS值(相对偏移量) WORD e_lfarlc; // 重分配表文件地址 WORD e_ovno; // 覆盖号 WORD e_res[4]; // 保留字 WORD e_oemid; // OEM标识符(相对e_oeminfo) WORD e_oeminfo; // OEM信息 WORD e_res2[10]; // 保留字 LONG e_lfanew; // 新exe头部的文件地址 } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

PE文件加密方法

对于一个软件开发商来说,要想了解PE文件加密处理的技术,第一步必须要研究PE文件格式,研究PE文件格式不但可以给我们洞悉Windows结构的良机,而且对于如何去保护自己开发的软件,有非常好的帮助,那么PE文件能否加密呢?下面我们就给大家介绍一下如何给PE文件加密。 一、什么是PE文件 PE文件的意思就是Portable Executable(可移植的执行体)。它是Win32环境自身所带的执行体文件格式,它的一些特性继承自Unix的Coff(common object fileformat)文件格式。“portable executable”(可移植的执行体)意味着此文件格式是跨win32平台的,即使Windows运行在非Intel的CPU上,任何win32平台的PE装载器都能识别和使用该文件格式。当然,移植到不同的CPU上PE执行体必然得有一些改变。所有win32执行体都使用PE文件格式,包括动态库NT的内核模式驱动程序(kernel?mode drivers)。EXE 与DLL的差别完全是语义上的,它们使用格式,其实都是PE文件格式。唯一的区别就是其中有一个字段标识出是EXE还是DLL,还有很多DLL的扩展比如OCX,CPL等都是PE文件格式。 二、PE文件加密 对被保护软件的可执行文件加密是软件保护产品的重要组成部分,一般的加密思路是对可执行文件进行加一层保护壳,即对原始文件的代码段、数据段、引入表和原始入口点等进行加密,只有在运行完加壳的代码,才对以上内容进行解密。对PE文件加密是软件开发商保护自己合法软件的一个重要步骤,它可以极大的提高被保护软件的安全性。下面介绍一下加过密的可执行文件的装载过程。

PE文件格式实验

PE文件格式分析实验 使用工具LordPE/PEview、winhex 选择一个exe或者DLL文件 阶段一:(本次实验) 1.DOS头部查看、对应DOS头结构进行数据逐项分析 2.PE头部查看、对应PE头结构进行数据逐项分析 3.Exe文件和DLL文件均是PE格式,他们的区别在哪里? 4.Section表结构的查看(是否可以增加一个新的section表?对齐边界是多少?) 5.PE文件section查看、对应section 块表结构进行数据分析 6.VA、RVA、RA计算 7.问题:你查看的PE文件DOS、PE头部的空隙是多大? 8.问题:你查看的PE文件在那个section的空隙最大/最小? 9.问题:如果手工增加一个section,要修改哪些字段,请手工试验。(提高:你的新块表 增加是否引起原文件的对齐位置的改变?) 10.问题(提高):一个section的属性字节如何设置,请在上一个问题基础上实验。 本次实验要求对照以上要求,自行选择文件进行分析,撰写报告。 阶段二:(后一阶段的工作) 1.资源查看、修改 2.编写PE文件分析程序 3.编写PE病毒程序 附录1PE格式详细讲解(一) 前几天发了一个PE信息查看器的小工具,本来想用那个获取邀请码的,可是觉得几率不是太大,于是再献上一篇教程,既是为了自己能获得邀请码,也是帮助那些想学习PE格式的人,让知识来源于网络再回归网络。 N年没写文章了,不知道句子还能不能写通顺,最近正在看《软件加密技术内幕》,刚看完PE结构那部分内容,所以想起来写篇教程作为读书笔记,既可加强记忆又可帮助别人,何乐而不为呢。 好了,废话少说好戏正式上场,PE是英文Portable Executable(可移植的执行体)的缩写,从缩写可以看出它是跨平台的,即使在非intel的CPU上也能正常运行的。它是 Win32环境自身所带的执行体文件格式。其实不光是EXE文件是PE格式,其它的一些重要文件,例如动态链接库文件(DLL),驱动文件(SYS)等也是PE格式的,所以学好PE格式是非常重要的,以下我把这类文件统称为PE文件。学习PE文件结构不仅可以使我们知道可执行文件是怎样运行的,也可以使我们了解一下windows操作系统的一些工作机制,精通PE是成为计算机高手的必经之路。 其实说白了PE文件格式就是一种文件组织的方式,里面对一些重要信息的存放做了一些规定,比如文件要运行,我们就得先知道入口地址,可是我们从哪去得到入口地址呢,我们必须把保存有入口地址信息

PE文件结构详解(三)PE导出表

PE文件结构详解(三)PE导出表 上篇文章PE文件结构详解(二)可执行文件头的结尾出现了一个大数组,这个数组中的每一项都是一个特定的结构,通过函数获取数组中的项可以用RtlImageDirectoryEntryToData函数,DataDirectory中的每一项都可以用这个函数获取,函数原型如下: PVOID NTAPI RtlImageDirectoryEntryToData(PVOID Base, BOOLEAN MappedAsImage, USHORT Directory, PULONG Size); Base:模块基地址。 MappedAsImage:是否映射为映象。 Directory:数据目录项的索引。 Size:对应数据目录项的大小,比如Directory为0,则表示导出表的大小。 返回值表示数据目录项的起始地址。 这次来看看第一项:导出表。 导出表是用来描述模块中的导出函数的结构,如果一个模块导出了函数,那么这个函数会被记录在导出表中,这样通过GetProcAddress函数就能动态获取到函数的地址。函数导出的方式有两种,一种是按名字导出,一种是按序号导出。这两种导出方式在导出表中的描述方式也不相同。模块的导出函数可以通过Dependency walker工具来查看:

上图中红框位置显示的就是模块的导出函数,有时候显示的导出函数名字中有一些符号,像 ??0CP2PDownloadUIInterface@@QAE@ABV0@@Z,这种是导出了C++的函数名,编译器将名字进行了修饰。 下面看一下导出表的定义吧: 结构还算比较简单,具体每一项的含义如下: Characteristics:现在没有用到,一般为0。 TimeDateStamp:导出表生成的时间戳,由连接器生成。 MajorVersion,MinorVersion:看名字是版本,实际貌似没有用,都是0。

4各种文件格式的不同分析

JPEG/BMP/TIF/PNG四种图像格式有什么不同? 一、BMP格式 BMP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发,BMP位图格式理所当然地被广泛应用。这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱生来的缺点--占用磁盘空间过大。所以,目前BMP在单机上比较流行。 二、GIF格式 GIF是英文Graphics Interchange Format(图形交换格式)的缩写。顾名思义,这种格式是用来交换图片的。事实上也是如此,上世纪80年代,美国一家著名的在线信息服务机构CompuServe针对当时网络传输带宽的限制,开发出了这种GIF图像格式。GIF格式的特点是压缩比高,磁盘空间占用较少,所以这种图像格式迅速得到了广泛的应用。最初的GIF 只是简单地用来存储单幅静止图像(称为GIF87a),后来随着技术发展,可以同时存储若干幅静止图象进而形成连续的动画,使之成为当时支持2D动画为数不多的格式之一(称为GIF89a),而在GIF89a图像中可指定透明区域,使图像具有非同一般的显示效果,这更使GIF风光十足。目前Internet上大量采用的彩色动画文件多为这种格式的文件,也称为GIF89a格式文件。此外,考虑到网络传输中的实际情况,GIF图像格式还增加了渐显方式,也就是说,在图像传输过程中,用户可以先看到图像的大致轮廓,然后随着传输过程的继续而逐步看清图像中的细节部分,从而适应了用户的"从朦胧到清楚"的观赏心理。目前Internet 上大量采用的彩色动画文件多为这种格式的文件。但GIF有个小小的缺点,即不能存储超过256色的图像。尽管如此,这种格式仍在网络上大行其道应用,这和GIF图像文件短小、下载速度快、可用许多具有同样大小的图像文件组成动画等优势是分不开的。 三、JPEG格式 JPEG也是常见的一种图像格式,它由联合照片专家组(Joint Photographic Experts Group)开发并以命名为"ISO10918-1",JPEG仅仅是一种俗称而已。JPEG文件的扩展名为.jpg 或.jpeg,其压缩技术十分先进,它用有损压缩方式去除冗余的图像和彩色数据,获取得极高的压缩率的同时能展现十分丰富生动的图像,换句话说,就是可以用最少的磁盘空间得到较好的图像质量。同时JPEG还是一种很灵活的格式,具有调节图像质量的功能,允许你用不同的压缩比例对这种文件压缩,比如我们最高可以把1.37MB的BMP位图文件压缩至20.3KB。当然我们完全可以在图像质量和文件尺寸之间找到平衡点。由于JPEG优异的品质和杰出的表现,它的应用也非常广泛,特别是在网络和光盘读物上,肯定都能找到它的影子。目前各类浏览器均支持JPEG这种图像格式,因为JPEG格式的文件尺寸较小,下载速度快,使得Web页有可能以较短的下载时间提供大量美观的图像,JPEG同时也就顺理成章地成为网络上最受欢迎的图像格式。 四、JPEG2000格式 JPEG2000同样是由JPEG组织负责制定的,它有一个正式名称叫做"ISO15444",与JPEG相比,它具备更高压缩率以及更多新功能的新一代静态影像压缩技术。JPEG2000作为JPEG的升级版,其压缩率比JPEG高约30%左右。与JPEG不同的是,JPEG2000同时支持有损和无损压缩,而JPEG只能支持有损压缩。无损压缩对保存一些重要图片是十分有用的。JPEG2000的一个极其重要的特征在于它能实现渐进传输,这一点与GIF的"渐显"有异曲同工之妙,即先传输图像的轮廓,然后逐步传输数据,不断提高图像质量,让图象由朦胧到清晰显示,而不必是像现在的JPEG一样,由上到下慢慢显示。此外,JPEG2000还支持所谓的"感兴趣区域"特性,你可以任意指定影像上你感兴趣区域的压缩质

相关文档