首页 > 其他分享 >2.11 PE结构:添加新的节区

2.11 PE结构:添加新的节区

时间:2023-09-09 14:12:12浏览次数:37  
标签:文件 FILE pTmpSec nSecSize PE DWORD 节区 2.11

在可执行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 许可协议。转载请注明出处!

标签:文件,FILE,pTmpSec,nSecSize,PE,DWORD,节区,2.11
From: https://www.cnblogs.com/LyShark/p/17689408.html

相关文章

  • C#结合OpenCVSharp4使用直方图算法比较图片相似度
    C#结合OpenCVSharp4使用直方图算法比较图片相似度直方图有灰度直方图、颜色直方图,如果是灰度图像,那么就用灰度直方图,这里使用颜色直方图来计算两个图片的相似度。这里只记录如何使用,至于算法原理,问就是不会。直方图算法效率高,但精度不够,适合快速比较,例如以图搜图1.下载O......
  • Zookeeper搭建
    1.ZookeeperZookeeper是ApacheHadoop项目下的一个子项目,是一个树形目录服务。Zookeeper是一个分布式的、开源的分布式应用程序的协调服务。 2.zookeeper搭建学习教程:04、ZooKeeper--集群搭建下--配置文件修改&启动_哔哩哔哩_bilibili前提:JDK已经安装好了输入java-version......
  • KdMapper扩展实现之CrystalMark(winring0x64.sys)
    1.背景  KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。 2.驱动信息 驱动名称winring0x64.sys 时间戳47......
  • PeaZip 9.4 发布
    导读PeaZip是一个适用于Windows和 Linux 的免费文件存档工具和rar提取器,可处理200多种存档类型(7z,ace,arc,bz2,cab,gz,iso,paq,pea,rar,tar,wim,zip,zipx...),处理跨区存档(001,r01,z01...)并支持多种存档加密标准。该项目旨在为多种开源技术(7-Zip、......
  • Why Software Developers Are Silent in Meetings
    TheyShouldn’tBeEversatinaSprintRetrowhereyourScrumMasterdidn’tarrivefortenminutes?Ijustdid.Wesatinsilence.EverbeeninaSprintRetrowherealmostnobodyparticipates?AreyouthinkingIjustdid?You’reagreatblogreaderifyo......
  • IT知识百科:什么是802.11ac(WiFi 5)?
    802.11ac,也被称为WiFi5,是无线局域网(WLAN)的一种标准,旨在提供更快的数据传输速度和更好的性能。该标准于2013年发布,逐渐取代了802.11n标准。本文将探讨802.11ac的背景、特点、应用和未来展望。一、802.11ac的背景随着移动设备和智能家居的普及,人们对于无线网络的需求也不断增长。......
  • 安装tomcat及supervisor管理tomcat
    安装tomcat及配置tomcat虚拟主机准备在部署Tomcat之前必须安装好jdk,应为jdk是tomcat运行的必要环境。1.关闭防火墙,将安装Tomcat所需软件包传到/opt目录下这里我用的安装包是jdk-8u201-linux-x64.rpmapache-tomcat-9.0.16.tar.gzsystemctldisable--nowfirewalld//关......
  • ffmpeg新旧函数对比
    从FFmpeg3.0开始,使用了很多新接口,对不如下:1.avcodec_decode_video2()原本的解码函数被拆解为两个函数avcodec_send_packet()和avcodec_receive_frame()具体用法如下:old:avcodec_decode_video2(pCodecCtx,pFrame,&got_picture,pPacket);new:avcodec_send_packet(pCo......
  • Proj CDeepFuzz Paper Reading: Metamorphic Testing of Deep Learning Compilers
    Abstract背景:CompilingDNNmodelsintohigh-efficiencyexecutablesisnoteasy:thecompilationprocedureofteninvolvesconvertinghigh-levelmodelspecificationsintoseveraldifferentintermediaterepresentations(IR),e.g.,graphIRandoperatorIR,an......
  • MyBatisCodeHelperPro支持动态解析sql
    通过setting找到插件搜索MyBatisCodeHelperPro点击【Install】进行安装github:https://github.com/gejun123456/MyBatisCodeHelper-Prohttps://brucege.com/doc/#/......