Windows Pe 第三章 PE头文件(下)
3.5 ?數(shù)據(jù)結(jié)構(gòu)字段詳解
3.5.1 ?PE頭IMAGE_NT_HEADER的字段
????1.IMAGE_NT_HEADER.Signature
????+0000h,雙字。PE文件標(biāo)識(shí),被定義為00004550h。也就是“P”“E”加上兩個(gè)0,這也是PE這個(gè)稱呼的由來(lái)。如果更改其中任何一個(gè)字節(jié),操作系統(tǒng)就無(wú)法把該文件識(shí)別為正確的PE文件。通過(guò)修改這個(gè)字段,會(huì)導(dǎo)致PE文件在32位系統(tǒng)中加載失敗,但由于這個(gè)文件的其他部分(特別是DOS頭)還沒有被破壞,系統(tǒng)還是可以識(shí)別出其為DOS系統(tǒng)下的可執(zhí)行程序,并通過(guò)調(diào)用純DOS環(huán)境來(lái)運(yùn)行DOS Stub中的程序代碼。
如果你確認(rèn)操縱系統(tǒng)中的某個(gè)PE文件攜帶病毒,并且開機(jī)后會(huì)被加載進(jìn)內(nèi)存運(yùn)行,最簡(jiǎn)單的處理辦法是通過(guò)WindowsPE盤啟動(dòng)系統(tǒng)。在系統(tǒng)中找到病毒文件,使用記事本簡(jiǎn)單地修改其中任何一個(gè)字符,保存文件,重新開機(jī)后即可防止病毒文件被加載。
? ? 2.IMAGE_NT_HEADER.FileHeader
? ? +0004h,結(jié)構(gòu)。該結(jié)構(gòu)指向IMAGE_FILE_HEADER,由于PE擴(kuò)展自通用COFF規(guī)范,所以,該字段在官方文檔中被稱為標(biāo)準(zhǔn)COFF頭。
? ? 3.IMAGE_NT_HEADER.OptionalHeader
? ? +0018h,結(jié)構(gòu)。該結(jié)構(gòu)指向IMAGE_OPTIONAL_HEADER32。Windows操作系統(tǒng)可執(zhí)行文件的大部分特性均在這個(gè)結(jié)構(gòu)里呈現(xiàn)。因?yàn)榉?/span>COLL規(guī)范的”.obj”目標(biāo)文件中該部分并不存在,所以該部分被稱為OptionalHeader(可選的頭部信息,簡(jiǎn)稱 可選頭),它是操作系統(tǒng)映象文件所獨(dú)有的頭部信息。
可選頭又分為兩部分,前10個(gè)字段原屬于COFF,用來(lái)加載和運(yùn)行一個(gè)可執(zhí)行文件;后21個(gè)字段則是通過(guò)連接器加載的。他們作為PE擴(kuò)展部分,用于描述可執(zhí)行文件的一些信息,供PE加載器加載使用。
3.5.2 ?標(biāo)準(zhǔn)PE頭IMAGE_FILE_HEADER的字段
? ? 4.IMAGE_FILE_HEADER.Machine
? ? +0004h,單字。用來(lái)指定PE文件運(yùn)行的平臺(tái)。由于Windows最初設(shè)計(jì)為可以運(yùn)行在Intel、Sun、Dec、IBM等多種硬件平臺(tái)上,或者能模擬這些平臺(tái)的軟件環(huán)境中,而不同的硬件平臺(tái)其指令的機(jī)器碼不相同,因此為不同平臺(tái)編譯的EXE文件是無(wú)法通用的。假設(shè)將運(yùn)行在Intel 386機(jī)器上的PE文件該字段設(shè)置為01f0h,既指定平臺(tái)為IBM POWER PC(小尾方式),則系統(tǒng)會(huì)有下圖所示提示:
?
? ? 5.IMAGE_FILE_HEADER.NumberOfSections
? ? +0006h,單字。文件中存在的節(jié)的總數(shù)(XP中可以有0個(gè)節(jié)),數(shù)值不能小于1,也不能超過(guò)96。如果將該值設(shè)置為0,則系統(tǒng)裝載時(shí)會(huì)提示不是有效的Win32程序。如果想在PE中增加或刪除節(jié),必須改變此處的值。
另外,這個(gè)值既不能比實(shí)際內(nèi)存中多,也不能少,否則裝載時(shí)會(huì)發(fā)生錯(cuò)誤。
? ? 6.IMAGE_FILE_HEADER.TimeDateStamp
? ? +0008h,雙字。編譯器創(chuàng)建此文件時(shí)的時(shí)間戳。低32位存放的值是自1970年1月1日00:00時(shí)開始到創(chuàng)建時(shí)間為止的總秒數(shù)。
? ? 該數(shù)值可以所以修改而不會(huì)影響程序的運(yùn)行。所以,有的連接器在這里填入固定的值,有的則隨意寫入任何值,這對(duì)用戶創(chuàng)建的文件并沒有實(shí)際的意義。另外,這個(gè)時(shí)間與操作系統(tǒng)文件屬性里看到的三個(gè)時(shí)間(創(chuàng)建時(shí)間、修改時(shí)間、訪問(wèn)時(shí)間)也沒有任何聯(lián)系。
? ? 7.IMAGE_FILE_HEADER.PointerToSymbolTable
? ? +0010h,雙字。COFF符號(hào)表的文件偏移。如果不存在COFF符號(hào)表,此值為0。對(duì)于映象文件來(lái)說(shuō),此值為0,因?yàn)槲④浺呀?jīng)不贊成在PE中使用COFF調(diào)試信息了。
? ? 8.IMAGE_FILE_HEADER.NumberOfSymbols
+0010h,雙字。符號(hào)表中元素?cái)?shù)目。對(duì)于映象文件來(lái)說(shuō),此值為0,主要用于調(diào)試。
? ? 9.IMAGE_FILE_HEADER.SizeOfOptionalHeader
? ? +0014h,單字。指定結(jié)構(gòu)IMAGE_OPTIONAL_HEADER32的長(zhǎng)度,默認(rèn)情況下這個(gè)值等于00e0h;如果是64位PE文件,該結(jié)構(gòu)的默認(rèn)大小為00F0h。
? ? 用戶可以自己定義這個(gè)值的大小,不過(guò)需要注意兩點(diǎn):
? ? 1)改完之后,需要自行將文件中IMAGE_OPTIONAL_HEADER32的大小擴(kuò)充為你指定的值(一般以0補(bǔ)足)。
? ? 2)擴(kuò)充完以后,要維持文件中的對(duì)齊特性(比如在HelloWorld.exe中,此處增加了8個(gè)自節(jié)后,一定在后面相應(yīng)地刪除8個(gè)字節(jié),以保證.txt節(jié)起始位置處于0400h)。
? ? 10.IMAGE_FILE_HEADER.Characteristics
? ? +0016h,單字。文件屬性標(biāo)識(shí)字段,它的不同數(shù)據(jù)位蒂尼了不同文件屬性,具體內(nèi)容見表3-3。這是一個(gè)很重要的字段,不同的定義將影響系統(tǒng)對(duì)文件的裝入方式。比如,當(dāng)位13位1時(shí),表示這是一個(gè)DLL文件,那么系統(tǒng)將使用調(diào)用DLL入口函數(shù)的方式執(zhí)行文件入口函數(shù);當(dāng)13位為0時(shí),表示這是一個(gè)普通的可執(zhí)行文件,系統(tǒng)將直接跳到入口處執(zhí)行。對(duì)于普通的可執(zhí)行PE文件來(lái)說(shuō),這個(gè)字段一般是010fh(我剛剛看的我電腦上是0103),而對(duì)于DLL文件來(lái)說(shuō),這個(gè)字段值一般是210eh。(我電腦上是2102)
? ? 如表3-3所示,當(dāng)?shù)?/span>0位為1時(shí),表明此文件不包含基址重定位信息,因此必須將其加載到文件頭指定的機(jī)智地址字段位置。如果進(jìn)程空間此處的位置被占用,加載器就會(huì)報(bào)錯(cuò)。在程序運(yùn)行前如果發(fā)現(xiàn)文件中存在可重定位信息,連接器會(huì)執(zhí)行移除可執(zhí)行文件的重定位信息操作。
?
?當(dāng)?shù)?/span>1位為1時(shí),表明此映象文件是合法的,可以運(yùn)行。如果未設(shè)置此標(biāo)志,表明出現(xiàn)了連接器錯(cuò)誤。
當(dāng)?shù)?/span>7位為1時(shí),表示文件小尾方式,既內(nèi)存中,最低有效位LSB位于最高有效位MSB的前面,與第15位的大尾方式一樣,都不贊成使用該標(biāo)志,最好將其設(shè)置為0。
當(dāng)?shù)?/span>10位為1時(shí),如果此映象文件可在移動(dòng)存儲(chǔ)介質(zhì)上,那么加載器將完全加載它并把它復(fù)制到內(nèi)存交換文件中。
當(dāng)?shù)?/span>11位為1時(shí),如果此映象文件在網(wǎng)絡(luò)上,那么加載器也將完全加載并把它復(fù)制到內(nèi)存交換文件中。
當(dāng)?shù)?/span>13位為1時(shí),表明此映象文件是動(dòng)態(tài)鏈接庫(kù)(DLL).這樣的文件總被認(rèn)為是可執(zhí)行文件,盡管它們不能直接運(yùn)行。
可執(zhí)行文件的標(biāo)識(shí)設(shè)置為010fh,既第0 1 2 3 8違背設(shè)置為1,表示該文件為可執(zhí)行文件,不包含重定位信息,不包含符號(hào)和行號(hào)信息,文件只在32位平臺(tái)上運(yùn)行。
3.5.3 ?擴(kuò)展PE頭IMAGE_OPTIONAL_HEADER32字段
? ? 11.IMAGE_OPTIONAL_HEADER32.Magic
? ? +0018h,單字。魔術(shù)字,說(shuō)明文件類型,如果為010BH,則表示該文件為PE32;如果為0107H,則表示文件為ROM影像;如果為020BH,則表示該文件為PE32+,既64位下的PE文件。
? ? 12.IMAGE_OPTIONAL_HEADER32.MajorLinkerVersion
? ? 13.IMAGE_OPTIONAL_HEADER32.MinorLinkerVersion
? ? +001ah,單字。這兩個(gè)字段都是字節(jié)型,指定連接器版本號(hào),對(duì)執(zhí)行沒有任何影響。
? ? 14.IMAGE_OPTIONAL_HEADER32.SizeOfCode
? ? +001ch,雙字。所有代碼節(jié)的總和(以字節(jié)計(jì)算),該大小事基于文件對(duì)齊后的大小,而非內(nèi)存對(duì)齊后的大小。稍后還會(huì)介紹一個(gè)字段SIzeOfImage,它是基于內(nèi)存對(duì)齊后的大小。需要注意一點(diǎn):判斷某個(gè)節(jié)是否包含代碼的方法不是根據(jù)節(jié)的屬性中是否有IMAGE_SCN_MEM_EXECUTE標(biāo)志,而是根據(jù)節(jié)中是否含有IMAGE_SCN_CNT_CODE標(biāo)志。
? ? 15.IMAGE_OPTIONAL_HEADER32.SizeOflnitializedData
? ? +20h,雙字。所有包含已經(jīng)初始化的節(jié)的總大小。
? ? 16.IMAGE_OPTIONAL_HEADER32.SizeOfUninitializedData
? ? +0024h,雙字。所有包含未初始化的節(jié)的總大小。這些數(shù)據(jù)被定義在文件中不占用空間;但在被加載到內(nèi)存以后,PE加在程序應(yīng)該為這些數(shù)據(jù)分配適當(dāng)?shù)奶摂M地址空間。
? ? 17.IMAGE_OPTIONAL_HEADER32.AddressOfEntryPoint
? ? +0028h,雙字。在Windows中,可執(zhí)行程序運(yùn)行在虛擬地址空間中,由于4GB空間對(duì)于程序是唯一的,所以這里的虛擬空間可以簡(jiǎn)單地理解為真實(shí)地址(我們暫且忘記物理內(nèi)存地址概念,這樣就不需要理解頁(yè)面調(diào)度機(jī)制了)。該字段的值是一個(gè)RVA,它記錄了啟動(dòng)代碼距離該PE加載后其實(shí)位置到底有多少個(gè)字節(jié)。
如果在一個(gè)可執(zhí)行文件中附加了一段自己的代碼,并且想讓這段代碼首先被執(zhí)行,一般都要修改這里的值使之指向自己的代碼的位置。對(duì)于一般程序映象來(lái)說(shuō),他就是啟動(dòng)地址;對(duì)于設(shè)備驅(qū)動(dòng)程序來(lái)說(shuō),他是初始化函數(shù)地址。入口點(diǎn)對(duì)于DLL來(lái)說(shuō)是可選的,如果不存在入口點(diǎn),這個(gè)字段必須設(shè)置為0。
(許多病毒程序、加載程序、補(bǔ)丁程序都會(huì)劫持這里的值,是指指向其他擁堵的代碼地址。)
? ? 18.IMAGE_OPTIONAL_HEADER32.BaseOfCode
? ?+002CH,雙字。代碼節(jié)的其實(shí)RVA,表示映象被加載進(jìn)內(nèi)存時(shí)執(zhí)行代碼節(jié)的開頭相對(duì)于映象基址的偏移地址。一般情況下,代碼節(jié)緊跟在PE頭部后面,節(jié)的名稱通常為”.text”。
? ? 19.IMAGE_OPTIONAL_HEADER32.BaseOfData
????+0030h,雙字。數(shù)據(jù)節(jié)的其實(shí)RVA,表示映象被加載進(jìn)內(nèi)存時(shí)數(shù)據(jù)節(jié)的開頭相對(duì)于映象基地址的偏移地址。一般情況下,數(shù)據(jù)節(jié)位于文件末尾,節(jié)的名稱通常稱為”.data”。
20.IMAGE_OPTIONAL_HEADER32.imageBase
????+0031h,雙字。該字段指出了PE映象的優(yōu)先裝入地址。也就是在IMAGE_OPTIONAL_HEADER32.AddressOfEntryPoint中說(shuō)的程序被加載到內(nèi)存后的起始VA.那么為什么要設(shè)置這個(gè)地址呢?因?yàn)殒溄悠髟诋a(chǎn)生可執(zhí)行文件的時(shí)候,是對(duì)應(yīng)這個(gè)地址來(lái)生成機(jī)器碼的。如果操作系統(tǒng)也是按照這個(gè)地址加載機(jī)器碼到內(nèi)存中,那么執(zhí)行中的許多重定位信息就不需要修改了,這樣運(yùn)行速度就會(huì)更快一些。
? ? 前面說(shuō)過(guò),對(duì)于EXE文件來(lái)說(shuō),每個(gè)文件使用的都是獨(dú)立的虛擬地址空間,所以,優(yōu)先裝入的地址通常不會(huì)被其他模塊占據(jù)。也就是說(shuō),EXE文件總是能按照這個(gè)地址裝入,這就意味著裝入后的EXE文件不需要進(jìn)行重定位了,例如,在HelloWorld.exe中就看不到重定位信息。
? ? 在鏈接的時(shí)候,可以使用參數(shù)“-base”來(lái)指定優(yōu)先裝入的地址,如果不指定,那么連接器默認(rèn)裝入EXE地址就是0x00400000。而對(duì)于DLL文件來(lái)說(shuō),它默認(rèn)優(yōu)先轉(zhuǎn)入地址則是0x10000000。如果一個(gè)進(jìn)程用到了多個(gè)DLL文件,其裝入地址可能會(huì)發(fā)生沖突。PE加載器會(huì)調(diào)整其中的地址。使所有的DLL文件都能被正確裝入、所以,不要錯(cuò)誤地認(rèn)為內(nèi)存中動(dòng)態(tài)鏈接庫(kù)的基地址和其文件頭字段IMAGE_OPTIONAL_HEADER32.imagrBase指定的完全一樣。
? ? 可以自己定義這個(gè)值,但取值有限制:第一,取值不能超出邊界,既取的值必須在進(jìn)程地址空間中;第二,該值必須是64KB的整數(shù)倍。
? ? 21.IMAGE_OPTIONAL_HEADER32.SectionAlignment
? ? +0038h,雙字。內(nèi)存中節(jié)的對(duì)齊粒度,該資源指定了節(jié)被裝入內(nèi)存后的對(duì)齊單位。為什么要對(duì)齊?不對(duì)齊的數(shù)據(jù)可以節(jié)省空間,但沒有規(guī)律,而且要在運(yùn)行時(shí)需要從磁盤文件調(diào)入內(nèi)存分也是容易導(dǎo)致效率低下。大家應(yīng)該學(xué)習(xí)過(guò)匯編,知道為什么在16位匯編里取數(shù)時(shí)要從偶地址開始嗎?(取一個(gè)字從偶地址開始,只需要一個(gè)CPU周期可以去到;而從奇地址取一個(gè)字節(jié),則需要兩個(gè)CPU周期。)其實(shí),對(duì)其和它是一個(gè)道理,內(nèi)存中的數(shù)據(jù)存取以頁(yè)面為單位。Win32的頁(yè)面大小事4KB,所以Win32PE中節(jié)的內(nèi)存對(duì)齊粒度一般都選擇4KB(01000h)。
? ? SectionAlignment必須大于或等于FileAlignment。當(dāng)它小于系統(tǒng)頁(yè)面大小時(shí),必須保證SectionAlinment和FileAlignment相等。
? ?22.IMAGE_OPTIONAL_HEADER32.FileAlignment
????+003ch,雙字。文件中節(jié)的對(duì)齊粒度。文件中的節(jié)對(duì)齊并不是提高程序本身的執(zhí)行效率,同樣也是為了從磁盤加載的效率。WindowsXP用來(lái)阻止硬盤的所有文件系統(tǒng)都是基于簇(分配單元)的,(每個(gè)簇包含幾個(gè)扇區(qū)的大小)。扇區(qū)是磁盤物理存取的最小單位。簇越大,磁盤存儲(chǔ)信息容量就越大,但存取所花的時(shí)間也越長(zhǎng)。通常情況下,Windows會(huì)選擇使用512字節(jié)的簇大小(一個(gè)物理扇區(qū)的大小)來(lái)格式化分區(qū),最大可以達(dá)到4KB。在本書的例子中,文件對(duì)齊粒度選擇了512字節(jié)(200h)。
查看簇大小:
?
? ? 23.IMAGE_OPTIONAL_HEADER32.MajorOperatingSystemVersion
? ? 24.IMAGE_OPTIONAL_HEADER32.MinorOperationgSystemVersion
? ? +0040h,23和24標(biāo)注的兩個(gè)字段都位單字,共計(jì)為雙字。表示操作系統(tǒng)的版本號(hào),分為主版本號(hào)和次版本號(hào)兩部分。
? ? 25.IMAGE_OPTIONAL_HEADER32.MajorlmageVersion
? ? 26.IMAGE_OPTIONAL_HEADER32.MinorlmageVersion
? ? +0044h,雙字。本PE文件影像的版本號(hào)。
? ? 27.IMAGE_OPTIONAL_HEADER32.MajorSubsystemVersion
? ? 28.IMAGE_OPTIONAL_HEADER32.MinorSubsystemVersion
? ? +0044h,雙字。本PE文件影響的版本號(hào)。
? ? 27.IMAGE_OPTIONAL_HEADER32.MajorSubsystemVersion
? ? 28.IMAGE_OPTIONAL_HEADER32.MinorSubsystemVersion
? ? +0048,雙字。運(yùn)行所需要的子系統(tǒng)的版本號(hào)。
????29.IMAGE_OPTIONAL_HEADER32.Win32VersionValue
? ? +004ch,雙字。子系統(tǒng)版本的值,保留,必須0.否則將導(dǎo)致運(yùn)行失敗。
? ? 30.IMAGE_OPTIONAL_HEADER32.SizeOfimage
? ? +0050h,雙字。內(nèi)存中整個(gè)PE文件的映射尺寸。已加載到內(nèi)充中的HelloWorld.exe為例,HelloWorld.exe中文件頭占用了1000h字節(jié),三個(gè)節(jié)各占用1000h,所以文件在內(nèi)存中占用的空間總大小為04000h。該值可以比實(shí)際的值大,但不能比他小,而且必須保證該值是SectionAlignment的整數(shù)倍。
????31.IMAGE_OPTIONAL_HEADER32.SizeOfHeaders
+0054h,雙字。所有頭+節(jié)表按照文件對(duì)齊粒度對(duì)齊后的大小,HellpWorld.exe中的值為0400h.在PE文件中,該部分?jǐn)?shù)據(jù)是嚴(yán)格按照200h對(duì)齊的,如果不對(duì)齊,系統(tǒng)加載時(shí)會(huì)提示出錯(cuò)。
? ? 32.IMAGE_OPTIONAL_HEADER32.CheckSum
? ? +0058h,雙字。校驗(yàn)和,在大多數(shù)的PE文件中,該值是0,但在一些內(nèi)核模式的驅(qū)動(dòng)程序和系統(tǒng)DLL中,該值則是必須存在且正確的,比如kernel32.dll中PE的校驗(yàn)和是0011E97eh。
我本機(jī)上的不是。
?
? ? Windows系統(tǒng)目錄下有一個(gè)動(dòng)態(tài)鏈接庫(kù)IMAGEHELP.DLL,它是Win32中專門用來(lái)操作PE文件的函數(shù)庫(kù),這里的函數(shù)CheckSumMappedFile就是用來(lái)計(jì)算文件頭校驗(yàn)和的,對(duì)于整個(gè)PE文件也有一個(gè)校驗(yàn)和函數(shù)MapFileAndCheckSum。該動(dòng)態(tài)間接庫(kù)中還包含其他一些常用的函數(shù),可以通過(guò)小工具PEinfo輸出并查看。關(guān)于校驗(yàn)和的具體計(jì)算方法,可參照3.7接種關(guān)于PE文件頭編程的部分。
? ? 33.IMAGE_OPTIONAL_HEADER32.Subsystem
? ? +005ch,單字。指定使用界面的子系統(tǒng),它的取值如表3-4所示。這個(gè)字段決定了系統(tǒng)如何為程序連接初始的界面,連接時(shí)使用參數(shù)-subsystem:xxx先選指定的就是這個(gè)字段的值,如果將子系統(tǒng)指定為Windows命令行交互模式(CUI),那么系統(tǒng)會(huì)自動(dòng)為程序建立一個(gè)控制臺(tái)窗口;如果是GUI,窗口程序代碼必須由用戶自己建立。
對(duì)于上面,我手動(dòng)測(cè)試了兩件事:
(1)cui程序我直接給成gui了,就是把
????
2改成3了,結(jié)果發(fā)現(xiàn)黑色界面消失了,但是進(jìn)程還在。
(2)又找到一個(gè)界面的程序,C++寫的,然后把3改成2了,結(jié)果是既彈出了主程序界面,又多彈出了一個(gè)cui的黑色界面(開始是想該C#寫的一個(gè)程序。結(jié)果二進(jìn)制編輯的那個(gè)軟件一直加載不了那個(gè)文件。)
MASM32的link程序的鏈接開關(guān)-subsystem的常見選項(xiàng)如3-5所示。
?
? ? 34.IMAGE_OPTIONAL_HEADER32.DLLCharacteristics
? ? +005eh,單字。DLL文件屬性。它是一個(gè)標(biāo)志集,不是針對(duì)DLL文件的,而是針對(duì)所有PE文件的。
?
? ? 該字段定義了PE文件裝載時(shí)的一些特性,第十章會(huì)提供一個(gè)使用該標(biāo)志的例子。
? ? 35.IMAGE_OPTIONAL_HEADER32.SizeOfStackReserve
? ? +0060h,雙字。初始化時(shí)八六棧的大小。該字段表示為初始化線程的棧而保留的虛擬內(nèi)存數(shù)量,然而并不是留出的所有虛擬內(nèi)存都可以做棧(真正的棧大小由下一個(gè)字段SizeOfStackCommit決定)。該字段的默認(rèn)值為0x100000(1M)
,如果調(diào)用API函數(shù)CreateThread時(shí),把NULL當(dāng)做當(dāng)做傳入的參數(shù),那么創(chuàng)建出來(lái)的棧大小也是1MB。
? ? 36.IMAGE_OPTIONAL_HEADER32.SizeOfStackCommit
? ? +0064h,雙字。初始化時(shí)實(shí)際提交的棧大小。
? ? 37.IMAGE_OPTIONAL_HEADER32.SizeOfHeapReserve
? ? +0068h,雙字。初始化是保留的堆大小。用來(lái)保留給初始進(jìn)程堆使用的虛擬內(nèi)存,這個(gè)堆的句柄可以通過(guò)調(diào)用GetProcessHeap函數(shù)獲得。每一個(gè)進(jìn)程至少會(huì)有一個(gè)默認(rèn)的進(jìn)程堆,該堆在進(jìn)程啟動(dòng)時(shí)被創(chuàng)建,而且在進(jìn)程的生命期中韻苑不會(huì)被刪除。默認(rèn)為1MB。
? ? 38.IMAGE_OPTIONAL_HEADER32.SizeOfHeapCommit
? ? +006ch,雙字。初始化實(shí)際提交的堆大小,在進(jìn)程初始化時(shí)設(shè)定的堆所占用的內(nèi)存空間。默認(rèn)值為1頁(yè)。
? ? 39.IMAGE_OPTIONAL_HEADER32.LoaderFlags
? ? +0074h,雙字。加載標(biāo)記。
? ? 40.IMAGE_OPTIONAL_HEADER32.NumberOfRvaAndSize
? ? +0074h,雙字。定義數(shù)據(jù)目錄結(jié)構(gòu)的數(shù)量,一般為00000010h,即16個(gè)。該值由字段SizeOfOptionalHeaders決定,實(shí)際應(yīng)用中可取2-16的值。
? ? 41.IMAGE_OPTIONAL_HEADER32.DataDirectory
? ? +0078h,結(jié)構(gòu)。由16個(gè)IMAGE_DATA_DIRECTORY結(jié)構(gòu)線性排列而成,用于定義PE中的16種不同類別的數(shù)據(jù)所在的位置和大小。前面已經(jīng)對(duì)這部分做過(guò)說(shuō)明,后面將會(huì)對(duì)這些數(shù)據(jù)進(jìn)行詳細(xì)描述。一下是對(duì)這16種數(shù)據(jù)的說(shuō)明:
?
3.5.4 ?數(shù)據(jù)目錄項(xiàng)IMAGE_DATA_DIRECTORY的字段
? ? 42.IMAGE_DATA_DIRECTORY.VirtualAddress
? ? +0000h,雙字。這個(gè)字段記錄了特定類型數(shù)據(jù)的起始RVA。當(dāng)然,針對(duì)不同的數(shù)據(jù)結(jié)構(gòu),該字段包含的數(shù)據(jù)含義并不一樣,有的數(shù)據(jù)甚至還不是RVA(如屬性證書數(shù)據(jù)中該字段的值表示的是FOA)。
? ? 43.IMAGE_DATA_DIRECTORY.isize
? ? +0004h,雙字。該字段記錄了特定類型的數(shù)據(jù)的長(zhǎng)度。
3.5.5 節(jié)表項(xiàng) IMAGE_SECTION_HEADER的字段
? ? 44.IMAGE_SECTION_HEADER.Name1
? ? +0000h,8字節(jié)。該字段一共8個(gè)字節(jié),一般情況下是以一個(gè)”\0”結(jié)尾的ASCII碼字符串來(lái)標(biāo)示節(jié)的名稱,內(nèi)容可以自行定義。
? ? 該名稱并不遵循Ansi字符串必須”\0”結(jié)尾的規(guī)律,如果不易”\0”結(jié)尾,系統(tǒng)依然會(huì)認(rèn)為它是一個(gè)字符串,但會(huì)根據(jù)8個(gè)字節(jié)長(zhǎng)度對(duì)其進(jìn)行截?cái)嗵幚怼?/span>
? ? 45.IMAGE_SECTION_HEADER.Misc
? ? +0008h,雙字。該字段是一個(gè)union型數(shù)據(jù),這是節(jié)數(shù)據(jù)在沒有對(duì)齊前的真是尺寸,不過(guò)很多PE文件里該節(jié)值并不準(zhǔn)確。
? ? 46.IMAGE_SECTION_HEADER.VirtualAddress
? ? +000ch,雙字。節(jié)區(qū)的RVA地址。
? ? 47.IMAGE_SECTION_HEADER.SizeOfRawData
? ? +0010h,雙字。節(jié)在文件中對(duì)齊后的尺寸。在HelloWorld.exe中,數(shù)據(jù)量不大的節(jié),其大小一般為200h。
? ??48.IMAGE_SECTION_HEADER.PointerToRawData
? ??+0014h,雙字。節(jié)區(qū)其實(shí)數(shù)據(jù)在文件中的偏移。
?
? ??49.IMAGE_SECTION_HEADER.PointerToRelocations
? ??+0018h,雙字。在.obj文件中使用,指向重定位表的指針。
? ??50.IMAGE_SECTION_HEADER.PointerToLinenumbers
? ??+001ch,雙字。行號(hào)表的位置(供調(diào)試用)。
? ??51.IMAGE_SECTION_HEADER.NumberOfRelocations
? ??+0020h,單子。重定位表的個(gè)數(shù)(在OBJ文件中使用)。
? ??52.IMAGE_SECTION_HEADER.NumberOfLinenumbers
? ??+0022h,單子。行號(hào)表中行號(hào)的數(shù)量。
? ??53.IMAGE_SECTION_HEADER.Characteristics
? ??+0024h,雙字。節(jié)的屬性。這個(gè)字段很重要,這是節(jié)的屬性標(biāo)志字段,其中不同的數(shù)據(jù)位代表了不同的屬性,具體的定義如表3-7所示,這些數(shù)據(jù)位的組合表述了內(nèi)存中一個(gè)節(jié)所擁有的訪問(wèn)屬性。
?
3.5.6 ?解析HelloWorld程序的字節(jié)碼
? ? 這一節(jié)是吧exe用二進(jìn)制工具打開,然后把上面的所有字段都找到然后在圖片上標(biāo)記出來(lái)。這個(gè)不總結(jié)了,比較簡(jiǎn)單。可以用一個(gè)可以看PE結(jié)構(gòu)的程序,去找到每個(gè)段的地址,然后去看對(duì)應(yīng)的內(nèi)容就行了。
最后還有一個(gè)提示:
3.6PE內(nèi)存映像
把exe加載到OD里,然后 查看->內(nèi)存 ,看其內(nèi)存分配。
?
文件字節(jié)碼在內(nèi)存中的大致分布 : PE頭文件+代碼+輸入表+數(shù)據(jù)
書中的HelloWorld的文件-內(nèi)存關(guān)系是
?
我自己編寫的Helloworld略有不同,.text段是2000h
?
?????由上面可以知道,頭+節(jié)表 部分的數(shù)據(jù)沒有任何更改,多出部分0填充。這個(gè)對(duì)于這個(gè)節(jié),
其對(duì)齊的方式則是由數(shù)據(jù)結(jié)構(gòu)中的字段IMAGE_ OPTIONAL_HEADER32.FileAlignment和IMAGE_OPTIONAL_HEADER32.Section Alignment分別定義。
總結(jié)
以上是生活随笔為你收集整理的Windows Pe 第三章 PE头文件(下)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows Pe 第三章 PE头文件
- 下一篇: Windows Pe 第三章 PE头文件