程式內部和外部的介面等元素的二進位制資料統稱為資源,程式把它們放在乙個特定的表中,符合資料和程式分離的設計原則。
windows程式中的資源大致分為六類:選單、對話方塊、位圖、游標、圖示、自定義資源
資源表是資料目錄表中的第三個元素,排在匯入表的後面。
資源表的解析比較複雜,可能是所有資料目錄表中最複雜的乙個。我將結合例子說明,這樣會比較好理解。
我們的檔案在十六進製制工具010editor的幫助下,將pe中的結構全部標記了出來。資源表是資料目錄表的第三個,查詢到它的rva是0x4000,轉換成offset還是0x4000,找到它的位置如下圖所示:
從0x4000開始就是資源表的結構體了,這個結構體叫image_resource_directory,有如下字段:
struct image_resource_directory
characteristics:屬性,一般為0,對應上圖中的0x00000000
timedatestamp:時間戳,一般為0(前面說過檔案頭也有這個字段,匯出表、匯入表都有這個字段,都有值,在這裡很多時間為0),對應上圖中的0x00000000
majorversion:資源的版本,一般為0,對應上圖中的0x0000
minorversion:一般為0,對應上圖中的0x0000
numberofnamedentries:以字串命名的資源數量,對應上圖中的0x0000
numberofidentries:以整型數字命名的資源數量,對應上圖中的0x0003
上圖中numberofnamedentries和numberofidentries的和是0x3,表明這個程式有3個資源專案,也就是說緊跟著image_resource_directory結構體的有3個image_resource_directory_entry結構,這裡展示一下image_resource_directory_entry結構體:
struct image_resource_directory_entry
name:對應上圖中的0x00000003(第乙個image_resource_directory_entry),當它的最高位是1的時候,表示低位作為乙個指標使用,指向image_resource_dir_string_u結構;當它的最高位是0的時候,分為三種情況:當結構用於第1層目錄時定義的是資源型別,用於第2層目錄時定義的是資源id,用於第3層目錄時定義的是資源語言型別(0x409表示是英語)。第1層-第3層是什麼意思呢?簡單的理解就是,資源表的解析分為三層,每一層都是image_resource_directory+image_resource_directory_entry的形式,第二個欄位offsettodata的最高位是1的時候就會指向下一層,每一層都是一樣的image_resource_directory和image_resource_directory_entry的結構,大概是這個樣子,後面會更詳細的介紹,現在有個印象就好。image_resource_dir_string_u的結構體如下:
struct image_resource_dir_string_u
這個資源的name是0x00000003,最高位是0,並且它在第一層,也就是說0x00000003代表的是資源型別,那麼資源型別又有哪些呢?下表列出了一些型別,所以這個資源是圖示。
offsettodata:對應上圖的0x80000028,當它的最高位是1的時候,低位資料指向下一層的image_resource_directory的起始位址,當它的最高位是0的時候,指標指向image_resource_data_entry結構,這個結構後面會說,它是真正的資源資料的位址,一般情況下,分析到第三層的時候,offsettodata的最高位會是0。值得注意的是offsettodata作為指標的時候(0x80000028),28是從資源塊最開始的地方開始計算偏移的,它不是rva。image_resource_data_entry的結構體是:
image_resource_data_entry struct
offsettodata dword ? ; 資源資料的rva
size1 dword ? ; 資源資料的長度
codepage dword ? ; **頁, 一般為0
reserved dword ? ; 保留字段
image_resource_data_entry ends
這個結構體,暫時先不用管它,等分析到第三層的時候再回來看。
先總結一下,我已經分析了第一層的image_resource_directory,它從0x4000開始,佔據16個位元組,它的numberofnameentries和numberofnameids的總和是0x3,因此從0x4010開始有3個image_resource_directory_entry結構體,也就是3個資源,每個結構體占8個位元組,所以從0x4010-0x4027是它的內容,這三個結構體的name欄位的最高位都是0,所以它們代表的是型別,分別是0x03圖示、0x04選單、0x0e圖示組,它們的offsettodata欄位的最高位是1,所以指向的位置是下一層。
接下來我們找到位置開始分析第二層的內容。
根據第乙個資源的offsettodata的低位位元組0x28,我們從0x4000往後數0x28個位元組,找到如下圖的內容,我們知道offsettodata這時指向的是第二層的image_resource_directory結構體。所以它同樣是16個位元組。
最後的numberofidentries為0x01,所以它的後面緊跟著乙個image_resource_directory_entry,也就是如下圖中所示:
name欄位的最高位是0,我們知道最高位是0,並且name在第二層代表的是資源id,所以這個資源的id是0x01,offsettodata最高位是1,所以它的最低位指向的是最後一層,也就是第三層。通過0x4000+0x70,我們找到0x4070,這裡就是第三層的image_resource_directory。如下圖
我們看到numberofidentries為0x01,所以第三層也只有乙個image_resource_directory_entry。如下圖:
這時我們看到它的第乙個元素name的最高位是0,在第三層name最高位為0就代表資源語言型別,這時表示的資源語言型別就是0x804,offsettodata的最高位是0,所以0xb8+0x4000處就是image_resource_data_entry,如下圖:
我們再來回顧一下這個結構體:
image_resource_data_entry struct
offsettodata dword ? ; 資源資料的rva
size1 dword ? ; 資源資料的長度
codepage dword ? ; **頁, 一般為0
reserved dword ? ; 保留字段
image_resource_data_entry ends
所以資源的rva是0x4100,轉為offset仍然是0x4100,這個資源的起始位置就是這個0x4100,長度是0x2e8。
我們還沒有碰到image_resource_directory_entry裡面的name為1的情況,以後可能會補充。資源表的理論說起來很複雜,其實沒那麼複雜,只要寫一遍pe分析工具,在**中可以更好地理解資源表。
PE 檔案格式學習
以前總在網上看看介紹pe檔案格式的文章,看的時候看到一大堆的結構體就蛋疼了,想想現在我這個居然都不清楚以後咋裝bi呢 今天下了個peview邊看變學了 先自己隨便寫個控制台程式,然後加進去就有了,讓後我們可以看看這個檔案到底是怎麼組成的。從這個樹形結構我們能很清楚的理解這個檔案的整體構成,在網上有很...
PE檔案格式
pe 的意思是 portable executable 可移植的執行體 它是 win32環境自身所帶的執行檔案格式。它的一些特性繼承自unix的coff common object file format 檔案格式。portable executable 可移植的執行體 意味著此檔案格式是跨win3...
PE檔案格式
pe檔案格式分析及修改 圖 1 2009 01 09 14 08 pe 的意思是 portable executable 可移植的執行體 它是 win32環境自身所帶的執行檔案格式。它的一些特性繼承自unix的coff common object file format 檔案格式。portable ...