滴水逆向——资源表

定位资源表

资源表位于PE结构中的数据目录表的第三项,下标为2

资源表总览

在这里插入图片描述
可以看到,资源表分为三层,每一个资源节点由两部分组成。最上面的绿色部分是一个资源目录:

typedef struct _IMAGE_RESOURCE_DIRECTORY {								
	DWORD   Characteristics;					//资源属性   保留 0		
	DWORD   TimeDateStamp;						//资源创建的时间		
	WORD    MajorVersion;						//资源版本号 未使用 0		
	WORD    MinorVersion;						//资源版本号 未使用 0	
	WORD    NumberOfNamedEntries;				//以名称命名的资源数量
	WORD    NumberOfIdEntries;					//以ID命名的资源数量		
//  IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];								
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;								

其中,NumberOfNamedEntries + NumberOfIdEntries == 资源节点里面黄色部分的数量

而每个黄色部分就是一个资源目录项:

typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {								
	union {						//目录项的名称、或者ID		
		struct {								
			DWORD NameOffset:31;								
			DWORD NameIsString:1;								
			};								
			DWORD   Name;								
			WORD    Id;								
	};								
	union {								
		DWORD   OffsetToData;	
		struct {								
			DWORD   OffsetToDirectory:31;								
			DWORD   DataIsDirectory:1;								
		};								
	};								
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY

其中,“ ” 表示位域,即该成员占多少个二进制位
在这里插入图片描述
也就是说,NameOffset占低31位,NameIsString占最高的1位,两个成员共同占据4字节空间

而这个Name成员在每一层中的含义也不一样:
在这里插入图片描述
在第一层中,Name代表了资源类型,从1到16,一共16种系统已经写好的预定义类型

而在这层,每个资源目录项的第一个union中存储的内容需要判断其最高位(也就是NameIsString的值)为0还是1来决定
若这个最高位的值为1,则代表这个union的低31位是一个指针,指向了一个结构:

typedef struct _IMAGE_RESOURCE_DIR_STRING_U {						
WORD    Length;						//Unicode字符串的长度
WCHAR   NameString[ 1 ];			//Unicode字符串的起始位置
} IMAGE_RESOURCE_DIR_STRING_U,
*PIMAGE_RESOURCE_DIR_STRING_U;						

若这个最高位的值为0,则代表这个union的低31位是一个数字,作ID使用

判断方法:
printf("%x\n",(pResourceEntry[i].Name & 0x80000000) == 0x80000000);		//位运算							
printf("%x\n",pResourceEntry[i].NameIsString == 1);						//直接比较NameIsString成员的值

第二个union的成员OffsetToData指向的则是下一层的相应资源节点的地址。我们可以发现第二个union同样也将OffsetToData分成了最高位和低31位

其中,最高位如果为1,低31位 + 资源地址 == 下一层目录节点的起始位置
第一层、第二层的最高位全为1
最高位如果为0,低31位就指向结构体IMAGE_RESOURCE_DATA_ENTRY:

typedef struct _IMAGE_DATA_DIRECTORY {					
DWORD   VirtualAddress;					
DWORD   Size;					
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

但是,OffsetToData并不是一个RVA:
首地址 + 资源表的FOA + OffsetToData的低31位 == 下一层的相应资源节点的真正地址(首地址 + 资源表的FOA == 资源表的首地址)

第三层为0,也就是说,第三层的OffsetToData通过上面加粗的公式得到的地址是结构体IMAGE_RESOURCE_DATA_ENTRY的真正地址

第二层的Name代表的是资源编号

第三层的Name代表的是代码页

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值