PE格式第九講,資源表解析


        PE格式第九講,資源表解析

一丶熟悉Windows管理文件的方法

首先,為什么標題是這個,主要是為了下邊講解資源方便,因為資源結構體很亂.如果直接拿出來講解,那么就會很暈.

1.windows管理文件方法

樹形結構

可以看出結構

根目錄

  子目錄

    文件.xxx

  子目錄

    子目錄 (子目錄里面還可以有文件夾)

  .....    

那么我們的資源也是這樣存儲的.

二丶資源結構體解析

首先,資源結構體分為很多個,但是有用的就3個.一般也分為三個

IMAGE_RESOURCE_DIRECTORY            根目錄(資源目錄頭)
IMAGE_RESOURCE_DIRECTORY_ENTRY         子目錄(資源目錄項)其中根目錄下可以有很多子目錄(也就是說根目錄下會有子目錄的)
IMAGE_RESOURCE_DATA_ENTRY            文件(資源數據)
結構體解析:

1.資源目錄頭(也可以看做管理文件的根目錄)

typedef struct _IMAGE_RESOURCE_DIRECTORY {
    DWORD   Characteristics;          資源屬性
    DWORD   TimeDateStamp;           時間戳
    WORD    MajorVersion;            資源大版本號
    WORD    MinorVersion;            資源小版本號
    WORD    NumberOfNamedEntries;       按照名稱命名的數量
    WORD    NumberOfIdEntries;         按照ID命名的數量
//  IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;

首先我們看到資源目錄頭的結構體了,這里大家要知道,有用的就最后兩個成員,還有一段注釋.

1.按照名稱命名的數量

意思就是我們的資源是字符串命名加載的有多少個

2.按照ID命名的數量

意思就是我們的資源如果按照ID有多少個.

一般都是用ID的.

最后兩個字段主要是資源的標識,是以ID的有多少個,以字符串標識的有多少個.

2.資源目錄項(子目錄)

typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
    union {
        struct {
            DWORD NameOffset:31;          位段: 低31位飄逝偏移 定義了目錄項的名稱或者ID
            DWORD NameIsString:1;          位段: 高位, 如果這位為1,則表示31位的偏移指向的是一個Unicode字符串的指針偏移
        };                       這里列出結構體,自己去看,IMAGE_RESOURCE_DIR_STRING_U 里面是字符串長度還有字符串,不是\0結尾         
        DWORD   Name;                 
        WORD    Id;
    };
    union {
        DWORD   OffsetToData;            偏移RVA因為是聯合體,所以有不同的解釋
        struct {
            DWORD   OffsetToDirectory:31;    看高位,如果高位是1,那么RVA偏移指向的是新的(根目錄)
            DWORD   DataIsDirectory:1;      
        };
    };
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;

前邊我們說了

根目錄(資源目錄頭)下面存放的是這個結構體,這個結構體是一個聯合體,所以會有不同的解釋

1.首先,聯合體是8個字節大小.

2.其中第一個DWORD大小,看高位,如果高位是1,那么低31位是指向新的目錄項名稱的結構體IMAGE_RESOURCE_DIR_STRING_U 

3.如果高位為0,則是ID號,這個ID號說的是 資源ID類型,比如3類型指的就是ICON

具體,可以隨便寫個RT_XXX開頭的宏去查看.

這里我寫下,跟一下看看.

4.第二個DWORD量,也是RVA偏移,如果高位為1,那么代表它還是一個目錄,也就是指向了一個新的根目錄了,這是個不斷遞歸的過程.

如果不是,則指向文件偏移結構體了.

文件偏移結構體:(應該是資源數據結構體)

typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
    DWORD   OffsetToData;          資源數據的偏移RVA
    DWORD   Size;               大小
    DWORD   CodePage;             代碼頁緩沖(CMD設置窗口的時候就是這個,沒用)
    DWORD   Reserved;             保留
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;

這個就很簡單了,直接前邊4個字節指向就是ICON資源的位置.

三丶實戰演練,定位ICON資源.

看了上面結構體,可能會暈,因為聯合體很多,不同的方式有不同的解釋方法,那么一步一步的跟隨

1.首先通過數據目錄定位資源根目錄(也就是根目錄,占16個字節,第一個結構體)

由此得出 RVA = 1B000 

然后查看屬於哪個節

由此得出,節的虛擬地址也是從1b000開始的,那么直接看文件偏移即可.

因為此時FA = RVA了,為了方便,一次截圖就指明了,在文件的7800h位置

然后我們定位到7800h的位置

2.找到位置,查看結構體

找到位置后,我們對比結構體成員,看看是什么一次,因為這個是資源根目錄,所以查看資源根目錄結構體

typedef struct _IMAGE_RESOURCE_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    WORD    NumberOfNamedEntries;
    WORD    NumberOfIdEntries;
//  IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;

我們發現,意思就是按照ID分類的資源有多少個,我們得出是7個,字符串標識的資源有0個,所以不用看了.

3.定位資源目錄項(子目錄)

我們知道,資源根目錄下面是子目錄,現在有7個按照ID分類的資源,那么就有7個資源目錄項(子目錄)

我們看下結構體.

typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
    union {
        struct {
            DWORD NameOffset:31;
            DWORD NameIsString:1;
        };
        DWORD   Name;
        WORD    Id;
    };
    union {
        DWORD   OffsetToData;
        struct {
            DWORD   OffsetToDirectory:31;
            DWORD   DataIsDirectory:1;
        };
    };
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;

首先,我們不要被這個結構體弄暈.我們首先要知道結構體的大小

結構體是2個union(聯合體,共用體),而里面的最大類型是DWORD,所以這個結構體大小是8個字節.

那么我們就知道了,在資源根目錄下有7各這樣的數組大小,也就是 7 * 8 = 56字節,整個數組占56個字節

那么我們看下

第二個紅色箭頭沒有弄完,截圖就完了,不好意思,第二個箭頭的意思就是,整個56個字節,是資源目錄項,其中黃色區域,屬於第一個資源目錄項

那么根據上面的結構體,我們先看黃色區域的第一的4個字節,看看高位是否是1

這里有兩種解釋方式

1.如果高位為1,那么表示一個字符串,那么低31位指向了一個字符串結構體

2.如果高位為0,那么表示是一個雙字節的ID (資源類型)

現在得出  00000003  很顯然,高位為0,那么表示一個資源類型,而資源類型上面看過了,3表示是一個ICON

那么在看黃色區域的第二的4個字節

1.高位為1,那么低31位表示指向了一個新的"根目錄" (結構體大小還是16個字節,還是最后4個字節有用,也就是上面第一個結構體)

2.如果高位為0,那么低31位表示指向了一個資源數據結構體(可以表示為文件)

現在得出, 80000048  很顯然高位為1,因為高1位是個8,那么低31位則表示指向一個新的"根目錄"

得出RVA偏移得48

那么根據剛才的FA = RVA  FA = 7800 那么現在新的目錄的FA = 7800 + 48 = 7848

那么在7848h表示新的根目錄,跟過去看下.

4.定位新的根目錄

可以看出,有是4個新的數據目錄項,那么我們接着看下4個數組是什么.

 

 

我們還是繼續,看資源類型為3的,通過上圖,我們得出,資源數據類型為三的(ICON)的高4個字節的高1位還是8

也就會80000140,那么意思就是又指向了一個新的"根目錄"

5.繼續尋找新的根目錄

上圖得出 偏移是140  FA = 7800 + 140  = 7940

那么文件位置7940是新的根目錄,接着數16個字節.

我們看到7940位置是一個新的根目錄,那么我們看出,它按照ID分類,就一項了,那么下面8個字節就是數據目錄項了.(子目錄)

那么我們由此得出,它的高位不是1,

現在的 00000238 高位不是1了,那么根據 "子目錄"結構體的定義,高位不是1那么這個RVA偏移則是指向了一個文件結構體的偏移

我們繼續計算FA ,一致FA = 7800 ,得出的RVA = 238  則FA = 7800+238 = 7A38h

6.定位資源數據(文件)

那么我們定義為7A38的位置,看下資源數據結構是什么樣子

為了防止大家結構體忘記,重新拷貝到這里觀看.

typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
    DWORD   OffsetToData;
    DWORD   Size;
    DWORD   CodePage;
    DWORD   Reserved;
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;

就第一個個成員有用,4個字節,表示ICON的RVA偏移.

那么定位到7A38

得出第一個成員的RVA偏移是 0001c018

RVA = 1C018

按照FA = RVA  ,的知剛才的RVA = 1B000

求FA = ?

FA = 1C018 - 1B000 + 7800 =  8818

那么文件偏移8818的位置,則是ICON的數據了.

我們看下.

可以看出,很像圖標資源了,那么此時,我們去看下我們的圖標二進制,是不是這個.

對比文件

我們可以看出,位置確實是這個地方了.那么此時就已經成功的找到了ICON類型的資源了

 

作者:IBinary
出處:http://www.cnblogs.com/iBinary/
版權所有,歡迎保留原文鏈接進行轉載:)



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM