com/exe文件結構及原理

http://hqiangbo.blog.163.com/blog/static/42933253200831062318739/

 

大家都害怕病毒,但都想了解病毒。要了解病毒,以及病毒的機理,就必須先了解一些文件的結構和原理,下面把COM/EXE文件的結構介紹一下:

 

一 .COM文件結構及原理

     com文件結構比較簡單,它包含程序的一個絕對映像,即爲了運行程序準確的處理器指令和內存中的數據,MS-DOS通過直接把該映像從文件直接複製到內存,從而加載com程序,而不做任何改變。

     爲加載一個com程序,MS-DOS首先試圖分配內存,因爲com程序必須位於一個64KB的段中,所以com文件的大小不能超過65024(64KB減去用於PSP的256B和用於一個起始堆棧的至少256B)。如果MS-DOS不能爲程序、一個PSP、一個起始堆棧分配足夠的內存,則分配嘗試失敗。否則,MS-DOS分配儘可能多的內存(直至所有保留內存),即使com程序本身不能大於64KB。在試圖運行另一個程序或分配另外的內存之前,大部分com程序釋放任何不需要的內存。

     分配內存後,MS-DOS在該內存的前256B建立一個PSP,如果PSP中的第一個FCB含有一個有效驅動器標識符,則置AL爲00H,否則置位0FFH。MS-DOS還置AH爲00或0FFH,這依賴於第二個FCB是否含有一個有效驅動器標識符。建造PSP後,MS-DOS在PSP後立即開始(偏移100H)加載com文件,它置SS、DS和ES爲PSP的段地址,接着創建一個堆棧。爲創建這個堆棧,在已分配了至少64KB內存的情況下,MS-DOS置SP爲0000H;否則它置寄存器比所分配的自己總數大2的值。最後,將0000H進棧(這是爲了保證與在早期MS-DOS版本上設計的程序的兼容性)。

     MS-DOS通過把控制傳遞給偏移100H處的指令而啓動程序。程序設計者必須保證COM文件的第一條指令是程序的入口點。

     注意:因爲程序是在偏移100H處加載,因此所有代碼和數據偏移也必須相對於100H。彙編語言程序設計者可通過設置程序的初值爲100H而保證這一點(例如通過在源程序的開始使用語句org 100h)。

 

二.exe文件結構及原理

     exe文件比較複雜,屬於一種多段的結構,是DOS最成功和複雜的設計之一。要了解exe文件,首先需要了解exe文件的文件頭結構。

     每個exe文件包含一個文件頭和一個可重定位程序的映像。文件頭包含MS-DOS用於加載程序的信息,例如程序的大小和寄存器的初始值。文件頭還指向一個重定位表,該表包含指向程序映像中可重定位段地址的指針鏈表。exe文件的文件頭結構如表所示:

偏移量 含義 

00h~01h MZ,exe文件標記 

02h~03h 文件長度除以512的餘數 

04h~05h 文件長度除以512的商 

06h~07h 重定位項的個數 

08h~09h 文件頭除以16的商 

0ah~0bh 程序運行所需最小段數 

0ch~0dh 程序運行所需最大段數 

0eh~0fh 堆棧段的段值(SS) 

10h~11h 堆棧段的段值(SP) 

12h~13h 文件校驗和 

14h~15h 裝入模塊入口時的IP值 

16h~17h 裝入模塊代碼相對段值(CS) 

18h~19h 重定位表,開始位置,以位移地址表示 

1ah~1bh 覆蓋號(程序駐留爲零) 

1ch 重定位表,起點由偏移18h~19h給出,項數由06h~07h標明 

 

 一、DOS EXE文件頭數據結構

 

   struct   DOSEXEHEAD_t

 

{

 

  unsigned   char     Mark1;            // LINK簽名0x4D

 

  unsigned   char     Mark2;            // LINK簽名0x5A

 

  unsigned   short   VolumeInLastPage;  // 最後一扇區字節數

 

  unsigned   short   CountOfPage;       // 扇區數

 

  unsigned   short   CountOfReallocItem; //重定位表的項數

 

  unsigned   short   SizeOfHeadInPara; // 以節爲單位的EXE頭大小

 

  unsigned   short   min_para;          // 程序下方所需最小節數

 

  unsigned   short   max_para;          // 程序下方所需最大節數

 

  unsigned   short   Start_SS;          // 入口點SS,相對值

 

  unsigned   short   Start_SP;          // 入口點SP

 

  unsigned   short   Reserved;          // 保留,目前爲0x0000

 

  unsigned   short   Start_IP;          // 入口點IP

 

  unsigned   short   Start_CS;          // 入口點CS,相對值

 

  unsigned   short   FirstReallocPtr;   // 首重定位表項距頭首部的字節數

 

};     程序映像包含處理代碼和程序的初始數據,緊接在文件頭之後。它的大小以字節爲單位,等於exe文件的大小減去文件頭的大小,也等於exHeaderSize的域的值乘以16。MS-DOS通過把該映像直接從文件複製到內存加載exe程序,然後調整定位表中說明的可重定位段地址。

     定位表是一個重定位指針數組,每個指向程序映像中的可重定位段地址。文件頭中的exRelocItems域說明了數組中指針的個數,exRelocTable域說明了分配表的起始文件偏移量。每個重定位指針由兩個16位值組成:偏移量和段值。爲加載exe程序,MS-DOS首先讀文件頭以確定exe標誌並計算程序映像的大小,然後它試圖申請內存。首先,它計算程序映像文件的大小加上PSP的大小,再加上EXEHEADER結構中的exMinAlloc域說明的內存大小這3者之和。如果總和超過最大可用內存塊的大小,則MS-DOS停止加載程序並返回一個出錯值。否則,它計算程序映像的大小加上PSP的大小再加上EXEHEADER結構中exMaxAlloc域說明的內存大小之和,如果第二個總和小於最大可用內存塊的大小,則MS-DOS分配計算得到的內存量。否則,它分配最大可用內存塊。

     分配完內存後,MS-DOS確定段地址,也稱爲起始段地址,MS-DOS從此處加載程序映像。如果exMinAlloc域和exMaxAlloc域中的值都爲零,則MS-DOS把映像儘可能地加載到內存最高端。否則,它把映像加載到緊挨着PSP域之上。

     接下來,MS-DOS讀取重定位表中的項目調整所有由重定位指針說明的段地址。對於重定位表的每個指針,MS-DOS尋找指針映像中相應的可重定位段地址,並把起始段地址加到它之上。一旦調整完畢,段地址便指向了內存中被加載程序的代碼和數據段。MS-DOS在所分配內存的最低部分建造256B的PSP,把AL和AH設置爲加載com程序時所設置的值。MS-DOS使用文件頭中的值設置SP與SS,調整SS初始值,把起始地址加載到它之上。MS-DOS還把EX和DS設置爲PSP的段地址。最後,MS-DOS從程序文件頭讀取CS和IP的初始值,把起始段地址加到CS之上,把控制轉移到位於調整後的地址處的程序。

 

三.什麼是psp

 

事實上,無論是"COM"還是"EXE"文件,DOS在調入它們時都要保留256字節來預置一些數據,我們把這256字節稱爲"程序段前綴"(PSP--Program Segment Prefix),對於一個"COM"文件,由於只有一個段,所以PSP、代碼、數據和堆棧都在這個段中,PSP在頭部,堆棧在尾部,中間是代碼和數據,一個"COM"程序在調入內存執行時DOS會自動在堆棧中存入一個0,所以"COM"程序只需使用近程的RET指令就能返回DOS,並且無需自己初始化堆棧。

 

 

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/idy_10000/archive/2011/03/05/6225612.aspx

發佈了38 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章