加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

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

发布时间:2020-12-14 03:56:01 所属栏目:Windows 来源:网络整理
导读:PE基础3 导入表的作用是什么? 没有它exe能运行吗? 导入外部模块,提供的API,变量,类 可以没有导入表(这个程序没有用到其它模块) 导出表的作用是什么? 没有它exe能运行吗? 导出模块名,函数(序号),变量,类 通常导出表用于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"版本信息",};
?
//显示资源表
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("%Sn",szBuff);    
        }       
        else {   
            //资源ID是数字      
            // 系统定义的 0 - 16 
            if (pResouceOneEntry[i].Id < 16) 
            {     
                wprintf(L"%sn",RES[pResouceOneEntry[i].Id]); 
            }    
            // 自定义的    
            else {     
                printf("%02dn",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->Length);   
                    printf("    %Sn",szBuff);
                    
                }          
                else {       
                    printf("   %02dn",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,资源大小 %02dn",pResourceData>OffsetToData,pResourceData->Size);
              
                }    
            }     
        }   
    }
}

?

?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读