PE 扩大节
适用条件:有的时候空白区不够需要进行扩大节
以对最后一个节扩大0x1000为例子:
为什么要扩大最后一个节呢?如果扩大最后的一个节之前的话,那么相对于当前扩大的节后面也会相应的变化,节表中每个节数据的信息都要相对应的纠正,相对比较繁琐!
typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //8个字节名字.自己可以起.编译器也可以给定.不重要. union { DWORD PhysicalAddress; DWORD VirtualSize; //节数据没有对齐后的大小.也就是没有对齐.节数据有多大. } Misc; DWORD VirtualAddress; //加载到内存中的第一个字节的地址.也就是虚拟地址.节在内存中哪里开始.内存中的VA + ImageBase 才是真正的节开始位置 DWORD SizeOfRawData; //修改这个属性的值,即可扩大节.并且在PE文件中添加相应的0数据进行填充. DWORD PointerToRawData; //在文件中的偏移.是文件对齐成员倍数. DWORD PointerToRelocations; //一下都是调试相关. DWORD PointerToLinenumbers; // WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; //节的属性 } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
扩大节其实很简单,修改节数据对齐后的大小就可以了,并且在PE文件中添加任意数据进行填充
步骤如下:
1、分配一块新的空间,大小为S
2、将最后一个节的SizeOfRawData和VirtualSize都改成N
N = (SizeOfRawData 或者 VirtualSize内存对齐后的值) + S
3、最后修改PE扩展头中的SizeofImage(内存PE镜像大小)
实现过程:
1、最后面插入0x1000字节大小,数据用0来填充
2、先观察是否文件对齐和内存对齐相同,如下图发现是不同的
2、那么继续,来到最后个节的节表部分,在该节中的virtualSize(内存中当前节没有对齐的实际大小)和 SizeOfRawData(文件中当前节对齐的大小)二者中选最大的值,然后再最大的值上添加0x1000
,然后把两个都改为最大的值
3、最后来到PE扩展头中的SizeofImage(内存PE镜像大小)成员进行修改,先按照内存对齐进行存放 然后再加上0x1000大小
实现逻辑:
逻辑顺序: 1、拉伸到内存 2、分配一块新的空间:SizeOfImage + Ex 3、将最后一个节的SizeOfRawData和VirtualSize改成N SizeOfRawData = VirtualSize = N N = (SizeOfRawData或者VirtualSize 内存对齐后的值) + Ex 4、修改SizeOfImage大小 SizeOfImage = SizeOfImage + Ex
实现代码:
void ExpandSection(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 TheBiggerOfSizeOfRawDataOrVirtualSize = 0; DWORD NewLength=0; 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); //生成对应的内存大小的空间 NewLength += *OldBufferSize + 0x1000; *pNewBuffer = (PVOID)malloc(NewLength); ZeroMemory(*pNewBuffer,NewLength); //拷贝之前内存空间 到 当前新生成的内存空间 memcpy(*pNewBuffer,pFileBuffer,*OldBufferSize); //修改节数据的偏移 if(pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-1].Misc.VirtualSize > pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-1].SizeOfRawData){ TheBiggerOfSizeOfRawDataOrVirtualSize = pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-1].Misc.VirtualSize; }else{ TheBiggerOfSizeOfRawDataOrVirtualSize = pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-1].SizeOfRawData; } pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-1].Misc.VirtualSize = TheBiggerOfSizeOfRawDataOrVirtualSize; pImageSectionHeaderGroup[pImageFileHeader->NumberOfSections-1].SizeOfRawData = TheBiggerOfSizeOfRawDataOrVirtualSize; // pImageOptionalHeader->SizeOfImage修改 pImageOptionalHeader->SizeOfImage = (DWORD)pImageOptionalHeader->SizeOfImage + 0x1000; *OldBufferSize = NewLength; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步