2.11 PE结构:添加新的节区

在可执行PE文件中,节(section)是文件的组成部分之一,用于存储特定类型的数据。每个节都具有特定的作用和属性,通常来说一个正常的程序在被编译器创建后会生成一些固定的节,通过将数据组织在不同的节中,可执行文件可以更好地管理和区分不同类型的数据,并为运行时提供必要的信息和功能。节的作用是对可执行文件进行有效的分段和管理,以便操作系统和加载器可以正确加载和执行程序。

可执行文件常用的节包括了:

节名作用功能说明权限
.text代码节包含可执行代码,例如程序的指令和函数体执行和读取
.data数据节包含程序的全局和静态变量的初始化数据。读取和写入
.rdata只读数据节包含只读的静态数据,如常量字符串和只读的全局变量。只读
.idata导入表节包含程序所依赖的外部函数和符号的引用信息,用于动态链接。读取和写入
.edata导出表节包含程序导出的函数和符号的信息,用于供其他程序或模块使用。读取
.rsrc资源节包含程序所使用的资源数据,如图标、位图、字符串等。读取
.reloc重定位节包含程序的重定位信息,用于在加载时修正代码和数据的内存地址。读取和写入

当然了并不是每一个标准的PE文件都具备这些节,某些程序可能会使用特殊的PE编辑工具新增一些特殊的节,或者当程序被加密压缩后该程序的节区也会发生不同的变化,对于新增节来说需要具备如下几个关键步骤:

  • 计算新节的偏移量和大小:确定要添加的新节的偏移量和大小。偏移量是新节在文件中的位置,大小是新节的长度。
  • 更新PE文件头:修改PE文件头中的相关字段,更新文件头中的NumberOfSections字段和SizeOfImage字段。
  • 创建新节:在PE文件末尾添加新的节表项,并填充新节的各个字段,例如名称、虚拟大小、文件大小、内存对齐等。

对于操作PE文件来说,在头文件中需要引入ImageHlp.h并且包含#pragma comment(lib,"Imagehlp.lib")库,该库提供了用于处理PE文件的函数和结构体,是Image Help Library库的一部分,读者可自行在项目内引入这个库。

当引入后我们来实现第一个功能,为可执行文件分配空间,如下AllocateSpace函数,该函数通过使用CreateFileA打开一个文件,并调用SetFilePointer将文件指针移动到FILE_END文件末尾处,接着通过循环的方式WriteFile填充开辟空间。

// 计算取整
DWORD AlignSize(int nSecSize, DWORD Alignment)
{int nSize = nSecSize;if (nSize %Alignment != 0){nSecSize = (nSize / Alignment + 1) * Alignment;}return nSecSize;
}// 为可执行文件分配空间
DWORD AllocateSpace(char *FileName, int FileSize)
{HANDLE hFile = CreateFileA(FileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE |FILE_SHARE_READ, NULL, OPEN_ALWAYS, NULL, NULL);DWORD ret = SetFilePointer(hFile, 0, 0, FILE_END);if (ret != NULL){for (int x = 0; x < FileSize; x++){WriteFile(hFile, "", 1, 0, 0);}CloseHandle(hFile);}return ret;
}

上述程序的使用方法很简单,通过AllocateSpace("d://lyshark.exe",4096)传入两个参数,分别是需要开辟空间的进程,以及开辟空间的长度,该长度可以与节区内的大小保持一致,当程序执行后则返回开辟位置,读者可使用WinHex工具跳转到程序末尾自行查看,如下图所示;

接着我们来实现添加节区功能,如下代码ImplantSection则可实现增加新节功能,该函数传入三个参数,分别是可执行文件地址,节区名称,以及节区长度,程序中通过映射方式打开文件,分别寻找到当前节表首地址,以及节的数量,通过复制一个节,并对该节内存参数进行更新(节内存大小,节文件大小,节内存属性)等,当这些数据被更正后,则加下来就是保存文件,并返回pTmpSec->PointerToRawData节所在文件地址。

// 计算取整
DWORD AlignSize(int nSecSize, DWORD Alignment)
{int nSize = nSecSize;if (nSize %Alignment != 0){nSecSize = (nSize / Alignment + 1) * Alignment;}return nSecSize;
}// 添加新的节区 szFileName = 打开exe文件 szSecName = 节名称 nSecSize = 节大小
DWORD ImplantSection(LPSTR szFileName, char szSecName[8], int nSecSize)
{HANDLE m_hFile = CreateFileA(szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);HANDLE m_hMap = CreateFileMapping(m_hFile, NULL, PAGE_READWRITE, 0, 0, 0);HANDLE m_lpBase = MapViewOfFile(m_hMap, FILE_MAP_READ | FILE_SHARE_WRITE, 0, 0, 0);// ------------------------------------------------------------------------// 定位到DOS/NT头部// ------------------------------------------------------------------------// 定位DOS头PIMAGE_DOS_HEADER m_pDosHdr = (PIMAGE_DOS_HEADER)m_lpBase;printf("[-] 当前DOS头: 0x%08X \n", m_pDosHdr);// 定位NT头PIMAGE_NT_HEADERS m_pNtHdr = (PIMAGE_NT_HEADERS)((DWORD)m_lpBase + m_pDosHdr->e_lfanew);printf("[-] 当前NT头: 0x%08X \n", m_pNtHdr);// 定位节表首地址PIMAGE_SECTION_HEADER m_pSecHdr = (PIMAGE_SECTION_HEADER)((DWORD)&(m_pNtHdr->OptionalHeader) +m_pNtHdr->FileHeader.SizeOfOptionalHeader);printf("[-] 定位当前节表首地址: 0x%08X \n", m_pSecHdr);// 定位节区数量int nSecNum = m_pNtHdr->FileHeader.NumberOfSections;DWORD dwFileAlignment = m_pNtHdr->OptionalHeader.FileAlignment;DWORD dwSecAlignment = m_pNtHdr->OptionalHeader.SectionAlignment;PIMAGE_SECTION_HEADER pTmpSec = m_pSecHdr + nSecNum;// 复制节名strncpy((char *)pTmpSec->Name, szSecName, 7);printf("[+] 拷贝节名称: %s \n", szSecName);// ------------------------------------------------------------------------// 节的内存大小// ------------------------------------------------------------------------pTmpSec->Misc.VirtualSize = AlignSize(nSecSize, dwSecAlignment);printf("[+] 节表内存大小: %d \n", nSecSize);// 节的内存起始位置pTmpSec->VirtualAddress = m_pSecHdr[nSecNum - 1].VirtualAddress +AlignSize(m_pSecHdr[nSecNum - 1].Misc.VirtualSize, dwSecAlignment);printf("[+] 节内存起始位置: 0x%08X \n", pTmpSec->VirtualAddress);// ------------------------------------------------------------------------// 节的文件大小// ------------------------------------------------------------------------pTmpSec->SizeOfRawData = AlignSize(nSecSize, dwFileAlignment);printf("[-] 节的文件大小: %d \n", pTmpSec->SizeOfRawData);// 节的文件起始位置,这里直接在文件末尾分配空间pTmpSec->PointerToRawData = SetFilePointer(m_hFile, 0, 0, FILE_END);printf("[-] 节的文件起始位置: 0x%08X \n", pTmpSec->PointerToRawData);// 这里开始循环在文件末尾分配nSecSize存储空间for (int x = 0; x < nSecSize; x++)WriteFile(m_hFile, "", 1, 0, 0);// ------------------------------------------------------------------------// 节访问属性,设置内存属性为可读可执行代码段// ------------------------------------------------------------------------pTmpSec->Characteristics = 0xE0000020;// 修正节区数量m_pNtHdr->FileHeader.NumberOfSections++;// 修正映像大小m_pNtHdr->OptionalHeader.SizeOfImage += pTmpSec->Misc.VirtualSize;FlushViewOfFile(m_lpBase, 0);return pTmpSec->PointerToRawData;
}

读者可自行调用上述函数,通过ImplantSection("d://Win32Project.exe", ".hack", 4096)传值,此时分别传入参数为需要修改的文件名,需要增加的节名称,以及创建节长度,在运行后读者可自行观察是否创建成功,如下图所示;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/19540578.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

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

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

相关文章

数学建模B多波束测线问题B

数学建模多波束测线问题 1.问题重述&#xff1a; 单波束测深是一种利用声波在水中传播的技术来测量水深的方法。它通过测量从船上发送声波到声波返回所用的时间来计算水深。然而&#xff0c;由于它是在单一点上连续测量的&#xff0c;因此数据在航迹上非常密集&#xff0c;但…

多通道振弦数据记录仪应用桥梁安全监测的关键要点

多通道振弦数据记录仪应用桥梁安全监测的关键要点 随着近年来桥梁建设和维护的不断推进&#xff0c;桥梁安全监测越来越成为公共关注的焦点。多通道振弦数据记录仪因其高效、准确的数据采集和处理能力&#xff0c;已经成为桥梁安全监测中不可或缺的设备。本文将从以下几个方面…

zabbix企业微信告警

目前&#xff0c;企业微信使用要设置可信域名 华为云搜索云函数 创建函数 选择http函数&#xff0c;随便输入函数名字 回到函数列表&#xff0c;选择刚创建的函数&#xff0c;创建触发器&#xff0c;安全模式选择none 点击右上角管理 选刚创建的api&#xff0c;右边操作点…

07-ThreadLocal有哪些使用场景?【Java面试题总结】

ThreadLocal有哪些使用场景&#xff1f; 7.1 多线程场景下共享变量问题 ThreadLocal是线程本地变量&#xff0c;可以存储共享变量副本&#xff0c;每一个独立线程都有与共享变量一模一样的副本。ThreadLocal在当前线程下共享变量是全局共享的&#xff0c;各个线程之间是相互独…

基于Dubbo实现服务的远程调用

目录 前言 RPC思想 为什么使用Dubbo Dubbo技术框架 ​编辑 调用关系流程 基础实现 A.提供统一业务Api B.编辑服务提供者Product B.a 添加依赖 B.b 添加Dubbo 配置(基于yaml配置文件) B.c 编写并暴露服务 C.编辑服务消费者 C.a 添加依赖 C.b 添加Dubbo配置 C.c 引用…

【Redis】3、Redis主从复制、哨兵、集群

Redis主从复制 主从复制&#xff0c;是指将一台Redis服务器的数据&#xff0c;复制到其他的Redis服务器。前者称为主节点(Master)&#xff0c;后者称为从节点(Slave)&#xff1b;数据的复制是单向的&#xff0c;只能由主节点到从节点。 默认情况下&#xff0c;每台Redis服务器…

PostgreSQL安装异常,服务无法启动导致创建服务器超时

win上安装pg后无法创建服务器&#xff0c;提示创建超时&#xff0c;发现服务列表里面pg15服务 并没有启动&#xff0c;启动服务器发现服务不了&#xff0c;截图忘记截了&#xff0c;复现不了&#xff0c;解决方法是 换个身份&#xff0c;然后继续启动&#xff0c;然后就可以在…

如何使用Docker部署Nacos服务?Nacos Docker 快速部署指南: 一站式部署与配置教程

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

说说 TCP的粘包、拆包

分析&回答 拆包和粘包是在socket编程中经常出现的情况&#xff0c; 在socket通讯过程中&#xff0c;如果通讯的一端一次性连续发送多条数据包&#xff0c;tcp协议会将多个数据包打包成一个tcp报文发送出去&#xff0c;这就是所谓的粘包。如果通讯的一端发送的数据包超过一…

【C++漂流记】一文搞懂类与对象的封装

本篇文章主要说明了类与对象中封装的有关知识&#xff0c;包括属性和行为作为整体、访问权限、class与struct的区别、成员属性的私有化&#xff0c;希望这篇文章可以帮助你更好的了解类与对象这方面的知识。 文章目录 一、属性和行为作为整体二、访问权限三、class与struct的区…

某米ax3000路由器组网解析

我们使用某米k60手机与某米ax3000 wifi6路由器组网&#xff0c;来分析和学习网络速率与瓶颈限制。 某米 AX3000 路由器简介 某米 AX3000 路由器是一款支持 WiFi 6 的双频路由器&#xff0c;它的 MIMO 是 22&#xff0c;也就是两根天线。MIMO 是 Multiple Input Multiple Outpu…

复制tr的一行数据或者复制数据使用,使用jq和php

效果图&#xff1a; 2.Html <!--复制的tr数据&#xff0c;s----------------------------------------------------------------------------------------------->{foreach from$arrs keykk itemvv} <tr><td style"text-align:center;" >1</t…

CH341 USB总线转接芯片

产品概述&#xff1a; CH341是一个USB总线的转接芯片&#xff0c;通过USB总线提供异步串口、打印口、并口以及常用的2线和4线等同步串行接口。 在异步串口方式下&#xff0c;CH341提供串口发送使能、串口接收就绪等交互式的速率控制信号以及常用的MODEM联络信号&#xff0c;用于…

日期--data与String的相互转换

首先我们要明确 yyyy-MM-dd HH:mm:ss 其中y:年份 MM:月份 dd:天 HH:小时 mm&#xff1a;分 ss&#xff1a;秒 date转String // 获取当前时间LocalDateTime dateLocalDateTime.now(); // 设置日期格式DateTimeFormatter formatterDateTimeFormatter.ofPattern("yyyy-MM-dd…

PostGreSQL:时间戳时区问题

时间|日期类型 PostGreSQL数据库内置的时间类型如下&#xff0c;注意到&#xff1a;内置的时间类型被分为了with time zone-带时区、without time zone-不带时区两种类型&#xff0c; time、timestamp和interval都可以接受一个可选的精度值 p&#xff08;取值&#xff1a;0-6&a…

JMeter 4.0 如何获取cookie

文章目录 前言JMeter 4.0 如何获取cookie1. 修改jmeter.properties 文件2. 添加HTTP Cookie 管理器3. 获取cookie信息 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天…

如何为虚拟机添加磁盘,扩充原有分区的磁盘空间

如何为虚拟机添加磁盘&#xff0c;扩充原有分区的磁盘空间 关机新增磁盘 虚拟机关机的状态下&#xff0c;在 VMware 当中新增一块磁盘&#xff0c;选中左边要添加磁盘的虚拟机镜像&#xff0c;然后鼠标右键点击设置。 选中磁盘点击添加 点击下一步&#xff0c;悬着SCSI这个…

慕尼黑主题活动!亚马逊云科技生成式AI全新解决方案,引领未来移动出行领域

IAA作为世界五大车展之一&#xff0c;一直对全球汽车产业的发展起着关键作用&#xff01;2023年9月5日在慕尼黑开幕的IAA MOBILITY 2023以“体验联动智慧出行”为主题&#xff0c;紧跟移动出行领域的前沿变化&#xff0c;将汇集整车企业、开发者、供应商、科技公司、服务提供商…

基于深度学习网络的火灾检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ................................................................................ load F…

vue: 使用下拉树组件@riophae/vue-treeselect

前言: 在vue中, 因为element-ui 2.X是没有tree-select组件的&#xff0c;到了element-plus就有了 riophae/vue-treeselect是一个基于 Vue.js 的树形选择器组件&#xff0c;可以用于选择树形结构的数据。它支持多选、搜索、异步加载等功能&#xff0c;可以自定义选项的样式和模…