?
3. PE文件頭?
??? 由 'PE' 00 00 4 bytes + PE文件頭 20 bytes 組成
???
??? typedef struct _IMAGE_NT_HEADERS
??? {
? ????? DWORD Signature;? //這個(gè)必需為50 45 00 (PE 00 00 )4字節(jié)? PE\0\0??
???????????????????????????????????????? //這是PE文件頭的標(biāo)記, 我們可以此識(shí)別給定文件是否為有效PE文件。
??????? // ?如果IMAGE_NT_HEADERS的signature域值等于"PE\0\0",那么就是有效的PE文件
??????? // 實(shí)際上,為了比較方便,Microsoft已定義了常量IMAGE_NT_SIGNATURE供我們使用。??????? // IMAGE_DOS_SIGNATURE????? equ 5A4Dh????? MZ
??????? // IMAGE_OS2_SIGNATURE?????? equ 454Eh
??????? // IMAGE_OS2_SIGNATURE_LE equ 454Ch
??????? // IMAGE_VXD_SIGNATURE????? equ 454Ch
??????? // IMAGE_NT_SIGNATURE equ 4550h????????
??????? // 該結(jié)構(gòu)域包含了關(guān)于PE文件邏輯分布的信息,雖然域名有"可選"字樣,但實(shí)際上本結(jié)構(gòu)總是存在的。
?
??????? IMAGE_FILE_HEADER FileHeader;? // 該結(jié)構(gòu)包含了PE文件物理分布的信息,如節(jié)數(shù)目,PE文件的執(zhí)行機(jī)器等?
???????????????
??????? IMAGE_OPTIONAL_HEADER32 OptionalHeader; 可選頭結(jié)構(gòu)
??? } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
?
??? typedef struct _IMAGE_FILE_HEADER
??? {
? ????? WORD? ? Machine;?????????????????????? ?//
INTEL 80386以上處理器必需為 4C 01 二字節(jié)
? ???? ?WORD? ? NumberOfSections;
?????? // 段的個(gè)數(shù) // P: 1. 是指哪里的 Sections ?? 2. 最多可以有多少個(gè) Sections?
??????? DWORD? TimeDateStamp;??????????? // 文件的創(chuàng)建日期和時(shí)間
??????? DWORD? PointerToSymbolTable;? // 用于調(diào)試
? ????? DWORD? NumberOfSymbols;??????? // 用于調(diào)試
? ????? WORD? ? SizeOfOptionalHeader;?? //
_IMAGE_OPTIONAL_HEADER有224字節(jié)所以為 E0 00
? ????? WORD? ? Characteristics;?????????? ?? // 關(guān)于文件信息的標(biāo)記,比如文件是EXE還是DLL?? EXE可執(zhí)行文件為02 00??
??? } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;?
?
??? 注:
???(1). Machine 字段表示這個(gè)PE文件被Build的目錄機(jī)器種類,eg DEC(R) Alpha、MIPS R4000、Inter(R) x86
????? 已知的合法值:?
??????IMAGE_FILE_MACHINE_I386 (0x14c)
??????????? Intel 80386 處理器或更高?
???? 0x014d
??????????? Intel 80386 處理器或更高?
???? 0x014e
??????????? Intel 80386 處理器或更高?
???? 0x0160?????????
???????????? R3000 (MIPS⑧)處理器,大尾⑨?
???? IMAGE_FILE_MACHINE_R3000 (0x162)
???????????? R3000 (MIPS)處理器,小尾?
???? IMAGE_FILE_MACHINE_R4000 (0x166)
???????????? R4000 (MIPS)處理器,小尾?
???? IMAGE_FILE_MACHINE_R10000 (0x168)
???????????? R10000 (MIPS)處理器,小尾?
???? IMAGE_FILE_MACHINE_ALPHA (0x184)
???????????? DEC Alpha AXP⑩處理器?
???? IMAGE_FILE_MACHINE_POWERPC (0x1F0)
???????????? IBM Power PC,小尾
(2).
NumberOfSections 字段表示 這個(gè)PE文件有多少個(gè)段(多少個(gè)段頭部和多少個(gè)段實(shí)體,每個(gè)段頭部和段實(shí)體都在文件中連續(xù)排列,?所以要決定段頭部和段實(shí)體在哪里結(jié)束的話,段的數(shù)目是必需的)
???
(3). 判斷一個(gè)文件是否是合法的PE文件
????????? a. 比較 MZ 頭的 e_magic 值是否為 IMAGE_DOS_SIGNATURE以驗(yàn)證是否是有效的DOS header
????????? b. 通過(guò) MZ 頭的 e_lfanew 所指向的偏移獲取 PE 頭
????????? c. 比較 PE 頭的 Signature 值是否為 IMAGE_NT_SIGNATURE
????????? 如果滿足以上條件,則可以認(rèn)為是一個(gè)合法的PE文件
?
(4). TimeDateStamp(32位),用來(lái)給出文件建立的時(shí)間。
???????? 同一個(gè)文件的不同版本必須唯一,時(shí)間戳的格式?jīng)]有明文規(guī)定,但似乎是按照UTC?
???????? (
時(shí)間“從1970年1月1日00:00:00算起的秒數(shù)值”----也就是大多數(shù)C語(yǔ)言編譯器給time_t標(biāo)志使用的格式。)
?????????P: 這個(gè)時(shí)間戳是用來(lái)綁定各個(gè)輸入目錄的?
???????? 警告:有一些鏈接器往往將時(shí)間戳設(shè)為荒唐的值,而不是如前所述的time_t格式的鏈接時(shí)間。
?
(5).
PointerToSymbolTable? 符號(hào)表指針
?????? NumberOfSymbols??????? 符號(hào)數(shù)
??????用于調(diào)試,
P: 總是為 0x00, 即使在 VC IDE 的 Project Setting 中設(shè)置了生成調(diào)試信息,也是為 0x00 , 為什么???????????
P: 1. NumberOfSections 表示 段的個(gè)數(shù),那么 WIN32.PE 最多有多少段?
?
?(6). SizeOfOptionalHeader
(16位)只是“IMAGE_OPTIONAL_HEADER(可選頭)”項(xiàng)的大小,?
P: 只是用于驗(yàn)證PE文件結(jié)構(gòu)的正確性?? 除了
E0 00 外是否有其它值?
(7). Characteristics (16位) 由許多標(biāo)志集合組成
位1? IMAGE_FILE_EXECUTABLE_IMAGE(可執(zhí)行映象文件) 表示如果文件是一個(gè)可執(zhí)行文件,
也即不是目標(biāo)文件或者庫(kù)文件時(shí),置1。?如果鏈接器嘗試創(chuàng)建一個(gè)可執(zhí)行文件,卻因?yàn)橐恍┰蚴×耍⒈4嬗诚褚员阆麓卫缭隽挎溄訒r(shí)使用,此時(shí)此標(biāo)志位也可能置1。?
位2? IMAGE_FILE_LINE_NUMS_STRIPPED(行數(shù)被剝離文件) 表示如果行數(shù)信息被剝除,此位置1;此位也不用于可執(zhí)行文件。P:可執(zhí)行文件不也有行數(shù)信息(假如PE編譯時(shí)加上調(diào)試信息的話)?
位3 IMAGE_FILE_LOCAL_SYMS_STRIPPED(本地符號(hào)被剝離文件) 表示如果文件中沒(méi)有關(guān)于本地符號(hào)的信息時(shí),此位置1(此位也不用于可執(zhí)行文件)。P: 同問(wèn)
位4 IMAGE_FILE_AGGRESIVE_WS_TRIM(強(qiáng)行工作集修剪文件) 表示如果操作系統(tǒng)被假定為:通過(guò)將正在運(yùn)行的進(jìn)程(它所使用的內(nèi)存數(shù)量)強(qiáng)行的頁(yè)清除來(lái)修剪它的工作集時(shí),此位置1。如果一進(jìn)程是大部分時(shí)間處于等待,且一天中僅被喚醒一次的演示性的應(yīng)用程序之類時(shí),此位也應(yīng)該被置1。P: 沒(méi)看懂這句的意思。
P: 第 5,6 位跑哪去了??
位7 IMAGE_FILE_BYTES_REVERSED_LO(低字節(jié)變換文件)和 位15IMAGE_FILE_BYTES_REVERSED_HI(高字節(jié)變換文件) 表示如果一文件的字節(jié)序不是機(jī)器所預(yù)期的形式,因此它在讀入前必須調(diào)換字節(jié)時(shí),此位置1。這樣做對(duì)可執(zhí)行文件是不可靠的(操作系統(tǒng)期望可執(zhí)行文件都已經(jīng)被正確地按字節(jié)排整齊了)。
位8 IMAGE_FILE_32BIT_MACHINE(32位機(jī)器文件) 表示如果使用的機(jī)器被期望為32位的機(jī)器時(shí),此位置1。現(xiàn)在的應(yīng)用程序總將此位置1;NT5系統(tǒng)可能工作不同。
位9 IMAGE_FILE_DEBUG_STRIPPED(調(diào)試信息被剝離文件) 表示如果文件中沒(méi)有調(diào)試信息,此位置1。此位可執(zhí)行文件不用。P: (PE文件不是可以包含調(diào)試信息?)
按照其它信息([6])(這里指的是參考書(shū)目中的第[6]種----譯者注),此位被稱作“恒定”,并且當(dāng)一個(gè)映象文件只有在被裝入優(yōu)先的裝入地址才能運(yùn)行(亦即:此文件不可重定位)時(shí),此位置1。
位10 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP(移動(dòng)介質(zhì)文件從交換文件運(yùn)行) 表示如果一個(gè)應(yīng)用程序不可以從可移動(dòng)的介質(zhì),如軟盤或CD-ROM上運(yùn)行時(shí),此位置1。在這種情況下,建議操作系統(tǒng)將文件復(fù)制到交換文件并從那里執(zhí)行。P: 不是很懂這里的意思,'軟盤或CD-ROM上運(yùn)行時(shí),此位置1。'
位11 IMAGE_FILE_NET_RUN_FROM_SWAP(網(wǎng)絡(luò)文件從交換文件運(yùn)行) 表示如果一個(gè)應(yīng)用程序不可以從網(wǎng)絡(luò)上運(yùn)行時(shí),此位置1。在這種情況下,建議操作系統(tǒng)將文件復(fù)制到交換文件并從那里執(zhí)行。
位12 IMAGE_FILE_SYSTEM(系統(tǒng)文件) 表示如果文件是一個(gè)象驅(qū)動(dòng)程序那樣的系統(tǒng)文件,此位置1。此位可執(zhí)行文件不用;我所見(jiàn)過(guò)的所有NT系統(tǒng)的驅(qū)動(dòng)程序也不用。
位13 IMAGE_FILE_DLL(DLL文件) 表示如果文件是一個(gè)DLL文件時(shí),此位置1。
位14 IMAGE_FILE_UP_SYSTEM_ONLY(僅但處理器系統(tǒng)的文件) 表示如果文件不設(shè)計(jì)運(yùn)行在多處理器系統(tǒng)上(也就是說(shuō),因?yàn)榇宋募?yán)格地依賴單一處理器的一些方式工作,所以它會(huì)發(fā)生沖突)時(shí),此位置1。
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES???? 16
typedef struct _IMAGE_OPTIONAL_HEADER
{?
???????? //
? ??? ?? // Standard fields.
? ???? ? //
? ????? ?WORD?? Magic;???????????????????
// 總是 0B 01??P: 可選頭的標(biāo)志?意義是?
???????? BYTE? ? MajorLinkerVersion;?? // 0 鏈接器的主版本號(hào)? // P:不同的鏈接器設(shè)置不同,因此不可靠?
???????? BYTE? ? MinorLinkerVersion;?? // 0 鏈接器的小版本號(hào)
???????? DWORD? SizeOfCode;?????????? // 0??????????????????????? // 可執(zhí)行的代碼的大小?
???????? P: 這里的可執(zhí)行代碼是指整個(gè)PE文件的可執(zhí)行代碼段?
???????? DWORD? SizeOfInitializedData;???? // 0????????????????? // 已初始化數(shù)據(jù)的大小 ,數(shù)據(jù)段
???????? DWORD? SizeOfUninitializedData;? // 0????????????????? // 未初始化數(shù)據(jù)的大小, BSS段?
???????? P: 已初始化的數(shù)據(jù)跟未初始化的數(shù)據(jù)有什么區(qū)別?它們都在數(shù)據(jù)段?
???????? DWORD? AddressOfEntryPoint;???? //??????????????????? //? 代碼的入口點(diǎn)地址(是一個(gè)偏移量,RVA), 如 LibMain, WinMain....
???????? DWORD? BaseOfCode;? // 0?????????????????????????????? //? 可執(zhí)行代碼的偏移量, 代碼基址?
???????? P: 不是很懂這里的意思,跟 AddressOfEntryPoint 的區(qū)別是?
???????? DWORD? BaseOfData;? // 0?????????????????????????????? //? 已初始化數(shù)據(jù)偏稱量,數(shù)據(jù)基址? P: 同問(wèn)
???????
???????? //
? ?????? // NT additional fields.
? ?????? //
? ?????? DWORD? ImageBase;????????? //載入程序的RVA地址,LOADER可以改變 00 00 40 00 == 0x400000
? ?????? DWORD? SectionAlignment; //段加載后在內(nèi)存的對(duì)齊方式 00 10 00 00
? ?????? DWORD? FileAlignment;????? //段在文件中的對(duì)齊方式 00 20 00 00
? ????? ?WORD? ? MajorOperatingSystemVersion;? // 0
? ????? ?WORD? ? MinorOperatingSystemVersion;? // 0
? ????? ?WORD? ? MajorImageVersion;??????????????? //? 0
??????? ?WORD? ? MinorImageVersion;??????????????? //? 0
? ????? ?WORD? ? MajorSubsystemVersion; //子系統(tǒng)版本號(hào)如果不是4.0? 對(duì)話框不能顯示3D風(fēng)格 04 00
? ????? ?WORD? ? MinorSubsystemVersion; // 0
? ????? ?DWORD? Win32VersionValue;?????? // 0
??????? ?DWORD? SizeOfImage;?????????????? // 映射到內(nèi)存的代碼長(zhǎng)度
??????? ?DWORD? SizeOfHeaders; //所有文件頭長(zhǎng)度之和 00 04 00 00???? (對(duì)齊后的, 包所在節(jié)?)
? ????? ?DWORD? CheckSum;????? // 校驗(yàn)和,用 0?
??????? ?WORD? ? Subsystem;???? // 子系統(tǒng) 02 00 或03 00 ?
? ????? ?WORD? ? DllCharacteristics;???? // 00
? ????? ?DWORD? SizeOfStackReserve;? // 00
??????? ?DWORD? SizeOfStackCommit;
? ????? ?DWORD? SizeOfHeapReserve;
? ????? ?DWORD? SizeOfHeapCommit;
? ????? ?DWORD? LoaderFlags;???????????? // 00
??????? ?DWORD? NumberOfRvaAndSizes;?
??????
????? ???IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
???????? // 16個(gè)結(jié)構(gòu),第二個(gè)結(jié)構(gòu)(導(dǎo)入表)?
???? } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;