pe文件格式

合集下载

PE文件格式详解

PE文件格式详解

PE文件格式详解(一)基础知识什么是PE文件格式:我们知道所有文件都是一些连续(当然实际存储在磁盘上的时候不一定是连续的)的数据组织起来的,不同类型的文件肯定组织形式也各不相同;PE文件格式便是一种文件组织形式,它是32位Window系统中的可执行文件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文件的时候有Window的加载器负责把EXE文件加载到线性地址空间,加载的时候便是根据上一节中说到的PE文件格式中的哪些重要信息。

pe文件格式

pe文件格式

pe文件格式:PE文件格式(1)疯狂代码 / ĵ:http://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包括个头文件<winnt.h>包括对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结构)他将指向个节 在头后面是节头实际上节内容就是真正需要运行个所需要东西所有头和目录成员就是帮你找到它每个节有几个标志:对齐包含数据类型(化数据等)是否可以共享等及数据自身多数节含有个或多个通过“可选头”内数据目录项引用目录没有目录类型内容是化数据或者可执行代码(节是物理意义上内容组织目录是逻辑意义上内容组织两者互相配合才能找到需要东西节是存储内容地方区域安排目录是如何对里面东西进行查找目是寻找里面内容) +-------------------+ |DOS-stub | +-------------------+ |file-header | +----------+ |optionalheader | |----------| | | |datadirectories | | | +-------------------+ | | |sectionheaders | | | +-------------------+ | | |section1 | | | +-------------------+ | | |section2 | | | +-------------------+ | | |... | | | +-------------------+ | | |sectionn | | | +-------------------+DOS-stubandSignature ---------------------- DOSSTUB概念在16位WINDOWS可执行文件内就已经被熟知了STUB是用于OS/2可执行文件自解压文档和其他对于PE文件它是DOS2兼容可执行文件总是包含100字节内容输出个信息:比如"thisprogramneedswindowsNT". 你认识到个DOSSTUB通过验证DOS-header就是个IMAGE_DOS_HEADER结构前两个字节必须使"MZ"(有个定义针对这个WORDIMAGE_DOS_SIGNATURE)你通过尾部'e_lfa'给出偏移量所确定签名区别个PE文件对于PE文件它是个32位按照8字节对齐边界其值0x00004550由IMAGE_NT_SIGNATURE定义.IMAGE_NT_HEADERSSTRUCT Signature DWORD ? FileHeader IMAGE_FILE_HEADER <> OptionalHeader IMAGE_OPTIONAL_HEADER32<>IMAGE_NT_HEADERSENDS 文件头FileHeader -----------IMAGE_FILE_HEADERSTRUCT Machine WORD ? NumberOfSections WORD ? TimeDateStamp DWORD ? PoerToSymbolTable DWORD ? NumberOfSymbols DWORD ? SizeOfOptionalHeader WORD ? Characteristics WORD ?IMAGE_FILE_HEADERENDS 要得到IMAGE_FILE_HEADER,确认DOS头前2个字节"MZ"然后找到'e_lfa'成员然后从文件开始跳过许多字节验证你找到签名文件头作为个IMAGE_FILE_HEADER结构,就从它后面开始从上到下描述其成员 第1:Machine,16位值指明可执行文件所需要系统已知合法值如下: IMAGE_FILE_MACHINE_I386 0x014c Intel80386处理器 0x014d Intel80486处理器 0x014e Pentium处理器 0x0160 R3000(MIPS)处理器 IMAGE_FILE_MACHINE_R3000(0x162)R3000(MIPS)处理器 IMAGE_FILE_MACHINE_R4000(0x166)R4000(MIPS)处理器 IMAGE_FILE_MACHINE_R10000(0x168)R10000(MIPS)处理器 IMAGE_FILE_MACHINE_ALPHA(0x184)DECAlphaAXP处理器 IMAGE_FILE_MACHINE_POWERPC(0x1F0)IBMPowerPC处理器 第2:NumberOfSections,16位值它是跟随于头后面节数我们在后面讨论 第3:TimeDateStamp32位值,文件创建时间可以通过该值区分区别文件版本时间戳用于绑定输入目录后面讲到有些连接器设置该值为荒唐值 第3:PoerToSymbolTable和NumberOfSymbols都是32位用于调试信息般都是0 第4:SizeOfOptionalHeader16位是IMAGE_OPTIONAL_HEADER尺寸.可以用它确认PE文件结构正确性 第5:Characteristics16位值包括个标志集合多数只对目标文件和库有效 Bit0(IMAGE_FILE_RELOCS_STRIPPED)如果文件内没有重定位信息该位置1这里指是每个节内重定位信息不用于可执行文件可执行文件重定位信息在后面提到baserelocation目录 Bit1(IMAGE_FILE_EXECUTABLE_IMAGE)如果文件是可执行则置1例如不是个目标文件或者库文件如果连接器试图创建可执行文件但由于某种原因失败了也置1 Bit2(IMAGE_FILE_LINE_NUMS_STRIPPED)如果行数信息剥离置1对可执行文件无效 Bit3(IMAGE_FILE_LOCAL_SYMS_STRIPPED)如果没有本地符号信息该位置1对可执行文件无效 Bit4(IMAGE_FILE_AGGRESIVE_WS_TRIM)如果操作系统被假定通过页换出抢占式修剪进程工作集(进程使用内存数)该位置1 Bits7(IMAGE_FILE_BYTES_REVERSED_LO)和15(IMAGE_FILE_BYTES_REVERSED_HI)如果文件endianess不是机器期望则置1于是读的前必须交换字节对可执行文件不可靠 Bit8(IMAGE_FILE_32BIT_MACHINE)如果机器被期望是32位机器置1 Bit9(IMAGE_FILE_DEBUG_STRIPPED)如果没有调试信息在文件内置1对可执行文件无效 Bit10(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)如果不能够从可移动媒体比如软盘或光驱置1操作系统建议拷贝文件到交换文件然后执行 Bit11(IMAGE_FILE_NET_RUN_FROM_SWAP)如果不能够才网络运行置1操作系统建议拷贝文件到交换文件然后执行 Bit12(IMAGE_FILE_SYSTEM)如果文件是类似驱动系统文件置1对执行文件无效 Bit13(IMAGE_FILE_DLL)如果文件是DLL置1. Bit14(IMAGE_FILE_UP_SYSTEM_ONLY)如果文件不是为多处理器设计置1 相对虚拟地址RelativeVirtualAddresses -------------------------- PE格式使用所谓RVA用于描述内存地址如果你不知道基地址话需要你加上基地址得到线性地址基地址是PE映像加载地址例如:假如可执行文件加载到0x400000可执行文件RVA是0x1560.有效执行起始地址为0x401560.如果被加载到0x100000,则执行起始位置在0x101560. 情况变复杂起来由于节不必按照加载映像那样对齐例如节般按照512字节对齐加载映像可能按照4096字节对齐参看'SectionAlignment'and'FileAlignment'对齐意思就是地址值=对齐长度倍数 于是为了找到个特殊RVA指向信息你必须计算偏移量好象文件被加载样假如知道执行起点在RVA0x1560,想从这反汇编代码要找到文件内地址你必须找出在RAM内按照4096对齐节".code"节自内存RVA0x1000开始16384字节长你知道RVA0x1560偏移量在那个节内是0x560.找出节在文件内按照512字节对齐且".code"从0x800开始那么在文件内代码执行起点是0x800+0x560=0xd60 然后反汇编并发现个存取地址0x1051d0处变量.线性地址在加载执行文件时重新分配并给出优先加载地址你发现优先加载地址是0x100000,于是我们处理RVA0x51d0.这是个开始于RVA0x5000数据区2048字节长它开始于文件偏移量0x4800.变量可以在文件偏移量0x4800+0x51d0-0x5000=0x49d0处发现 可选头OptionalHeader --------------- 紧跟在文件头后面是IMAGE_OPTIONAL_HEADER尽管名字是可选实际直存在包含有关如何精确处理PE文件信息从上到下介绍成员IMAGE_OPTIONAL_HEADER32STRUCT Magic WORD ? MajorLinkerVersion BYTE ? MinorLinkerVersion BYTE ? SizeOfCode DWORD ? SizeOfInitializedData DWORD ? SizeOfUninitializedData DWORD ? AddressOfEntryPo DWORD ? BaseOfCode DWORD ? BaseOfData DWORD ? ImageBase DWORD ? SectionAlignment DWORD ? FileAlignment DWORD ? MajorOperatingVersion WORD ? MinorOperatingVersion WORD ? MajorImageVersion WORD ? MinorImageVersion WORD ? MajorSubsystemVersion WORD ? MinorSubsystemVersion WORD ? Win32VersionValue DWORD ? SizeOfImage DWORD ? SizeOfHeaders DWORD ? CheckSum DWORD ? Subsystem WORD ? DllCharacteristics WORD ? SizeOfStackReserve DWORD ? SizeOfStackCommit DWORD ? SizeOfHeapReserve DWORD ? SizeOfHeapCommit DWORD ? LoaderFlags DWORD ? NumberOfRvaAndSizes DWORD ? DataDirectory IMAGE_DATA_DIRECTORYIMAGE_NUMBEROF_DIRECTORY_ENTRIESdup(<> )IMAGE_OPTIONAL_HEADER32ENDSIMAGE_OPTIONAL_HEADER equ <IMAGE_OPTIONAL_HEADER32> 第1个16位字是'Magic'总是0x010b. 下面2个字节是连接器版本号'MajorLinkerVersion'和'MinorLinkerVersion'这些值都不可靠不能总是妥当反映连接器版本有些连接器不设置该域 下面3个longwords(32位)指定执行代码尺寸('SizeOfCode'),化数据尺寸 'SizeOfInitializedData',所谓数据段"datasegment",未化数据尺寸 'SizeOfUninitializedData',所谓"bsssegment".这些数值也不可靠 往下个32位RVA.是入口点偏移量('AddressOfEntryPo').执行从此开始 下面2个32位是可执行代码('BaseOfCode')和化数据('BaseOfData')RVAs我们对它没有兴趣可以通过节来查看更可靠信息非化数据没有RVA 下面是个32位值ImageBase'作为整个文件优先加载地址包括所有头在内该值总是 64KB倍数文件已经被连接器重定位如果文件能够真正加载到这个地址加载器不必重定位文件如果另个映像已经被加载到那个地址则优先地址不可使用这种情况下映像被加载到其他地址需要重定位如果映像是DLL还有更多结果"boundimports"不再有效需要对使用DLL执行文件进行修正参见'importdirectory' 下面2个32位是当映像文件加载后PE文件节在内存内对齐'SectionAlignment',以及在文件内对齐'FileAlignment'.般文件对齐是512节对齐是4096. 下面2个16位字是期望操作系统版本'MajorOperatingVersion'和'MinorOperatingVersion' 下面2个16位字是期望可执行文件版本'MajorImageVersion'和 'MinorImageVersion'.许多连接器不正确设置这些信息 下面2个16位字是期望子系统版本'MajorSubsystemVersion和MinorSubsystemVersion.这个必须是Win32版本或者POSIX版本该版本需要正确提供它被检查并使用如果是Win32-GUI并运行在NT4,子系统版本不是4.0,对话框不是3D效果 然后是Win32VersionValue32位大部分情况下是0 下面是32位映像需要内存数量'SizeOfImage'.是所有头和节总和如果节已经对齐它是给加载器线索需要多少页加载映像 下面个是32位所有头总和包括数据目录和节头'SizeOfHeaders'.它也是才文件开始到第节偏移量 然后是32位校验码'CheckSum'.对当前版本NT只校验映像是否是NT驱动对于其他可执行文件类型不必提供这个码可能为0 然后是16子系统Subsystem'表明在什么系统上运行: IMAGE_SUBSYSTEM_NATIVE(1)执行文件不需要子系统用于驱动 IMAGE_SUBSYSTEM_WINDOWS_GUI(2)映像是Win32图形可以打开控制台 IMAGE_SUBSYSTEM_WINDOWS_CUI(3)映像是Win32控制台可以得到缺省控制台 IMAGE_SUBSYSTEM_OS2_CUI(5)映像是OS/2控制台是OS/2格式 IMAGE_SUBSYSTEM_POSIX_CUI(7)映像使用POSIX控制台子系统 Windows95可执行文件总是使用Win32subsystem,于是合法值是2和3 下面是16位DllCharacteristics,表明是否是DLL,如果0位置1DLL被通知进程结合位1置1DLL被通知线程脱离位2置1DLL被通知线程结合位3置1DLL被通知进程脱离 下面4个32位预留堆栈大小'SizeOfStackReserve',提交堆栈大小'SizeOfStackCommit',预留堆大小'SizeOfHeapReserve'和提交堆大小'SizeOfHeapCommit'. 预留数量是地址空间不是真实RAM启动时提交数量是真正分配内存这个值也是堆和栈根据需要增长个数量 例如:个预留1MB堆并提交堆时64KB,该堆就从64KB开始并保证可以加大到1MB.堆将以64KB块增长该堆在这里是主要堆默认堆个进程可以创建多个堆如果需要话栈是第个线程栈进程可以创建许多线程每个都有自己堆栈DLLs没有栈或者堆于是在其映像内该值被忽略 下面是32位LoaderFlags,没有用 然后是32位NumberOfRvaAndSizes,在随后目录内有效项目数最好使用 IMAGE_NUMBEROF_DIRECTORY_ENTRIES即16 下面是具有IMAGE_NUMBEROF_DIRECTORY_ENTRIES(16)个成员IMAGE_DATA_DIRECTORYs结构.IMAGE_DATA_DIRECTORYSTRUCT VirtualAddress DWORD ? isize DWORD ?IMAGE_DATA_DIRECTORYENDS 每个目录描述了节内特定信息位置32bitsRVAVirtualAddress和尺寸32bit,各个成员索引如下(括号内为索引值): IMAGE_DIRECTORY_ENTRY_EXPORT(0)输出符号目录用于DLL IMAGE_DIRECTORY_ENTRY_IMPORT(1)输入符号目录 IMAGE_DIRECTORY_ENTRY_RESOURCE(2)资源目录 IMAGE_DIRECTORY_ENTRY_EXCEPTION(3)异常目录 IMAGE_DIRECTORY_ENTRY_SECURITY(4)安全目录 IMAGE_DIRECTORY_ENTRY_BASERELOC(5)重定位表 IMAGE_DIRECTORY_ENTRY_DEBUG(6)调试目录 IMAGE_DIRECTORY_ENTRY_COPYRIGHT(7)描述版权串 IMAGE_DIRECTORY_ENTRY_GLOBALPTR(8)机器值 IMAGE_DIRECTORY_ENTRY_TLS(9)Threadlocalstorage目录 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG(10)Loadconfiguration目录 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT(11)Boundimportdirectory目录 IMAGE_DIRECTORY_ENTRY_IAT(12)ImportAddressTable输入地址表目录 例如如果我们找到索引72个值0x12000和33,加载地址是0x10000,我们知道版权数据是在0x10000+0x12000版权字数为33如果个特定类型目录没有被使用地址和尺寸都为0 节目录Sectiondirectories ------------------- 节包含2个部分:节头IMAGE_SECTION_HEADER节数据在数据目录的后我们看到个具有NumberOfSections个节头成员按RVA排序 节头包括:IMAGE_SECTION_HEADERSTRUCT Name1dbIMAGE_SIZEOF_SHORT_NAMEdup(?) unionMisc PhysicalAddressdd ? VirtualSizedd ? ends VirtualAddressdd ? SizeOfRawDatadd ? PoerToRawDatadd ? PoerToRelocationsdd? PoerToLinenumbersdd? NumberOfRelocationsdw ? NumberOfLinenumbersdw ? Characteristicsdd ?IMAGE_SECTION_HEADERENDS IMAGE_SIZEOF_SHORT_NAME(8)个字节组成节名字如果所有8个字节被用掉没有0做为结尾典型名字如".data"或者".text"或者".bss".没有必要前导'.',可以是是"CODE"或"IAT".注意名字不全部跟节内容有关个".code"节可能或没有可能包括可执行代码可能只包括输入地址表可能包含代码和地址表和化数据要找到在节内信息必须通过“可选头”内数据目录查找他们不要依赖名字不要假定节原始数据起始于节开始2009-2-3 3:24:50疯狂代码 /。

PE 文件格式

PE 文件格式

PE文件格式”完整译文(附注释)一、前言(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⑤中包含一个名叫<winnt.h>的头文件,其中含有很多用于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签名;十六进制数45和50分别代表ASCII码字母E和P----译者注)。

之后是文件头(按COFF格式),用来说明该二进制文件将运行在何种机器之上、分几个区段、链接的时间、是可执行文件还是DLL、等等。

WindowsPE文件格式

WindowsPE文件格式

WindowsPE⽂件格式在PE⽂件头之前理论Windows的PE(Portable Executable)⽂件有两个头,⼀个是是Windows头,⼀个是DOS头。

在⽂件的最开始会有⼀段DOS的EXE⽂件头,来说明这个程序不可以在DOS环境下运⾏。

我们需要在DOS头+3Ch处,会有⼀个4字节的指针指向windows头。

根据+3Ch处的值,定位到Windows⽂件头可以看到"PE"两个字节,Windows头就从此处开始。

这也就是Windows EXE⽂件经常被称为PE⽂件的原因。

实践1. 在xp环境下,⽤QuickView打开⼀个EXE⽂件,观察其头部。

在00h处有两个字节4D 5A表⽰这是⼀个DOS头。

在4Eh处,有⼀个字符串This program cannot be run in DOS mode. 表明这不是⼀个DOS⽂件在3C处,有⼀个四字节指针,其值为000000D0h,颜⾊标黄,指向windows头2. 查看⽂件地址D0处的值可以看到此处的两个字节为50 45即“PE”,表⽰这个EXE⽂件是⼀个PE⽂件,从这两个字节开始才是PE的⽂件头。

PE⽂件头背景知识要了解PE⽂件头的具体内容,我们需要对Windows的内存管理,⽂件存储有⼀定的了解。

接下来做简要的说明,想要了解更详细的内容可以去学习操作系统的相关知识。

Windows通过分段以及分页两种机制管理内存和实现进程的隔离及保护。

以下说明会涉及到⼀些寄存器和⽐较抽象的概念,不懂也没有关系。

只需要知道结论,*⼀个进程的虚拟地址会经过⼀些转换成为真正的物理地址. *进程之间的虚拟地址可以相同,但相同的虚拟地址会转化成不同的物理地址。

在Windows系统中,为了向下兼容,保留了分段(section)的的机制,但是CS,DS,SS这些段地址在GDT表中的值全部为0,所以经过分段后的逻辑地址(logical address)与线性地址(linear address)是完全⼀致的,在此处不⽤过多理会。

pe格式化方法

pe格式化方法

pe格式化方法PE格式(Portable Executable format)是Windows操作系统下的一种可执行文件的格式标准,它定义了可执行文件、动态链接库(DLL)和驱动程序等二进制文件的结构和标识方法。

本文将介绍PE格式化的基本原理和方法,并举例说明。

一、PE格式基本原理1. PE格式定义:PE格式是一种COFF(Common Object File Format)文件格式的变体,用于描述32位和64位Windows可执行文件的结构和组织。

2. 文件头部分:PE格式文件的开头是一个固定大小的文件头(File Header),用于描述整个PE文件的组织结构和属性信息,如文件类型、目标体系结构、节表位置等。

3. 节部分:紧随文件头部分的是节(Section)部分,它描述了PE格式文件中各个段或区块的属性和内容,如代码段、数据段、资源段等。

4. 数据目录:PE格式文件中包含了多个数据目录(Data Directory),每个数据目录描述了PE文件中某个特定功能的位置和大小信息,如导入表、导出表、资源表等。

1. 创建空白PE文件:使用合适的开发工具,如Visual Studio等,新建一个空白的PE 文件。

2. 定义文件头:根据所需的文件类型和目标体系结构,填写文件头部分的属性信息。

如指定文件类型为可执行文件(Executable)、目标体系结构为32位或64位等。

3. 定义节表:根据需求,定义PE文件中的各个节的属性和内容,如代码段、数据段、资源段等。

可以使用合适的工具,如Hex编辑器等,手动修改节表。

4. 填充数据目录:根据PE格式的规定,将所需的功能的位置和大小信息填写入数据目录表中,如导入表、导出表、资源表等。

5. 填充节内容:根据需求,将代码、数据和资源等内容填写入相应的节中。

可以使用合适的工具,如文本编辑器等,手动修改和填充节内容。

6. 调整文件大小:根据实际内容大小,调整整个PE文件的大小,确保文件大小与实际内容相符。

PE文件格式(内容详细)

PE文件格式(内容详细)
EXE文件的格式
简介
在DOS环境下有四种基本的可执行文件格式
批处理文件,以.BAT结尾的文件
设备驱动文件,是以.SYS结尾的文件,如CONFIG.SYS
COM文件,是以.COM结尾的纯代码文件
• 没有文件头部分,缺省情况下总是从0x100H处开始执行, 没有重定位项,所有代码和数据必须控制在64K以内
在Win32位平台可执行文件格式:可移植的可执行文件 (Portable Executable File)格式,即PE格式。MZ文件头 之后是一个以“PE”开始的文件头
安装在硬盘上的程序没运行-静态 加载到内存-动态
EXE文件的格式
MZ文件格式-Mark Zbikowski
.EXE文件由三部分构成:文件头、重定位表和二进制代码 允许代码、数据、堆栈分别处于不同的段,每一段都可以是64KB.
EXE文件的格式
PE文件格式
一般来说,病毒往往先于HOST程序获得控制权。运行 Win32病毒的一般流程示意如下:
①用户点击或系统自动运行HOST程序; ②装载HOST程序到内存;
③通过PE文件中的AddressOfEntryPoint+ImageBase,
定位第一条语句的位置(程序入口); ④从第一条语句开始执行(这时执行的其实是病毒代码); ⑤病毒主体代码执行完毕,将控制权交给HOST程序原来的
病毒通过“MZ”、“PE”这两个标志,初步判断当前程序 是否是目标文件——PE文件。如果要精确校验指定文件是 否为一有效PE文件,则可以检验PE文件格式里的各个数 据结构,或者仅校验一些关键数据结构。大多数情况下, 没有必要校验文件里的每一个数据结构,只要一些关键数 据结构有效,就可以认为是有效的PE文件
PE的意思就是Portable Executable(可移植、可执 行),它是Win32可执行文件的标准格式

PE文件格式分析及修改

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。

pe文件

pe文件
文件层次解释
A.
谢谢观看
Hale Waihona Puke pe文件可移植的可执行的文件
01 定义
03 PE首部
目录
02 相关概念 04 文件格式
PE文件的全称是Portable Executable,意为可移植的可执行的文件,常见的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格式已经普遍应用,并且在不短的将来仍是不可避免的。
和微软的其它可执行格式一样,你可以通过查找它的起始偏移来得到真实首部,这个偏移放在DOS残留首部 中。WINNT.H头文件包含了DOS残留程序的数据结构定义,使得很容易找到PE首部的起始位置。e_lfanew域是PE 真实首部的偏移。为了得到PE首部在内存中的指针,只需要把这个值加到映像的基址上即可。
线程局部变量
我最后不会让你盯住无穷无尽的十六进制Dump,也不会详细讨论页面的每一个单独的位的重要性。代替的, 我会向你介绍包含在 PE文件中的概念,并且将他们和你每天都遇到的东西联系起来。比如,线程局部变量的概 念,如下所述:
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

pe文件格式:PE文件格式(1)疯狂代码 / ĵ:http://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包括个头文件<winnt.h>包括对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结构)他将指向个节 在头后面是节头实际上节内容就是真正需要运行个所需要东西所有头和目录成员就是帮你找到它每个节有几个标志:对齐包含数据类型(化数据等)是否可以共享等及数据自身多数节含有个或多个通过“可选头”内数据目录项引用目录没有目录类型内容是化数据或者可执行代码(节是物理意义上内容组织目录是逻辑意义上内容组织两者互相配合才能找到需要东西节是存储内容地方区域安排目录是如何对里面东西进行查找目是寻找里面内容) +-------------------+ |DOS-stub | +-------------------+ |file-header | +----------+ |optionalheader | |----------| | | |datadirectories | | | +-------------------+ | | |sectionheaders | | | +-------------------+ | | |section1 | | | +-------------------+ | | |section2 | | | +-------------------+ | | |... | | | +-------------------+ | | |sectionn | | | +-------------------+DOS-stubandSignature ---------------------- DOSSTUB概念在16位WINDOWS可执行文件内就已经被熟知了STUB是用于OS/2可执行文件自解压文档和其他对于PE文件它是DOS2兼容可执行文件总是包含100字节内容输出个信息:比如"thisprogramneedswindowsNT". 你认识到个DOSSTUB通过验证DOS-header就是个IMAGE_DOS_HEADER结构前两个字节必须使"MZ"(有个定义针对这个WORDIMAGE_DOS_SIGNATURE)你通过尾部'e_lfa'给出偏移量所确定签名区别个PE文件对于PE文件它是个32位按照8字节对齐边界其值0x00004550由IMAGE_NT_SIGNATURE定义.IMAGE_NT_HEADERSSTRUCT Signature DWORD ? FileHeader IMAGE_FILE_HEADER <> OptionalHeader IMAGE_OPTIONAL_HEADER32<>IMAGE_NT_HEADERSENDS 文件头FileHeader -----------IMAGE_FILE_HEADERSTRUCT Machine WORD ? NumberOfSections WORD ? TimeDateStamp DWORD ? PoerToSymbolTable DWORD ? NumberOfSymbols DWORD ? SizeOfOptionalHeader WORD ? Characteristics WORD ?IMAGE_FILE_HEADERENDS 要得到IMAGE_FILE_HEADER,确认DOS头前2个字节"MZ"然后找到'e_lfa'成员然后从文件开始跳过许多字节验证你找到签名文件头作为个IMAGE_FILE_HEADER结构,就从它后面开始从上到下描述其成员 第1:Machine,16位值指明可执行文件所需要系统已知合法值如下: IMAGE_FILE_MACHINE_I386 0x014c Intel80386处理器 0x014d Intel80486处理器 0x014e Pentium处理器 0x0160 R3000(MIPS)处理器 IMAGE_FILE_MACHINE_R3000(0x162)R3000(MIPS)处理器 IMAGE_FILE_MACHINE_R4000(0x166)R4000(MIPS)处理器 IMAGE_FILE_MACHINE_R10000(0x168)R10000(MIPS)处理器 IMAGE_FILE_MACHINE_ALPHA(0x184)DECAlphaAXP处理器 IMAGE_FILE_MACHINE_POWERPC(0x1F0)IBMPowerPC处理器 第2:NumberOfSections,16位值它是跟随于头后面节数我们在后面讨论 第3:TimeDateStamp32位值,文件创建时间可以通过该值区分区别文件版本时间戳用于绑定输入目录后面讲到有些连接器设置该值为荒唐值 第3:PoerToSymbolTable和NumberOfSymbols都是32位用于调试信息般都是0 第4:SizeOfOptionalHeader16位是IMAGE_OPTIONAL_HEADER尺寸.可以用它确认PE文件结构正确性 第5:Characteristics16位值包括个标志集合多数只对目标文件和库有效 Bit0(IMAGE_FILE_RELOCS_STRIPPED)如果文件内没有重定位信息该位置1这里指是每个节内重定位信息不用于可执行文件可执行文件重定位信息在后面提到baserelocation目录 Bit1(IMAGE_FILE_EXECUTABLE_IMAGE)如果文件是可执行则置1例如不是个目标文件或者库文件如果连接器试图创建可执行文件但由于某种原因失败了也置1 Bit2(IMAGE_FILE_LINE_NUMS_STRIPPED)如果行数信息剥离置1对可执行文件无效 Bit3(IMAGE_FILE_LOCAL_SYMS_STRIPPED)如果没有本地符号信息该位置1对可执行文件无效 Bit4(IMAGE_FILE_AGGRESIVE_WS_TRIM)如果操作系统被假定通过页换出抢占式修剪进程工作集(进程使用内存数)该位置1 Bits7(IMAGE_FILE_BYTES_REVERSED_LO)和15(IMAGE_FILE_BYTES_REVERSED_HI)如果文件endianess不是机器期望则置1于是读的前必须交换字节对可执行文件不可靠 Bit8(IMAGE_FILE_32BIT_MACHINE)如果机器被期望是32位机器置1 Bit9(IMAGE_FILE_DEBUG_STRIPPED)如果没有调试信息在文件内置1对可执行文件无效 Bit10(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)如果不能够从可移动媒体比如软盘或光驱置1操作系统建议拷贝文件到交换文件然后执行 Bit11(IMAGE_FILE_NET_RUN_FROM_SWAP)如果不能够才网络运行置1操作系统建议拷贝文件到交换文件然后执行 Bit12(IMAGE_FILE_SYSTEM)如果文件是类似驱动系统文件置1对执行文件无效 Bit13(IMAGE_FILE_DLL)如果文件是DLL置1. Bit14(IMAGE_FILE_UP_SYSTEM_ONLY)如果文件不是为多处理器设计置1 相对虚拟地址RelativeVirtualAddresses -------------------------- PE格式使用所谓RVA用于描述内存地址如果你不知道基地址话需要你加上基地址得到线性地址基地址是PE映像加载地址例如:假如可执行文件加载到0x400000可执行文件RVA是0x1560.有效执行起始地址为0x401560.如果被加载到0x100000,则执行起始位置在0x101560. 情况变复杂起来由于节不必按照加载映像那样对齐例如节般按照512字节对齐加载映像可能按照4096字节对齐参看'SectionAlignment'and'FileAlignment'对齐意思就是地址值=对齐长度倍数 于是为了找到个特殊RVA指向信息你必须计算偏移量好象文件被加载样假如知道执行起点在RVA0x1560,想从这反汇编代码要找到文件内地址你必须找出在RAM内按照4096对齐节".code"节自内存RVA0x1000开始16384字节长你知道RVA0x1560偏移量在那个节内是0x560.找出节在文件内按照512字节对齐且".code"从0x800开始那么在文件内代码执行起点是0x800+0x560=0xd60 然后反汇编并发现个存取地址0x1051d0处变量.线性地址在加载执行文件时重新分配并给出优先加载地址你发现优先加载地址是0x100000,于是我们处理RVA0x51d0.这是个开始于RVA0x5000数据区2048字节长它开始于文件偏移量0x4800.变量可以在文件偏移量0x4800+0x51d0-0x5000=0x49d0处发现 可选头OptionalHeader --------------- 紧跟在文件头后面是IMAGE_OPTIONAL_HEADER尽管名字是可选实际直存在包含有关如何精确处理PE文件信息从上到下介绍成员IMAGE_OPTIONAL_HEADER32STRUCT Magic WORD ? MajorLinkerVersion BYTE ? MinorLinkerVersion BYTE ? SizeOfCode DWORD ? SizeOfInitializedData DWORD ? SizeOfUninitializedData DWORD ? AddressOfEntryPo DWORD ? BaseOfCode DWORD ? BaseOfData DWORD ? ImageBase DWORD ? SectionAlignment DWORD ? FileAlignment DWORD ? MajorOperatingVersion WORD ? MinorOperatingVersion WORD ? MajorImageVersion WORD ? MinorImageVersion WORD ? MajorSubsystemVersion WORD ? MinorSubsystemVersion WORD ? Win32VersionValue DWORD ? SizeOfImage DWORD ? SizeOfHeaders DWORD ? CheckSum DWORD ? Subsystem WORD ? DllCharacteristics WORD ? SizeOfStackReserve DWORD ? SizeOfStackCommit DWORD ? SizeOfHeapReserve DWORD ? SizeOfHeapCommit DWORD ? LoaderFlags DWORD ? NumberOfRvaAndSizes DWORD ? DataDirectory IMAGE_DATA_DIRECTORYIMAGE_NUMBEROF_DIRECTORY_ENTRIESdup(<> )IMAGE_OPTIONAL_HEADER32ENDSIMAGE_OPTIONAL_HEADER equ <IMAGE_OPTIONAL_HEADER32> 第1个16位字是'Magic'总是0x010b. 下面2个字节是连接器版本号'MajorLinkerVersion'和'MinorLinkerVersion'这些值都不可靠不能总是妥当反映连接器版本有些连接器不设置该域 下面3个longwords(32位)指定执行代码尺寸('SizeOfCode'),化数据尺寸 'SizeOfInitializedData',所谓数据段"datasegment",未化数据尺寸 'SizeOfUninitializedData',所谓"bsssegment".这些数值也不可靠 往下个32位RVA.是入口点偏移量('AddressOfEntryPo').执行从此开始 下面2个32位是可执行代码('BaseOfCode')和化数据('BaseOfData')RVAs我们对它没有兴趣可以通过节来查看更可靠信息非化数据没有RVA 下面是个32位值ImageBase'作为整个文件优先加载地址包括所有头在内该值总是 64KB倍数文件已经被连接器重定位如果文件能够真正加载到这个地址加载器不必重定位文件如果另个映像已经被加载到那个地址则优先地址不可使用这种情况下映像被加载到其他地址需要重定位如果映像是DLL还有更多结果"boundimports"不再有效需要对使用DLL执行文件进行修正参见'importdirectory' 下面2个32位是当映像文件加载后PE文件节在内存内对齐'SectionAlignment',以及在文件内对齐'FileAlignment'.般文件对齐是512节对齐是4096. 下面2个16位字是期望操作系统版本'MajorOperatingVersion'和'MinorOperatingVersion' 下面2个16位字是期望可执行文件版本'MajorImageVersion'和 'MinorImageVersion'.许多连接器不正确设置这些信息 下面2个16位字是期望子系统版本'MajorSubsystemVersion和MinorSubsystemVersion.这个必须是Win32版本或者POSIX版本该版本需要正确提供它被检查并使用如果是Win32-GUI并运行在NT4,子系统版本不是4.0,对话框不是3D效果 然后是Win32VersionValue32位大部分情况下是0 下面是32位映像需要内存数量'SizeOfImage'.是所有头和节总和如果节已经对齐它是给加载器线索需要多少页加载映像 下面个是32位所有头总和包括数据目录和节头'SizeOfHeaders'.它也是才文件开始到第节偏移量 然后是32位校验码'CheckSum'.对当前版本NT只校验映像是否是NT驱动对于其他可执行文件类型不必提供这个码可能为0 然后是16子系统Subsystem'表明在什么系统上运行: IMAGE_SUBSYSTEM_NATIVE(1)执行文件不需要子系统用于驱动 IMAGE_SUBSYSTEM_WINDOWS_GUI(2)映像是Win32图形可以打开控制台 IMAGE_SUBSYSTEM_WINDOWS_CUI(3)映像是Win32控制台可以得到缺省控制台 IMAGE_SUBSYSTEM_OS2_CUI(5)映像是OS/2控制台是OS/2格式 IMAGE_SUBSYSTEM_POSIX_CUI(7)映像使用POSIX控制台子系统 Windows95可执行文件总是使用Win32subsystem,于是合法值是2和3 下面是16位DllCharacteristics,表明是否是DLL,如果0位置1DLL被通知进程结合位1置1DLL被通知线程脱离位2置1DLL被通知线程结合位3置1DLL被通知进程脱离 下面4个32位预留堆栈大小'SizeOfStackReserve',提交堆栈大小'SizeOfStackCommit',预留堆大小'SizeOfHeapReserve'和提交堆大小'SizeOfHeapCommit'. 预留数量是地址空间不是真实RAM启动时提交数量是真正分配内存这个值也是堆和栈根据需要增长个数量 例如:个预留1MB堆并提交堆时64KB,该堆就从64KB开始并保证可以加大到1MB.堆将以64KB块增长该堆在这里是主要堆默认堆个进程可以创建多个堆如果需要话栈是第个线程栈进程可以创建许多线程每个都有自己堆栈DLLs没有栈或者堆于是在其映像内该值被忽略 下面是32位LoaderFlags,没有用 然后是32位NumberOfRvaAndSizes,在随后目录内有效项目数最好使用 IMAGE_NUMBEROF_DIRECTORY_ENTRIES即16 下面是具有IMAGE_NUMBEROF_DIRECTORY_ENTRIES(16)个成员IMAGE_DATA_DIRECTORYs结构.IMAGE_DATA_DIRECTORYSTRUCT VirtualAddress DWORD ? isize DWORD ?IMAGE_DATA_DIRECTORYENDS 每个目录描述了节内特定信息位置32bitsRVAVirtualAddress和尺寸32bit,各个成员索引如下(括号内为索引值): IMAGE_DIRECTORY_ENTRY_EXPORT(0)输出符号目录用于DLL IMAGE_DIRECTORY_ENTRY_IMPORT(1)输入符号目录 IMAGE_DIRECTORY_ENTRY_RESOURCE(2)资源目录 IMAGE_DIRECTORY_ENTRY_EXCEPTION(3)异常目录 IMAGE_DIRECTORY_ENTRY_SECURITY(4)安全目录 IMAGE_DIRECTORY_ENTRY_BASERELOC(5)重定位表 IMAGE_DIRECTORY_ENTRY_DEBUG(6)调试目录 IMAGE_DIRECTORY_ENTRY_COPYRIGHT(7)描述版权串 IMAGE_DIRECTORY_ENTRY_GLOBALPTR(8)机器值 IMAGE_DIRECTORY_ENTRY_TLS(9)Threadlocalstorage目录 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG(10)Loadconfiguration目录 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT(11)Boundimportdirectory目录 IMAGE_DIRECTORY_ENTRY_IAT(12)ImportAddressTable输入地址表目录 例如如果我们找到索引72个值0x12000和33,加载地址是0x10000,我们知道版权数据是在0x10000+0x12000版权字数为33如果个特定类型目录没有被使用地址和尺寸都为0 节目录Sectiondirectories ------------------- 节包含2个部分:节头IMAGE_SECTION_HEADER节数据在数据目录的后我们看到个具有NumberOfSections个节头成员按RVA排序 节头包括:IMAGE_SECTION_HEADERSTRUCT Name1dbIMAGE_SIZEOF_SHORT_NAMEdup(?) unionMisc PhysicalAddressdd ? VirtualSizedd ? ends VirtualAddressdd ? SizeOfRawDatadd ? PoerToRawDatadd ? PoerToRelocationsdd? PoerToLinenumbersdd? NumberOfRelocationsdw ? NumberOfLinenumbersdw ? Characteristicsdd ?IMAGE_SECTION_HEADERENDS IMAGE_SIZEOF_SHORT_NAME(8)个字节组成节名字如果所有8个字节被用掉没有0做为结尾典型名字如".data"或者".text"或者".bss".没有必要前导'.',可以是是"CODE"或"IAT".注意名字不全部跟节内容有关个".code"节可能或没有可能包括可执行代码可能只包括输入地址表可能包含代码和地址表和化数据要找到在节内信息必须通过“可选头”内数据目录查找他们不要依赖名字不要假定节原始数据起始于节开始2009-2-3 3:24:50疯狂代码 /。

相关文档
最新文档