PE基础3-资源表-重定位表-TLS表-DLL延迟加载表

PE基础3

导入表的作用是什么? 没有它exe能运行吗?

导入外部模块,提供的API,变量,类 可以没有导入表(这个程序没有用到其它模块)

导出表的作用是什么? 没有它exe能运行吗?

导出模块名,函数(序号),变量,类 通常导出表用于dll,没有导出表程序也可以运行

已知一个dll名,和一个dll导出函数的名字,如何得到这个函数名的地址?

导出表中查找 ENT(导出名称表) EOT(导出序号表) EAT(导出地址表)

 

怎么才能知道一个exe都使用了哪些API?

通过遍历导入表(INT,IAT)

如何判断导入函数是以序号导入或是以名称导入?

IMAGE_THUNK_DATA.DWORD 最高位1,说明序号导入

IMAGE_THUNK_DATA.DWORD 最高位0,说明名称导入

怎么才知道导出函数是仅以序号导出还是以名称导出?

遍历导出地址表,再遍历导出序号表,序号表中的值与导出地址表下标对应,

说明这个函数是名称导出, 如果序号表中的值没有与地址表下标对应,那么它是序号导出(序号+BASE)

 

资源表

概述

windows的资源有菜单、图标、快捷键、版本信息以及其它未格式化的二进制资源比如菜单、图标、快捷键、 版本信息以及其它未格式化的二进制资源。。。

资源由三层一样的结构体组成

第一层:资源的类型是什么(图标,位图,菜单....)

第二次:资源的叫什么名字 (1.png, 2.png)

第三层:资源的语言,资源的信息(大小,文件中位置)

 

 

资源表结构

资源表位于数据目标表,下标为2

资源目录结构体

typedef struct _IMAGE_RESOURCE_DIRECTORY {  
   DWORD   Characteristics;        // (1) 资源属性标识
   DWORD   TimeDateStamp;      // (2) 资源建立的时间  
   WORD    MajorVersion;       // (3) 资源主版本
   WORD    MinorVersion;       // (4) 资源子版本  
   WORD    NumberOfNamedEntries;   // (5) 资源名称条目个数  
   WORD    NumberOfIdEntries;  // (6) 资源ID条目个数
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { 
   union {      
       struct {      
           DWORD NameOffset   :31; // (1) 资源名偏移  
           DWORD NameIsString:1;   // (2) 资源名为字符串  
      };    
       DWORD   Name;               // (3) 资源/语言类型  
       WORD    Id;                 // (4) 资源数字ID    
  };  
   union {  
       DWORD   OffsetToData;       // (5) 数据偏移地址    
       struct {          
           DWORD   OffsetToDirectory:31;// (6) 子目录偏移地址    
           DWORD   DataIsDirectory   :1;// (7) 数据为目录  
      };
  };
}IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY;

当资源的名字为字符时,它指向这样一个结构体

typedef struct _IMAGE_RESOURCE_DIR_STRING_U {  
   WORD    Length;     // (1) 字符串长度  
   WCHAR   NameString[ 1 ];    // (2) 字符串数组
} IMAGE_RESOURCE_DIR_STRING_U,*PIMAGE_RESOURCE_DIR_STRING_U;

最后一层指向真正数据的信息

typedef struct _IMAGE_RESOURCE_DATA_ENTRY {  
   DWORD   OffsetToData;   // (1) 资源数据的RVA  
   DWORD   Size;       // (2) 资源数据的长度  
   DWORD   CodePage;       // (3) 代码页    
   DWORD   Reserved;       // (4) 保留字段
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
解析资源表
//获取资源表
PIMAGE_RESOURCE_DIRECTORY PE::GetResourceDirectory()
{
    //资源表位于数据目录表, 下标为2
    DWORD dwResourceRva = 
        GetNtHeader()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
​
    DWORD dwResourceFoa = RvaToFoa(dwResourceRva) + (DWORD)m_pBuff;
​
    return (PIMAGE_RESOURCE_DIRECTORY)(dwResourceFoa);
}
//自定义
const WCHAR* RES[20] = {
    L"光标",
    L"位图",
    L"图标",
    L"菜单",
    L"对话框",
    L"字符串列表",
    L"字体目录",
    L"字体",
    L"快捷键",
    L"非格式化资源",
    L"消息列表",
    L"鼠标指针数组",
    L"NULL",
    L"图标组",
    L"NULL",
    L"版本信息",
};
​
//显示资源表
void PE::ShowResourceInfo() {    //1. 获取资源目录表 
    PIMAGE_RESOURCE_DIRECTORY pResourceOne = GetResourceDirectory();   
    //获取资源数组项  
    PIMAGE_RESOURCE_DIRECTORY_ENTRY pResouceOneEntry =         (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceOne + 1);
    //1.2 遍历所有资源类型  
    //资源总个数  
    DWORD dwResourceNumber = pResourceOne->NumberOfIdEntries + pResourceOne>NumberOfNamedEntries;  
    for (int i = 0; i < dwResourceNumber; i++)   
    {      
        //1.3 判断资源类型,是数字还是字符串    
        if (pResouceOneEntry[i].NameIsString)   
        {          
            //资源ID是字符串     
            //那么NameOffset 有效(基于资源表的偏移)   
            PIMAGE_RESOURCE_DIR_STRING_U szName =                 (PIMAGE_RESOURCE_DIR_STRING_U)(pResouceOneEntry[i].NameOffset + (DWORD)pResourceOne); 
            TCHAR szBuff[100];    
            wcsncpy_s(szBuff, szName->NameString, szName->Length);  
            printf("%S\n", szBuff);    
        }       
        else {   
            //资源ID是数字      
            // 系统定义的 0 - 16 
            if (pResouceOneEntry[i].Id < 16) 
            {     
                wprintf(L"%s\n", RES[pResouceOneEntry[i].Id]); 
            }    
            // 自定义的    
            else {     
                printf("%02d\n", pResouceOneEntry[i].Id);
            }    
        }    
        //2 解析第二层数据   
        //2.1 是否有第二层数据    
        if (pResouceOneEntry[i].DataIsDirectory)    
        {         
            //2.2 获取第二层资源表     
            PIMAGE_RESOURCE_DIRECTORY pResourceTwo =                 (PIMAGE_RESOURCE_DIRECTORY)(pResouceOneEntry[i].OffsetToDirectory + (DWORD)pResourceOne);            //获取资源数组项       
            PIMAGE_RESOURCE_DIRECTORY_ENTRY pResouceTwoEntry =                (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceTwo + 1);
            //这种资源有多少个    
            DWORD dwNumber2 = pResourceTwo->NumberOfIdEntries + pResourceTwo>NumberOfNamedEntries;
            //2.3 遍历资源    
            for (int i = 0; i < dwNumber2; i++)      
            {           
                //资源名字是 数字,还是字符串   
                if (pResouceTwoEntry[i].NameIsString)  
                {           
                    PIMAGE_RESOURCE_DIR_STRING_U szName =                        (PIMAGE_RESOURCE_DIR_STRING_U)(pResouceTwoEntry[i].NameOffset + (DWORD)pResourceOne);
                    TCHAR szBuff[100];  
                    wcsncpy_s(szBuff, szName->NameString, szName->Length);   
                    printf("    %S\n", szBuff);
                    
                }          
                else {       
                    printf("   %02d\n", pResouceTwoEntry[i].Id);  
                }       
                //3. 解析第3层  
                //3.1 是否有第三层数据   
                if (pResouceTwoEntry[i].DataIsDirectory)   
                {             
                    //3.2 获取第三层资源表           
                    PIMAGE_RESOURCE_DIRECTORY pResourceThree =                        (PIMAGE_RESOURCE_DIRECTORY)(pResouceTwoEntry[i].OffsetToDirectory + (DWORD)pResourceOne);                   PIMAGE_RESOURCE_DIRECTORY_ENTRY pResourceThreadEntry =                        (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceThree + 1);
                    //第三层 执行真正数据                    
                    PIMAGE_RESOURCE_DATA_ENTRY pResourceData =                        (PIMAGE_RESOURCE_DATA_ENTRY)(pResourceThreadEntry->OffsetToData + (DWORD)pResourceOne);                   
                    printf("            资源位置 %08X,资源大小 %02d\n", pResourceData>OffsetToData, pResourceData->Size);
              
                }    
            }     
        }   
    }
}

 

 

转载于:https://www.cnblogs.com/ltyandy/p/11093641.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值