日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows Pe 第三章 PE头文件(下)

發布時間:2025/6/17 windows 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows Pe 第三章 PE头文件(下) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

3.5 ?數據結構字段詳解

3.5.1 ?PEIMAGE_NT_HEADER的字段

????1.IMAGE_NT_HEADER.Signature

????+0000h,雙字。PE文件標識,被定義為00004550h。也就是“P”“E”加上兩個0,這也是PE這個稱呼的由來。如果更改其中任何一個字節,操作系統就無法把該文件識別為正確的PE文件。通過修改這個字段,會導致PE文件在32位系統中加載失敗,但由于這個文件的其他部分(特別是DOS頭)還沒有被破壞,系統還是可以識別出其為DOS系統下的可執行程序,并通過調用純DOS環境來運行DOS Stub中的程序代碼。

如果你確認操縱系統中的某個PE文件攜帶病毒,并且開機后會被加載進內存運行,最簡單的處理辦法是通過WindowsPE盤啟動系統。在系統中找到病毒文件,使用記事本簡單地修改其中任何一個字符,保存文件,重新開機后即可防止病毒文件被加載。

? ? 2.IMAGE_NT_HEADER.FileHeader

? ? +0004h,結構。該結構指向IMAGE_FILE_HEADER,由于PE擴展自通用COFF規范,所以,該字段在官方文檔中被稱為標準COFF頭。

? ? 3.IMAGE_NT_HEADER.OptionalHeader

? ? +0018h,結構。該結構指向IMAGE_OPTIONAL_HEADER32。Windows操作系統可執行文件的大部分特性均在這個結構里呈現。因為符合COLL規范的”.obj”目標文件中該部分并不存在,所以該部分被稱為OptionalHeader(可選的頭部信息,簡稱 可選頭),它是操作系統映象文件所獨有的頭部信息。

可選頭又分為兩部分,前10個字段原屬于COFF,用來加載和運行一個可執行文件;后21個字段則是通過連接器加載的。他們作為PE擴展部分,用于描述可執行文件的一些信息,供PE加載器加載使用。

3.5.2 ?標準PEIMAGE_FILE_HEADER的字段

? ? 4.IMAGE_FILE_HEADER.Machine

? ? +0004h,單字。用來指定PE文件運行的平臺。由于Windows最初設計為可以運行在Intel、SunDec、IBM等多種硬件平臺上,或者能模擬這些平臺的軟件環境中,而不同的硬件平臺其指令的機器碼不相同,因此為不同平臺編譯的EXE文件是無法通用的。假設將運行在Intel 386機器上的PE文件該字段設置為01f0h,既指定平臺為IBM POWER PC(小尾方式),則系統會有下圖所示提示:

?


? ? 5.IMAGE_FILE_HEADER.NumberOfSections

? ? +0006h,單字。文件中存在的節的總數(XP中可以有0個節),數值不能小于1,也不能超過96。如果將該值設置為0,則系統裝載時會提示不是有效的Win32程序。如果想在PE中增加或刪除節,必須改變此處的值。

另外,這個值既不能比實際內存中多,也不能少,否則裝載時會發生錯誤。

? ? 6.IMAGE_FILE_HEADER.TimeDateStamp

? ? +0008h,雙字。編譯器創建此文件時的時間戳。低32位存放的值是自19701100:00時開始到創建時間為止的總秒數。

? ? 該數值可以所以修改而不會影響程序的運行。所以,有的連接器在這里填入固定的值,有的則隨意寫入任何值,這對用戶創建的文件并沒有實際的意義。另外,這個時間與操作系統文件屬性里看到的三個時間(創建時間、修改時間、訪問時間)也沒有任何聯系。

? ? 7.IMAGE_FILE_HEADER.PointerToSymbolTable

? ? +0010h,雙字。COFF符號表的文件偏移。如果不存在COFF符號表,此值為0。對于映象文件來說,此值為0,因為微軟已經不贊成在PE中使用COFF調試信息了。

? ? 8.IMAGE_FILE_HEADER.NumberOfSymbols

+0010h,雙字。符號表中元素數目。對于映象文件來說,此值為0,主要用于調試。

? ? 9.IMAGE_FILE_HEADER.SizeOfOptionalHeader

? ? +0014h,單字。指定結構IMAGE_OPTIONAL_HEADER32的長度,默認情況下這個值等于00e0h;如果是64PE文件,該結構的默認大小為00F0h

? ? 用戶可以自己定義這個值的大小,不過需要注意兩點:

? ? 1)改完之后,需要自行將文件中IMAGE_OPTIONAL_HEADER32的大小擴充為你指定的值(一般以0補足)。

? ? 2)擴充完以后,要維持文件中的對齊特性(比如在HelloWorld.exe中,此處增加了8個自節后,一定在后面相應地刪除8個字節,以保證.txt節起始位置處于0400h)。

? ? 10.IMAGE_FILE_HEADER.Characteristics

? ? +0016h,單字。文件屬性標識字段,它的不同數據位蒂尼了不同文件屬性,具體內容見表3-3。這是一個很重要的字段,不同的定義將影響系統對文件的裝入方式。比如,當位131時,表示這是一個DLL文件,那么系統將使用調用DLL入口函數的方式執行文件入口函數;當13位為0時,表示這是一個普通的可執行文件,系統將直接跳到入口處執行。對于普通的可執行PE文件來說,這個字段一般是010fh(我剛剛看的我電腦上是0103),而對于DLL文件來說,這個字段值一般是210eh。(我電腦上是2102

? ? 如表3-3所示,當第0位為1時,表明此文件不包含基址重定位信息,因此必須將其加載到文件頭指定的機智地址字段位置。如果進程空間此處的位置被占用,加載器就會報錯。在程序運行前如果發現文件中存在可重定位信息,連接器會執行移除可執行文件的重定位信息操作。

?

?當第1位為1時,表明此映象文件是合法的,可以運行。如果未設置此標志,表明出現了連接器錯誤。

當第7位為1時,表示文件小尾方式,既內存中,最低有效位LSB位于最高有效位MSB的前面,與第15位的大尾方式一樣,都不贊成使用該標志,最好將其設置為0。

當第10位為1時,如果此映象文件可在移動存儲介質上,那么加載器將完全加載它并把它復制到內存交換文件中。

當第11位為1時,如果此映象文件在網絡上,那么加載器也將完全加載并把它復制到內存交換文件中。

當第13位為1時,表明此映象文件是動態鏈接庫(DLL.這樣的文件總被認為是可執行文件,盡管它們不能直接運行。

可執行文件的標識設置為010fh,既第0 1 2 3 8違背設置為1,表示該文件為可執行文件,不包含重定位信息,不包含符號和行號信息,文件只在32位平臺上運行。

3.5.3 ?擴展PEIMAGE_OPTIONAL_HEADER32字段

? ? 11.IMAGE_OPTIONAL_HEADER32.Magic

? ? +0018h,單字。魔術字,說明文件類型,如果為010BH,則表示該文件為PE32;如果為0107H,則表示文件為ROM影像;如果為020BH,則表示該文件為PE32+,既64位下的PE文件。

? ? 12.IMAGE_OPTIONAL_HEADER32.MajorLinkerVersion

? ? 13.IMAGE_OPTIONAL_HEADER32.MinorLinkerVersion

? ? +001ah,單字。這兩個字段都是字節型,指定連接器版本號,對執行沒有任何影響。

? ? 14.IMAGE_OPTIONAL_HEADER32.SizeOfCode

? ? +001ch,雙字。所有代碼節的總和(以字節計算),該大小事基于文件對齊后的大小,而非內存對齊后的大小。稍后還會介紹一個字段SIzeOfImage,它是基于內存對齊后的大小。需要注意一點:判斷某個節是否包含代碼的方法不是根據節的屬性中是否有IMAGE_SCN_MEM_EXECUTE標志,而是根據節中是否含有IMAGE_SCN_CNT_CODE標志。

? ? 15.IMAGE_OPTIONAL_HEADER32.SizeOflnitializedData

? ? +20h,雙字。所有包含已經初始化的節的總大小。

? ? 16.IMAGE_OPTIONAL_HEADER32.SizeOfUninitializedData

? ? +0024h,雙字。所有包含未初始化的節的總大小。這些數據被定義在文件中不占用空間;但在被加載到內存以后,PE加在程序應該為這些數據分配適當的虛擬地址空間。

? ? 17.IMAGE_OPTIONAL_HEADER32.AddressOfEntryPoint

? ? +0028h,雙字。在Windows中,可執行程序運行在虛擬地址空間中,由于4GB空間對于程序是唯一的,所以這里的虛擬空間可以簡單地理解為真實地址(我們暫且忘記物理內存地址概念,這樣就不需要理解頁面調度機制了)。該字段的值是一個RVA,它記錄了啟動代碼距離該PE加載后其實位置到底有多少個字節。

如果在一個可執行文件中附加了一段自己的代碼,并且想讓這段代碼首先被執行,一般都要修改這里的值使之指向自己的代碼的位置。對于一般程序映象來說,他就是啟動地址;對于設備驅動程序來說,他是初始化函數地址。入口點對于DLL來說是可選的,如果不存在入口點,這個字段必須設置為0

(許多病毒程序、加載程序、補丁程序都會劫持這里的值,是指指向其他擁堵的代碼地址。)

? ? 18.IMAGE_OPTIONAL_HEADER32.BaseOfCode

? ?+002CH,雙字。代碼節的其實RVA,表示映象被加載進內存時執行代碼節的開頭相對于映象基址的偏移地址。一般情況下,代碼節緊跟在PE頭部后面,節的名稱通常為”.text”。

? ? 19.IMAGE_OPTIONAL_HEADER32.BaseOfData

????+0030h,雙字。數據節的其實RVA,表示映象被加載進內存時數據節的開頭相對于映象基地址的偏移地址。一般情況下,數據節位于文件末尾,節的名稱通常稱為”.data”。

20.IMAGE_OPTIONAL_HEADER32.imageBase

????+0031h,雙字。該字段指出了PE映象的優先裝入地址。也就是在IMAGE_OPTIONAL_HEADER32.AddressOfEntryPoint中說的程序被加載到內存后的起始VA.那么為什么要設置這個地址呢?因為鏈接器在產生可執行文件的時候,是對應這個地址來生成機器碼的。如果操作系統也是按照這個地址加載機器碼到內存中,那么執行中的許多重定位信息就不需要修改了,這樣運行速度就會更快一些。

? ? 前面說過,對于EXE文件來說,每個文件使用的都是獨立的虛擬地址空間,所以,優先裝入的地址通常不會被其他模塊占據。也就是說,EXE文件總是能按照這個地址裝入,這就意味著裝入后的EXE文件不需要進行重定位了,例如,在HelloWorld.exe中就看不到重定位信息。

? ? 在鏈接的時候,可以使用參數-base”來指定優先裝入的地址,如果不指定,那么連接器默認裝入EXE地址就是0x00400000。而對于DLL文件來說,它默認優先轉入地址則是0x10000000。如果一個進程用到了多個DLL文件,其裝入地址可能會發生沖突。PE加載器會調整其中的地址。使所有的DLL文件都能被正確裝入、所以,不要錯誤地認為內存中動態鏈接庫的基地址和其文件頭字段IMAGE_OPTIONAL_HEADER32.imagrBase指定的完全一樣。

? ? 可以自己定義這個值,但取值有限制:第一,取值不能超出邊界,既取的值必須在進程地址空間中;第二,該值必須是64KB的整數倍。

? ? 21.IMAGE_OPTIONAL_HEADER32.SectionAlignment

? ? +0038h,雙字。內存中節的對齊粒度,該資源指定了節被裝入內存后的對齊單位。為什么要對齊?不對齊的數據可以節省空間,但沒有規律,而且要在運行時需要從磁盤文件調入內存分也是容易導致效率低下。大家應該學習過匯編,知道為什么在16位匯編里取數時要從偶地址開始嗎?(取一個字從偶地址開始,只需要一個CPU周期可以去到;而從奇地址取一個字節,則需要兩個CPU周期。)其實,對其和它是一個道理,內存中的數據存取以頁面為單位。Win32的頁面大小事4KB,所以Win32PE中節的內存對齊粒度一般都選擇4KB(01000h)。

? ? SectionAlignment必須大于或等于FileAlignment。當它小于系統頁面大小時,必須保證SectionAlinmentFileAlignment相等。

? ?22.IMAGE_OPTIONAL_HEADER32.FileAlignment

????+003ch,雙字。文件中節的對齊粒度。文件中的節對齊并不是提高程序本身的執行效率,同樣也是為了從磁盤加載的效率。WindowsXP用來阻止硬盤的所有文件系統都是基于簇(分配單元)的,(每個簇包含幾個扇區的大小)。扇區是磁盤物理存取的最小單位。簇越大,磁盤存儲信息容量就越大,但存取所花的時間也越長。通常情況下,Windows會選擇使用512字節的簇大小(一個物理扇區的大小)來格式化分區,最大可以達到4KB。在本書的例子中,文件對齊粒度選擇了512字節(200h)。

查看簇大小:

?

? ? 23.IMAGE_OPTIONAL_HEADER32.MajorOperatingSystemVersion

? ? 24.IMAGE_OPTIONAL_HEADER32.MinorOperationgSystemVersion

? ? +0040h2324標注的兩個字段都位單字,共計為雙字。表示操作系統的版本號,分為主版本號和次版本號兩部分。

? ? 25.IMAGE_OPTIONAL_HEADER32.MajorlmageVersion

? ? 26.IMAGE_OPTIONAL_HEADER32.MinorlmageVersion

? ? +0044h,雙字。本PE文件影像的版本號。

? ? 27.IMAGE_OPTIONAL_HEADER32.MajorSubsystemVersion

? ? 28.IMAGE_OPTIONAL_HEADER32.MinorSubsystemVersion

? ? +0044h,雙字。本PE文件影響的版本號。

? ? 27.IMAGE_OPTIONAL_HEADER32.MajorSubsystemVersion

? ? 28.IMAGE_OPTIONAL_HEADER32.MinorSubsystemVersion

? ? +0048,雙字。運行所需要的子系統的版本號。

????29.IMAGE_OPTIONAL_HEADER32.Win32VersionValue

? ? +004ch,雙字。子系統版本的值,保留,必須0.否則將導致運行失敗。

? ? 30.IMAGE_OPTIONAL_HEADER32.SizeOfimage

? ? +0050h,雙字。內存中整個PE文件的映射尺寸。已加載到內充中的HelloWorld.exe為例,HelloWorld.exe中文件頭占用了1000h字節,三個節各占用1000h,所以文件在內存中占用的空間總大小為04000h。該值可以比實際的值大,但不能比他小,而且必須保證該值是SectionAlignment的整數倍。

????31.IMAGE_OPTIONAL_HEADER32.SizeOfHeaders

+0054h,雙字。所有頭+節表按照文件對齊粒度對齊后的大小,HellpWorld.exe中的值為0400h.PE文件中,該部分數據是嚴格按照200h對齊的,如果不對齊,系統加載時會提示出錯。

? ? 32.IMAGE_OPTIONAL_HEADER32.CheckSum

? ? +0058h,雙字。校驗和,在大多數的PE文件中,該值是0,但在一些內核模式的驅動程序和系統DLL中,該值則是必須存在且正確的,比如kernel32.dllPE的校驗和是0011E97eh。

我本機上的不是。

?

? ? Windows系統目錄下有一個動態鏈接庫IMAGEHELP.DLL,它是Win32中專門用來操作PE文件的函數庫,這里的函數CheckSumMappedFile就是用來計算文件頭校驗和的,對于整個PE文件也有一個校驗和函數MapFileAndCheckSum。該動態間接庫中還包含其他一些常用的函數,可以通過小工具PEinfo輸出并查看。關于校驗和的具體計算方法,可參照3.7接種關于PE文件頭編程的部分。

? ? 33.IMAGE_OPTIONAL_HEADER32.Subsystem

? ? +005ch,單字。指定使用界面的子系統,它的取值如表3-4所示。這個字段決定了系統如何為程序連接初始的界面,連接時使用參數-subsystem:xxx先選指定的就是這個字段的值,如果將子系統指定為Windows命令行交互模式(CUI,那么系統會自動為程序建立一個控制臺窗口;如果是GUI,窗口程序代碼必須由用戶自己建立。


對于上面,我手動測試了兩件事:

1cui程序我直接給成gui了,就是把

????

2改成3了,結果發現黑色界面消失了,但是進程還在。

2)又找到一個界面的程序,C++寫的,然后把3改成2了,結果是既彈出了主程序界面,又多彈出了一個cui的黑色界面(開始是想該C#寫的一個程序。結果二進制編輯的那個軟件一直加載不了那個文件。)

MASM32link程序的鏈接開關-subsystem的常見選項如3-5所示。

?

? ? 34.IMAGE_OPTIONAL_HEADER32.DLLCharacteristics

? ? +005eh,單字。DLL文件屬性。它是一個標志集,不是針對DLL文件的,而是針對所有PE文件的。

?


? ? 該字段定義了PE文件裝載時的一些特性,第十章會提供一個使用該標志的例子。

? ? 35.IMAGE_OPTIONAL_HEADER32.SizeOfStackReserve

? ? +0060h,雙字。初始化時八六棧的大小。該字段表示為初始化線程的棧而保留的虛擬內存數量,然而并不是留出的所有虛擬內存都可以做棧(真正的棧大小由下一個字段SizeOfStackCommit決定)。該字段的默認值為0x100000(1M)

,如果調用API函數CreateThread時,把NULL當做當做傳入的參數,那么創建出來的棧大小也是1MB。

? ? 36.IMAGE_OPTIONAL_HEADER32.SizeOfStackCommit

? ? +0064h,雙字。初始化時實際提交的棧大小。

? ? 37.IMAGE_OPTIONAL_HEADER32.SizeOfHeapReserve

? ? +0068h,雙字。初始化是保留的堆大小。用來保留給初始進程堆使用的虛擬內存,這個堆的句柄可以通過調用GetProcessHeap函數獲得。每一個進程至少會有一個默認的進程堆,該堆在進程啟動時被創建,而且在進程的生命期中韻苑不會被刪除。默認為1MB。

? ? 38.IMAGE_OPTIONAL_HEADER32.SizeOfHeapCommit

? ? +006ch,雙字。初始化實際提交的堆大小,在進程初始化時設定的堆所占用的內存空間。默認值為1頁。

? ? 39.IMAGE_OPTIONAL_HEADER32.LoaderFlags

? ? +0074h,雙字。加載標記。

? ? 40.IMAGE_OPTIONAL_HEADER32.NumberOfRvaAndSize

? ? +0074h,雙字。定義數據目錄結構的數量,一般為00000010h,16個。該值由字段SizeOfOptionalHeaders決定,實際應用中可取2-16的值。

? ? 41.IMAGE_OPTIONAL_HEADER32.DataDirectory

? ? +0078h,結構。由16IMAGE_DATA_DIRECTORY結構線性排列而成,用于定義PE中的16種不同類別的數據所在的位置和大小。前面已經對這部分做過說明,后面將會對這些數據進行詳細描述。一下是對這16種數據的說明:


?

3.5.4 ?數據目錄項IMAGE_DATA_DIRECTORY的字段

? ? 42.IMAGE_DATA_DIRECTORY.VirtualAddress

? ? +0000h,雙字。這個字段記錄了特定類型數據的起始RVA。當然,針對不同的數據結構,該字段包含的數據含義并不一樣,有的數據甚至還不是RVA(如屬性證書數據中該字段的值表示的是FOA)

? ? 43.IMAGE_DATA_DIRECTORY.isize

? ? +0004h,雙字。該字段記錄了特定類型的數據的長度。

3.5.5 節表項 IMAGE_SECTION_HEADER的字段

? ? 44.IMAGE_SECTION_HEADER.Name1

? ? +0000h,8字節。該字段一共8個字節,一般情況下是以一個”\0”結尾的ASCII碼字符串來標示節的名稱,內容可以自行定義。

? ? 該名稱并不遵循Ansi字符串必須”\0”結尾的規律,如果不易”\0”結尾,系統依然會認為它是一個字符串,但會根據8個字節長度對其進行截斷處理。

? ? 45.IMAGE_SECTION_HEADER.Misc

? ? +0008h,雙字。該字段是一個union型數據,這是節數據在沒有對齊前的真是尺寸,不過很多PE文件里該節值并不準確。

? ? 46.IMAGE_SECTION_HEADER.VirtualAddress

? ? +000ch,雙字。節區的RVA地址。

? ? 47.IMAGE_SECTION_HEADER.SizeOfRawData

? ? +0010h,雙字。節在文件中對齊后的尺寸。在HelloWorld.exe中,數據量不大的節,其大小一般為200h。

? ??48.IMAGE_SECTION_HEADER.PointerToRawData

? ??+0014h,雙字。節區其實數據在文件中的偏移。

?

? ??49.IMAGE_SECTION_HEADER.PointerToRelocations

? ??+0018h,雙字。在.obj文件中使用,指向重定位表的指針。

? ??50.IMAGE_SECTION_HEADER.PointerToLinenumbers

? ??+001ch,雙字。行號表的位置(供調試用)。

? ??51.IMAGE_SECTION_HEADER.NumberOfRelocations

? ??+0020h,單子。重定位表的個數(在OBJ文件中使用)。

? ??52.IMAGE_SECTION_HEADER.NumberOfLinenumbers

? ??+0022h,單子。行號表中行號的數量。

? ??53.IMAGE_SECTION_HEADER.Characteristics

? ??+0024h,雙字。節的屬性。這個字段很重要,這是節的屬性標志字段,其中不同的數據位代表了不同的屬性,具體的定義如表3-7所示,這些數據位的組合表述了內存中一個節所擁有的訪問屬性。

?

3.5.6 ?解析HelloWorld程序的字節碼

? ? 這一節是吧exe用二進制工具打開,然后把上面的所有字段都找到然后在圖片上標記出來。這個不總結了,比較簡單。可以用一個可以看PE結構的程序,去找到每個段的地址,然后去看對應的內容就行了。

最后還有一個提示:


3.6PE內存映像

exe加載到OD里,然后 查看->內存 ,看其內存分配。

?

文件字節碼在內存中的大致分布 PE頭文件+代碼+輸入表+數據


書中的HelloWorld的文件-內存關系是

?

我自己編寫的Helloworld略有不同,.text段是2000h

?

?????由上面可以知道,頭+節表 部分的數據沒有任何更改,多出部分0填充。這個對于這個節,

其對齊的方式則是由數據結構中的字段IMAGE_ OPTIONAL_HEADER32.FileAlignmentIMAGE_OPTIONAL_HEADER32.Section Alignment分別定義。

總結

以上是生活随笔為你收集整理的Windows Pe 第三章 PE头文件(下)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。