首页 > 技术文章 > PE

doubleconquer 2021-12-04 17:26 原文

PE

需要用到的工具

十六进制文本编辑器:winhex或者UltraEdit

工具的使用

首先任何文件在计算机中存储都是0和1
上面两个工具就是用于查看文件在计算机中的存储内容
由于0和1比较冗长,所以使用十六进制来显示数据

可执行文件

什么是可执行文件

可执行文件 (executable file) 指的是可以由操作系统进行加载执行的文件

可执行文件的格式

  • windows系统
    PE(Porttable Excutable)文件结构 可执行

  • linux系统
    ELF(Executable and Linking Format)文件 执行 和 链接格式

常见可执行文件

.exe .sys .dll都是windows下的可执行文件(它们都遵循PE文件的格式)

为什么要学习PE

  • PE文件时windwos可执行程序必须满足的规范
  • 对软件的加壳和脱壳都是基于PE
  • EXE文件的加载也涉及PE的知识

如何识别一个文件是否为PE文件




这三个文件的头2个字节都是4D 5A(ASCII码为MZ)

小总结

如果一个文件,它的头两个字节为4D 5A(ASCII码为MZ),并且数据为PE则基本可以断定这个文件是Windows下的

可执行文件(满足PE结构)

PE在C语言中的定义

PE文件结构自然是一种数据结构,不过这种数据结构比较复杂

在C语言的winnt.h这个头文件中定义了PE文件结构相关的结构体

可以通过C语言中PE的定义来更好地学习PE

创建一个空的控制台项目,然后引入winnt.h这个头文件

#include<winnt.h>
int main(int argc, char* argv[])
{
        return 0;
}

然后在头文件这里右键→打开文档<winnt.h>即可

DOS首部

该部分结构对应winnt.h中的_IMAGE_DOS_HEADER结构体

可以在先前打开的winnt.h中Ctrl+F搜索_IMAGE_DOS_HEADER

代码

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;

PE文件(NT头部)

该部分结构对应winnt.h中的_IMAGE_NT_HEADERS结构体

使用同样的方法得到对应的代码:

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

节表

该部分结构对应winnt.h中的_IMAGE_SECTION_HEADER结构体

使用同样的方法得到对应的代码:

typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

块表主要用来表示当前文件一共分为几个部分,和后面的块相对应

块表决定了后面的块,每一块从哪里开始,里面存储的数据是什么等等

总结

推荐阅读