亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

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

PE文件格式詳解(2)

2019-11-17 05:04:16
字體:
來源:轉載
供稿:網友
  MS-DOS頭部/實模式頭部
  如上所述,PE文件格式的第一個組成部分是MS-DOS頭部。在PE文件格式中,它并非一個新概念,因為它與MS-DOS 2.0以來就已有的MS-DOS頭部是完全一樣的。保留這個相同結構的最主要原因是,當你嘗試在Windows 3.1以下或MS-DOS 2.0以上的系統下裝載一個文件的時候,操作系統能夠讀取這個文件并明白它是和當前系統不相兼容的。換句話說,當你在MS-DOS 6.0下運行一個Windows NT可執行文件時,你會得到這樣一條消息:“This PRogram cannot be run in DOS mode.”假如MS-DOS頭部不是作為PE文件格式的第一部分的話,操作系統裝載文件的時候就會失敗,并提供一些完全沒用的信息,例如:“The name specified is not recognized as an internal or external command, Operable program or batch file.”
  MS-DOS頭部占據了PE文件的頭64個字節,描述它內容的結構如下:
  WINNT.H
  typedef strUCt _IMAGE_DOS_HEADER { // DOS的.EXE頭部
  USHORT e_magic; // 魔術數字
  USHORT e_cblp; // 文件最后頁的字節數
  USHORT e_cp; // 文件頁數
  USHORT e_crlc; // 重定義元素個數
  USHORT e_cparhdr; // 頭部尺寸,以段落為單位
  USHORT e_minalloc; // 所需的最小附加段
  USHORT e_maxalloc; // 所需的最大附加段
  USHORT e_ss; // 初始的SS值(相對偏移量)
  USHORT e_sp; // 初始的SP值
  USHORT e_csum; // 校驗和
  USHORT e_ip; // 初始的IP值
  USHORT e_cs; // 初始的CS值(相對偏移量)
  USHORT e_lfarlc; // 重分配表文件地址
  USHORT e_ovno; // 覆蓋號
  USHORT e_res[4]; // 保留字
  USHORT e_oemid; // OEM標識符(相對e_oeminfo)
  USHORT e_oeminfo; // OEM信息
  USHORT e_res2[10]; // 保留字
  LONG e_lfanew; // 新exe頭部的文件地址
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
  第一個域e_magic,被稱為魔術數字,它被用于表示一個MS-DOS兼容的文件類型。所有MS-DOS兼容的可執行文件都將這個值設為0x5A4D,表示ASCII字符MZ。MS-DOS頭部之所以有的時候被稱為MZ頭部,就是這個緣故。還有許多其它的域對于MS-DOS操作系統來說都有用,但是對于Windows NT來說,這個結構中只有一個有用的域——最后一個域e_lfnew,一個4字節的文件偏移量,PE文件頭部就是由它定位的。對于Windows NT的PE文件來說,PE文件頭部是緊跟在MS-DOS頭部和實模式程序殘余之后的。

  實模式殘余程序
  實模式殘余程序是一個在裝載時能夠被MS-DOS運行的實際程序。對于一個MS-DOS的可執行映像文件,應用程序就是從這里執行的。對于Windows、OS/2、Windows NT這些操作系統來說,MS-DOS殘余程序就代替了主程序的位置被放在這里。這種殘余程序通常什么也不做,而只是輸出一行文本,例如:“This program requires Microsoft Windows v3.1 or greater.”當然,用戶可以在此放入任何的殘余程序,這就意味著你可能經常看到像這樣的東西:“You can't run a Windows NT application on OS/2, it's simply not possible.”

  當為Windows 3.1構建一個應用程序的時候,鏈接器將向你的可執行文件中鏈接一個名為WINSTUB.EXE的默認殘余程序。你可以用一個基于MS-DOS的有效程序取代WINSTUB,并且用STUB模塊定義語句指示鏈接器,這樣就能夠取代鏈接器的默認行為。為Windows NT開發的應用程序可以通過使用-STUB:鏈接器選項來實現。   PE文件頭部與標志   PE文件頭部是由MS-DOS頭部的e_lfanew域定位的,這個域只是給出了文件的偏移量,所以要確定PE頭部的實際內存映射地址,就需要添加文件的內存映射基地址。例如,以下的宏是包含在PEFILE.H源文件之中的:
  PEFILE.H
  #define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + /
                       ((PIMAGE_DOS_HEADER)a)->e_lfanew))
  在處理PE文件信息的時候,我發現文件之中有些位置需要經常查閱。既然這些位置僅僅是對文件的偏移量,那么用宏來實現這些定位就比較輕易,因為它們較之函數有更好的表現。
  請注重這個宏所獲得的是PE文件標志,而并非PE文件頭部的偏移量。那是由于自Windows與OS/2的可執行文件開始,.EXE文件都被賦予了目標操作系統的標志。對于Windows NT的PE文件格式而言,這一標志在PE文件頭部結構之前。在Windows和OS/2的某些版本中,這一標志是文件頭的第一個字。同樣,對于PE文件格式,Windows NT使用了一個DWord值。
  以上的宏返回了文件標志的偏移量,而不管它是哪種類型的可執行文件。所以,文件頭部是在DWORD標志之后,還是在WORD標志處,是由這個標志是否Windows NT文件標志所決定的。要解決這個問題,我編寫了ImageFileType函數(如下),它返回了映像文件的類型:
  PEFILE.C
  DWORD WINAPI ImageFileType (LPVOID lpFile)
  {
  /* 首先出現的是DOS文件標志 */
  if (*(USHORT *)lpFile == IMAGE_DOS_SIGNATURE)
  {
    /* 由DOS頭部決定PE文件頭部的位置 */
    if (LOWORD (*(DWORD *)NTSIGNATURE (lpFile)) ==
        IMAGE_OS2_SIGNATURE
        LOWORD (*(DWORD *)NTSIGNATURE (lpFile)) ==
        IMAGE_OS2_SIGNATURE_LE)
      return (DWORD)LOWORD(*(DWORD *)NTSIGNATURE (lpFile));
    else if (*(DWORD *)NTSIGNATURE (lpFile) ==
      IMAGE_NT_SIGNATURE)
    return IMAGE_NT_SIGNATURE;
    else
      return IMAGE_DOS_SIGNATURE;
  }
  else
    /* 不明文件種類 */
    return 0;
  }
  以上列出的代碼立即告訴了你NTSIGNATURE宏有多么有用。對于比較不同文件類型并且返回一個適當的文件種類來說,這個宏就會使這兩件事變得非常簡單。WINNT.H之中定義的四種不同文件類型有:
  WINNT.H
  #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
  #define IMAGE_OS2_SIGNATURE 0x454E // NE
  #define IMAGE_OS2_SIGNATURE_LE 0x454C // LE
  #define IMAGE_NT_SIGNATURE 0x00004550 // PE00
  首先,Windows的可執行文件類型沒有出現在這一列表中,這一點看起來很希奇。但是,在稍微研究一下之后,就能得到原因了:除了操作系統版本規范的不同之外,Windows的可執行文件和OS/2的可執行文件實在沒有什么區別。這兩個操作系統擁有相同的可執行文件結構。

  現在把我們的注重力轉向Windows NT PE文件格式,我們會發現只要我們得到了文件標志的位置,PE文件之后就會有4個字節相跟隨。下一個宏標識了PE文件的頭部:
  PEFILE.C
  #define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + /
                        ((PIMAGE_DOS_HEADER)a)->e_lfanew + /
                        SIZE_OF_NT_SIGNATURE))
  這個宏與上一個宏的唯一不同是這個宏加入了一個常量SIZE_OF_NT_SIGNATURE。不幸的是,這個常量并未定義在WINNT.H之中,于是我將它定義在了PEFILE.H中,它是一個DWORD的大小。
  既然我們知道了PE文件頭的位置,那么就可以檢查頭部的數據了。我們只需要把這個位置賦值給一個結構,如下:
  PIMAGE_FILE_HEADER pfh;
  pfh = (PIMAGE_FILE_HEADER)PEFHDROFFSET(lpFile);
  在這個例子中,lpFile表示一個指向可執行文件內存映像基地址的指針,這就顯出了內存映射文件的好處:不需要執行文件的I/O,只需使用指針pfh就能存取文件中的信息。PE文件頭結構被定義為:
  WINNT.H
  typedef struct _IMAGE_FILE_HEADER {
  USHORT Machine;
  USHORT NumberOfSections;
  ULONG TimeDateStamp;
  ULONG PointerToSymbolTable;
  ULONG NumberOfSymbols;
  USHORT SizeOfOptionalHeader;
  USHORT Characteristics;
  } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;  #define IMAGE_SIZEOF_FILE_HEADER 20
  請注重這個文件頭部的大小已經定義在這個包含文件之中了,這樣一來,想要得到這個結構的大小就很方便了。但是我覺得對結構本身使用sizeof運算符(譯注:原文為“function”)更簡單一些,因為這樣的話我就不必記住這個常量的名字IMAGE_SIZEOF_FILE_HEADER,而只需要記住結構IMAGE_FILE_HEADER的名字就可以了。另一方面,記住所有結構的名字已經夠有挑戰性的了,尤其在是這些結構只有WINNT.H中才有的情況下。
  PE文件中的信息基本上是一些高級信息,這些信息是被操作系統或者應用程序用來決定如何處理這個文件的。第一個域是用來表示這個可執行文件被構建的目標機器種類,例如DEC(R) Alpha、MIPS R4000、Intel(R) x86或一些其它處理器。系統使用這一信息來在讀取這個文件的其它數據之前決定如何處理它。
  Characteristics域表示了文件的一些特征。比如對于一個可執行文件而言,分離調試文件是如何操作的。調試器通常使用的方法是將調試信息從PE文件中分離,并保存到一個調試文件(.DBG)中。要這么做的話,調試器需要了解是否要在一個單獨的文件中尋找調試信息,以及這個文件是否已經將調試信息分離了。我們可以通過深入可執行文件并尋找調試信息的方法來完成這一工作。要使調試器不在文件中查找的話,就需要用到IMAGE_FILE_DEBUG_STRIPPED這個特征,它表示文件的調試信息是否已經被分離了。這樣一來,調試器可以通過快速查看PE文件的頭部的方法來決定文件中是否存在著調試信息。

  WINNT.H定義了若干其它表示文件頭信息的標記,就和以上的例子差不多。我把研究這些標記的事情留給讀者作為練習,由你們來看看它們是不是很有趣,這些標記位于WINNT.H中的IMAGE_FILE_HEADER結構之后。
  PE文件頭結構中另一個有用的入口是NumberOfSections域,它表示假如你要方便地提取文件信息的話,就需要了解多少個段——更明確一點來說,有多少個段頭部和多少個段實體。每一個段頭部和段實體都在文件中連續地排列著,所以要決定段頭部和段實體在哪里結束的話,段的數目是必需的。以下的函數從PE文件頭中提取了段的數目:
  PEFILE.C
  int WINAPI NumOfSections(LPVOID lpFile)
  {
  /* 文件頭部中所表示出的段數目 */
  return (int)((PIMAGE_FILE_HEADER)
    PEFHDROFFSET (lpFile))->NumberOfSections);
  }
  如你所見,PEFHDROFFSET以及其它宏用起來非常方便。
(未完待續)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国模精品一区二区三区色天香| 亚洲视频网站在线观看| 日韩欧美中文字幕在线播放| 91高清视频在线免费观看| 成人黄色av网| 97精品视频在线| 国产精品99一区| 97精品国产97久久久久久春色| 欧美人在线视频| 中国日韩欧美久久久久久久久| 亚洲最大福利视频| 亚洲国产中文字幕在线观看| 国产丝袜一区二区三区免费视频| 91精品国产91久久久久福利| 欧美成年人视频网站| 美女视频久久黄| 国产亚洲精品久久| 欧美激情一区二区三区在线视频观看| 中国日韩欧美久久久久久久久| 成年无码av片在线| 国产精品国模在线| 日韩在线视频网站| 一区二区亚洲欧洲国产日韩| 国产极品精品在线观看| 亚洲国产成人在线视频| 日韩精品视频在线免费观看| 一区二区三欧美| 欧美精品做受xxx性少妇| 国产免费一区二区三区在线观看| 中文字幕在线看视频国产欧美在线看完整| 琪琪第一精品导航| 亚洲精品电影在线观看| www.亚洲免费视频| 色视频www在线播放国产成人| 97在线视频一区| 91色琪琪电影亚洲精品久久| 黑人巨大精品欧美一区二区三区| 亚洲аv电影天堂网| 国产欧美日韩免费| 岛国av在线不卡| 黑人巨大精品欧美一区二区一视频| 91久久久久久久久久久久久| 日韩美女写真福利在线观看| 日韩精品有码在线观看| 国产精品91久久| 国产一区二区三区在线看| 91精品国产成人| 亚洲护士老师的毛茸茸最新章节| 亚洲精品久久久久中文字幕欢迎你| 国产丝袜一区二区三区免费视频| 91网在线免费观看| 久久久999精品免费| 国产精品扒开腿做爽爽爽视频| 成人激情在线播放| 亚洲欧美国产精品久久久久久久| 亚洲精品色婷婷福利天堂| 精品国产91久久久久久老师| 亚洲一区二区三区四区在线播放| 亚洲伊人成综合成人网| 亚洲天堂成人在线视频| 黄色成人在线播放| 国产精品在线看| wwwwwwww亚洲| 国产亚洲精品久久久久久| 亚洲精品按摩视频| 国产精品国产自产拍高清av水多| 欧美高清在线视频观看不卡| 精品亚洲国产成av人片传媒| 午夜精品久久久久久久白皮肤| 国模精品系列视频| 91精品国产色综合久久不卡98| 欧美噜噜久久久xxx| 日韩精品在线私人| 中文字幕免费国产精品| 亚洲国产精品成人av| 欧美日韩亚洲一区二区| 97在线视频国产| 欧美性精品220| 国产精品久久久久国产a级| 亚洲另类xxxx| 亚洲男人天堂2019| 亚洲成**性毛茸茸| 久久久久99精品久久久久| 久久99久久99精品中文字幕| 国产suv精品一区二区三区88区| 成人免费视频在线观看超级碰| 久久免费高清视频| 国产精品一区二区三区成人| 日韩成人在线播放| 久久久久久国产精品久久| 欧美一级在线播放| 亚洲高清一区二| 中文字幕九色91在线| 91av在线免费观看视频| 国产亚洲精品日韩| 久久97精品久久久久久久不卡| 国产免费一区视频观看免费| 亚洲综合一区二区不卡| 久久精品成人动漫| 91网在线免费观看| 久久精视频免费在线久久完整在线看| 美女扒开尿口让男人操亚洲视频网站| 国产伦精品一区二区三区精品视频| 91精品中国老女人| 欧美色xxxx| 日韩成人小视频| 欧美视频一二三| 欧美日韩高清区| 日本视频久久久| 精品少妇一区二区30p| 国产精品久久久久999| 国产一区二区日韩精品欧美精品| 成人性生交大片免费看视频直播| 国产成人在线一区二区| 另类色图亚洲色图| 欧美一级片久久久久久久| 国产精品男人爽免费视频1| 亚洲另类xxxx| 伊人久久久久久久久久久| 欧美黑人视频一区| 亚洲人午夜精品| 久久久久久有精品国产| 91精品视频免费看| 久久久久免费精品国产| 精品日本美女福利在线观看| 亚洲精品日韩欧美| 国产在线999| 国产成人精品久久亚洲高清不卡| 在线观看日韩专区| 国产精品久久在线观看| 成人高清视频观看www| 国产精品福利无圣光在线一区| 久久精品男人天堂| 色婷婷综合成人av| 欧美色图在线视频| 日韩av网站导航| 日本电影亚洲天堂| 亚洲片在线资源| 久久精品国产成人| 亚洲成人av在线播放| 欧美成人午夜激情在线| 欧美另类第一页| 日韩av在线免播放器| 日韩亚洲成人av在线| 国产欧美一区二区三区久久| 国产精品一区久久久| 日韩电影视频免费| 国产精品激情av在线播放| 国内精品久久久| 91社区国产高清| 亚洲欧美精品suv| 成人免费网站在线| 欧美性jizz18性欧美| 国产日韩欧美在线观看| 亚洲人成网站免费播放| y97精品国产97久久久久久| 亚洲精品乱码久久久久久按摩观| 日韩免费av在线| 国模视频一区二区| 久久综合免费视频| 国产日韩在线看| 国产精品va在线播放| 精品免费在线视频| 欧美电影免费观看高清|