国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

PE文件格式詳解(3)

2019-11-17 05:04:19
字體:
來源:轉載
供稿:網友
  PE可選頭部  PE可執行文件中接下來的224個字節組成了PE可選頭部。雖然它的名字是“可選頭部”,但是請確信:這個頭部并非“可選”,而是“必需”的。

  OPTHDROFFSET宏可以獲得指向可選頭部的指針:
  PEFILE.H
  #define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + /
                        ((PIMAGE_DOS_HEADER)a)->e_lfanew + /
                        SIZE_OF_NT_SIGNATURE + /
                        sizeof(IMAGE_FILE_HEADER)))
  可選頭部包含了很多關于可執行映像的重要信息,例如初始的堆棧大小、程序入口點的位置、首選基地址、操作系統版本、段對齊的信息等等。

  IMAGE_OPTIONAL_HEADER結構如下:
  WINNT.H
  typedef strUCt _IMAGE_OPTIONAL_HEADER {
  //
  // 標準域
  //
  USHORT Magic;
  UCHAR MajorLinkerVersion;
  UCHAR MinorLinkerVersion;
  ULONG SizeOfCode;
  ULONG SizeOfInitializedData;
  ULONG SizeOfUninitializedData;
  ULONG AddressOfEntryPoint;
  ULONG BaSEOfCode;
  ULONG BaseOfData;
  //
  // NT附加域
  //
  ULONG ImageBase;
  ULONG SectionAlignment;
  ULONG FileAlignment;
  USHORT MajorOperatingSystemVersion;
  USHORT MinorOperatingSystemVersion;
  USHORT MajorImageVersion;
  USHORT MinorImageVersion;
  USHORT MajorSubsystemVersion;
  USHORT MinorSubsystemVersion;
  ULONG Reserved1;
  ULONG SizeOfImage;
  ULONG SizeOfHeaders;
  ULONG CheckSum;


  USHORT Subsystem;
  USHORT DllCharacteristics;
  ULONG SizeOfStackReserve;
  ULONG SizeOfStackCommit;
  ULONG SizeOfHeaPReserve;
  ULONG SizeOfHeapCommit;
  ULONG LoaderFlags;
  ULONG NumberOfRvaAndSizes;

  IMAGE_DATA_DirectorY DataDirectory   [IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
  } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;

  如你所見,這個結構中所列出的域實在是冗長得過分。為了不讓你對所有這些域感到厭煩,我會僅僅討論有用的——就是說,對于探究PE文件格式而言有用的。  標準域  首先,請注重這個結構被劃分為“標準域”和“NT附加域”。所謂標準域,就是和UNIX可執行文件的COFF格式所公共的部分。雖然標準域保留了COFF中定義的名字,但是Windows NT仍然將它們用作了不同的目的——盡管換個名字更好一些。

  ·Magic。我不知道這個域是干什么的,對于示例程序EXEVIEW.EXE示例程序而言,這個值是0x010B或267(譯注:0x010B為.EXE,0x0107為ROM映像,這個信息我是從eXeScope上得來的)。

  ·MajorLinkerVersion、MinorLinkerVersion。表示鏈接此映像的鏈接器版本。隨Window NT build 438配套的Windows NT SDK包含的鏈接器版本是2.39(十六進制為2.27)。

  ·SizeOfCode。可執行代碼尺寸。
  ·SizeOfInitializedData。已初始化的數據尺寸。
  ·SizeOfUninitializedData。未初始化的數據尺寸。
  ·AddressOfEntryPoint。在標準域中,AddressOfEntryPoint域是對PE文件格式來說最為有趣的了。這個域表示應用程序入口點的位置。并且,對于系統黑客來說,這個位置就是導入地址表(IAT)的末尾。以下的函數示范了如何從可選頭部獲得Windows NT可執行映像的入口點。

  PEFILE.C
  LPVOID WINAPI GetModuleEntryPoint(LPVOID lpFile)
  {
  PIMAGE_OPTIONAL_HEADER poh;
  poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(lpFile);
  if (poh != NULL)
    return (LPVOID)poh->AddressOfEntryPoint;
  else
    return NULL;
  }
  ·BaseOfCode。已載入映像的代碼(“.text”段)的相對偏移量。
  ·BaseOfData。已載入映像的未初始化數據(“.bss”段)的相對偏移量。   Windows NT附加域
  添加到Windows NT PE文件格式中的附加域為Windows NT特定的進程行為提供了裝載器的支持,以下為這些域的概述。

  ·ImageBase。進程映像地址空間中的首選基地址。Windows NT的Microsoft Win32 SDK鏈接器將這個值默認設為0x00400000,但是你可以使用-BASE:linker開關改變這個值。

  ·SectionAlignment。從ImageBase開始,每個段都被相繼的裝入進程的地址空間中。SectionAlignment則規定了裝載時段能夠占據的最小空間數量——就是說,段是關于SectionAlignment對齊的。

  Windows NT虛擬內存治理器規定,段對齊不能少于頁尺寸(當前的x86平臺是4096字節),并且必須是成倍的頁尺寸。4096字節是x86鏈接器的默認值,但是它可以通過-ALIGN: linker開關來設置。

  ·FileAlignment。映像文件首先裝載的最小的信息塊間隔。例如,鏈接器將一個段實體(段的原始數據)加零擴展為文件中最接近的FileAlignment邊界。早先提及的2.39版鏈接器將映像文件以0x200字節的邊界對齊,這個值可以被強制改為512到65535這么多。

  ·MajorOperatingSystemVersion。表示Windows NT操作系統的主版本號;通常對Windows NT 1.0而言,這個值被設為1。

  ·MinorOperatingSystemVersion。表示Windows NT操作系統的次版本號;通常對Windows NT 1.0而言,這個值被設為0。

  ·MajorImageVersion。用來表示應用程序的主版本號;對于Microsoft Excel 4.0而言,這個值是4。

  ·MinorImageVersion。用來表示應用程序的次版本號;對于Microsoft Excel 4.0而言,這個值是0。


  ·MajorSubsystemVersion。表示Windows NT Win32子系統的主版本號;通常對于Windows NT 3.10而言,這個值被設為3。

  ·MinorSubsystemVersion。表示Windows NT Win32子系統的次版本號;通常對于Windows NT 3.10而言,這個值被設為10。

  ·Reserved1。未知目的,通常不被系統使用,并被鏈接器設為0。

  ·SizeOfImage。表示載入的可執行映像的地址空間中要保留的地址空間大小,這個數字很大程度上受SectionAlignment的影響。   例如,考慮一個擁有固定頁尺寸4096字節的系統,假如你有一個11個段的可執行文件,它的每個段都少于4096字節,并且關于65536字節邊界對齊,那么SizeOfImage域將會被設為11 * 65536 = 720896(176頁)。

  而假如一個相同的文件關于4096字節對齊的話,那么SizeOfImage域的結果將是11 * 4096 = 45056(11頁)。這只是個簡單的例子,它說明每個段需要少于一個頁面的內存。在現實中,鏈接器通過個別地計算每個段的方法來決定SizeOfImage確切的值。它首先決定每個段需要多少字節,并且最后將頁面總數向上取整至最接近的SectionAlignment邊界,然后總數就是每個段個別需求之和了。

  ·SizeOfHeaders。這個域表示文件中有多少空間用來保存所有的文件頭部,包括MS-DOS頭部、PE文件頭部、PE可選頭部以及PE段頭部。文件中所有的段實體就開始于這個位置。

  ·CheckSum。校驗和是用來在裝載時驗證可執行文件的,它是由鏈接器設置并檢驗的。由于創建這些校驗和的算法是私有信息,所以在此不進行討論。

  ·Subsystem。用于標識該可執行文件目標子系統的域。每個可能的子系統取值列于WINNT.H的IMAGE_OPTIONAL_HEADER結構之后。

  ·DllCharacteristics。用來表示一個DLL映像是否為進程和線程的初始化及終止包含入口點的標記。

  ·SizeOfStackReserve、SizeOfStackCommit、SizeOfHeapReserve、SizeOfHeapCommit。這些域控制要保留的地址空間數量,并且負責棧和默認堆的申請。在默認情況下,棧和堆都擁有1個頁面的申請值以及16個頁面的保留值。這些值可以使用鏈接器開關-STACKSIZE:與-HEAPSIZE:來設置。

  ·LoaderFlags。告知裝載器是否在裝載時中止和調試,或者默認地正常運行。

  ·NumberOfRvaAndSizes。這個域標識了接下來的DataDirectory數組。請注重它被用來標識這個數組,而不是數組中的各個入口數字,這一點非常重要。

  ·DataDirectory。數據目錄表示文件中其它可執行信息重要組成部分的位置。它事實上就是一個IMAGE_DATA_DIRECTORY結構的數組,位于可選頭部結構的末尾。當前的PE文件格式定義了16種可能的數據目錄,這之中的11種現在在使用中。   數據目錄  WINNT.H之中所定義的數據目錄為:

  WINNT.H
  // 目錄入口
  // 導出目錄
  #define IMAGE_DIRECTORY_ENTRY_EXPORT 0
  // 導入目錄
  #define IMAGE_DIRECTORY_ENTRY_IMPORT 1
  // 資源目錄
  #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
  // 異常目錄
  #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
  // 安全目錄
  #define IMAGE_DIRECTORY_ENTRY_SECURITY 4
  // 重定位基本表
  #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
  // 調試目錄
  #define IMAGE_DIRECTORY_ENTRY_DEBUG 6

  // 描述字串
  #define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
  // 機器值(MipS GP)
  #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
  // TLS目錄
  #define IMAGE_DIRECTORY_ENTRY_TLS 9
  // 載入配置目錄
  #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10

  基本上,每個數據目錄都是一個被定義為IMAGE_DATA_DIRECTORY的結構。雖然數據目錄入口本身是相同的,但是每個特定的目錄種類卻是完全唯一的。每個數據目錄的定義在本文的以后部分被描述為“預定義段”。

  WINNT.H
  typedef struct _IMAGE_DATA_DIRECTORY {
  ULONG VirtualAddress;
  ULONG Size;
  } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

  每個數據目錄入口指定了該目錄的尺寸和相對虛擬地址。假如你要定義一個特定的目錄的話,就需要從可選頭部中的數據目錄數組中決定相對的地址,然后使用虛擬地址來決定該目錄位于哪個段中。一旦你決定了哪個段包含了該目錄,該段的段頭部就會被用于查找數據目錄的精確文件偏移量位置。

  所以要獲得一個數據目錄的話,那么首先你需要了解段的概念。我在下面會對其進行描述,這個討論之后還有一個有關如何定位數據目錄的示例。(未完待續)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 临夏县| 丰镇市| 棋牌| 腾冲县| 吉木萨尔县| 梁山县| 阳东县| 南丰县| 图木舒克市| 原平市| 衡阳县| 怀安县| 科技| 赣榆县| 三亚市| 竹溪县| 泸定县| 浑源县| 万荣县| 禹州市| 南丰县| 得荣县| 星座| 怀安县| 无棣县| 永济市| 博爱县| 红河县| 奇台县| 江华| 苍南县| 开阳县| 墨竹工卡县| 贵定县| 万山特区| 池州市| 华池县| 桦甸市| 夏邑县| 龙门县| 曲周县|