一、前言
不知大家用過exescope沒有,那是日本鬼子寫的一個(gè)很有用的東西,它能把exe等pe格式(portable executable)文件的資源(圖標(biāo)、位圖、對(duì)話框、聲音等等)分析出來,并能改寫回去。當(dāng)然vc的ide也有類似功能。大家是不是覺得很神秘?其實(shí)只要弄清了pe文件的結(jié)構(gòu),你也可以寫一個(gè)類似的工具出來。下面是我近 來對(duì)pe文件的分析經(jīng)驗(yàn),給大家作參考。同時(shí)希望看到有中國(guó)人能寫出比日本鬼子更牛的分析工具來。
PE文件總結(jié)構(gòu)如下表:
01.
02.
DOS MZ header ;dos頭
03.
DOS stub ;dos附加段
04.
PE header ;NT頭
05.
Section table ;節(jié)表
06.
Section 1 ;第一節(jié)
07.
Section 2 ;
08.
Section ...
09.
Section n ;第n節(jié)
10.
其中NT頭:
11.
typedef
struct
_IMAGE_NT_HEADERS {
12.
DWORD
Signature;
//PE文件頭標(biāo)志 :"PE\0\0"。
13.
IMAGE_FILE_HEADER FileHeader;
//PE文件物理分布的信息
14.
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
//PE文件邏輯分布的信息
15.
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
16.
節(jié)表數(shù)據(jù)結(jié)構(gòu):(可參考winnt.h)
17.
typedef
struct
_IMAGE_SECTION_HEADER {
18.
BYTE
Name[IMAGE_SIZEOF_SHORT_NAME];
//節(jié)表名稱,如“.text”
19.
union
{
DWORD
PhysicalAddress;
//物理地址
20.
DWORD
VirtualSize;
//真實(shí)長(zhǎng)度
21.
} Misc;
22.
DWORD
VirtualAddress;
//RVA
23.
DWORD
SizeOfRawData;
//物理長(zhǎng)度
24.
DWORD
PointerToRawData;
//節(jié)基于文件的偏移量
25.
DWORD
PointerToRelocations;
//重定位的偏移
26.
DWORD
PointerToLinenumbers;
//行號(hào)表的偏移
27.
WORD
NumberOfRelocations;
//重定位項(xiàng)數(shù)目
28.
WORD
NumberOfLinenumbers;
//行號(hào)表的數(shù)目
29.
DWORD
Characteristics;
//節(jié)屬性
30.
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
31.
32.
2.2位圖文件格式。由文件頭,位圖信息和數(shù)據(jù)段組成。
33.
typedef
struct
tagBITMAPFILEHEADER {
// bmfh文件頭
34.
WORD
bfType;
//"BM"
35.
DWORD
bfSize;
36.
WORD
bfReserved1;
37.
WORD
bfReserved2;
38.
DWORD
bfOffBits;
39.
} BITMAPFILEHEADER;
40.
typedef
struct
tagBITMAPINFO {
// bmi----位圖信息
41.
BITMAPINFOHEADER bmiHeader;
// ----位圖信息頭
42.
RGBQUAD bmiColors[1];
// ----調(diào)色板*
43.
} BITMAPINFO;
44.
typedef
struct
tagBITMAPINFOHEADER{
// bmih 位圖信息頭
45.
DWORD
biSize;
//該結(jié)構(gòu)大小
46.
LONG
biWidth;
47.
LONG
biHeight;
48.
WORD
biPlanes;
49.
WORD
biBitCount;
50.
DWORD
biCompression;
51.
DWORD
biSizeImage;
//位圖數(shù)據(jù)大小
52.
LONG
biXPelsPerMeter;
53.
LONG
biYPelsPerMeter;
54.
DWORD
biClrUsed;
55.
DWORD
biClrImportant;
56.
} BITMAPINFOHEADER;
//該結(jié)構(gòu)后緊接著就是DATA了。
三、取資源主要思路
先要判斷是否PE文件。文件頭兩byte應(yīng)為0x4d5a即("MZ"),然后到地址0x3c中讀出PE文件頭(_IMAGE_NT_HEADERS)。判斷文件頭結(jié)構(gòu)的Signature是否為17744(即"PE\0\0")。
讀出節(jié)表(_IMAGE_SECTION_HEADER),判斷有沒有資源節(jié)。我采用了一個(gè)簡(jiǎn)單的方法:節(jié)表名為".rsrc\0\0"即是資源節(jié)。(注:據(jù)說該法不定可靠)
如有資源節(jié),則讀取資源目錄(_IMAGE_RESOURCE_DIRECTORY)和資源入口(_IMAGE_RESOURCE_DIRECTORY_ENTRY)。資源在pe文件中處一樹型結(jié)構(gòu)中,可有三層。在資源目錄根部,如果資源入口的資源名是一個(gè)id,那么它代表一種資源類型。否則,它指向下一層資源入口。(祥見例程)
讀出具體資源的數(shù)據(jù)來。具體資源的入口(_IMAGE_RESOURCE_DATA_ENTRY)在就是資源樹的葉子。它的OffsetToData成員指明了具體資源的物理位置。不過特別要注意的是,OffsetToData并不是具體資源在文件中的實(shí)際偏移,具體見我的例程。具體資源的長(zhǎng)度則由Size成員指定。
導(dǎo)出bmp資源。pe文件里的bmp資源由BITMAPINFO部分和BITMAPDATA部分組成。我們只要為它構(gòu)造一個(gè)文件頭(BITMAPFILEHEADER),就可以寫成bmp文件了。這里特別要注意的是BITMAPINFO的bmiColors成員是未定長(zhǎng)的。你要為它
指明長(zhǎng)度,以申請(qǐng)內(nèi)存。
好了,我不說了,有什么不明白就看例程吧。
我的例子程序基本實(shí)現(xiàn)了讀取pe文件的資源信息,并能把位圖顯示、導(dǎo)出。其它資源的操作還在研究中。由于作者水平有限,在分析有些文件時(shí)可能會(huì)不成功。歡迎指正!主頁(yè): http://vcangle.8u8.com,郵箱:king_koo@163.net.
聯(lián)系客服