作者:李建國
版權所有:廣東南海市昭信科技有限公司-李建國
轉載請與作者聯系
一、前言
不知大家用過exescope沒有,那是日本鬼子寫的一個很有用的東西,它能把exe等pe格式(portable executable)文件的資源(圖標、位圖、對話框、聲音等等)分析出來,並能改寫回去。當然vc的ide也有類似功能。大家是不是覺得很神秘?其實只要弄清了pe文件的結構,你也可以寫一個類似的工具出來。下面是我近
來對pe文件的分析經驗,給大家作參考。同時希望看到有中國人能寫出比日本鬼子更牛的分析工具來。
二、重要的數據結構
PE格式簡要說明:(更詳細的資料見http://vcangle.8u8.com文件格式專頁)
PE文件總結構如下表:
DOS MZ header ;dos頭
DOS stub ;dos附加段
PE header ;NT頭
Section table ;節表
Section 1 ;第一節
Section 2 ;
Section ...
Section n ;第n節
其中NT頭:
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;//PE文件頭標志 :"PE\0\0"。
IMAGE_FILE_HEADER FileHeader; //PE文件物理分布的信息
IMAGE_OPTIONAL_HEADER32 OptionalHeader;//PE文件邏輯分布的信息
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
節表數據結構:(可參考winnt.h)
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];//節表名稱,如“.text”
union { DWORD PhysicalAddress; //物理地址
DWORD VirtualSize; //真實長度
} Misc;
DWORD VirtualAddress; //RVA
DWORD SizeOfRawData; //物理長度
DWORD PointerToRawData; //節基於文件的偏移量
DWORD PointerToRelocations; //重定位的偏移
DWORD PointerToLinenumbers; //行號表的偏移
WORD NumberOfRelocations; //重定位項數目
WORD NumberOfLinenumbers; //行號表的數目
DWORD Characteristics; //節屬性
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
2.2位圖文件格式。由文件頭,位圖信息和數據段組成。
typedef struct tagBITMAPFILEHEADER { // bmfh文件頭
WORD bfType; //"BM"
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFO { // bmi----位圖信息
BITMAPINFOHEADER bmiHeader; // ----位圖信息頭
RGBQUAD bmiColors[1];// ----調色板*
} BITMAPINFO;
typedef struct tagBITMAPINFOHEADER{ // bmih 位圖信息頭
DWORD biSize; //該結構大小
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage; //位圖數據大小
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER; //該結構後緊接著就是DATA了。
三、取資源主要思路
先要判斷是否PE文件。文件頭兩byte應為0x4d5a即("MZ"),然後到地址0x3c中讀出PE文件頭(_IMAGE_NT_HEADERS)。判斷文件頭結構的Signature是否為17744(即"PE\0\0")。
讀出節表(_IMAGE_SECTION_HEADER),判斷有沒有資源節。我采用了一個簡單的方法:節表名為".rsrc\0\0"即是資源節。(注:據說該法不定可靠)
如有資源節,則讀取資源目錄(_IMAGE_RESOURCE_DIRECTORY)和資源入口(_IMAGE_RESOURCE_DIRECTORY_ENTRY)。資源在pe文件中處一樹型結構中,可有三層。在資源目錄根部,如果資源入口的資源名是一個id,那麼它代表一種資源類型。否則,它指向下一層資源入口。(祥見例程)
讀出具體資源的數據來。具體資源的入口(_IMAGE_RESOURCE_DATA_ENTRY)在就是資源樹的葉子。它的OffsetToData成員指明了具體資源的物理位置。不過特別要注意的是,OffsetToData並不是具體資源在文件中的實際偏移,具體見我的例程。具體資源的長度則由Size成員指定。
導出bmp資源。pe文件裡的bmp資源由BITMAPINFO部分和BITMAPDATA部分組成。我們只要為它構造一個文件頭(BITMAPFILEHEADER),就可以寫成bmp文件了。這裡特別要注意的是BITMAPINFO的bmiColors成員是未定長的。你要為它指明長度,以申請內存。
好了,我不說了,有什麼不明白就看例程吧。
四、例子程序簡介
我的例子程序基本實現了讀取pe文件的資源信息,並能把位圖顯示、導出。其它資源的操作還在研究中。由於作者水平有限,在分析有些文件時可能會不成功。歡迎指正!主頁:
http://vcangle.8u8.com,郵箱:[email protected].
五、參考資料
http://www.csdn.net/dev/Format/
http://mantousoft.51.net