分析PE格式文件中的图标信息

 
PE格式的资源段是比较复杂的,目前几种介绍PE格式的书籍在介绍到这部分时都是不够深入(本人认为写得比较好的有《Windows95系统程式设计奥秘》候捷译本),因此不
得不拿起工具自已研究,分析PE格式比较好的工具有:stud_PE,UltraEdit等。以下记录我在研究图标资源时的过程,请结合PE格式分析教材阅读
 
步骤:
1、得到资源段的偏移地址;
用Stud_PE打开PE格式文件,“sections”页中有个名称为“.rsrc”的行(如果程序有资源的话)。 查看该行的“VirtualOffset”字段,其值即是资源段的偏移,也是文件中的偏移;
 
2、用一款十六进制编辑软件(可使用UltraEdit)打开PE格式文件,定位到资源段;
 
3、资源段首先是个IMAGE_RESOURCE_DIRECTORY结构数据,该结构的NumberOf-
NamedEntries表示“使用名称的资源”的个数,NumberOfIdEntries表示“使用整数ID的资源”;
 
4、然后是数个IMAGE_RESOURCE_DIRECTORY_ENTRY结构,个数是NumberOfNam-
       edEntries和NumberOfIdEntries的和;IMAGE_RESOURCE_DIRECTORY_ENT
RY结构只有8字节,虽然结构看起来很大。前4个字节表示资源类型,后4个字节表示位置。资源类型的值如果是3(RT_ICON)表示图标,其它值参考文档,例如,2(RT_BITMAP)表示位图,1(RT_CURSOR)表示光标;后4个字节表示资源的位置,如果高位被置位,余下的31位就是指向资源目录的偏移,这个偏移相对于资源区块开始的位置而不是RVA;
 
5、找到图标资源的偏移,这里又是一个IMAGE_RESOURCE_DIRECTORY结构,结构的
       NumberOfIdEntries表示图标的个数;此后又是数个IMAGE_RESOURCE_DIRECTO
RY_ENTRY(与图标个数相同),前4个字节应该是图标的ID,后期个字节是图标
的位置;
 
6、由上步的偏移再次找到一个IMAGE_RESOURCE_DIRECTORY结构,感觉没什么有用
       信息;之后又是一个IMAGE_RESOURCE_DIRECTORY_ENTRY结构(好烦),此时,
       通过后4个字节(与资源区首的偏移值)可以找到另一个IMAGE_RESOURCE_DATA_
ENTRY结构,该结构的有用信息是: offsetToData表示图标数据的位置(是RVA,此时不是偏移了),size 图标数据块的大小。
 
7、最后注意,这里的图标信息比普通的图标文件的信息好,粗略一看,至少少了文件头和
       图标头两部分数据,直接从图片数据开始,即BITMAPINFOHEADER(没写错哦)。
 
 
上面过程当RAV=RAW(在可执行文件中的偏移)情况,但多数情况下这两个值均不相等。
如何得到RAV和RAW和偏移呢(offset):
在IMAGE_OPTION_HEADER 结构之后就是数个IMAGE_SECTION_HEADER(区表),每个区表关联一种资源的信息,个数由IMAGE_NT_HEADERS.FileHeader.NumberOfSe-
ctions指定,在区表结构有一个字段是PointerToRawData, 即表示块在磁盘文件中的偏移。
记住这个RAW,并算出其与RAV的offset 。在后面给出的许多地址均是RAV,通过这个
offset就可计算出其对应的RAW。
 
下面的代码给出查找EXE文件中第一个图标数据所在磁盘文件的编移和大小(代码比较凌乱):
 
CFileDialog dlg ( TRUE ) ;
if( dlg.DoModal() != IDOK )
         return ;
 
HANDLE hFile = CreateFile( dlg.GetPathName() , GENERIC_READ | GENERIC_WRITE,
                                              FILE_SHARE_READ | FILE_SHARE_WRITE , NULL , OPEN_EXISTING ,
                                              FILE_ATTRIBUTE_NORMAL , NULL ) ;
if( hFile == INVALID_HANDLE_VALUE )
         return ;
 
HANDLE hMap = ::CreateFileMapping( hFile , NULL ,
PAGE_READWRITE , 0 , ::GetFileSize(hFile,NULL)+1 , NULL ) ;
        
if( hMap )
{
         LPVOID buffer = ::MapViewOfFile( hMap , FILE_MAP_WRITE | FILE_MAP_READ , 0 , 0 , 0 ) ;
         if( buffer )
         {
                                              
                  IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER *)buffer ;
                  IMAGE_NT_HEADERS *pNtHeader = (IMAGE_NT_HEADERS *)((DWORD)buffer
+ pDosHeader->e_lfanew ) ;
                           
 
                  DWORD dwNumberOfSections = pNtHeader->FileHeader.NumberOfSections ;
                  IMAGE_SECTION_HEADER *pSectionHeader = (IMAGE_SECTION_HEADER *)
((DWORD)pNtHeader + sizeof(IMAGE_NT_HEADERS) ) ;
 
                  for( DWORD i = 0 ; i < dwNumberOfSections ; i ++ )
                   {
                            if( lstrcmp( (char *)pSectionHeader->Name , ".rsrc" ) == 0 )
                                     break ;
                            pSectionHeader ++ ;
                   }
 
                   if( i < dwNumberOfSections )
                   {
                            DWORD dwOffsetRavToRaw = pNtHeader->OptionalHeader.DataDirectory[2].
VirtualAddress –>pSectionHeader->PointerToRawData ;
                                                                                                               
                            IMAGE_RESOURCE_DIRECTORY *pResourceDirect =
(IMAGE_RESOURCE_DIRECTORY *)
                                        ((DWORD)buffer + pSectionHeader->PointerToRawData ) ;
 
                            TRACE("res section rav:%x/n " , pNtHeader->OptionalHeader.
DataDirectory[2].VirtualAddress ) ;
                            TRACE("res raw: %x/n" , pSectionHeader->PointerToRawData ) ;
 
                                    
                            IMAGE_RESOURCE_DIRECTORY_ENTRY *pEntry =
(IMAGE_RESOURCE_DIRECTORY_ENTRY *)
                                              ( (DWORD)pResourceDirect + sizeof(IMAGE_RESOURCE_DIRECTORY) ) ;
                                    
                            int nRes = pResourceDirect->NumberOfIdEntries +
pResourceDirect->NumberOfNamedEntries ;
                                    
                            for( int i = 0 ; i < nRes ; i ++ )
                            {
                                     if( pEntry->Id == 3 )
                                     {
                                              TRACE("icon entry is %x/n" , pEntry->OffsetToData ) ;
                                               break;
                                     }
                                     pEntry ++ ;
                            }
                                    
                                    
                                    
                                    
                            int offset = pEntry->OffsetToData ;
                            if( offset & 0x80000000 )
                                     offset &= 0x7FFFFFFF ;
                            TRACE("%x/n" , offset ) ;
                                    
                            IMAGE_RESOURCE_DIRECTORY *pIconDirect =
(IMAGE_RESOURCE_DIRECTORY *)((DWORD)pResourceDirect + offset ) ;
                                    
                            IMAGE_RESOURCE_DIRECTORY_ENTRY *pIconEntry =
(IMAGE_RESOURCE_DIRECTORY_ENTRY *)((DWORD)pIconDirect + 16);
                                    
                            offset = pIconEntry->OffsetToData ;
                            if( offset & 0x80000000 )
                                     offset &= 0x7FFFFFFF ;
                            TRACE("%x/n" , offset ) ;
                                    
                                    
                            pIconEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)
((DWORD)pResourceDirect + offset +16 ) ;
                            offset = pIconEntry->OffsetToData ;
                            if( offset & 0x80000000 )
                                     offset &= 0x7FFFFFFF ;
                            TRACE("%x/n" , offset ) ; // offset = 0x168
                                    
pIconEntry=(IMAGE_RESOURCE_DIRECTORY_ENTRY *)((DWORD)
pResourceDirect + offset ) ;
                                    
                            int icon_offset = pIconEntry->Name ;
                            int icon_size = pIconEntry->OffsetToData ;
                                    
                                                                
                            CString str ;
                                    
                            str.Format(" ICON 's RVA = %X , RAW = %X , size = %X /n" ,
                                              icon_offset , icon_offset - dwOffsetRavToRaw,
                                              icon_size ) ;
                            AfxMessageBox( str ) ;
                                    
                   }
                  ::UnmapViewOfFile( buffer ) ;
         }
 
         ::CloseHandle( hMap ) ;
       ::CloseHandle( hFile ) ;
 

你可能感兴趣的:(image,header,File,dos,null,buffer)