在PE权威指南书中 ,p211页代码
-------------------------
;递归函数,遍历资源表项
;_lpFile:文件地址
;_lpRes:资源表地址
;_lpResDir:目录地址
;_dwLevel:目录级别
;-------------------------
_processRes proc _lpFile,_lpRes,_lpResDir,_dwLevel
local @dwNextLevel,@szBuffer[1024]:byte
local @szResName[256]:byte
pushad
mov eax,_dwLevel
inc eax
mov @dwNextLevel,eax ;为下一次递归准备第四个参数
mov esi,_lpResDir ;指向目录表
;计算目录项的个数
assume esi:ptr IMAGE_RESOURCE_DIRECTORY
mov cx,[esi].NumberOfNamedEntries
add cx,[esi].NumberOfIdEntries
movzx ecx,cx
;跳过目录头定位到目录项
add esi,sizeof IMAGE_RESOURCE_DIRECTORY
assume esi:ptr IMAGE_RESOURCE_DIRECTORY_ENTRY
.while ecx>0
push ecx
;查看IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData
mov ebx,[esi].OffsetToData
.if ebx & 80000000h ;如果最高位为1
and ebx,7FFFFFFFh ;求其他目录项
add ebx,_lpRes ;偏移是基于资源表起始地址的
;为下一次递归准备第三个参数
.if _dwLevel==1 ;如果是第一级资源类别
mov eax,[esi].Name1
.if eax & 80000000h ;如果是按名称定义的资源类型
;该部分结束后,eax指向了名称字符串
and eax,7FFFFFFFh
add eax,_lpRes
movzx ecx,word ptr [eax] ;ecx=名字长度
;跳过2个字节的IMAGE_RESOURCE_DIR_STRING_U.Length1
add eax,2
mov edx,eax ;edx=名字地址
;将UNICODE字符转换为多字节字符
invoke WideCharToMultiByte,CP_ACP,\
WC_COMPOSITECHECK,edx,ecx,\
addr @szResName,sizeof @szResName,\
NULL,NULL
lea eax,@szResName
.else ;如果是按编号定义的资源类型
;该分支结束后,eax指向了资源编号
.if eax<=10h ;系统内定的资源编号
;定位编号所在字符串eax=(n-1)*sizeof szType
dec eax
mov ecx,sizeof szType
mul ecx
add eax,offset szType
.else
invoke wsprintf,addr @szBuffer,\
addr szOut5,eax
jmp _goHere
.endif
.endif
invoke wsprintf,addr @szBuffer,addr szLevel1,eax
_goHere:
.elseif _dwLevel==2 ;如果是第二级资源ID
mov edx,[esi].Name1
.if edx & 80000000h ;如果是按字符串定义的资源ID
and edx,7FFFFFFFh
add edx,_lpRes
movzx ecx,word ptr [edx] ;ecx=名字长度
;跳过2个字节的IMAGE_RESOURCE_DIR_STRING_U.Length1
add edx,2
;将UNICODE字符转换为多字节字符
invoke WideCharToMultiByte,CP_ACP,\
WC_COMPOSITECHECK,edx,ecx,\
addr @szResName,sizeof @szResName,\
NULL,NULL
invoke wsprintf,addr @szBuffer,addr szLevel2,\
addr @szResName
.else ;如果是按编号定义的资源类型
invoke wsprintf,addr @szBuffer,\
addr szOut6,edx
.endif
.else
.break ;跳出递归
.endif
invoke _appendInfo,addr @szBuffer
invoke _processRes,_lpFile,_lpRes,ebx,@dwNextLevel
;如果IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData最高位为0
.else ;第三级目录
add ebx,_lpRes
mov ecx,[esi].Name1 ;代码页
assume ebx:ptr IMAGE_RESOURCE_DATA_ENTRY
mov eax,[ebx].OffsetToData
invoke _RVAToOffset,_lpFile,eax
invoke wsprintf,addr @szBuffer,addr szLevel3,\
ecx,eax,[ebx].Size1
invoke _appendInfo,addr @szBuffer
.endif
add esi,sizeof IMAGE_RESOURCE_DIRECTORY_ENTRY
pop ecx
dec ecx
.endw
assume esi:nothing
assume ebx:nothing
popad
ret
_processRes endp
红色标记的语句 : jmp _goHere
这里是不是判断,如果不是系统内定资源编号,就结束递归?
如果是我想问什么情况下会有资源编号不是系统内定的,前边好像没有讲到这个知识点,还是所有PE文件资源编号不存在大于16的。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课