2.8 PE结构:资源表详细解析

这篇具有很好参考价值的文章主要介绍了2.8 PE结构:资源表详细解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在Windows PE中,资源是指可执行文件中存放的一些固定不变的数据集合,例如图标、对话框、字符串、位图、版本信息等。PE文件中每个资源都会被分配对应的唯一资源ID,以便在运行时能够方便地查找和调用它们。PE文件中的资源都被组织成一个树形结构,其中最顶层为根节点(Root),下一级为资源类型(Type),再下一级为资源名称(Name),最终是实际的资源内容。

PIMAGE_RESOURCE_DIRECTORY是Windows PE可执行文件中的一个结构类型,用于描述资源(Resource)的树形结构,其中包括了每个资源的类型(Type)、名称(Name)和语言(Language),以及指向下一级PE资源目录的地址和相关信息等。

typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY
{
    union {
        struct {
            DWORD NameOffset:31;
            DWORD NameIsString:1;
        } DUMMYSTRUCTNAME;
        DWORD   Name;
        WORD    Id;
    } DUMMYUNIONNAME;
    union {
        DWORD   OffsetToData;
        struct {
            DWORD   OffsetToDirectory:31;
            DWORD   DataIsDirectory:1;
        } DUMMYSTRUCTNAME2;
    } DUMMYUNIONNAME2;
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;

PIMAGE_RESOURCE_DIRECTORY描述了Windows PE资源的目录结构,每个资源目录包括以下字段:

  • Characteristics:指定该目录的属性,如是否允许命名、是否允许ID等;
  • TimeDateStamp:指定该目录的时间戳;
  • MajorVersion / MinorVersion:指定PE文件中允许的最高版本和最低版本;
  • NumberOfNamedEntries:指定该目录中已经命名的资源条目数量;
  • NumberOfIdEntries:指定资源ID类型的数量;
  • PIMAGE_RESOURCE_DIRECTORY_ENTRY:指针,指向资源入口表,即PE文件中每个资源的入口地址。
  • PIMAGE_RESOURCE_DIRECTORY_ENTRY用于引用PE文件中资源的名称、类型和语言信息,它包括了Name/Id:指定资源的名称或ID,根据缩小范围的优先级进行查找,ID的优先级高于名称;
  • OffsetToData:指向该资源的数据偏移地址或其Resource Data Entry的地址。

读者在解析时通常需要在数据目录表PIMAGE_DATA_DIRECTORY中定位到IMAGE_DIRECTORY_ENTRY_RESOURCE资源表,通过循环的方式以此遍历出PIMAGE_RESOURCE_DIRECTORY_ENTRY中的每一个节点,最终输出资源信息,这段输出代码如下所示;

// --------------------------------------------------
// 定义资源表解析结构
// --------------------------------------------------
static char* szResName[0x11] = { 0, (char*)"鼠标指针", (char*)"位图", (char*)"图标", (char*)"菜单", (char*)"对话框", (char*)"字符串列表", (char*)"字体目录", (char*)"字体", (char*)"快捷键", (char*)"非格式化资源", (char*)"消息列表", (char*)"鼠标指针组", (char*)"zz", (char*)"图标组", (char*)"xx", (char*)"版本信息" };


int main(int argc, char * argv[])
{
    BOOL PE = IsPeFile(OpenPeFile("c://pe/x86.exe"), 0);

    if (PE == TRUE)
    {
        // 获取数据目录表
        PIMAGE_DATA_DIRECTORY pData = NtHeader->OptionalHeader.DataDirectory;

        // 获取到资源目录表
        pData = &(pData[IMAGE_DIRECTORY_ENTRY_RESOURCE]);

        // 获取资源目录表的偏移
        DWORD dwResOffset = RVAtoFOA(pData->VirtualAddress);

        // 获取到资源目录表
        PIMAGE_RESOURCE_DIRECTORY pRes = (PIMAGE_RESOURCE_DIRECTORY)(GlobalFileBase + dwResOffset);

        // 获取紧跟着的IMAGE_RESOURCE_DIRECTORY_ENTRY的个数
        DWORD dwResSize = pRes->NumberOfNamedEntries + pRes->NumberOfIdEntries;

        // 获取到PIMAGE_RESOURCE_DIRECTORY_ENTRY 
        PIMAGE_RESOURCE_DIRECTORY_ENTRY  pResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pRes + 1);

        printf("资源类型ID \t 类型 \n");

        for (DWORD i = 0; i < dwResSize; i++)
        {

            // 如果为0则执行
            if (!pResEntry[i].NameIsString)
            {
                if (pResEntry[i].Id < 0x11)
                {
                    // printf("资源类型ID: %p --> 类型: %s\n", pResEntry[i].Id, szResName[pResEntry[i].Id]);
                    printf("%p \t %s \n", pResEntry[i].Id, szResName[pResEntry[i].Id]);
                }
                else
                {
                    char  type[20];
                    sprintf_s(type, "%d", pResEntry[i].Id);
                    // printf("资源类型ID: %p --> 类型: %s\n", pResEntry[i].Id, type);
                    printf("%p \t %s \n", pResEntry[i].Id, type);
                }
            }
            // 如果为1则执行
            else
            {
                PIMAGE_RESOURCE_DIR_STRING_U pstcString = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pRes + pResEntry[i].NameOffset);
                WCHAR szStr[MAX_PATH] = { 0 };
                memcpy_s(szStr, MAX_PATH, pstcString->NameString, pstcString->Length * sizeof(WCHAR));
                // printf("资源字符串: %ls\n", szStr);
            }
        }
    }
    else
    {
        printf("非标准程序 \n");
    }

    system("pause");
    return 0;
}

编译并运行上述程序片段,则读者可以看到当前程序中所包含的所有资源信息,为了简单可用此处并没有输出递归资源,仅仅输出了第一层,输出效果图如下所示;

2.8 PE结构:资源表详细解析,《Visual C++ 安全编程技术实践》,《灰帽黑客:攻守道》,PE结构,信息安全,C++,微软技术,Visual C++,网络安全文章来源地址https://www.toymoban.com/news/detail-702777.html

到了这里,关于2.8 PE结构:资源表详细解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 驱动开发:内核解析PE结构导出表

    在笔者的上一篇文章 《驱动开发:内核特征码扫描PE代码段》 中 LyShark 带大家通过封装好的 LySharkToolsUtilKernelBase 函数实现了动态获取内核模块基址,并通过 ntimage.h 头文件中提供的系列函数解析了指定内核模块的 PE节表 参数,本章将继续延申这个话题,实现对PE文件导出表的

    2024年02月07日
    浏览(26)
  • [系统安全] 五十四.恶意软件分析 (6)PE文件解析及利用Python获取样本时间戳

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列。因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全、逆向分析和恶意代码检测,“系统安全”系列文章会更

    2024年01月19日
    浏览(51)
  • Microsoft Visual C++ Redistributable资源下载

    微软官网:Microsoft Visual C++ Redistributable latest supported downloads

    2024年02月06日
    浏览(38)
  • Unity 3D脚本编程与游戏开发(2.8)

    5.1.2 矩形变换(Rect Transform)组件         如果选中界⾯上的控件,读者会发现每个物体并不带有基本的Transform组件,取⽽代之的是Rect Transform(矩形变换)组件。其实Rect Transform组件是Transform组件的⼦类,因此并不违反“每个物体必须有且只有⼀个Transform组件”的规定。

    2024年02月03日
    浏览(30)
  • visual stdio c++调用python混合编程

    关于环境创建可以参考https://blog.csdn.net/qq_36559788/article/details/123174309 这里python我用的是anaconda里的python38 ,并且没有debug库,所以我只用了release库 在vs中设置项目属性,添加 包含目录 以及 附加库目录 ,注意都是在release模式下添加的 在main.cpp中添加头文件 添加代码 编译运行

    2024年02月01日
    浏览(32)
  • C++编程:Visual Studio启动之后如何创建项目

    Visual Studio启动之后,我们首先应该创建一个项目。所谓“项目”,就是一个工作任务,需要实现相应的需求。点击“创建新项目”。   直接选择一个空项目。   指定项目名称和保存位置。   这里还有一个“解决方案”(Solution)的概念,其实就是一组有关联的项目,共同合

    2024年02月07日
    浏览(43)
  • C++ 混合Python编程 及 Visual Studio配置

    接手了一个C++应用程序,解析csv和生成csv文件,但是如果要把多个csv文件合并成一个Excel,分布在不同的Sheet中,又想在一次运行中完成,不想说运行完C++ 的App后,再调用一个Python脚本或程序,这需要两步操作 根据安装的Visual Studio 的版本,我安装的是64-bit的。 如何查看当前

    2024年02月13日
    浏览(32)
  • 【计算机视觉】Visual Transformer (ViT)模型结构以及原理解析

    Visual Transformer (ViT) 出自于论文《AN IMAGE IS WORTH 16X16 WORDS: TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE》,是基于Transformer的模型在视觉领域的开篇之作。 本文将尽可能简洁地介绍一下ViT模型的整体架构以及基本原理。 ViT模型是基于Transformer Encoder模型的,在这里假设读者已经了解Transfo

    2024年02月02日
    浏览(34)
  • 深入探究 C++ 编程中的资源泄漏问题

    目录 1、GDI对象泄漏 1.1、何为GDI资源泄漏? 1.2、使用GDIView工具排查GDI对象泄漏

    2024年02月08日
    浏览(34)
  • 【Azure】微软 Azure 基础解析(五)核心体系结构之管理组、订阅、资源和资源组以及层次关系

    本系列博文还在更新中,收录在专栏:「Azure探秘:构建云计算世界」 专栏中。 本系列文章列表如下: 【Azure】微软 Azure 基础解析(三)描述云计算运营中的 CapEx 与 OpEx,如何区分 CapEx 与 OpEx 【Azure】微软 Azure 基础解析(四)Azure核心体系结构组件之数据中心、区域与区域

    2024年02月07日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包