这个结构长度为8个字节。共有两个字段,每个字段4个字节。
根据不同情况,这两个字段的含义不一样。这个结构的定义如果看不懂的话,后面的例子一看就会明白了。
第一个字段,当第一个字段的最高位是1的时候,表示,这个DWORD的剩下31位表明一个相对于资源开始位置的偏移,这个偏移的内容是一个IMAGE_RESOURCE_DIR_STRING,用里面的字符串来标明这个IMAGE_RESOURCE_DIRECTORY_ENTRY。当第一个字段的最高位是0的时候,表示,这个DWORD的低WORD中的值作为id标明这个IMAGE_RESOURCE_DIRECTORY_ENTRY。
第二个字段,当第二个字段的最高位是1的时候,表示,还有下一层的结构。这个DWORD的剩下31位表明一个相对于资源开始位置的偏移,这个偏移的内容会是一个下一层的IMAGE_RESOURCE_DIRECTORY结构,这个请看后面的例子中的说明。
当第二个字段的最高位是0的时候,表示,已经没有下一层的结构了。这个DWORD的剩下31位表明一个相对于资源开始位置的偏移,这个偏移的内容会是一个IMAGE_RESOURCE_DATA_ENTRY结构,IMAGE_RESOURCE_DATA_ENTRY结构会说明资源的位置。
标示一个IMAGE_RESOURCE_DIRECTORY_ENTRY一般都是使用id,就是一个整数。
但是也有少数的使用IMAGE_RESOURCE_DIR_STRING来标示一个IMAGE_RESOURCE_DIRECTORY_ENTRY。
IMAGE_RESOURCE_DIRECTORY_ENTRY结构定义如下。
typedef struct _IMAGE_RESOURCE_DIR_STRING_U {
WORD Length;
WCHAR NameString[ 1 ];
} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U;
这个结构中将有一个Unicode的字符串,是字对齐的。所有这些用来标识的IMAGE_RESOURCE_DIR_STRING都放在一起,这个结构的长度是可变的,由第一个字段Length指明后面的Unicode字符串的长度。
经过3层IMAGE_RESOURCE_DIRECTORY_ENTRY(一般是3层,也有可能更少些。第一层资源类型bmp,menu等等,第二层资源名,第三层是资源的Language。)最终会找到一个IMAGE_RESOURCE_DATA_ENTRY结构,这个结构中存有相应(某资源类型,某资源名,某资源Language)资源的位置和大小,就真正找到资源了。IMAGE_RESOURCE_DATA_ENTRY定义如下。
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData;
DWORD Size;
DWORD CodePage;
DWORD Reserved;
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
这个结构长16个字节,有4个字段。
OffsetToData:这是一个内存中的RVA,要转化成文件中的位置,需要用这个值减去资源节的开始RVA,
资源节的开始RVA可以由Optional Header中的DataDirectory数组中的第三项中的VirtualAddress的值得到。
或者节表中,资源节那项中的VirtualAddress的值得到。相减之后,就可以得到相对于资源节开始的偏移。
再加上资源节在文件中的开始位置,节表中资源节那项中的PointerToRawData的值,就是资源在文件中的位置。
Size:资源的大小,以字节为单位。
CodePage:一般来说是Unicode code page。
Reserved:保留,值为0。
上面是资源各种结构的说明,知道这些结构还远远不够,下面我们通过一个例子来看如何通过这些结构找到资源。
我们的例子是Win2k中的可执行文件telnet.exe。为了防止大家版本不同,本文附带了这个PE文件。
PE文件的资源的各种结构放在一个树型结构中,这个结构一般有3层,如图4.1,就是telnet.exe中的情况。
图4.1
图中长的长方形表示一个IMAGE_RESOURCE_DIRECTORY结构,长16个字节,简称directory。
图中短的长方形表示一个IMAGE_RESOURCE_DIRECTORY_ENTRY结构,长8个字节,简称directory_entry。
图中圆圈表示一个IMAGE_RESOURCE_DATA_ENTRY结构,长16个字节,简称data_entry。
上一页 1 2 3 4 下一页