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;
块表主要用来表示当前文件一共分为几个部分,和后面的块相对应
块表决定了后面的块,每一块从哪里开始,里面存储的数据是什么等等