PE結構分析(二)

Profs發表於2021-04-24

在表中,我們知道了0x01 4c對應的平臺結構是i386;

我們接著分析下一個欄位,給出PE結構圖

 

 向後推移2個位元組,現在來到(圖片高亮部分):

 高亮部分對應IMAGE_NT_HEADERS結構的NumberofSections欄位;

圖中高亮部分是PE_HEADER部分的TimeDateStamp欄位,這個欄位的功能是記錄檔案的建立時間(姑且就叫時間戳欄位)

對應下圖中的:

 

我們接著分析下一個欄位(PE_HEADER結構中的PointertoSymbolTable),這個欄位的指向“符號表”(Coff符號表的偏移地址):

對應下圖中的:

 

 

 

 符號表是什麼?

首先我們先來解釋下COFF檔案格式:

 

 

 

 1.檔案頭(File Header)

 

 

 

 

 

 現在接著來轉到PE_HEADER部分的NumberofSymbols(這個欄位表示Coff表中符號的個數);

 

 

 我們定位到具體檔案中的16進位制程式碼中去:

 

我們接著轉到PE_HEADER部分(結構體_IMAGE_FILE_HEADER)中的欄位SizeOfOptionalHeader中去;

 

 

看到程式碼中高亮的部分顯示0xE0h,說明這是一個32位檔案。

我們接著轉到PE_HEADER部分(結構_IMAGE_FILE_HEADER)中的Characteristics欄位中去;

可以看到是0x0102h。

 

 

 

 說明我們的這個軟體是可執行檔案(也就是EXE可執行程式)。

我們接著轉出PE_HEADER部分,重新轉到_IMAGE_NT_HEADERS結構體當中的_IMAGE_OPTIONAL_HEADER OptionalHeader中去;

 

 

 

 

 

 接著按照OPTIONAL_PE_HEADER部分(_IMAGE_OPTIONAL_HEADER)的程式碼結構去看對應的16進位制程式碼

 

 

 可以看到是0x010bh。

從01到42就是_IMAGE_OPTIONAL_HEADER結構體中各部分所對應的註釋。

01.typedef struct _IMAGE_OPTIONAL_HEADER {
02.    //
03.    // Standard fields.
04.    //
05.  
06.    00h WORD    Magic;                   //幻數,32位pe檔案總為010bh
07.    02h BYTE    MajorLinkerVersion;      //聯結器主版本號
08.    03h BYTE    MinorLinkerVersion;      //聯結器副版本號
09.    04h DWORD   SizeOfCode;              //程式碼段總大小
10.    08h DWORD   SizeOfInitializedData;   //已初始化資料段總大小
11.    0ch DWORD   SizeOfUninitializedData; //未初始化資料段總大小
12.    10h DWORD   AddressOfEntryPoint;     //程式執行入口地址(RVA)
13.    14h DWORD   BaseOfCode;              //程式碼段起始地址(RVA)
14.    18h DWORD   BaseOfData;              //資料段起始地址(RVA)
15.  
16.    //
17.    // NT additional fields.
18.    //
19.  
20.    1ch DWORD   ImageBase;               //程式預設的裝入起始地址
21.    20h DWORD   SectionAlignment;        //記憶體中區塊的對齊單位
22.    24h DWORD   FileAlignment;           //檔案中區塊的對齊單位
23.    28h WORD    MajorOperatingSystemVersion; //所需作業系統主版本號
24.    2ah WORD    MinorOperatingSystemVersion; //所需作業系統副版本號
25.    2ch WORD    MajorImageVersion;       //自定義主版本號
26.    2eh WORD    MinorImageVersion;       //自定義副版本號
27.    30h WORD    MajorSubsystemVersion;   //所需子系統主版本號
28.    32h WORD    MinorSubsystemVersion;   //所需子系統副版本號
29.    34h DWORD   Win32VersionValue;       //總是0
30.    38h DWORD   SizeOfImage;             //pe檔案在記憶體中的映像總大小
31.    3ch DWORD   SizeOfHeaders;           //從pe檔案開始到節表(包含節表)的總大小
32.    40h DWORD   CheckSum;                //pe檔案CRC校驗和
33.    44h WORD    Subsystem;               //使用者介面使用的子系統型別
34.    46h WORD    DllCharacteristics;      //為0
35.    48h DWORD   SizeOfStackReserve;      //為執行緒的棧初始保留的虛擬記憶體的預設值
36.    4ch DWORD   SizeOfStackCommit;       //為執行緒的棧初始提交的虛擬記憶體的大小
37.    50h DWORD   SizeOfHeapReserve;       //為程式的堆保留的虛擬記憶體的大小
38.    54h DWORD   SizeOfHeapCommit;        //為程式的堆初始提交的虛擬記憶體的大小
39.    58h DWORD   LoaderFlags;             //為0
40.    5ch DWORD   NumberOfRvaAndSizes;     //資料目錄結構陣列的項數,總為 00000010h
41.    60h IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];  //資料目錄結構陣列
42.} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

 

 我們接著來看MajorLinkerVersion欄位部分對應的16進位制程式碼:

 

 接著看第二個欄位MaionrLinkerVersion;

 

 所對應的16進位制程式碼是:

 

 接著看下一個欄位SizeOfCode(程式碼總大小):

 

 所對應的十六進位制程式碼是:

接著看下一個欄位SizeOfInitializedData(已初始化程式碼總大小):

 

 所對應的16進位制程式碼為:

 

 接著看下一個欄位SizeofUninitlizedData:

所對應的16進位制程式碼為:

 

我們轉到下一個欄位AddressOfEntryPoint(這個欄位表示的是程式執行入口的地址,相對於C語言的main函式的地址)接著分析:

 

 

 

 所對應的16進位制程式碼為0x00001869h:

 

 這個地址對應的是程式對應的預設裝入的起始地址為0x00001869h;

接著分析下一個欄位BaseOfCode(這個欄位指向的是程式的程式碼段起始地址):

可以看到所對應的16進位制程式碼為0x00001000h

 

接著轉到SizeOfData欄位(這一欄位指向的是程式程式碼的資料段起始地址)分析:

下面的這一個是SizeOfData欄位對應的16進位制程式碼:

 

這一個欄位(ImageBase欄位)所對應的是記憶體映像的基址:

 什麼是記憶體映像?

https://baike.baidu.com/item/%E5%86%85%E5%AD%98%E6%98%A0%E5%83%8F/9046372?fr=aladdin

相關文章