WindowsPE 第七章 资源表
資源表
? ? 在程序設計中,總會設計一些數據。這些數據可能是源代碼內部需要用到的常量,菜單選項、界面描述等;也可能是源代碼外部的,比如程序的圖標文件、北京音樂文件、配置文件等,以上這些數據統稱為資源。按照程序與數據分離的設計思想,最理想的方案是單獨為程序所需要的數據安排一節來存儲-PE中的資源就是這么做的。
7.1資源分類
? ? 資源數據在PE里是最復雜的一種。其難度主要體現在對資源數據的遍歷定位上,以及資源塊的不易閱讀性。因為即使通過信息定位方法找到了資源塊,其內部結構還需要進一步解析。首先來看資源分類的歷史。
? ? 剛開始資源類型方面,以為16個種類足以了,然而后來發現并不夠,這類問題再之前很容易理解。就如千年蟲問題...
程序中常用的六類資源包括:
位圖資源、光標資源、圖標資源、菜單資源、對話框資源、自定義資源。
7.1.1??位圖、光標、圖標資源
? ? 位圖、光標和圖標是標識程序用途、修飾程序的最簡約的符號,一般對應ico、cur、ani和bmp文件內容。這三種資源最終都是基于圖片文件。在對資源腳本文件進行定義時,通常使用文件名,最后由資源編譯器rc.exe將像素數據讀入,在轉化為二進制格式存儲在PE的資源表指向的位置。位圖、光標、圖標這三類資源在腳本文件中的定義格式如下:
?
7.1.2??菜單資源
? ? 菜單資源是大部分應用程序都具備的資源。在資源腳本文件中,菜單的定義格式如下所示:
菜單ID?MENU?[DISCARDABLE]
BEGIN
菜單項定義
......
END
7.1.3??對話框資源
? ? 對話框也是大部分程序具備的一種資源。彈出式對話框人性化地排列著文本框、說明文字和按鈕等可視化控件,使復雜的計算機操作變得容易。語法如下:
對話框ID?DIALOG[DISCARDABLE]?x坐標,y坐標,寬度,高度[options]
BEGIN
子窗口控件1
子窗口控件2
......
END
對話框的可可選屬性及描述:
7.1.4??自定義資源
? ? 通常,當開發者需要在PE文件中附帶自定義數據時,可以使用自定義資源。其在資源文件中的定義語法如下:
資源ID????類型ID??[DISCARDABLE]
BEGIN
數據定義
......
END
? ? 大部分情況下,都是講一個磁盤文件當做資源的內容。此時的語法簡化為:
資源ID?類型ID?[DISCARDABLE]?文件名
類型ID可以是大于255的數值或字符串,如可以定義如下自定義資源:
7.2??PE資源表組織
? ? 這節主要說PE文件中資源數據的組織方式,并通過實例介紹針對資源數據定義的數據結構以及在PE中定位資源表的方法。
7.2.1??資源表的組織方式
? ? PE的資源組織方式類似于操作系統的文件管理方式。從根目錄開始,下設一級子目錄、二級子目錄和三級子目錄;三級子目錄下才是文件。其三級目錄結構如下:
一級子目錄按照資源類型分類。
二級子目錄按照資源ID分類。
三級子目錄按照資源代碼頁分類。
三級子目錄后即為節點,也就是所說的文件。這里的文件其實就是包含了資源數據的指針和大小等信息的一個數據結構而已。對于所有資源數據塊的訪問均可以從這里開始。
?
????由于一、二、三級目錄的數據結構是相同的,均是由一個資源目錄頭加上多個現行跟隨著的資源目錄項組成,將主干和枝干的節點成為資源目錄結構單元。如下圖:
? ? 從數據結構的角度來看,資源表示一個四層的兒茶排序樹結構。其中,第一層為主干,第二、三層為枝干,葉子節點為第四層。主干和枝干的節點即為資源目錄結構單元,完整示意圖如下:
7.2.2??資源表數據定位
? ? 資源表是一張描述資源數據在PE中的分布情況的表。資源表是數據目錄中注冊的數據類型之一,其描述信息位于數據目錄第3個目錄項中。
?
7.2.3??資源目錄頭IMAGE_RESOURCE_DIRECTORY
? ? 資源表數據從第一級資源目錄開始。資源的每一級目錄都會有一個資源目錄頭,它標識了該類資源的屬性、創建日期和版本等信息,其中也包含了隨后的目錄項的數量描述信息。
詳細結構定義如下:
然后是結構詳解:
73.MAGE_RESOURCE_DIRECTORY.Characteristics
+0000h,雙字。資源屬性,保留為將來使用,必須為0。
74.MAGE_RESOURCE_DIRECTORY.TimeDateStamp
+0004h,雙字。時間戳,即創建該資源的時間。
75.MAGE_RESOURCE_DIRECTORY.MajorVersion/MinorVersion;
+0008h,雙字。資源版本號。未用,大部分情況為0。
76.MAGE_RESOURCE_DIRECTORY.NumberOfNamedEntries
+000ch,雙字。以名稱命名的資源個數。
77.MAGE_RESOURCE_DIRECTORY.NumberOfIdEntries
+000eh,雙字。以ID命名的資源個數。
以上字段中,最重要的是76和77兩個字段。在資源腳本文件中,定義資源時,既可以使用字符串作為名稱來標識一個資源,也可以通過ID號來標識資源。資源目錄項的數量等于兩者之和。
7.2.4資源目錄項IMAGE_RESOURCE_DIRECTORY_ENTRY?
? ? 緊跟在資源目錄后的數據結構,就是在資源目錄中聲明的資源目錄項。一個資源目錄可能有多個資源目錄項(以名稱定義的資源目錄項或以ID定義的資源目錄項,或兩者組合),目錄項和目錄項之間是線性排列的。首先按照字母升序(不區分大小寫)排列名稱資源目錄項,然后再按照ID升序排列資源目錄項。下圖是資源目錄項及目錄項之間的關系示意圖。
資源目錄項數據結構的詳細定義如下:
?
上面有一個union定義,我也是第一次看到這個類型,百度了一下:
78.IMAGE_RESOURCE_DIRECTORY_ENTRY.Namee1
??+0000h,雙字。第一個union字段,它定義了目錄項的名稱或者ID。
??該雙字的高位(即31位)如果為1,則表示低地址部分為一個紙箱Uniconde字符串的指針(注意,這里的字符串不是Ansi字符串,所以另有規定);如果為0,則表示該字段為一個編號。
資源中對字符串的定義全部采用Unicode編碼,該指針并不是直接指向一個以“\0”結尾的字符串所在地址,而是指向了結構IMAGE_RESOURCE_DIR_STRING_U。
該結構完善了指針的定義(即不僅包含指針,還包含指針紙箱的塊的長度),其詳細結構如下:
?
79.IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData
??+0004h,雙字。這個字段是一個指針,當它的高位(第31位)為0時,指針指向的是描述資源數據塊的指針,通常出現在第三級目錄中;當高位為1時,地位數據指向下一級目錄快的起始地址。
提示:字段78、79中的地址并不是基于文件起始地址的,它的偏移是基于資源表的起始位置。一定要清楚這一點,否則在定位資源表的時候會出現錯誤。
7.2.5??資源數據項IMAGE_RESOURCE_DATA_ENTRY
? ? 資源數據項其實就是前面所說的目錄-文件中的文件。他是通過三次目錄定位后找到的一個數據結構,下圖顯示了資源數據項與三級目錄和最終的資源數據塊之間的關系。
? ? 第三級目錄項中的字段IMAGE_RESOURCE_DIREXTORY_ENTRY.OffsetToData指向了資源數據項,而資源數據項中的OffsetToData字段則指向了資源數據塊。
資源數據項的詳細結構如下:
80.IMAGE_RESOURCE_DATA_ENTRY.OffsetToData
+0000h,雙字。該字段是一個紙箱資源數據塊的指針,是一個RVA值,在文件中訪問時需要注意轉換成文件偏移。此處指向的資源數據塊還不是赤裸裸的資源信息,而是附加了一些數據結構的資源快。
81.IMAGE_RESOURCE_DATA_ENTRY.Size1
+0004h,雙字。資源數據的大小。
82.IMAGE_RESOURCE_DATA_ENTRY.CodePage
+0008h,雙字。代碼頁,未用,大多數情況下為0.
83.IMAGE_RESOURCE_DATA_ENTRY.Reserved
+000ch,雙字。保留字段。總是0。
對資源表的大部分編程,只要能解析出該結構中制定資源快所處的地址和資源快的大小,資源表的使命也就算完成了。
7.2.6??三級結構中目錄項的區別
? ? 由于目錄處的級別不同,目錄中各字段所表述的內容也不一樣;盡管他們具有相同的數據結構和完全相同的字段,在不同級別的目錄項中有些數字段的含義是不一樣的。
1.IMAGE_RESOURCE_DATA_ENTRY.Name1
(1)字段最高位(即31位)為1
??當結構用于第一層目錄時,表示這是一個非標準的類型。
??當結構用于第二層目錄時,表示這是一個非標準的命名。
??當結構用于第三層目錄時,表示這是一個非標準的語言。
(2)字段31位為0
??當結構用于第一層目錄時,表示這是一個標準的類型。
??當結構用于第二層目錄時,表示這是一個標準的命名。
??當結構用于第三層目錄時,表示這是一個標準的語言。
2.IMAGE_RESOURCE_DATA_ENTRY.OffsetToData
(1)字段第31位為1
??當結構用于第一層目錄時,下一級目錄地址。
??當結構用于第二層目錄時,下一級目錄地址。
??當結構用于第三層目錄時,第31位不為0。
(2)字段第31位為0
??第一層,第二層的這一位都不為0。
??當結構用于第三層目錄時,表示該字段指向一個數據項IMAGE_RESOURCE_DATA_ENTRY。
注意:由低31位組成的地址是基于資源起始地址的。
總結
以上是生活随笔為你收集整理的WindowsPE 第七章 资源表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows核心编程 第27章 硬件输
- 下一篇: Windows PE资源表编程(枚举资源