365体育足球中文版

逆向工程——PE(一)

逆向工程——PE(一)

本章参考书《逆向工程核心原理》

什么是PE?

PE(Protable Executable),是Windows操作系统下使用的可执行文件,因为Windows分32位操作系统和64位操作系统,因此与之相对应有PE(或称为PE32),PE+(或称为PE32+)。这里主要分析PE32。

PE的分类

其中我们遇见的比较多的是exe可执行文件、sys驱动程序文件、dll动态链接库文件以及obj对象文件。

在这些文件中,除了obj对象文件,其他的文件都能够被直接或者间接地执行(例如驱动程序和库文件,就要使用相应的调试器,加载器或者是服务等来执行)。

PE文件的基本结构

DOS头

DOS头的主要作用是使PE文件对DOS文件具有兼容性,表现为IMAGE_DOS_HEADER结构体(大小为64字节)。

1 typedef struct _IMAGE_DOS_HEADER{

2 WORD e_magic ;

3 WORD e_cblp ;

4 WORD e_cp ;

5 WORD e_crlc ;

6 WORD e_cparhdr ;

7 WORD e_minalloc ;

8 WORD e_maxalloc ;

9 WORD e_ss ;

10 WORD e_sp ;

11 WORD e_csum ;

12 WORD e_ip ;

13 WORD e_cs ;

14 WORD e_lfarlc ;

15 WORD e_ovno ;

16 WORD e_res[4] ;

17 WORD e_oemid ;

18 WORD e_oeminfo ;

19 WORD e_res2[10] ;

20 WORD e_lfanew ;

21 } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

其中比较重要的是 e_magic (DOS签名) , e_lfanew(NT头的偏移)

其中“5A4D”(橘色标记)为e_magic(一般的PE文件的DOS头都是“5A4D”),而000000F8(红色标记)则是e_lfanew,NT头开始的位置,注意,此处为小端序表记法。

DOS存根

DOS存根在DOS头的下方,是个可选项,大小不固定。DOS存根由代码和数据混合组成。

深色区域即为DOS存根,而用红框框出来的则是DOS系统下16位汇编指令,因此32位Windows不会识别,此16位汇编指令为:

1 0E PUSH CS

2 1F POP DS

3 BA0E00 MOV DX,000E ; DX = 0E : "This program cannot be run in DOS mode"

4 B409 MOV AH,09 ;WriteString()

5 CD21 INT 21

6 B8014C MOV AX,4C01 ;Exit()

7 CD21 INT 21

NT头

NT头是PE头中的核心部分,在整个PE头中也占据很大的空间。

1 typedef struct _IMAGE_NT_HEADERS{

2 DWORD Signature ;

3 IMAGE_FILE_HEADER FileHeader ;

4 IMAGE_OPTIONAL_HEADER32 OptionalHeader;

5 }IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

IMAGE_NT_HEADERS结构体主要由以上3个成员组成。

根据DOS头中的e_lfanew值(000000F8),我们找到了NT头中的第一个变量Signture(50450000h)一般ASCLL码都是"PE"

NT头:文件头(IMAGE_FILE_HEADER)

1 typedef struct _IMAGE_FILE_HEADER{

2 WORD Machine ;

3 WORD NumberOfSections ;

4 DWORD TimeDateStamp ;

5 DWORD PointerToSymbolTable ;

6 DWORD NumberOfSymbols ;

7 WORD SizeOfOptionalHeader ;

8 WORD Characteristics ;

9 }IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

#1.Machine

每个cpu都有唯一的Machine码。兼容32位Intel的Machine码为0x014c。

1 #define IMAGE_FILE_MACHINE_UNKNOWN 0

2 #define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.

3 #define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian

4 #define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian

5 #define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian

6 #define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2

7 #define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP

8 #define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian

9 #define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian

10 #define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian

11 #define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian

12 #define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian

13 #define IMAGE_FILE_MACHINE_THUMB 0x01c2

14 #define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64

15 #define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS

16 #define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS

17 #define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS

18 #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64

19 #define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64

#2.NumberOfSections

NumberOfSections用来指出此文件中存在的节区个数。

#3.SizeOfOptionalHeader

用来指出IMAGE_OPTIONAL_HEADER32的长度。尽管说,IMAGE_OPTIONAL_HEADER32结构体大小已经确定,但是为了和PE32+区分(在PE32+中,可选头为IMAGE_OPTIONAL_HEADER64,大小与PE中的可选头不同),因此需要SizeOfOptionalHeader来明确结构体大小。

#4.Characteristics

用来标识文件属性,来表示文件是否可运行,是否为DLL等信息。

1 #define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.

2 #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references).

3 #define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.

4 #define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.

5 #define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 // Agressively trim working set

6 #define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // App can handle >2gb addresses

7 #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.

8 #define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.

9 #define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file

10 #define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file.

11 #define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file.

12 #define IMAGE_FILE_SYSTEM 0x1000 // System File.

13 #define IMAGE_FILE_DLL 0x2000 // File is a DLL.

14 #define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine

15 #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.

#5.TimeDateStamp

记录编译器创造此文件的时间。

以下是notepad.exe的IMAGE_FILE_HEADER结构体:

014C machine

0005 number of sections

144CAAC5 TimeDateStamp

00000000 PointerToSymbolTable

00000000 NumberOfSymbols

00E0 SiezOfOptionalHeader

0102 Characteristics:

IMAGE_FILE_32BIT_MACHINE

IMAGE_FILE_EXECUTABLE_IMAGE

NT头:可选头(IMAGE_OPTIONAL_HEADER32)

1 typedef struct _IMAGE_DATA_DIRECTORY {

2 DWORD VirtualAddress;

3 DWORD Size;

4 } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

5

6 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16

7

8 //

9 // Optional header format.

10 //

11

12 typedef struct _IMAGE_OPTIONAL_HEADER {

13 //

14 // Standard fields.

15 //

16

17 WORD Magic;

18 BYTE MajorLinkerVersion;

19 BYTE MinorLinkerVersion;

20 DWORD SizeOfCode;

21 DWORD SizeOfInitializedData;

22 DWORD SizeOfUninitializedData;

23 DWORD AddressOfEntryPoint;

24 DWORD BaseOfCode;

25 DWORD BaseOfData;

26

27 //

28 // NT additional fields.

29 //

30

31 DWORD ImageBase;

32 DWORD SectionAlignment;

33 DWORD FileAlignment;

34 WORD MajorOperatingSystemVersion;

35 WORD MinorOperatingSystemVersion;

36 WORD MajorImageVersion;

37 WORD MinorImageVersion;

38 WORD MajorSubsystemVersion;

39 WORD MinorSubsystemVersion;

40 DWORD Win32VersionValue;

41 DWORD SizeOfImage;

42 DWORD SizeOfHeaders;

43 DWORD CheckSum;

44 WORD Subsystem;

45 WORD DllCharacteristics;

46 DWORD SizeOfStackReserve;

47 DWORD SizeOfStackCommit;

48 DWORD SizeOfHeapReserve;

49 DWORD SizeOfHeapCommit;

50 DWORD LoaderFlags;

51 DWORD NumberOfRvaAndSizes;

52 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

53 } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

其中红字标识的是可选头中比较重要的变量,以下我来对它们一一介绍。

#1.Magic

当文件为PE时,可选头为IMAGE_OPTIONAL_HEADER32,Magic = 10B

当文件为PE+时,可选头为IMAGE_OPTIONAL_HEADER64,Magic = 20B

#2.AddressOfEntryPoint

程序最先被执行的代码起始地址。相当重要。

#3.ImageBase

当PE文件被装载到内存空间中去时,ImageBase指出文件的优先装入地址。执行PE文件时,PE装载器先创建进程,再将文件载入内存,然后把EIP寄存器的值设置为ImageBase + AddressOfEntryPoint 。

#4.SectionAlignment,FileAlignment

SectionAlignment指定了节区在内存中的最小单位

FileAlignment指定了节区在磁盘中的最小单位

一个文件的SectionAlignment和FileAlignment可能相同,也有可能不同。

磁盘文件或内存中的节区大小必定为FileAlignment或SectionAlignment值的整数倍。

#5.SizeOfImage

SizeOfImage指定了PE在加载入内存中所占空间的大小,在一般情况下,文件的大小与加载到内存中的大小是不同的。

#6.SizeOfHeaders

整个PE头的大小,值为FileAlignment的整数倍。第一节区所在位置与SizeOfHeaders距文件偏移量相同。

#7.Subsystem

用来区分不同的文件。

#8.NumberOfRvaAndSizes

指定DataDirectory(IMAGE_OPTIONAL_HEADER32结构体中最后一个成员)数组的个数。

#9.DataDirectory

DataDirectory是由IMAGE_DATA_DIRECTORY结构体组成的数组,数组的每项都有被定义的值。

DataDirectory[0] = EXPORT Directory

DataDirectory[1] = IMPORT Directory

DataDirectory[2] = RESOURCE Directory

DataDirectory[3] = EXCEPTION Directory

DataDirectory[4] = SECURITY Directory

DataDirectory[5] = BASERELOC Directory

DataDirectory[6] = DEBUG Directory

DataDirectory[7] = COPYRIGHT Directory

DataDirectory[8] = GLOBALPTR Directory

DataDirectory[9] = TLS Directory

DataDirectory[A] = LOAD_CONFIG Directory

DataDirectory[B] = BOUND_IMPORT Directory

DataDirectory[C] = IAT Directory

DataDirectory[D] = DELAY_IMPORT Directory

DataDirectory[E] = COM_DESCRIPTOR Directory

DataDirectory[F] = Reserved Directory

介绍完了可选头里的每个成员,再带大家实际分析一下notepad.exe

地址 十六进制 备注000110 010B magic

000120 0001B2B0 AdressOfEntryPoint

000130 00001000 SectionAlignment

000134 00000200 FileAlignment

00014C 00000400 SizeOfHeaders

000154 0002 Subsystem

000170 00000000 DataDirectory[0].VirtualAdress(RVA of EXPORT Directory)

000178 0001F4AC DataDirectory[1].VirtualAdress(RVA of IMPORT Directory)

00017C 00000230 DataDirectory[1].Size(size of IMPORT Directory)

这里只列出来了一些比较重要的成员,各位朋友们可以自己练习,把剩下的成员都标识出来哦!~

至此,NT头已经讲完了,在进入下一内容前,我建议各位读者把NT头再回顾一下。

节区头

节区头由IMAGE_SECTION_HEADER结构体组成的数组,有多少个节区就有多少个结构体。并且在节区中有这样的规定:把代码(code),数据(data)和资源(resourse)分类存储在不同的节区里。

#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;

VirtualSize :内存中节区所占大小。

VirtualAddress :内存中节区起始地址(RVA)。

SizeOfRawData:磁盘文件中节区所占大小。

PointerToRawData:磁盘文件中节区起始位置。

characteristics:节区属性。

1 //

2 // Section characteristics.

3 //

4 // IMAGE_SCN_TYPE_REG 0x00000000 // Reserved.

5 // IMAGE_SCN_TYPE_DSECT 0x00000001 // Reserved.

6 // IMAGE_SCN_TYPE_NOLOAD 0x00000002 // Reserved.

7 // IMAGE_SCN_TYPE_GROUP 0x00000004 // Reserved.

8 #define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.

9 // IMAGE_SCN_TYPE_COPY 0x00000010 // Reserved.

10

11 #define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code.

12 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data.

13 #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data.

14

15 #define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.

16 #define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information.

17 // IMAGE_SCN_TYPE_OVER 0x00000400 // Reserved.

18 #define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.

19 #define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat.

20 // 0x00002000 // Reserved.

21 // IMAGE_SCN_MEM_PROTECTED - Obsolete 0x00004000

22 #define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 // Reset speculative exceptions handling bits in the TLB entries for this section.

23 #define IMAGE_SCN_GPREL 0x00008000 // Section content can be accessed relative to GP

24 #define IMAGE_SCN_MEM_FARDATA 0x00008000

25 // IMAGE_SCN_MEM_SYSHEAP - Obsolete 0x00010000

26 #define IMAGE_SCN_MEM_PURGEABLE 0x00020000

27 #define IMAGE_SCN_MEM_16BIT 0x00020000

28 #define IMAGE_SCN_MEM_LOCKED 0x00040000

29 #define IMAGE_SCN_MEM_PRELOAD 0x00080000

30

31 #define IMAGE_SCN_ALIGN_1BYTES 0x00100000 //

32 #define IMAGE_SCN_ALIGN_2BYTES 0x00200000 //

33 #define IMAGE_SCN_ALIGN_4BYTES 0x00300000 //

34 #define IMAGE_SCN_ALIGN_8BYTES 0x00400000 //

35 #define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified.

36 #define IMAGE_SCN_ALIGN_32BYTES 0x00600000 //

37 #define IMAGE_SCN_ALIGN_64BYTES 0x00700000 //

38 #define IMAGE_SCN_ALIGN_128BYTES 0x00800000 //

39 #define IMAGE_SCN_ALIGN_256BYTES 0x00900000 //

40 #define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 //

41 #define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 //

42 #define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 //

43 #define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 //

44 #define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 //

45 // Unused 0x00F00000

46

47 #define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // Section contains extended relocations.

48 #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded.

49 #define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable.

50 #define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable.

51 #define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable.

52 #define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable.

53 #define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable.

54 #define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable.

接下来以notepad.exe的节区为例做分析:

1 0001F0 2E746578 74000000 Name(.text)

2 0001F8 0001AE2C Misc.VirtualSize

3 0001FC 00001000 VirtualAddress

4 000200 0001B000 SizeOfRawData

5 000204 00000400 PointerToRawData

6 000214 60000020 Characteristics:

IMAGE_SCN_MEM_EXECUTE

IMAGE_SCN_MEM_READ

IMAGE_SCN_CNT_CODE

由于.text是第一块节区,因此VirtualAddress和PointerToRawData是不带任何值的(是由IMAGE_OPTIONAL_HEADER32中)SectionAlignment和FileAlignment确定的。

因为文件从磁盘中载入到内存中,因为载入点不同,会引起地址的变化,在磁盘中的相对位置称为RAW,在内存中的相对地址是RVA,在内存中的绝对地址是VA。这三者的对应转换关系如下:

VA = ImageBase + RVA

RAW = RVA - VirtualAddress + PointerToRawData

比如说,现在有一段数据,RVA = 7000 ,查节区,发现第一节区为1B000(SizeOfRawData可知)> 7000 ,说明这个数据段在第一节区,再将7000减去1000(内存中节区的起始地址),加上400(文件中节区的起始地址),就得到该数据段在文件中的位置。

以上的地址转换称为:RVA to RAW,极为重要!!

好了,本篇文章的内容主要是讲解PE文件和其重要的PE头结构,以及重要的地址转换公式,在(二)中将继续讲解PE头的核心内容IAT(Import Address Table)。

欢迎读者讨论,批评与指正!

相关推荐

民营银行24年盘点:互联网银行领跑,网商银行AUM突破1万亿
365网站是正规平台吗

民营银行24年盘点:互联网银行领跑,网商银行AUM突破1万亿

📅 2025-07-23 👁️ 4785
南非足球教父曼德拉去世 世界杯因他而来到非洲
365网站是正规平台吗

南非足球教父曼德拉去世 世界杯因他而来到非洲

📅 2025-07-27 👁️ 5070
野生青蛙怎么清理才干净?
365网站是正规平台吗

野生青蛙怎么清理才干净?

📅 2025-07-26 👁️ 9873
英雄聯盟
365网站是正规平台吗

英雄聯盟

📅 2025-07-16 👁️ 6739