小甲魚PE詳解之資源(PE詳解11)

原文出自:www.fishc.com

最近一直在安排第一屆魚C 學習班的事情,忙活了好一陣子,真是對不住大家,還大家久等了,這裏要跟大家說聲不好意思 ^_^

今天我們來談談資源部分,資源部分可以說是 PE 文件所有結構中,最複雜的一部分,也最讓人揪心。很多朋友都想通過自己動手修改一些遊戲的資源、工具的界面、或者一些軟件的圖標等,都知道要改資源部分。但純粹一進去就像走進了迷宮……出不來……

雖然說是迷霧重重,但是本節的學習確意義非凡,例如我們可以對遊戲進行漢化!怎麼樣?刺激吧?給力吧?我們可以自己漢化我們喜歡的**遊戲哦!



小甲魚PE詳解之資源(PE詳解11)

我們知道,Windows 將程序的各種界面定義爲資源,包括加速鍵(Accelerator)、位圖(Bitmap)、光標(Cursor)、對話框(Dialog Box)、圖標(Icon)、菜單(Menu)、串表(String Table)、工具欄(Toolbar)和版本信息(Version Information)等。

爲了吸引大家的興趣和目光,咱先來做個學前試驗,然後再憧憬一下我們將來學習的內容有啥意義!好,小甲魚先來演示一下如何用工具來修改資源實現漢化、改圖標等,接着我們進一步從原理上來解剖 PE文件如何對資源進行存放和索引。最後,在 PE系列章節講解完畢後,小甲魚和大家將所有學到的知識結合在一起,我們自己打造屬於我們的個性 PE工具。

試驗對象:360zip(實在找不到幾個鳥文軟件,我們就隨便改改,不做漢化了,做“英化”^_^)
所需工具:Resource Hacker,eXeScope(附件提供下載
小小演示:請看視頻哈 @_@



資源結構

資源是PE 文件中非常重要的部分,幾乎所有的PE 文件中都包含着資源,與導入表和導出表相比,資源的組織方式要複雜很多,其實我們只要看下圖就知道俺所言不虛。




我們知道我們的資源有很多種類型,每種類型的資源中可能存在多個資源項,這些資源項用不同的ID 或者名稱來區分。但是要將這麼多種類型的不同ID 的資源有序地組織起來是一件非常痛苦的事情,因此,我們採取類似於磁盤目錄結構的方式保存。

從圖中我們可以看到,PE 文件中的資源是按照 資源類型 -> 資源ID -> 資源代碼頁 的3層樹型目錄結構來組織資源的,通過層層索引才能夠進入相應的子目錄找到正確的資源。



資源目錄結構

數據目錄表中的 IMAGE_DIRECTORY_ENTRY_RESOURCE 條目(第三項)包含資源的 RVA 和大小。資源目錄結構中的每一個節點都是由 IMAGE
_RESOURCE_DIRECTORY 結構和緊跟其後的數個IMAGE_RESOURCE_DIRECTORY_ENTRY 結構組成的。(是不是有點像我們之前提到的文件目錄?文件夾每個都長得一樣,一個嵌套另一個,這樣子可以實現將非常複雜的數據細化切分,小澤瑪利亞、蒼井空、吉澤明步、鬆島楓……)

我們再來看這張圖:




認識了這層關係後,我們來看下
 IMAGE_RESOURCE_DIRECTORY 這個結構,該結構長度爲 16 字節,共有 6 個字段,定義如下:

IMAGE_RESOURCE_DIRECTORY STRUCT

Characteristics        DWORD      ?   ;理論上爲資源的屬性,不過事實上總是0
TimeDateStamp      DWORD      ?   ;資源的產生時刻
MajorVersion          WORD        ?   ;理論上爲資源的版本,不過事實上總是0
MinorVersion          WORD        ?
NumberOfNamedEntries  WORD     ?   ;以名稱(字符串)命名的入口數量
NumberOfIdEntries         WORD     ?   ;以ID(整型數字)命名的入口數量
IMAGE_RESOURCE_DIRECTORY ENDS

其實在這裏邊我們唯一要注意的就是 NameberOfNamedEntries 和 NumberOfIdEntries,它們說明了本目錄中目錄項的數量。兩者加起來就是本目錄中的目錄項總和。也就是後邊跟着的
IMAGE_RESOURCE_DIRECTORY_ENTRY 數目。


資源目錄入口的結構(
IMAGE_RESOURCE_DIRECTORY_ENTRY

IMAGE_RESOURCE_DIRECTORY_ENTRY 緊跟在資源目錄結構後,此結構長度爲 8 個字節,包含 2 個字段。該結構定義如下:

IMAGE_RESOURCE_DIRECTORY_ENTRY STRUCT
Name                  DWORD    ?   ;目錄項的名稱字符串指針或ID
OffsetToData        DWORD    ?   ;目錄項指針
IMAGE_RESOURCE_DIRECTORY_ENTRY ENDS

Name 字段完全是個百變精靈,改字段定義的是目錄項的名稱或ID。當結構用於第一層目錄時,定義的是資源類型;當結構定義於第二層目錄時,定義的是資源的名稱;當結構用於第三層目錄時,定義的是代碼頁編號。

注意:當最高位爲 0  的時候,表示字段的值作爲 ID 使用;而最高位爲 1 的時候,字段的低位作爲指針使用(資源名稱字符串是使用 UNICODE編碼),但是這個指針不是直接指向字符串哦,而是指向一個 IMAGE_RESOURCE_DIR_STRING_U 結構的。
該結構定義如下:
IMAGE_RESOURCE_DIR_STRING_U STRUCT
Length             DWORD       ?   ; 字符串的長度
NameString      DWORD       ?   ; UNICODE字符串,由於字符串是不定長的。由Length 制定長度
IMAGE_RESOURCE_DIR_STRING_U ENDS

OffsetOfData 字段是一個指針,當最高位爲 1 時,低位數據指向下一層目錄塊的其實地址;當最高位爲 0 時,指針指向 IMAGE_RESOURCE_DATA_ENTRY 結構。

注意:將 Name 和 OffsetToData 用做指針時需要注意,該指針是從資源區塊開始的地方算起的偏移量(即根目錄的起始位置的偏移量),不是我們習慣的 RVA 哦。

最後,在上圖中我們看到,在第一層的時候,
IMAGE_RESOURCE_DIRECTORY_ENTRY的Name 字段作爲資源類型使用。

具體類型匹配見下表:





資源數據入口

經過三層 IAMGE_RESOURCE_DIRECTORY_ENTRY (一般是3層,偶爾更年期少一些。第一層資源類型,第二層資源名,第三層是資源的 Language),第三層目錄結構中的 OffsetOfData 指向 IMAGE_RESOURCE_DATA_ENTRY 結構。該結構描述了資源數據的位置和大小,定義如下:

IMAGE_RESOURCE_DATA_ENTRY STRUCT
OffsetToData     DWORD     ?    ; 資源數據的RVA
Size                  DWORD     ?    ; 資源數據的長度
CodePage          DWORD     ?    ; 代碼頁, 一般爲0
Reserved           DWORD     ?    ; 保留字段
IMAGE_RESOURCE_DATA_ENTRY ENDS

千山萬水,此處的 
IMAGE_RESOURCE_DATA_ENTRY 結構就是真正的資源數據了。結構中的OffsetOfData 指向資源數據的指針,其爲 RVA 值。


資源結構實例分析(具體過程將在視頻中演示,這裏不再羅嗦^_^)

工具:PEinfo.exe, UltraEdit
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章