能力值:
(RANK:350 )
|
-
-
2 楼
6.1.6 资源区块的处理
一般程序的资源都集中在资源区块(.rsrc)中,对于那些资源格式比较特殊的程序文件,
由于它们不具有普遍性,在此就不去讨论了。
资源区块的大致结构先是资源目录,紧接在后面的才是资源数据。系统必须根据资源目录
才能找到正确的资源数据。一般的资源只有在程序真正运行时才会被用到,但是有些特殊
类型的资源却不是这样,即使程序没有运行,它们也可能会被系统读取、使用。例如,当
使用“我的电脑”查看某个文件夹的内容时,该目录下的所有应用程序的图标都会被显示
出来。这些图标就是程序资源的一部分,它们在程序没有被执行时仍然会被系统读取。这种
特殊的资源类型通常包括了:Icon(图标)、Group icon(组图标)、Version information
(版本信息)等,它们一般是不能压缩的,因为它们一旦被错误处理,轻则产生程序异常如
丢失图标,重则可能根本无法运行。另外,由于系统必须根据资源目录才能找到它们,所以
资源目录也不能压缩。因此,对于资源区块的压缩一般需要分成三步来做:
1) 找到资源目录和资源数据的分割点,也就是资源数据的起点,在这之前的资源目录
部分不能被压缩。
2) 把那些不能压缩的资源类型如图标等从资源数据中提取出来,转移到一个不被压缩
的部分,一般是在外壳数据中找一段空间存放它们。同时还要修改资源目录项中相应的指针,
以保证当它们被移动后系统仍然可以找到它们。
3) 压缩资源区块中的资源数据。
下面就这三步分别来分析。
第一步使用一个自定义函数来完成,通过这个函数将找到的资源数据起点RVA地址作为返回
值放入EAX。函数所依据的原理是遍历所有的资源数据项,比较它们的起始RVA,找出最小的
那个作为整个资源数据的起点。函数中涉及资源目录结构的部分,读者可以参考前面章节或
MSDN里的资料。函数代码如下:
FindFirstResADDR PROC
;函数功能:查找程序资源数据的起点
;没有入口参数,所使用的数据皆为全局变量,函数执行过程中都不做改变。
;出口参数:EAX=资源数据起点的RVA
LOCAL FirstResAddr:DWORD ;在其中存放资源数据的起点
push edi
push esi
push ecx
mov FirstResAddr,7fffffffh ;先放置一较大值,然后根据比较逐渐减小
mov esi,PeHeadBase
assume esi : ptr IMAGE_NT_HEADERS
mov eax,dword ptr [esi].OptionalHeader.DataDirectory[2*SIZEOF IMAGE_DATA_DIRECTORY].VirtualAddress
mov esi,eax ;资源起点偏移
add eax,MapOfFile
mov edi,eax ;资源起点地址
xor ecx,ecx
mov cx,word ptr [edi+0ch]
add cx,word ptr [edi+0eh] ;有几类资源
add edi,10h
SearchNextResType:
push ecx
push edi
mov edi,dword ptr [edi+4h]
and edi,7fffffffh ;该类型目录相对于资源起点的偏移
add edi,esi
add edi,MapOfFile ;该类型目录地址
xor ecx,ecx
mov cx,word ptr [edi+0ch]
add cx,word ptr [edi+0eh] ;该类型中有几个项目
add edi,10h
SearchNextResObject:
push edi
mov edi,dword ptr [edi+4h]
and edi,7fffffffh ;该项目目录相对于资源起点的偏移
add edi,esi
add edi,MapOfFile ;该项目目录地址
add edi,10h
mov edi,dword ptr [edi+4h] ;该项目相对于资源起点的偏移
add edi,esi
add edi,MapOfFile ;该项目地址
mov eax,dword ptr [edi] ;该项目存放偏移
.if eax > esi
.if eax < FirstResAddr
mov FirstResAddr,eax
.endif
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
老大就是热心哈,这几天我也在啃书
|