在表中,我們知道了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