PE 新增节

新增节后,需要修改以下信息

1、添加一个新节,可以复制一份,最好是拥有可执行属性的节,如.text

2、在节表区,新增节的后面,填充一个节,用零填充

3、修改标准PE头中NumberOfSections中节的数量,我这里原来5个,现在6个了

4、修改SizeOfImage的大小,这里自己新增了0x1000,原本是27000,现在改为28000

5、在原有数据的后面,新增一个节的数据(大小为内存对齐的整倍数)

6、修正新增节表的属性,比如.text段的一般都为可执行属性,0x60000020

拓展知识:

1、正常来说上面的操作都可以实现新增节,但是大家有没有考虑过,如果节表那部分不足以能够添加一个节表的大小呢?比如如下notepad.exe,可以发现节表下的直接存在数据的,那么我们也不能确定这些数据如果删除是否会影响该程序的正常运行

所以我们就需要考虑其他的方法,那么就是移动NT头,移动的原因就是dos sub这部分是垃圾数据可以将其删除,然后整个前置移动,最终的效果如下

这时候再去新增节,就会发现不但可以新增节,并且程序还可以正常运行,否则该程序是无法运行的!


Name:名字随便修改,不能超过八个字节。

VirtualSize:申请的新节空间大小,比如1000

VirtualAddress:等于上一个节的VirtualAddress + SizeOfRawData,VirtualAddress为在内存中的起始地址

SizeOfRawData:当前节在文件中对齐后的大小,这里设置为0x1000

这里SizeOfRawData和VirtualSize一样大小的原因是当前PE程序的内存对齐大小和文件对齐大小是相同的!

PointerToRawData:等于上一个节的PointerToRawData + SizeOfRawData,当前节 数据在文件中的起始地址就是 上个节 在文件中对齐后的大小SizeOfRawData 加上 上个节 数据在文件中的起始地址PointerToRawData

PointerToRelocation:设置成零

PointerToLineNumbers:设置成零

NumberOfLineRelocations:设置成零

NumberOfLineNumbers:设置成零

Characteristics:块属性0x20000060为可执行

实现的代码:

void AddNewSection(PVOID pFileBuffer,PDWORD OldBufferSize,PVOID* pNewBuffer){
PIMAGE_DOS_HEADER pImageDosHeader = NULL;
PIMAGE_FILE_HEADER pImageFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pImageOptionalHeader = NULL;
PIMAGE_SECTION_HEADER pImageSectionHeaderGroup = NULL;
PIMAGE_SECTION_HEADER NewSec = NULL;
DWORD isOk;
DWORD NewLength=0;
PVOID LastSection = NULL;
PVOID CodeSection = NULL;
pImageDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageDosHeader + pImageDosHeader->e_lfanew + 4);
pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pImageFileHeader + sizeof(IMAGE_FILE_HEADER));
pImageSectionHeaderGroup = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader + pImageFileHeader->SizeOfOptionalHeader);
//判断是否可以容纳相应的节表
isOk = (DWORD)pImageOptionalHeader->SizeOfHeaders - ((DWORD)pImageDosHeader->e_lfanew + IMAGE_SIZEOF_FILE_HEADER + pImageFileHeader->SizeOfOptionalHeader + 40*pImageFileHeader->NumberOfSections);
if(isOk < 80){
printf("空间太小 无法进行添加!");
return;
}
//生成对应的内存大小的空间
NewLength += *OldBufferSize + 0x1000;
*pNewBuffer = (PVOID)malloc(NewLength);
ZeroMemory(*pNewBuffer,NewLength);
//拷贝之前内存空间 到 当前新生成的内存空间
memcpy(*pNewBuffer,pFileBuffer,*OldBufferSize);
//获取新的结构体
pImageDosHeader = (PIMAGE_DOS_HEADER)(*pNewBuffer);
pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageDosHeader + pImageDosHeader->e_lfanew + 4);
pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pImageFileHeader + sizeof(IMAGE_FILE_HEADER));
pImageSectionHeaderGroup = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader + pImageFileHeader->SizeOfOptionalHeader);
// pImageFileHeader->NumberOfSections修改
pImageFileHeader->NumberOfSections = pImageFileHeader->NumberOfSections + 1;
// pImageOptionalHeader->SizeOfImage修改
pImageOptionalHeader->SizeOfImage = (DWORD)pImageOptionalHeader->SizeOfImage + 0x1000;
// 复制代码段的节数据到 当前最后一个节数据后面
CodeSection = (PVOID)(&pImageSectionHeaderGroup[0]);
LastSection = (PVOID)(DWORD)(&pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-1]);
memcpy(LastSection,CodeSection,40);
//修正相关属性
NewSec = (PIMAGE_SECTION_HEADER)LastSection;
strcpy(NewSec,".NewSec");
NewSec->Misc.VirtualSize = 0x1000;
NewSec->SizeOfRawData = 0x1000;
NewSec->VirtualAddress = pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].VirtualAddress + pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].SizeOfRawData;
NewSec->PointerToRawData = pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].PointerToRawData + pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-2].SizeOfRawData;
*OldBufferSize = NewLength;
}

参考文章:https://www.cnblogs.com/iBinary/p/9735276.html

posted @   zpchcbd  阅读(533)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示