pe文件学习(未完成)

pe文件学习

本文目录

  1. pe文件概述

pe文件概述

pe文件就是windows系统下的可执行文件所要遵循的格式,再深究一点就是Windows的装载器是按照pe文件的格式把程序装载到内存的。

如何好好的学习pe文件

pe文件说白了就是很多的结构体,程序的很多运行信息都存储在这个结构体中,只有把这些结构体掌握了才能对于pe文件有个大体掌握,为了简单,我们先来学习很标准的pe文件结构,也就是正常情况下编译器给你生成的正常pe文件结构,很多变形的pe文件结构都是建立在基础pe文件结构之上的,我们要先易后难。

pe文件大体

从最外面一层来讲pe文件包括pe头和pe主体
在这里插入图片描述

pe头讲解

pe头包括上面提到的DOS头,DOS stub,NT头,节区头这四个部分。前面说到pe其实大部分都是结构体,而且这些结构体都定义在winnt.h这个头文件里面。
DOS头

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // Magic number  pe指纹
    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;

对于dos头我们只需要关注上面代码翻译的部分 pe指纹文件头的偏移位置
那么这里有小伙伴就要问了,为什么上面结构体那么多属性,我们只需要关注这两个属性呢?原因是,Windows装载器并没有参考上面其他的属性,就算你把其他的属性都手动修改为任意值,可执行文件也不会出现错误。
pe指纹:装载器装载的时候首先要查询文件开头的pe指纹,好确定这是个pe文件,如果这个指纹错了,那么操作系统会不认识你这个文件。指纹这个东西在多种文件结构中都有,其实他就是一种用来区分文件格式的标志。
文件头的偏移位置:这个属性告诉装载器文件头在文件中的偏移位置是多少。什么是文件偏移?就是这个数据相对于文件开头的偏移。下面我们来用winhex打开一个pe文件来看一看。
在这里插入图片描述
相信聪明的小伙伴们一定能推断出我上面用红框标注的两个属性,没错,就是pe指纹和文件头的文件偏移属性。
鉴于可能有人是第一次这样查看文件内容,所以这里有必要说明一下,这个是按照
小端
来放置的内容,什么是
小端
?就是低字节内容在低位置,对应的还有一个大端,是和小端相反的。
DOS stub
在这里插入图片描述
根据文件头偏移我们可以得出上方指向的位置就是DOS stub了,至于这个部分是历史遗留,那些内容其实都是汇编指令,我们运行一下对应的汇编指令发现他的作用就是在控制台打印
This program cannot be run in DOS mode。
这个部分随意更改也不会影响文件在Windows系统上的运行。
这里那么大一个地方其实是可以存储一些我们自己定义的信息的,这个等以后学了非正常的pe文件再说。
文件头
这里补充一下文件头前面还有一个pe标志,这个和之前的pe指纹是一样的作用,装载器也会寻找这个标志,否则也不认它是pe文件。

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;  //运行平台
    WORD    NumberOfSections; //节区数
    DWORD   TimeDateStamp;  
    DWORD   PointerToSymbolTable; 
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader; //可选头的大小
    WORD    Characteristics; //pe文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

文件头这里我们也是只需要关注上面翻译的部分。
首先是运行平台。我们每个cpu都有一个对应的机器码,其定义也可以在winnt.h中找到。


#define IMAGE_FILE_MACHINE_UNKNOWN           0
#define IMAGE_FILE_MACHINE_TARGET_HOST       0x0001  // Useful for indicating we want to interact with the host and not a WoW guest.
#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_SH3               0x01a2  // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3DSP            0x01a3
#define IMAGE_FILE_MACHINE_SH3E              0x01a4  // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4               0x01a6  // SH4 little-endian
#define IMAGE_FILE_MACHINE_SH5               0x01a8  // SH5
#define IMAGE_FILE_MACHINE_ARM               0x01c0  // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB             0x01c2  // ARM Thumb/Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_ARMNT             0x01c4  // ARM Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_AM33              0x01d3
#define IMAGE_FILE_MACHINE_POWERPC           0x01F0  // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_POWERPCFP         0x01f1
#define IMAGE_FILE_MACHINE_IA64              0x0200  // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16            0x0266  // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64           0x0284  // ALPHA64
#define IMAGE_FILE_MACHINE_MIPSFPU           0x0366  // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16         0x0466  // MIPS
#define IMAGE_FILE_MACHINE_AXP64             IMAGE_FILE_MACHINE_ALPHA64
#define IMAGE_FILE_MACHINE_TRICORE           0x0520  // Infineon
#define IMAGE_FILE_MACHINE_CEF               0x0CEF
#define IMAGE_FILE_MACHINE_EBC               0x0EBC  // EFI Byte Code
#define IMAGE_FILE_MACHINE_AMD64             0x8664  // AMD64 (K8)
#define IMAGE_FILE_MACHINE_M32R              0x9041  // M32R little-endian
#define IMAGE_FILE_MACHINE_ARM64             0xAA64  // ARM64 Little-Endian
#define IMAGE_FILE_MACHINE_CEE               0xC0EE

节区数:我们的pe主体是按照一节一节来分的,其中有代码段,数据段,资源段等等节区,如果这里没有明白,那么可以先放一放,我们稍后会介绍,这个时候就记住他是一个节的数目就行了。
可选头大小:在文件头之中规定了可选头的大小,那么我们怎么定位可选头呢?其实可选头就是紧挨着文件头的,这个时候我告诉你pe文件那么多结构体属性中并没有给出可选头所在的文件偏移而只给出了它的大小,就是因为可选头是紧挨着在文件头后面的,否则我们只知道大小不知道位置,就尴尬了。
pe文件属性:这两个字节标识着pe文件的一些属性,下面我们一一列出来你就明白了。

#define IMAGE_FILE_RELOCS_STRIPPED           0x0001  // Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE          0x0002  // File is executable  (i.e. no unresolved external references).
#define IMAGE_FILE_LINE_NUMS_STRIPPED        0x0004  // Line nunbers stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED       0x0008  // Local symbols stripped from file.
#define IMAGE_FILE_AGGRESIVE_WS_TRIM         0x0010  // Aggressively trim working set
#define IMAGE_FILE_LARGE_ADDRESS_AWARE       0x0020  // App can handle >2gb addresses
#define IMAGE_FILE_BYTES_REVERSED_LO         0x0080  // Bytes of machine word are reversed.
#define IMAGE_FILE_32BIT_MACHINE             0x0100  // 32 bit word machine.
#define IMAGE_FILE_DEBUG_STRIPPED            0x0200  // Debugging info stripped from file in .DBG file
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP   0x0400  // If Image is on removable media, copy and run from the swap file.
#define IMAGE_FILE_NET_RUN_FROM_SWAP         0x0800  // If Image is on Net, copy and run from the swap file.
#define IMAGE_FILE_SYSTEM                    0x1000  // System File.
#define IMAGE_FILE_DLL                       0x2000  // File is a DLL.
#define IMAGE_FILE_UP_SYSTEM_ONLY            0x4000  // File should only be run on a UP machine
#define IMAGE_FILE_BYTES_REVERSED_HI         0x8000  // Bytes of machine word are reversed.

这里我们只要记住0x0002和0x2000就行了,一个是可执行文件,一个是dll文件。
下面我们给一张图片包括了上面各种属性的翻译(既然有现成的,那么我就不一个一个敲了)

此处图片保留。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值