一、前言 |
不知大家用过exescope没有,那是日本鬼子写的一个很有用的东西,它能把exe等pe格式(portable executable)文件的资源(图标、位图、对话框、声音等等)分析出来,并能改写回去。当然vc的ide也有类似功能。大家是不是觉得很神秘?其实只要弄清了pe文件的结构,你也可以写一个类似的工具出来。下面是我近 来对pe文件的分析经验,给大家作参考。同时希望看到有中国人能写出比日本鬼子更牛的分析工具来。 |
二、重要的数据结构 |
PE格式简要说明:(更详细的资料见http://vcangle.文件格式专页)
PE文件总结构如下表: |
01. 02. DOS MZ header ;dos头 03. DOS stub ;dos附加段 04. PE header ;NT头 05. Section table ;节表 06. Section 1 ;第一节 07. Section 2 ; 08. Section ... 09. Section n ;第n节 10. 其中NT头: 11. typedef struct _IMAGE_NT_HEADERS { 12. DWORD Signature; //PE文件头标志 :"PE\0\0"。 13. IMAGE_FILE_HEADER FileHeader; //PE文件物理分布的信息 14. IMAGE_OPTIONAL_HEADER32 OptionalHeader; //PE文件逻辑分布的信息 15. } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; 16. 节表数据结构:(可参考winnt.h) 17. typedef struct _IMAGE_SECTION_HEADER { 18. BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //节表名称,如“.text” 19. union { DWORD PhysicalAddress; //物理地址 20. DWORD VirtualSize; //真实长度 21. } Misc; 22. DWORD VirtualAddress; //RVA 23. DWORD SizeOfRawData; //物理长度 24. DWORD PointerToRawData; //节基于文件的偏移量 25. DWORD PointerToRelocations; //重定位的偏移 26. DWORD PointerToLinenumbers; //行号表的偏移 27. WORD NumberOfRelocations; //重定位项数目 28. WORD NumberOfLinenumbers; //行号表的数目 29. DWORD Characteristics; //节属性 30. } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; 31. 32. 2.2位图文件格式。由文件头,位图信息和数据段组成。 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]; // ----调色板* 43. } BITMAPINFO; 44. typedef struct tagBITMAPINFOHEADER{ // bmih 位图信息头 45. DWORD biSize; //该结构大小 46. LONG biWidth; 47. LONG biHeight; 48. WORD biPlanes; 49. WORD biBitCount; 50. DWORD biCompression; 51. DWORD biSizeImage; //位图数据大小 52. LONG biXPelsPerMeter; 53. LONG biYPelsPerMeter; 54. DWORD biClrUsed; 55. DWORD biClrImportant; 56. } 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.,邮箱:king_koo@163.net. |
五、参考资料 http://www.csdn.net/dev/Format/ http://mantousoft. |
|