6.2 遍历重定位表

news2024/12/26 12:42:08

本节我们将编写一个遍历重定位表的示例程序,打印重定位表。

本节必须掌握的知识点:

        遍历重定位表

6.2.1 遍历重定位表

实验四十三:遍历重定位表

Image_093

以下代码实现打印"c:\\notepad64.exe"进程重定位表的所有信息。

/*------------------------------------------------------------------------

 FileName:PrintImportDescriptor.c

 实验43:遍历重定位表(支持32位和64位PE)

 (c) bcdaren, 2024

-----------------------------------------------------------------------*/

#include <stdio.h>

#include <windows.h>

#include <winnt.h>

#define WIN64



PBYTE creatfilemap(LPCWSTR szFile);

VOID printReloc(PBYTE lpvResult);

DWORD RvaToFoa(PIMAGE_NT_HEADERS ntHeaders, DWORD rva);



int main(int argc, char* argv[])

{

    //LPCWSTR szFileName = TEXT("c:\\winResult.dll");

    LPCWSTR szFileName = TEXT("c:\\notepad64.exe");

    PBYTE lpAddress = NULL; //PE文件内存映射文件地址



    lpAddress = creatfilemap(szFileName);

    if (lpAddress)

    {

        printf("%ls\n", szFileName);

        printReloc(lpAddress);

    }

    system("pause");

    return 0;

}



//创建PE文件映射对象

PBYTE creatfilemap(LPCWSTR szFile)

{

    HANDLE hFile;

    HANDLE hMapFile = NULL;

    PBYTE lpMemory = NULL;  //PE文件内存映射文件地址

    char buffer[16] = { 0 };

    DWORD dwFileSize;

    DWORD dwBytesRead = 0;

    PIMAGE_DOS_HEADER lpstDOS = NULL;

    PIMAGE_NT_HEADERS lpstNT = NULL;



    hFile = CreateFile(szFile,

        GENERIC_READ,          // 只读打开

        FILE_SHARE_READ,       // 允许其他进程以读取方式打开文件

        NULL,                  // 默认安全属性

        OPEN_EXISTING,         // 打开已存在的文件

        FILE_ATTRIBUTE_NORMAL, // 普通文件

        NULL);



    if (hFile == INVALID_HANDLE_VALUE)

        printf("打开文件失败!\n");

    else

    {

        dwFileSize = GetFileSize(hFile, 0);//获得文件大小可通过结构体获取

        //创建内存映射文件

        if (dwFileSize)

        {

            if (hMapFile = CreateFileMapping(hFile, NULL,

PAGE_READONLY, 0, 0, NULL))

            {

                //获得文件在内存的映象起始位置

                lpMemory = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);

                if (!lpMemory)

                    printf("获取映像起始地址失败!\n");



                //检查PE文件是否有效

                lpstDOS = (PIMAGE_DOS_HEADER)lpMemory;

                if (lpstDOS->e_magic != IMAGE_DOS_SIGNATURE)

                    printf("非PE格式文件!\n");



                lpstNT = (PIMAGE_NT_HEADERS)(lpMemory + lpstDOS->e_lfanew);



                if (lpstNT->Signature != IMAGE_NT_SIGNATURE)

                    printf("非PE格式文件!\n");

            }

        }

    }

    return lpMemory;

}



//32位PE文件

VOID printReloc(PBYTE lpvResult)

{

    PIMAGE_DOS_HEADER pImageDOSHeader = (PIMAGE_DOS_HEADER)lpvResult;

#ifdef WIN64

    PIMAGE_NT_HEADERS64 psImageNTHeader = (PIMAGE_NT_HEADERS64)(lpvResult + pImageDOSHeader->e_lfanew);

#else

    PIMAGE_NT_HEADERS32 psImageNTHeader = (PIMAGE_NT_HEADERS32)(lpvResult + pImageDOSHeader->e_lfanew);

#endif

    //重定位表RVA

    DWORD RelocRVA = psImageNTHeader->OptionalHeader.DataDirectory[5].VirtualAddress;

    DWORD dwTemp = 0;

    //获取重定位表FOA地址

    PIMAGE_BASE_RELOCATION pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)RvaToFoa((PIMAGE_NT_HEADERS)psImageNTHeader, RelocRVA);

    dwTemp = (DWORD)pImageDOSHeader + (DWORD)pImageBaseRelocation;



    for(DWORD i = 0; (DWORD*)(((PIMAGE_BASE_RELOCATION)dwTemp)->VirtualAddress ) != 0; i++)

    {

        printf("virtual address : 0x%08x\n", ((PIMAGE_BASE_RELOCATION)dwTemp)->VirtualAddress);

        printf("size of block   : 0x%08x\n", ((PIMAGE_BASE_RELOCATION)dwTemp)->SizeOfBlock);

        for (DWORD j = 0; j < ((PIMAGE_BASE_RELOCATION)dwTemp)->SizeOfBlock - 8; j += 2)

        {

            printf("%4x\t", *(WORD*)(dwTemp + 8 + j));

        }

        dwTemp += ((PIMAGE_BASE_RELOCATION)dwTemp)->SizeOfBlock;

        printf("\n");

    }

}



//RVA转FOA

DWORD RvaToFoa(PIMAGE_NT_HEADERS ntHeaders, DWORD rva) {

    //ntHeaders+4+sizeof(IMAGE_FILE_HEADER)+FileHeader.SizeOfOptionalHeader(32或64位PE)

    PIMAGE_SECTION_HEADER sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);

    WORD numberOfSections = ntHeaders->FileHeader.NumberOfSections;



    for (WORD i = 0; i < numberOfSections; i++) {

        DWORD sectionStartRva = sectionHeader->VirtualAddress;

        DWORD sectionEndRva = sectionStartRva + sectionHeader->SizeOfRawData;



        if (rva >= sectionStartRva && rva < sectionEndRva) {

            DWORD foa = sectionHeader->PointerToRawData + (rva –

sectionStartRva);

            return foa;

        }

        sectionHeader++;

    }

    return 0;  // RVA not found

}

图6-3 打印notepad64.exe重定位表

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2212560.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

衡石分析平台系统-分析人员手册

应用创建​ 用户可以通过多种方式创建应用&#xff0c;不同场景下应用创建方法不同。 新建空白应用​ 新建空白应用是新建一个空的应用&#xff0c;应用中没有数据集和仪表盘。 点击应用创作页面右上方的新建应用&#xff0c;新建空白的分析应用和查询应用。 新建的空白应用…

记录一下,android studio 登录不上github的问题

android studio 2023.3.1.18 版本的编译器&#xff0c;出现问题&#xff0c;之前连接过的项目可以正常提交和拉取到github。 但是新建立的项目无法上传到github&#xff0c;提示错误cannot load information for github.com/:request response;access to this site&#xff0c;…

log4j2实际项目中使用

一 添加依赖 <!--移除spring-boot中默认的logback日志组件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.spring…

实验9 结构体

1、商品信息处理 【问题描述】 设计结构体&#xff0c;用于存储商品的信息&#xff0c;包含商品编号、商品名称、商品价格以及商品折扣信息。 设计函数input&#xff0c;实现商品数据的输入。 设计函数display&#xff0c;实现商品信息的输出。 在主函数main中定义keyboar…

国外解压视频素材哪里找?五个海外解压视频素材网站推荐

国外解压视频素材哪里找&#xff1f;五个海外解压视频素材网站推荐 如果你正在寻找国外的解压视频素材&#xff0c;那么今天这篇文章一定能帮助你。无论是修牛蹄、洗地毯&#xff0c;还是切肥皂、玩解压游戏等&#xff0c;下面分享的几个网站都是你找到高质量海外解压视频素材…

信息抽取数据集处理——RAMS

引言 RAMS数据集&#xff08;RAMS&#xff1a;Richly Annotated Multilingual Schema-guided Event Structure&#xff09;由约翰斯霍普金斯大学于2020年发布&#xff0c;是一个以新闻为基础的事件抽取数据集。它标注了9,124个事件&#xff0c;涵盖了139种不同的事件类型和65种…

celery 项目中mysql 数据库连接数耗尽事故记录

python 项目中使用 celery 中导致mysql数据库连接耗尽记录【mysql数据库连接池使用错误】 结论&#xff1a;由于使用 celery 进行项目的多任务管理&#xff0c;在worker任务定义的过程中&#xff0c;使用了 dbutils 中的 PooledDB 连接池进行 mysql数据库连接&#xff0c; 因此…

IO密集型任务及Vertx框架入门

注意&#xff1a; 本文内容于 2024-10-02 02:25:47 创建&#xff0c;可能不会在此平台上进行更新。如果您希望查看最新版本或更多相关内容&#xff0c;请访问原文地址&#xff1a;IO密集型任务及Vertx框架入门。感谢您的关注与支持&#xff01; 一、背景 1.1 铺垫知识 涉及到…

C++入门基础知识112—【关于C++嵌套 switch 语句】

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C嵌套 switch 语句的相关内容&#xff…

C++20中头文件numbers的使用

<numbers>是C20中新增加的头文件&#xff0c;提供一组常量用于表示数学中的某些特殊值&#xff0c;此头文件是numeric库的一部分。包括&#xff1a; 1. 圆周率π:std::numbers::pi、std::numbers::pi_v<T> 2. 圆周率π的倒数&#xff1a;numbers::inv_pi、std::num…

灵当CRM data/pdf.php 任意文件读取漏洞复现

0x01 产品简介 灵当CRM是一款专为中小企业打造的智能客户关系管理工具,由上海灵当信息科技有限公司开发并运营。广泛应用于金融、教育、医疗、IT服务、房地产等多个行业领域,帮助企业实现客户个性化管理需求,提升企业竞争力。无论是新客户开拓、老客户维护,还是销售过程管…

软件开发----SQL基础每日刷题(转载于牛客)

1. 查询语句select stuff(lo ina,3, 1, ve ch)结果为&#xff1f; A love B love china C china love D china 正确答案&#xff1a;B 解析&#xff1a; STUFF(原字符, 开始位置, 删除长度, 插入字符) 从指定的起点处开始删除指定长…

六tomcat

​​​​​​ Java Web环境搭建 1. 初识Tomcat Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试JSP 程序的首选。Tomcat 是 Apache 服务器…

redis集成到spring boot中使用

&#xff08;一&#xff09;添加依赖 redis服务器在官网中公开了自己使用的协议--RESP&#xff0c;所以我们可以使用这个协议来访问redis服务器&#xff0c;但是如果我们要自己实现库&#xff0c;那肯定是非常麻烦的&#xff0c;所以我们可以使用网上的库&#xff0c;我们直接调…

读数据工程之道:设计和构建健壮的数据系统08主要架构概念

1. 域和服务 1.1. 域是你正在为其构建的现实世界主题区域 1.2. 服务是一组功能&#xff0c;其目标是完成一项任务 1.3. 一个域可以包含多个服务 1.4. 确定领域中应包含的内容 1.4.1. 确定领域应该包含什么以及要包括哪些服务时&#xff0c;最好的建议是简单地去与用户和利益…

SQLAlchemy入门:详细介绍SQLAlchemy的安装、配置及基本使用方法

SQLAlchemy是一个流行的Python SQL工具包和对象关系映射&#xff08;ORM&#xff09;框架&#xff0c;它为开发人员提供了一种高效、灵活的方式来与数据库进行交互。本文将详细介绍SQLAlchemy的安装、配置及基本使用方法&#xff0c;并通过代码示例和案例分析&#xff0c;帮助新…

C++ | Leetcode C++题解之第478题在圆内随机生成点

题目&#xff1a; 题解&#xff1a; class Solution { private:mt19937 gen{random_device{}()};uniform_real_distribution<double> dis;double xc, yc, r;public:Solution(double radius, double x_center, double y_center): dis(0, 1), xc(x_center), yc(y_center),…

Web前端高级工程师培训:异步处理专题

异步处理专题 课前准备 工具 编辑器 VSCode浏览器 Chorme 前置知识 ES6基础语法 课堂主题 同步及异步概念方块运动的实现promise的用法then的返还值Async 函数 和 await 课堂目标 理解并学会使用promise使用方式以及async 、await的使用 同步异步概念 js是单线程 单线程…

动态规划-多状态问题——LCR.090.打家劫舍

1.题目解析 题目来源&#xff1a;LCR.090.打家劫舍——力扣 测试用例 2.算法原理 1.状态表示 每一个房子都有两个状态&#xff1a;被偷与不被偷&#xff0c;因此需要两个dp表f/g来表示被偷与不被偷&#xff0c;其中f[i]/g[i]表示小偷走到第i个位置的最大偷钱数 2.状态转移方程…

【开源物联网平台】Fastbee系统稳定性和压测报告

目录 一、机器准备 二、压测步骤 2.1 去除认证&#xff0c;修改clientid识别问题 2.2 添加重发布脚本 三、压测结果 四、压测工具使用 一、机器准备 准备两台服务器&#xff0c;一台为部署fastbee服务端应用&#xff0c;另一台为客户端压力机。其中&#xff1a; fastbee…