可执行文件:可以由操作系统进行加载执行的文件
在Windows平台中若要程序可执行,必须遵守可执行文件的格式
可执行文件的格式:
Windows平台:PE(Portable Executable)文件结构,其中Portable也就是Windows系统中能够跨平台运行
Linux平台:ELF(Executable and Linking Format)文件结构
PE文件特征:
如exe、dll、vxd、sys和vdm等文件都遵守可执行文件的格式!
常用的识别PE文件的方法:
1、用HEX编辑器打开文件,头两个字节是不是MZ
,然后向后到第64字节的位置,例如为10 01 00 00
,因为存储模式为小端存储所以,实际是0x00000110
2、再去找到0x00000110的位置,向后2字节,如果为字符显示为PE则基本就是PE文件了
PE文件结构:
PE文件结构分为四大部分:
1、Dos部分 2、PE文件头 3、节表 4、节数据
1、Dos部分:
MZ文件头
:IMAGE_DOS_HEADER
结构体,其大小占64个字节,并且该结构中的最后一个LONG类型e_lfanew
成员指向PE文件头的位置为中的PE文件头标志的地址
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 指向PE文件头的位置为中的PE文件头标志的地址
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
Dos Stub
:属于链接器进行填充的,大小不一定,属于DOS部分的DOS块,无实际作用,但是可以作为注入手段进行利用!图中第二个红框则是Dos Stub
2、PE文件头:
整个PE头的结构体
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; //PE文件头标志
IMAGE_FILE_HEADER FileHeader; //PE文件表头
IMAGE_OPTIONAL_HEADER32 OptionalHeader; //扩展PE头
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
PE文件头分为三部分:
1、PE文件头标志(PE标识),占4个字节,作为标识用,如上图查看是否为PE文件就是利用这个方法!
2、PE文件表头(标准PE头),占20个字节,为IMAGE_FILE_HEADER
结构体,该结构体中SizeOfOptionalHeader
结构体中有个成员可以看出可扩展文件表头的大小
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader; // 可以看出可扩展文件表头的大小,也分为x32 x64 x32大小为E0 x64大小为F0
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
3、可扩展文件表头(扩展PE头),占224字节,结构体分两种 一种是32位的,一种是16位的,分别是IMAGE_OPTIONAL_HEADER32
结构体 和 16xIMAGE_DATA_DIRECTORY
结构体
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
//
// NT additional fields.
//
DWORD ImageBase;
DWORD SectionAlignment; //内存中加载的时候,文件对齐之后的大小
DWORD FileAlignment; //硬盘中存储的时候,文件对齐之后的大小
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage; //扩展PE头的镜像大小
DWORD SizeOfHeaders;// 头+节表的大小
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
其中FileAlignment
成员的值为文件对齐之后的大小,SizeOfHeaders
成员的值一定是FileAlignment
的值的整数倍,而且SizeOfHeaders
保存的值是所有的头(有DOS部分 PE文件头)加上节表的大小
如果FileAlignment
(文件对齐之后的大小)是200 那么SizeOfHeaders
头一定是200的整数倍,那么就是400,如果FileAlignment
不到200那么SizeOfHeaders
就按照200对齐,如下图可以看到文件对齐后的FileAlignment
的大小为0x200H,SectionAlignment
是在内存中加载的时候,文件对齐之后的大小,在FileAlignment
前四个字节,那么就是0x1000H
那么再去看下SizeOfHeaders
的大小,相差二十个字节,继续往后移,结果如下:0x400,的确是FileAlignment
的两倍
如果每次都是整数倍,那肯定有很多地方空出来,实际上是用空间换取时间,增加了处理效率,具体以后自己知道了再补上!
3、节表: 其中每个节大小占40个字节,十六进制 0x28
IMAGE_SECTION_HEADER
结构体(40字节) * 节的数量(大小取决于节的数量)
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress; //当前节的名称 , 占8字节
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;
我这边有五个节,如下显示:
4、节数据:
sizeofHeaders 按照文件对齐.存储着 头 + 节表的大小,这里就是0x400之后的数据了!也就是如下:
在硬盘中存储的时候文件的每个节数据之间的大小由FileAlignment
决定!
上面都是空的,同样可以进行非法利用!