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