PE文件资源遍历.docx
《PE文件资源遍历.docx》由会员分享,可在线阅读,更多相关《PE文件资源遍历.docx(21页珍藏版)》请在冰豆网上搜索。
PE文件资源遍历
资源中的所有地址都是以相对于资源节开始地址的偏移量的形式给出的:
(重要)
资源遍历就是遍历一个资源树
树的基本结构为表所示
一共分为三层结构
下面是三个结构体的具体数据结构
//
//Resourcedirectoryconsistsoftwocounts,followingbyavariablelength
//arrayofdirectoryentries.Thefirstcountisthenumberofentriesat
//beginningofthearraythathaveactualnamesassociatedwitheachentry.
//Theentriesareinascendingorder,caseinsensitivestrings.Thesecond
//countisthenumberofentriesthatimmediatelyfollowthenamedentries.
//Thissecondcountidentifiesthenumberofentriesthathave16-bitinteger
//Idsastheirname.Theseentriesarealsosortedinascendingorder.
//
//Thisstructureallowsfastlookupbyeithernameornumber,butforany
//givenresourceentryonlyoneformoflookupissupported,notboth.
//Thisisconsistantwiththesyntaxofthe.RCfileandthe.RESfile.
//
typedefstruct_IMAGE_RESOURCE_DIRECTORY{
DWORDCharacteristics;
DWORDTimeDateStamp;
WORDMajorVersion;
WORDMinorVersion;
WORDNumberOfNamedEntries;
WORDNumberOfIdEntries;
//IMAGE_RESOURCE_DIRECTORY_ENTRYDirectoryEntries[];
}IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY;
/Eachdirectorycontainsthe32-bitNameoftheentryandanoffset,
//relativetothebeginningoftheresourcedirectoryofthedataassociated
//withthisdirectoryentry.Ifthenameoftheentryisanactualtext
//stringinsteadofanintegerId,thenthehighorderbitofthenamefield
//issettooneandtheloworder31-bitsareanoffset,relativetothe
//beginningoftheresourcedirectoryofthestring,whichisoftype
//IMAGE_RESOURCE_DIRECTORY_STRING.Otherwisethehighbitisclearandthe
//low-order16-bitsaretheintegerIdthatidentifythisresourcedirectory
//entry.Ifthedirectoryentryisyetanotherresourcedirectory(i.e.a
//subdirectory),thenthehighorderbitoftheoffsetfieldwillbe
//settoindicatethis.Otherwisethehighbitisclearandtheoffset
//fieldpointstoaresourcedataentry.
//
typedefstruct_IMAGE_RESOURCE_DIRECTORY_ENTRY{
union{
struct{
DWORDNameOffset:
31;
DWORDNameIsString:
1;
};
DWORDName;
WORDId;
};
union{
DWORDOffsetToData;
struct{
DWORDOffsetToDirectory:
31;
DWORDDataIsDirectory:
1;
};
};
}IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY;
在下面还是指向一个PIMAGE_RESOURCE_DATA_ENTRY的结构体,这个结构体再指向真正的资源的数据其中的偏移量是相对于文件开始的(不是资源开始)(重要)
//Eachresourcedataentrydescribesaleafnodeintheresourcedirectory
//tree.Itcontainsanoffset,relativetothebeginningofthemaptothe
//directoryofthedatafortheresource,asizefieldthatgivesthenumber
//ofbytesofdataatthatoffset,aCodePagethatshouldbeusedwhen
//decodingcodepointvalueswithintheresourcedata.Typicallyfornew
//applicationsthecodepagewouldbetheunicodecodepage.
//
typedefstruct_IMAGE_RESOURCE_DATA_ENTRY{
DWORDOffsetToData;
DWORDSize;
DWORDCodePage;
DWORDReserved;
}IMAGE_RESOURCE_DATA_ENTRY,*PIMAGE_RESOURCE_DATA_ENTRY;
一、光标的结构及读取(type=1)
二、光标资源很像图标资源。
它们以成组的格式存储,前置组头。
组头也使用固定长度的组件索引,允许随机访问每个单独组件。
光标头的结构如下:
1、 [资源头(type=12)]被保存在组光标中
structCursorHeader{
WORD wReserved; //当前为0
WORD wType; //光标=2
WORD cwCount; //组件数量
};
三、
下一部分对每个组件资源都是重复的,起始于双字边界:
structResourceDirectory{
WORD wWidth;
WORD wHeight;
WORD wPlanes;
WORD wBitCount;
DWORD lBytesInRes; //指向组件
WORD wNameOrdinal;
WORD padding; //填充数据
};
●2、以下的结构保存在光标中(Type=1)
每个光标组件和图标组件也都相似。
不过有一个重要的不同点:
光标有一个“热点”,而图标没有。
下面是组件的结构:
[资源头]
structCursorComponent{
short xHotspot;
short yHotspot;
}
[单色异或掩码(MonochromeXORmask)]
[单色异或掩码(MonochromeANDmask)]
这些掩码是拷贝自.cur文件的位图。
在这一点上,光标资源和图标资源之间的不同点是:
图标资源有颜色DIB异或掩码,而光标没有。
虽然光标位图是单色位图,没有DIB头和颜色表,但为了方便处理,它们的位仍然以DIB格式存储,关于DIB格式参见SDK参考手册。
四、位图的结构及读取(type=2)
从PE文件中读取出的位图数据与完整的位图结构比较缺少位图文件头
位图文件头主要用于识别位图文件。
以下是位图文件头结构的定义:
typedef struct tagBITMAPFILEHEADER { // bmfh
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序
一、位图文件结构
位图文件由三部分组成:
文件头 + 位图信息 + 位图像素数据
1、位图文件头。
位图文件头主要用于识别位图文件。
以下是位图文件头结构的定义:
typedef struct tagBITMAPFILEHEADER { // bmfh
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
}BITMAPFILEHEADER;
其中的bfType值应该是“BM”(0x4d42),标志该文件是位图文件。
bfSize的值是位图文件的大小。
2、位图信息中所记录的值用于分配内存,设置调色板信息,读取像素值等。
以下是位图信息结构的定义:
typedefstructtagBITMAPINFO{
BITMAPINFOHEADERbmiHeader;
RGBQUAD bmiColors[1];
}BITMAPINFO;
可见位图信息也是由两部分组成的:
位图信息头 + 颜色表
2.1位图信息头。
位图信息头包含了单个像素所用字节数以及描述颜色的格式,此外还包括位图的宽度、高度、目标设备的位平面数、图像的压缩格式。
以下是位图信息头结构的定义:
typedef struct tagBITMAPINFOHEADER{ // bmih
DWORD biSize; // 结构BITMAPINFOHEADER的字节数
LONG biWidth; // 以像素为单位的图像宽度*
LONG biHeight; // 以像素为单位的图像长度*
WORD biPlanes; // 目标设备的位平面数,此值常为1
WORD biBitCount // 每个像素的位数*
DWORD biCompression;// 图像的压缩格式(这个值几乎总是为0)
DWORD biSizeImage;//以字节为单位的图像数据的大小
LONG biXPelsPerMeter;// 水平方向上的每米的像素个数
LONG biYPelsPerMeter;// 垂直方向上的每米的像素个数
DWORD biClrUsed;// 调色板中实际使用的颜色数
(2)
DWORD biClrImportant;// 现实位图时必须的颜色数(3)
} BITMAPINFOHEADER;
下表是对结构体当中各个成员的说明:
结构成员
说 明
biCompression
图像的压缩格式(这个值几乎总是为0)
压缩说明:
有0(不压缩),1(RLE8,8位RLE压缩),2(RLE4,4位RLE压缩,3(Bitfields, 位域存放)。
RLE简单地说是采用像素数+像素值的方式进行压缩。
T408采用的是位域存放方式,用两个字节表示一个像素,位域分配为r5b6g5。
图中03000000为00000003h=3。
说明:
*是需要加以注意的部分,因为它们是我们在进行位图操作时经常参考的变量
(1)对于每个像素的字节数,分别有一下意义:
0,用在JPEG格式中
1,单色图,调色板中含有两种颜色,也就是我们通常说的黑白图片
4,16色图
8,256色图,通常说的灰度图
16,64K图,一般没有调色板,图像数据中每两个字节表示一个像素,5个或6个位表示一个RGB分量
24,16M真彩色图,一般没有调色板,图像数据中每3个字节表示一个像素,每个字节表示一个RGB分量
32,4G真彩色,一般没有调色板,每4个字节表示一个像素,相对24位真彩图而言,加入了一个透明度,即RGBA模式
(2)这个值通常为0,表示使用biBitCount确定的全部颜色,例外是使用的颜色树木小于制定的颜色深度的颜色数目的最大值。
(3)这个值通常为0,表示所有的颜色都是必需的
2.2颜色表。
颜色表一般是针对16位以下的图像而设置的,对于16位和16位以上的图像,由于其位图像素数据中直接对对应像素的RGB(A)颜色进行描述,因而省却了调色板。
而对于16位一下的图像,由于其位图像素数据中记录的只是调色板索引值,因而需要根据这个索引到调色板去取得相应的RGB(A)颜色。
颜色表的作用就是创建调色板。
下图是带调色板和不带调色板的位图的简单示意图
图1 带调色板和不带调色板位图之间的区别
颜色表是由颜色表项组成的,颜色表项结构的定义如下:
typedef struct tagRGBQUAD { // rgbq
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
其中需要注意的问题是,RGBQUAD结构中的颜色顺序是BGR,而不是平常的RGB。
3、位图数据。
最后,在位图文件头、位图信息头、位图颜色表之后,便是位图的主体部分:
位图数据。
根据不同的位图,位图数据所占据的字节数也是不同的,比如,对于8位位图,每个字节代表了一个像素,对于16位位图,每两个字节代表了一个像素,对于24位位图,每三个字节代表了一个像素,对于32位位图,每四个字节代表了一个像素。
五、图标的结构及读取(type=3)
从PE文件中读取出的图标与完整的图标结构比较缺少图标文件头,图标的文件头被放在了组图标(type=14)中
1、以下结构被放在组图标中
文件头结构
C原型定义:
typedefstruct
{
word idreserved; //必须为0
word idtype; //1:
表示图标2:
表示光标
word idcount; //该组中图片的数目
icondirentry identries[1];//一个描述图片信息的结构体的串
}icondir,*lpicondir;
icondirentry结构,图标资源索引目录结构。
C原型定义:
typedefstruct
{
byte bwidth; //图片的宽度,以像素为单位
byte bheight; //图片的高度,以像素为单位
byte bcolorcount; //图片的颜色数目,如果颜色数大于等于8时该值为0
byte breserved; //保留为0
word wplanes; //colorplanes
word wbitcount; //每个像素的位数
dword dwbytesinres; //该图片的字节数
dword dwimageoffset; //表示图表数据的在图标数据中的开始位置//在PE文件中为WORD型,
//表示为该图标的编号
}icondirentry,*lpicondirentry;
其中dwbytesinres记录了该目录指向的图像数据区的尺寸,dwimageoffset指的是该段目录指向的图像数据段的起点在整个文件中的偏移量。
2、图像数据被存放在图标段中
Icon头的总体结构:
iconimage
typdefstruct
{
BITMAPINFOHEADER icheader; //DIB头
RGBQUAD iccolors[1]; //颜色表
byte icxor[1]; //dibbitsforxormask掩码
byte icand[1]; //dibbitsforandmask掩码
}iconimage,*lpiconimage;
DIB位图信息头:
bitmapinfoheader
typedefstructtagBITMAPINFOHEADER{/*bmih*/
DWORDbiSize;//结构BITMAPINFOHEADER的字节数
LONGbiWidth;//该图片的宽度,以像素为单位
LONGbiHeight;//该图片的高度的2倍,以像素为单位
WORDbiPlanes;//面数
WORDbiBitCount;//一个颜色所占的bit数
DWORDbiCompression;//0
DWORDbiSizeImage;//图片数据所占的字节数,包括掩码信息
LONGbiXPelsPerMeter;//0
LONGbiYPelsPerMeter;//0
DWORDbiClrUsed;//0
DWORDbiClrImportant;//0
}BITMAPINFOHEADER;
其中的icheader采用的是DIB结构的BMP文件(常用)的位图信息头的定义类型(参见BMP文件结构分析),但是其中使用的关键变量只用到:
bisize,biwidth,biheight,biplanes,bibitcount,bisizeimage.几个,其他变量必须为0。
其中的biheight变量和BMP文件里稍有不同,在BMP文件里,该变量指的是文件的高度象素量,而在ICON文件里,可能由于采用了两段掩码图像数据的缘故,该变量的值一般设定为高度象素量的2倍。
色彩表:
rgbquad
[摘自:
BMP文件格式分析:
彩色表包含的元素与位图所具有的颜色数相同,象素的颜色用RGBQUAD结构来定义。
对于24-位真彩色图象就不使用彩色表(同样也包括16位、和32位位图),因为位图中的RGB值就代表了每个象素的颜色。
彩色表中的颜色按颜色的重要性排序,这可以辅助显示驱动程序为不能显示足够多颜色数的显示设备显示彩色图象。
RGBQUAD结构描述由R、G、B相对强度组成的颜色,定义如下]
C原型定义:
typedefstructtagRGBQUAD{/*rgbq*/
BYTErgbBlue;
BYTErgbGreen;
BYTErgbRed;
BYTErgbReserved;
}RGBQUAD;
色彩表的定义也是来自BMP文件结构的定义,定义的类型格式和BMP文件的相同。
色彩表iccolors的尺寸由文件使用的色彩数量决定,对于16色的图像数据为:
iccolors(0to15),对于256色的图像数据为:
iccolors(0to255)。
但这个数量不是绝对的,
数据区:
描述每一个像素的数据
最后定义的时候还是应该由icheader中的bisize,biwidth,biheight,bibitcount变量和索引目录中的dwbytesinres计算得出=(dwbytesinres-biSize-AndMaskall-(biHeight/2)*Lb)/4'其中AndMaskall为1bpp那段掩码的尺寸,Lb为每行象素所占的字节数。
icxor数据尺寸为Lb乘以图标高度(biHeight/2)。
icand尺寸为1bpp的掩码数据段每行所占字节数乘以图标高度(biHeight/2)。
每行象素所占字节数=((icheader.biWidth*icheader.biBitCount+31)And&HFFFFF