上文提到过PE文件新增节的技术,但是,新增节油一个前提条件,那就是SizeOfHeaders的区域,本来就有剩余空间可以新增节表,或者没有抬高PE头,假如这两个条件都不满足的情况下,我们就需要使用到合并节或者扩大节的技术。
所谓合并节,就是将原本文件中所有的节,变成一个节,该操作要在拉伸状态下,修改节表数量,以及第一个节表头里面的VirtualSize、SizeOfRawData,这两个属性的大小将是所有节在内拉伸状态下的大小,然后将拉伸状态下的数据直接保存成文件,该操作的好处是会多出很多空间来让我们执行操作,坏处是文件可能会变得很大!本文中不多介绍。
所谓扩大节,就是将节可使用的内存区域扩大,来达到能容纳我们所注入功能的目的,该操作有一个限制,那就是改最后一个节表的大小最方便省事,否则改在中间位置,要考虑一系列的偏移问题,因此本文只修改最后一个节,步骤如下。
1.修改SizeOfImage+要扩充的大小(扩充大小是0x1000的整数倍,拉伸默认是这个值,如果有改动则看内部属性)
2.获取最后一个节表,VirtualSize、SizeOfRawData,取二者间较大值+要扩充的大小(0x200的整数倍,磁盘状态下默认是这个值,如果有改动则看内部属性),并赋值给VirtualSize、SizeOfRawData
3.申请一个新的内存空间,该内存空间的大小,是原文件的在磁盘状态下的大小+要扩充的大小(0x200的整数倍)
核心代码:
/*
* 扩大节
*
* 步骤:
* 1.修改SizeOfImage,加0x1000的整数倍
* 2.修改最后一个节的VirutalSize、SizeOfRawData,取大的那个值,加上我们要加的大小
* 3.物理文件状态下加0x200个字节,随便加点数据
*
* 参数&返回值:
* buff 磁盘文件读取到内存的数据
* buffSize 磁盘文件读取到内存的数据大小
* return 扩大节后的文件数据
*/
char* ExpandSection(char* buff, DWORD buffSize)
{
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)buff;
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)(buff + dosHeader->e_lfanew);
// 修改SizeOfImage
ntHeader->OptionalHeader.SizeOfImage += 0x1000;
// 获取最后一个节
PIMAGE_SECTION_HEADER sectionHeader = GetFirstSectionHeader(buff) + (ntHeader->FileHeader.NumberOfSections - 1);
DWORD max = sectionHeader->SizeOfRawData > sectionHeader->Misc.VirtualSize ? sectionHeader->SizeOfRawData : sectionHeader->Misc.VirtualSize;
sectionHeader->SizeOfRawData = max + 0x200;
sectionHeader->Misc.VirtualSize = max + 0x200;
/*
* 增加节区,我里默认增加0x1000
*/
char* newBuff = new char[buffSize + 0x200];
memcpy(newBuff, buff, buffSize);
memset(newBuff + buffSize, 0x20, 0x200);
newBuff[buffSize] = 'h';
newBuff[buffSize + 1] = 'e';
newBuff[buffSize + 2] = 'l';
newBuff[buffSize + 3] = 'l';
newBuff[buffSize + 4] = 'o';
newBuff[buffSize + 5] = 0x00;
delete[] buff;
buff = nullptr;
return newBuff;
}
修改后对比:
修改后的文件中有我们加上的hello,这里你们加你想要的任何东西
代码文件,要的自取:
链接: https://pan.baidu.com/s/1tXTN5mhIEIzhmFXSCaI4HQ 提取码: jbpw