免杀之重识PE文件(一) 前言 虽然已经会免杀,但是对这些基础掌握不牢。因此重新学习一下。
PE文件 PE的指纹识别 PE文件以MZ开头
在偏移3C的位置,硬编码为78,ASCII码为x
找到偏移78的位置,硬编码为50和45对应ASCII的PE
PE结构 PE结构分为4部分,DOS部分、PE文件头、节表、节数据
DOS部分 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 typedef struct _IMAGE_DOS_HEADER { WORD e_magic; WORD e_cblp; WORD e_cp; WORD e_crlc; WORD e_cparhdr; WORD e_minalloc; WORD e_maxalloc; WORD e_ss; WORD e_sp; WORD e_csum; WORD e_ip; WORD e_cs; WORD e_lfarlc; WORD e_ovno; WORD e_res[4 ]; WORD e_oemid; WORD e_oeminfo; WORD e_res2[10 ]; LONG e_lfanew; } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
对照着看下
要记得的是e_lfanew,是指向PE头的指针
在PE头开始和DOS头中间的部分是DOS块没什么用,可以用来填充一小段shellcode
PE头(NT头) PE头分为标识PE头、标准PE头、扩展PE头
PE文件一些重要信息通常存储在标准PE头和扩展PE头中
PE头结构体代码
32位
1 2 3 4 5 typedef struct _IMAGE_NT_HEADERS {DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
64位
1 2 3 4 5 typedef struct _IMAGE_NT_HEADERS64 { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER64 OptionalHeader; } IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
标识PE头
标准PE头(文件头)
标准PE头通常占20个字节,包括了PE文件的基本属性和信息,例如文件类型、机器架构、入口点、标 志、段信息等等。其结构体代码如下所示
1 2 3 4 5 6 7 8 9 typedef struct _IMAGE_FILE_HEADER {WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
拓展PE头(可选头)
扩展PE头通常占224个字节,以下结构体成员中有几个成员要重点注意 如果一个可执行文件它的dos部分+pe头+节表的共同大小为332,其 200, 那么 FileAlignment (文件对齐)的值为 SizeOfHeaders 的值应该为文件对齐的整数倍,所以 SizeOfHeaders 的值为400
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 typedef struct _IMAGE_OPTIONAL_HEADER { WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; 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;
节表 节表包含了PE文件中所有的节信息,每个节都包括了一个段的名称、大小、属性和数据等信息 节表是由一系列 IMAGE_SECTION_HEADER 结构的元素组成的结构体数组, 每个元素占40个字节
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #define IMAGE_SIZEOF_SHORT_NAME 8 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;
节数据 节数据是PE文件中实际的二进制数据,它包含了PE文件中所有的代码、数据和资源等信息。每个节的数 据都位于PE文件中的一个连续的段中 PE文件中,不同的节用于存储不同类型的数据,通常包括以下几个节:
data节:用于存储PE文件中的静态数据,它是可读写的,通常包含全局变量、静态变量、已初始化 的数据等等。
rdata节:用于存储PE文件中的只读数据,它是只读的,通常包含字符串、常量、只读数据等等。
text节:用于存储PE文件中的可执行代码,它是可执行的,通常包含程序的主要代码,例如函数、 指令等等
.rsrc节:用于存储PE文件中的资源,包括图标、位图、字符串、菜单等等,通常是只读的。
.reloc节:reloc节用于存储PE文件中的重定位信息,它包含了需要被修改的地址和偏移量等信息, 通常是只读写的。
.tls节:用于存储PE文件中的线程本地存储(Thread Local Storage,TLS)相关信息,包括TLS索引、 初始化回调函数等等, 通常是可读写的。
__END__