DWORD AddNewSection(IN PVOID pFileBuffer, OUT PVOID* pNewFileBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pPEHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
if(!pFileBuffer)
{
printf("FileBuffer无效!\n");
free(pFileBuffer);
return;
}
if(*(PWORD)pFileBuffer != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的PE文件\n");
free(pFileBuffer);
return;
}
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)(pDosHeader + pDosHeader->e_lfanew);
pPEHeader = (PIMAGE_FILE_HEADER)(pNTHeader + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)(pOptionHeader + pPEHeader->SizeOfOptionalHeader);
//判断是否有足够的空间添加一个节表
if((pOptionHeader->SizeOfHeaders - (pDosHeader->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER + pPEHeader->SizeOfOptionalHeader + IMAGE_SIZEOF_SECTION_HEADER * pPEHeader->NumberOfSections)) < IMAGE_SIZEOF_SECTION_HEADER * 2)
{
printf("添加节表空间不足\n");
free(pFileBuffer);
return;
}
//计算添加节后的大小sizeOfFileBuffer
DWORD sizeOfNewFileBuffer = 0;
DWORD sizeOfSections = 0;
DWORD sizeOfFileBuffer = 0;
PIMAGE_SECTION_HEADER pTemOfSectionHeader = pSectionHeader;
for(int i=0;i<pPEHeader->NumberOfSections;pTemOfSectionHeader++,i++)
{
sizeOfSections += pTemOfSectionHeader->PointerToRawData;
}
sizeOfFileBuffer = sizeOfSections + pOptionHeader->SizeOfHeaders;
sizeOfNewFileBuffer = sizeOfFileBuffer + pOptionHeader->FileAlignment;//增加一个文件对齐长度的大小的节
//分配新的缓冲区
PVOID pTemOfNewFileBuffer = NULL;
pTemOfNewFileBuffer = malloc(sizeOfNewFileBuffer);
if(!pTemOfNewFileBuffer)
{
printf("pTemOfNewFileBuffer分配失败!\n");
free(pFileBuffer);
return;
}
//复制PE文件到新的缓冲区
memset(pTemOfNewFileBuffer,0,sizeOfNewFileBuffer);
memcpy(pTemOfNewFileBuffer,pFileBuffer,sizeOfFileBuffer);
//添加新节表并修改属性
//通过上面的循环后,pTemOfSectionHeader是新节表的RVA
PIMAGE_SECTION_HEADER pNewSectionHeader = (PIMAGE_SECTION_HEADER)(((DWORD)pTemOfSectionHeader - (DWORD)pFileBuffer) + (DWORD)pNewFileBuffer);
memset(pNewSectionHeader,0,0x80);//填充两个节表大小的0
memcpy(pNewSectionHeader->Name,"new",sizeof("new"));
pNewSectionHeader->Misc.VirtualSize = pOptionHeader->FileAlignment;
pNewSectionHeader->VirtualAddress = (pNewSectionHeader - 1)->VirtualAddress + pOptionHeader->SectionAlignment;
pNewSectionHeader->SizeOfRawData = pOptionHeader->FileAlignment;
pNewSectionHeader->PointerToRawData = (pNewSectionHeader - 1)->PointerToRawData + (pNewSectionHeader - 1)->SizeOfRawData;
pNewSectionHeader->Characteristics = pNewSectionHeader->Characteristics||0x60000020;
//修改NumberOfSections和sizeofimage
pPEHeader->NumberOfSections += 1;
pOptionHeader->SizeOfImage += pOptionHeader->FileAlignment;
*pNewFileBuffer = pTemOfNewFileBuffer;
pTemOfNewFileBuffer = NULL;
free(pFileBuffer);
return sizeOfNewFileBuffer;
}
1、判断是否有足够的空间,可以添加一个节表. |
判断条件: |
SizeOfHeader
- (DOS + 垃圾数据 + PE标记 + 标准PE头 + 可选PE头 + 已存在节表) |
>= 2个节表的大小 |
2、需要修改的数据 |
1) 添加一个新的节(可以copy一份) |
2) 在新增节表后面
填充一个节大小的0; |
3) 修改PE头中节的数量 |
4) 修改sizeOfImage的大小 |
5) 再原有数据的最后,新增一个节的数据(内存对齐的整数倍). |
6)修正新增节表的属性 |